{"id":13582209,"url":"https://github.com/tomMoulard/fail2ban","last_synced_at":"2025-04-06T14:30:29.860Z","repository":{"id":44333423,"uuid":"306021510","full_name":"tomMoulard/fail2ban","owner":"tomMoulard","description":"Traefik plugin on fail2ban middleware","archived":false,"fork":false,"pushed_at":"2025-04-01T11:21:00.000Z","size":2083,"stargazers_count":221,"open_issues_count":17,"forks_count":19,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-02T20:51:39.177Z","etag":null,"topics":["fail2ban","hackathon","traefik","traefik-plugin"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tomMoulard.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["tommoulard"],"custom":["https://www.paypal.me/tommoulard"]}},"created_at":"2020-10-21T12:44:36.000Z","updated_at":"2025-04-01T11:21:05.000Z","dependencies_parsed_at":"2023-02-17T21:45:43.254Z","dependency_job_id":"57e5bf49-2e4d-4f6c-b866-0df95fe0f608","html_url":"https://github.com/tomMoulard/fail2ban","commit_stats":{"total_commits":165,"total_committers":13,"mean_commits":"12.692307692307692","dds":0.6363636363636364,"last_synced_commit":"03522c4f7871cbaa14b9b6410ad103888437ee18"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomMoulard%2Ffail2ban","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomMoulard%2Ffail2ban/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomMoulard%2Ffail2ban/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomMoulard%2Ffail2ban/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tomMoulard","download_url":"https://codeload.github.com/tomMoulard/fail2ban/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247495612,"owners_count":20948084,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fail2ban","hackathon","traefik","traefik-plugin"],"created_at":"2024-08-01T15:02:29.777Z","updated_at":"2025-04-06T14:30:29.507Z","avatar_url":"https://github.com/tomMoulard.png","language":"Go","funding_links":["https://github.com/sponsors/tommoulard","https://www.paypal.me/tommoulard"],"categories":["Go","hackathon"],"sub_categories":[],"readme":"# Fail2ban plugin for traefik\n\n[![Build Status](https://github.com/tomMoulard/fail2ban/actions/workflows/main.yml/badge.svg)](https://github.com/tomMoulard/fail2ban/actions/workflows/main.yml)\n\nThis plugin is an implementation of a Fail2ban instance as a middleware\nplugin for Traefik.\n\n## Middleware\n\nAfter installing the plugin, it can be configured through a Middleware, e.g.:\n\n```yml\napiVersion: traefik.io/v1alpha1\nkind: Middleware\nmetadata:\n  name: fail2ban-test\nspec:\n  plugin:\n    fail2ban:\n      logLevel: DEBUG\n      denylist:\n        ip: 127.0.0.1\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eAdd the middleware to an ingressroute\u003c/summary\u003e\n\n```yml\napiVersion: traefik.io/v1alpha1\nkind: IngressRoute\nmetadata:\n  name: simplecrd\n  namespace: default\nspec:\n  entryPoints:\n    - web\n  routes:\n  - match: Host(`fail2ban.localhost`)\n    kind: Rule\n    middlewares:\n    - name: fail2ban-test\n    services:\n    ...\n```\n\n\u003c/details\u003e\n\n## Configuration\n\nPlease note that the allowlist and denylist functionality described below can\n_only_ be used _concurrently_ with Fail2ban functionality (if you are looking\nfor a way to allowlist or denylist IPs without using any of the Fail2ban\nlogic, you might want to use a different plugin.)\n\n### Allowlist\nYou can allowlist some IP using this:\n```yml\ntestData:\n  allowlist:\n    files:\n      - \"tests/test-ipfile.txt\"\n    ip:\n      - \"::1\"\n      - \"127.0.0.1\"\n```\n\nWhere you can use some IP in an array of files or directly in the\nconfiguration.\n\nIf you have a single IP, this: `ip: 127.0.0.1` should also work.\n\n### Denylist\nLike allowlist, you can denylist some IP using this:\n```yml\ntestData:\n  denylist:\n    files:\n      - \"tests/test-ipfile.txt\"\n    ip:\n      - \"::1\"\n      - \"127.0.0.1\"\n```\n\nWhere you can use some IP in an array of files or directly in the\nconfiguration.\n\nPlease note that Fail2ban logs will _only_ be visible when Traefik's log level\nis set to `DEBUG`.\n\n## Fail2ban\nWe plan to use all default fail2ban configuration but at this time only a\nfew features are implemented:\n```yml\ntestData:\n  rules:\n    urlregexps:\n    - regexp: \"/no\"\n      mode: block\n    - regexp: \"/yes\"\n      mode: allow\n    bantime: \"3h\"\n    findtime: \"10m\"\n    maxretry: 4\n    enabled: true\n    statuscode: \"400,401,403-499\"\n```\n\nWhere:\n - `findtime`: is the time slot used to count requests (if there is too many\nrequests with the same ip in this slot of time, the ip goes into ban). You can\nuse 'smart' strings: \"4h\", \"2m\", \"1s\", ...\n - `bantime`: correspond to the amount of time the IP is in Ban mode.\n - `maxretry`: number of request before Ban mode.\n - `enabled`: allow to enable or disable the plugin (must be set to `true` to\nenable the plugin).\n - `urlregexp`: a regexp list to block / allow requests with regexps on the url\n - `statuscode`: a comma separated list of status code (or range of status\ncodes) to consider as a failed request.\n\n#### URL Regexp\nUrlregexp are used to defined witch part of your website will be either\nallowed, blocked or filtered :\n- allow : all requests where the url match the regexp will be forwarded to the\nbackend without any check\n- block : all requests where the url match the regexp will be stopped\n\n##### No definitions\n\n```yml\ntestData:\n  rules: {}\n```\n\nBy default, fail2ban will be applied.\n\n##### Multiple definition\n\n```yml\ntestData:\n  rules:\n    urlregexps:\n    - regexp: \"/whoami\"\n      mode: allow\n    - regexp: \"/do-not-access\"\n      mode: block\n```\n\nIn the case where you define multiple regexp on the same url, the order of\nprocess will be :\n1. Block\n2. Allow\n\nIn this example, all requests to `/do-not-access` will be denied and all\nrequests to `/whoami` will be allowed without any fail2ban interaction.\n\n#### Status code\nWhen this configuration is set (i.e., `statuscode` is not empty), the plugin\nwill wait for the request to be completed and check the status code of the\nresponse. If the status code is in the list of status codes, the request will\nbe considered as a failed request.\n\nNote that the request is considered completed when the response is back sent to the\nplugin, therefore, the request went through the middleware, traefik, to the backend,\nand back to the middleware.\n\n\u003cdetails\u003e\n\u003csummary\u003eHere is a little schema to explain the process\u003c/summary\u003e\n\n```mermaid\nsequenceDiagram\n    actor C as Client\n    participant A as Middleware\n    participant B as Backend\n    C-\u003e\u003eA: Request\n    A-\u003e\u003eB: Request\n    B-\u003e\u003eA: Response\n    A-\u003e\u003eA: Check status code\n    critical [Check status code]\n    option Invalid status code\n        A--X C: Log error\n    option valid status code\n        A-\u003e\u003eC: Log error\n    end\n```\n\n\u003c/details\u003e\n\n#### Schema\nFirst request, IP is added to the Pool, and the `findtime` timer is started:\n```\nA |-------------\u003e\n  ↑\n```\n\nSecond request, `findtime` is not yet finished thus the request is fine:\n```\nA |--x----------\u003e\n     ↑\n```\n\nThird request, `maxretry` is now full, this request is fine but the next wont.\n```\nA |--x--x-------\u003e\n        ↑\n```\n\nFourth request, too bad, now it's jail time, next request will go through after\n`bantime`:\n```\nA |--x--x--x----\u003e\n           ↓\nB          |-------------\u003e\n```\n\nFifth request, the IP is in Ban mode, nothing happen:\n```\nA |--x--x--x----\u003e\nB          |--x----------\u003e\n              ↑\n```\n\nLast request, the `bantime` is now over, another `findtime` is started:\n```\nA |--x--x--x----\u003e            |-------------\u003e\n                             ↑\nB          |--x----------\u003e\n```\n\n## How to dev\n\n```bash\n$ docker compose up\n```\n\n# Authors\n| Tom Moulard | Clément David | Martin Huvelle | Alexandre Bossut-Lasry |\n|-------------|---------------|----------------|------------------------|\n|[![](https://github.com/tomMoulard/fail2ban/blob/main/.assets/gopher-tom_moulard.png)](https://tom.moulard.org)|[![](https://github.com/tomMoulard/fail2ban/blob/main/.assets/gopher-clement_david.png)](https://github.com/cledavid)|[![](https://github.com/tomMoulard/fail2ban/blob/main/.assets/gopher-martin_huvelle.png)](https://github.com/nitra-mfs)|[![](https://github.com/tomMoulard/fail2ban/blob/main/.assets/gopher-alexandre_bossut-lasry.png)](https://www.linkedin.com/in/alexandre-bossut-lasry/)|\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FtomMoulard%2Ffail2ban","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FtomMoulard%2Ffail2ban","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FtomMoulard%2Ffail2ban/lists"}