-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
action.d/pf.conf actionban doesn't kill state after adding ban. #1924
Comments
I doubt it, because the ban occurs after failure, recognized from corresponding application. Normally it closes the connection hereafter. But possibly it would be really a nice feature. |
Hi @sebres, For any rule that has a "keep state" part, which is the default option, the firewall keeps information of packets that already have matched a rule in the "state table". Any new packets are checked first against the state table and will only be processed by "the rule set evaluation" if there is no match in the "state table". This will lead to a prior granted "pass .." until the state table TTL expires. Default TTL vary from 10s to 1h, depending on current connection state. |
You have not understood what I wanted to say you... BTW, I'm not against this as "enhancement". Even possibly to enable it per default... But I'll try to explain what I meant with "Normally the application closes connection after failures":
As you see, sshd will reject connection on step 4 regardless the ban, etc... P.S. I should not be familiar with the FreeBSD packet filter, to understand what P.P.S. This is already too many issues with |
The "state table tcp.closed timeout" is set to 90s and starts to count down after sshd disconnecting. There's no need to be offensive. Since you have neither the time nor the desire, please don't bother me with an answer. Issue closed due to lack of commitment |
You still not understood me...
Hmmm... where?
Sure we're interested, but for real fixing.
Maybe... But it is IMHO not a bug, rather matter of opinion resp. missing or insufficient functionality of FreeBSD's pf-firewall. |
Corresponding man of pfctl:
Together with:
Would be this not a solution (as replacement for |
Currently I've tried the old pf-syntax (without modifications) on a freebsd-vm with generic kernel (default settings)... Simplified PoC:# ---- SERVER/1st session: on target FreeBSD machine (with pf/fail2ban):
$ tclsh8.6
% set s [socket -server srv 8080]; proc srv {s args} {
fconfigure $s -buffering line; while 1 {
puts $s test; after 1000; puts [gets $s]}}; vwait infinite
# ++++ CLIENT/1st session on source machine (test client should be banned):
$ tclsh8.6
% set s [socket test-server 8080]; fconfigure $s -buffering line; while 1 {
puts $s [clock seconds]; after 1000; puts [clock seconds]-[gets $s]}
1508257243-test
1508257244-test
1508257245-test
...
# **** SERVER/2nd session: on target FreeBSD machine (with pf/fail2ban):
$ echo "block return quick proto tcp from <f2b-test> to any port {8080}" | pfctl -a f2b/test -f-
$ pfctl -a f2b/test -t f2b-test -T add test-client
1 table created.
1/1 addresses added.
# ++++ CLIENT/1st session:
1508257274-
error writing "sock480": software caused connection abort
while executing
"puts $s [clock seconds]"
# **** SERVER/2nd session:
$ pfctl -a f2b/test -t f2b-test -T flush
1 addresses deleted.
$ pfctl -a f2b/test -t f2b-test -T kill
1 table deleted. I concretes again - connection rejected almost immediately... The same affects the active ssh-sessions (just to uncomfortable to debug it). Thus closed, until more info provided. |
Strumbled over the same issue as @ghost. In my case it is an nginx webserver, where I use the nginx-auth filter. The session is not terminated with the default action at pf.conf. So the attacker can continue brute forcing quite undisturbed. @sebres I think your PoC might not be portraying this completely. For me the -k parameter is suitable for the moment. Tested with Fail2Ban 0.10.1 on FreeBSD LTS-Version (10.3-RELEASE-p25). Just my 2 cents. |
For how long? I mean, is it sure not just the rest of the submitted buffer resp. fail2ban latency withing filter-backend? |
Don't think this is the delay from the action execution... With -k parameter it's applied in 2-3 seconds.
|
I would like to understand why I cannot reproduce it... The statement "until TTL expires" does not really explained it. But again, I'm not against "kill states", but if properly... If you know how it could be made using same anchor/table as implemented in current banaction, please provide an example. |
I was using |
@catsem, @IdahoPL, @distler, @koeppea, @fail2ban/contributors -actionban = <pfctl> -t <tablename>-<name> -T add <ip>
+actionban = <pfctl> -t <tablename>-<name> -T add <ip> && <pfctl> -F states Additionally, does someone know any another syntax, how the states can be killed/flushed without kill of ALL connections for the IP (to all ports), e. g. using labels, anchor, table, etc? |
pfctl -F states will kill all states causing every connection to drop. This would be far worse than pfctl -k I don't think that we can do better than pfctl -k |
You are wrong a bit in the abovementioned case, - I meant not |
Or we'll need additionally the table, besides anchor in this case? |
My quick test showed that: pfctl -a f2b/named -t f2b-named -F states and pfctl -a f2b/named -F states killed my active ssh connection, so I'm not sure that flush states in this case is limited only to specific anchor. Of course my ssh connection IP wasn't in f2b-named table (it was in fact empty). |
:(
according to pfctl-docu it is so, as regards the anchor,... but unfortunately there is nothing about table. |
The (OpenBSD) manpage on pfctl says:
So, at least on OpenBSD, you have pretty fine-grained control over what state(s) get removed with the Unfortunately, I don't believe this feature is implemented in MacOSX's pfctl. I have to say, though, that I have never seen the behaviour described in the bug report. It only happens if there are multiple denied requests over the same TCP connection. I'm surprised that NGINX doesn't close the connection after denying an authentication request. (I think that's what Apache does, and it kinda makes sense that it should.) |
I know, but port 32123 is dynamical port on source side, so we need to find it between all the states; and think about multiport jails, so we should iterate over all target-ports to kill it (which will be not so trivial).
I believe it does (at least after 3 attempts, also by keep-alive requests), but the attacker can build multiple connections before start authenticate process. Additionally there is several auth-modules (that can act differently), request multiplexing on HTTP/2, etc. |
@IdahoPL Just to be sure, how your Because if ports were specified, we could talk about a bug in
|
Multiport:
named jail looks like this:
BTW: Protocol has to use {} when using multiple ports but ports works without it (and fails when using {}). |
So what would you say, bug of |
I'd go with bug in pf or in it's documentation. |
Although you're right in that this looks like a bug in pf ( If you have a fully whitelisted config like
Then when someone new connects to your server, they are matching the pass rule outside of the nginx-basic-auth anchor. This is where the state is stored. If they then trigger fail2ban, it adds them to the f2b-nginx-basic-auth table inside the nginx-basic-auth anchor. The next time they create a new connection, they will match this rule and be blocked (with no state, as it's a block). But the process of adding an IP to that table doesn't "move" the existing state from the main ruleset into the anchor so I don't think you could use the anchor to query or flush the state of the first connection even if that feature did work as documented. Flushing all state for the main table would be bad (for the reasons IdahoPL gave) so it does seem that killing all states for a single IP on any port is the closest, and trusting whatever process on the client was using those ports to reconnect if necessary (and either being allowed, or not, as per the new firewall config). |
In the long term maybe the project could find some use for py-pf (http://www.kernel-panic.it/programming/py-pf/pf2.html)? This seems to have the ability to more granularly kill states based on (for example) source IP and destination port (for example, terminate SSH connections but no other ports):
|
I've never suggested to do this.
As already said, it's not an option for fail2ban, sorry. I'll accept such PR for
Do you really see here no conflict? |
@IdahoPL I tried currently the multiport test and I cannot reproduce this "pf-bug" with anchors at all. root@test-server # echo "block return quick proto tcp from <f2b-test> to any port {8080}" | pfctl -a f2b/test -f-
...
root@test-server # pfctl -a f2b/test -t f2b-test -T add test-client; pfctl -a f2b/test -F states
1/1 addresses added.
0 states cleared
...
root@test-server # pfctl -a f2b/test -t f2b-test -T flush
1 addresses deleted. My problem is that I cannot reproduce the issue at all (connection to 8080 will be closed immediately). But strange is, that I've 2 active ssh connections from test-client to test-server, and call of root@test-server # pfctl -F states
0 states cleared I get Very strange is also that |
pfctl -s all should do "show all". What do pfctl -s info says? |
|
And what pfctl -s all says? What version of FreeBSD are you using? |
Details of pfctl -s all ...
If I call it with anchor, then I see the filter and table additionally.
Still confusing:
And nothing is killed from the test-client. |
is the kill maybe also anchor sensitive? |
That is what I would want to test... But even calling without anchor ( |
Hello All, I made some changes and (maybe? :) ) improvements to the pf.conf action in fail2ban locally. I will open a PR if my testing shows that there are no unforeseen bugs. So without flushing any states the connection I believe will remain untouched until the TCP connection changes from established, or there are any different session timeouts that take place. In theory this could mean that an attacker could try different authentication mechanisms until he/she gets a deny from the application itself. Then when the IP is banned and the rule matches for a service no new connection can be made.
But I already had an established ssh session and after the ban I could still work with that despite having the same dst port:
Then I clear the session for the IP and the connection breaks:
Session breaks here as expected... and no new connection can be made I understand that this is not how fail2ban wants to operate in case someone does not use the allports directive... TESTCASE2: Still could try other passwords as sshd config allows 3 tries
TESTCASE3:
I tried to find a working solution and checked multiple workarounds:
This is how it looks like:
So in theory it can be implemented, but the question is, should we even bother? Or maybe it could be done with a pluggable module or configuration directive that is relying on py-pf or some other helper function. What do you think? |
Ah I also wanted to mention PF-s solution to this problem, however it's a little bit simple and oldschool. |
Just a mark for me (see how we made it in #3018 for |
Really interesting topic and I face the same issue under FreeBSD 13. I agree all what @ghost posts here above.
The attacker should immediately get banned from the server, including his/her already-established connections/current sessions. Why? Think about a WordPress attacker, brute-forcing /wp-login.php - sessions would never get terminated, otherwise. |
What sounds reasonable and plausible for you, isn't necessarily acceptable for someone else.
Think of possible false positives and mistakes, differently grading jails, complex fail2ban configurations (serving complicated large IDS/IPS requirements), proxying or relaying points, backwards compatibility, etc... Anyway, fortunately the action can be adjusted to any particular requirement by everyone (inclusive maintainers of fail2ban for FreeBSD) according their own individual needs. |
Environment:
The issue:
actionban = <pfctl> -t <tablename>-<name> -T add <ip>
actionban should invoke an additional
pfctl -k <ip>
to kill the state entries, since rules are only applied to new connections. Without clearing the state an attacker is able to keep the connection open and to continue the attackExpected behavior
actionban = <pfctl> -t <tablename>-<name> -T add <ip> && <pfctl> -k <ip>
The text was updated successfully, but these errors were encountered: