0

running on Rocky Linux 9.2 with podman 4.4.1. I got a podman Pod with keycloak + postgresql inside, running rootless. The pod itself with --network 'slirp4netns:port_handler=slirp4netns'. The keycloak container is running with --log-driver json-file --log-opt path=/var/log/keycloak.log so I have the log file on the host system itself. There is also a traefik proxy making keycloak accessible, ssl termination on traefik + ssl termination on keycloak itself.

Everything works so far, I see the real IP address of a user trying to login in the logs. Fail2ban is running on the host system, the regex is also working, and it's banning the correct IP address BUT even though the IP is banned (I see it in fail2ban-client status keycloak), the user is still able to continue submitting logins.

/etc/fail2ban/jail.d/keycloak.local

[keycloak]
backend = auto
enabled = true
filter = keycloak
maxretry = 3
bantime = 86400
findtime = 86400
logpath = /var/log/keycloak.log
action = iptables-allports[name=keycloak]

So before the ban, iptables is empty:

iptables -n -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

After the ban:

iptables -n -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
f2b-keycloak  tcp  --  0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain f2b-keycloak (1 references)
target     prot opt source               destination         
REJECT     all  --  xx.xx.xx.xx       0.0.0.0/0            reject-with icmp-port-unreachable
RETURN     all  --  0.0.0.0/0            0.0.0.0/0

I also read something about that Docker is using the FORWARD chain, so I set action = iptables-allports[name=keycloak, protocol=all, chain=FORWARD] in the keycloak jail file, iptables had then the rule in the FORWARD chain but it was still not working. Same behaviour like when using the default setting (in the INPUT chain).

How can I make the rootless podman container obey the ip ban from iptables? Any ideas?

8
  • podman with slirp4netns doesn't use iptables for routing so that's not the issue. Commented Sep 6, 2023 at 6:15
  • @Ginnungagap okay but what does that mean, I can't use fail2ban with rootless podman (slirp4netns) at all?
    – Leo
    Commented Sep 6, 2023 at 8:59
  • No, I'm just saying this isn't an issue with FORWARD rules. Blocking on INPUT should work, I'm guessing there are more rules than what we see, especially since RHEL 9 uses nftables underneath which supports more chains than what iptables can display, although the iptables chain should still be capable of rejecting packets. Commented Sep 6, 2023 at 11:10
  • 1
    It might be worth checking what traffic tcpdump sees when filtering on the IP you expect to be blocked, it might also be that your handling of upstream IPs is flawed and what you log isn't really the remote IP. Commented Sep 6, 2023 at 11:12
  • okay, tcpdump shows the "wrong" ip, it shows the communication between the two local IP addresses (traefik proxy and keycloak VM). Hmm I see, so it's basically connected to the X-Forwarded-For topic, I had to deal with to get the real user ip into the logs. So afaik, the traefik sets this header with the real ip when redirecting. It ends up at keycloak, which interprets this header, therefore I have the correct IP. But how would iptables respect that header and not the other local IP?
    – Leo
    Commented Sep 6, 2023 at 12:23

2 Answers 2

1

Fail2ban works (by default) at the firewall level which itself works at the IP level.

Given your setup, all traffic is relayed by an external Traefik instance whose IP is the only one contacting Keycloak which means the firewall can either block that IP or allow it.

If you want to block misbehaving IPs, you need to block them on the Traefik host (given the information you provided).

1
  • Doing a regular fail2ban setup would be the easiest but obviously it isn't that easy with such setup. I also thought about either sharing the log file with the traefik VM and block it there using fail2ban OR using the opnsense API to blacklist the IP. Don't know which approach is the best.
    – Leo
    Commented Sep 6, 2023 at 15:28
0

fiddling around with fail2ban and X-Forwarded-For header wouldn't be a satisfying solution. I solved this by using the opnsense API approach. Quick summary:

  • created a user (api key) with the permissions for alias_util and diagnostics firewall states endpoints.
  • created an alias ipv4_blacklist of type External (advanced)
  • created a firewall wan rule to block everything from source ipv4_blacklist
  • created keycloak custom action using actionban and actionunban

for actionban you need two commands:

  1. Adding the given ip to the blacklist via api/firewall/alias_util/add/ipv4_blacklist
  2. Killing the active sessions via api/diagnostics/firewall/kill_states, so the ban action take effect immediately

for actionunban one command is enough:

  1. Simply delete the given ip via api/firewall/alias_util/delete/ipv4_blacklist

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .