I'm migrating DemureSoft over to the new gitplace at t/suki, but during the migration one of the members got banned by fail2ban. This is what they did:
- https clone (failed)
- set their password on forgejo
- https clone (success)
- https fetch (could not connect, banned by fail2ban)
I was not expecting them to be banned at all,
much less so quickly, so I took a look at the
fail2ban logs at
log/fail2ban/fail2ban.log
(member's ip
address redacted):
2025-04-14 16:17:35,681 fail2ban.filter [747]: INFO [nginx-unauthorized] Found x.x.x.x - 2025-04-14 16:17:35
2025-04-14 16:17:45,689 fail2ban.filter [747]: INFO [nginx-unauthorized] Found x.x.x.x - 2025-04-14 16:17:44
2025-04-14 16:17:45,690 fail2ban.filter [747]: INFO [nginx-unauthorized] Found x.x.x.x - 2025-04-14 16:17:45
2025-04-14 16:18:47,145 fail2ban.filter [747]: INFO [nginx-unauthorized] Found x.x.x.x - 2025-04-14 16:18:47
2025-04-14 16:20:44,052 fail2ban.filter [747]: INFO [nginx-unauthorized] Found x.x.x.x - 2025-04-14 16:20:44
2025-04-14 16:20:44,287 fail2ban.actions [747]: NOTICE [nginx-unauthorized] Ban x.x.x.x
2025-04-14 16:30:44,586 fail2ban.actions [747]: NOTICE [nginx-unauthorized] Unban x.x.x.x
Taking a look at the nginx log
log/nginx/access.log
, I see (member's
username and ip address redacted):
x.x.x.x - - [14/Apr/2025:16:17:35 +0000] "GET /DemureSoft/Ultraprocessor-Ribbon.git/info/refs?service=git-upload-pack HTTP/2.0" 401 13 "-" "git/2.43.0"
x.x.x.x - username [14/Apr/2025:16:17:44 +0000] "GET /DemureSoft/Ultraprocessor-Ribbon.git/info/refs?service=git-upload-pack HTTP/2.0" 401 139 "-" "git/2.43.0"
x.x.x.x - username [14/Apr/2025:16:17:45 +0000] "GET /DemureSoft/Ultraprocessor-Ribbon.git/info/refs?service=git-upload-pack HTTP/2.0" 401 139 "-" "git/2.43.0"
x.x.x.x - - [14/Apr/2025:16:17:55 +0000] "GET /user/events HTTP/2.0" 200 27 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
x.x.x.x - - [14/Apr/2025:16:17:55 +0000] "GET /user/settings HTTP/2.0" 200 28177 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
x.x.x.x - - [14/Apr/2025:16:18:01 +0000] "GET /user/events HTTP/2.0" 200 0 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
x.x.x.x - - [14/Apr/2025:16:18:01 +0000] "GET /user/settings/security HTTP/2.0" 200 31335 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
x.x.x.x - - [14/Apr/2025:16:18:04 +0000] "GET /user/events HTTP/2.0" 200 0 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
x.x.x.x - - [14/Apr/2025:16:18:04 +0000] "GET /user/settings HTTP/2.0" 200 28176 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
x.x.x.x - - [14/Apr/2025:16:18:05 +0000] "GET /user/events HTTP/2.0" 200 0 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
x.x.x.x - - [14/Apr/2025:16:18:05 +0000] "GET /user/settings/account HTTP/2.0" 200 30995 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
x.x.x.x - - [14/Apr/2025:16:18:06 +0000] "GET /user/settings/account HTTP/2.0" 200 30993 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
x.x.x.x - - [14/Apr/2025:16:18:35 +0000] "GET /user/events HTTP/2.0" 200 0 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
x.x.x.x - - [14/Apr/2025:16:18:36 +0000] "POST /user/settings/account HTTP/2.0" 303 0 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
x.x.x.x - - [14/Apr/2025:16:18:36 +0000] "GET /user/settings/account HTTP/2.0" 200 31362 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
x.x.x.x - - [14/Apr/2025:16:18:47 +0000] "GET /DemureSoft/Ultraprocessor-Ribbon.git/info/refs?service=git-upload-pack HTTP/2.0" 401 13 "-" "git/2.43.0"
x.x.x.x - username [14/Apr/2025:16:18:58 +0000] "GET /DemureSoft/Ultraprocessor-Ribbon.git/info/refs?service=git-upload-pack HTTP/2.0" 200 172 "-" "git/2.43.0"
x.x.x.x - username [14/Apr/2025:16:18:59 +0000] "POST /DemureSoft/Ultraprocessor-Ribbon.git/git-upload-pack HTTP/2.0" 200 472 "-" "git/2.43.0"
x.x.x.x - username [14/Apr/2025:16:19:14 +0000] "POST /DemureSoft/Ultraprocessor-Ribbon.git/git-upload-pack HTTP/2.0" 200 257310866 "-" "git/2.43.0"
x.x.x.x - - [14/Apr/2025:16:20:44 +0000] "GET /DemureSoft/Ultraprocessor-Ribbon.git/info/refs?service=git-upload-pack HTTP/2.0" 401 13 "-" "git/2.43.0"
It appears that whenever git tries tries to do HTTPS authentication, it always tries unauthenticated first. This must be what's causing nginx to ban the user so quickly, since every normal https git action results in an unauthorized response before the username and password form is prompted to the user. Looking up this issue online to figure out how I can get around it with SWAG, I find a conversation about this issue, but it's largely unhelpful as the maintainers and the person who opened the support request just get into an argument.
I also found a thread from someone who has the same issue with gitea, but it was also shut down in the same way.
Neither of these topics describe how to get
around this issue, so I guess I have to figure it
out on my own. Apparently, there's
a configuration file to change what jails are
enabled at
/etc/fail2ban/jail.local
. I can see
this file in the docker container for swag, but it's
not clear now I'm supposed to update it.
Eventually, I find this official SWAG
documentation which mentions that jail.local
is found at fail2ban/jail.local
. I find
the entry for nginx-unauthorized
and
disable it:
[nginx-unauthorized]-enabled = true
+enabled = false
port = http,https
filter = nginx-unauthorized logpath = /config/log/nginx/access.log
Running
docker exec -it <container id> fail2ban-client status
,
I can see that the jail has been disabled:
Status
|- Number of jail: 4
`- Jail list: nginx-badbots, nginx-botsearch, nginx-deny, nginx-http-auth
After asking the user to pull the repo again, I can see that fail2ban doesn't log the 401s anymore. It seems to have worked!