Skip to content
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

Request about fail2ban running at Host level + many LXC containers with unique IP address + interface alias pairs #1470

Open
davidfavor opened this issue Jun 28, 2016 · 14 comments

Comments

@davidfavor
Copy link

Environment:

Ubuntu Xenial + LXC + Fail2Ban v0.9.3 + all latest OS updates.

The issue:

Trying to get fail2ban running at host level to track logs in all LXC containers (there are many).

Idea is to block attacking IP at host level for all containers, whenever any site on any container is attacked.

fail2ban config modification

[sshd]
enabled = false
port = ssh
logpath = /var/log/auth.log tail
/var/lib/lxc/*/rootfs/var/log/auth.log tail

Problem

This approach seems to simplistic, because what appears to be happening (my guess, haven't fired up tcpdump to figure it out yet) is that the iptables blocking rule added only applies to the base interface.

In my case I have the base interface + one alias/container, where all packets flow from public interface alias to each container's dynamically generated IP.

Base interface is eth2.

Alias interfaces are eth2:1 - eth2:XXX

My guess is anytime an iptables block rule is added via an iptables command, the same command has to run for each alias.

This means logic for actioncheck + actionban + actionunban requires some additional complexity to handle this.

My questions...

  1. If there's a know approach for handling this type of setup, pass me a pointer.

  2. If not, I'm imaging the way to approach this is to create an ipset + then change action files like iptables-multiport.conf to reference the ipset.

Suggestions are appreciated.

Thanks.

@davidfavor
Copy link
Author

Maybe using firewallcmd-ipset.conf in some way.

@davidfavor
Copy link
Author

Hum... This seems to work... Some let me know if this might be correct...

  1. apt-get install firewalld ipset

  2. In jail.conf

[lxc-sshd]
enabled = true
port = ssh
logpath = /var/lib/lxc/*/rootfs/var/log/auth.log tail
action = firewallcmd-ipset[name=lxc-sshd, port="ssh", protocol=tcp]
filter = sshd
maxretry = 1
findtime = 60
bantime = 3600

@davidfavor
Copy link
Author

I suppose the host /var/log/auth.log can go into the same logpath too.

@davidfavor
Copy link
Author

Once again fail2ban saves the day!

@davidfavor
Copy link
Author

davidfavor commented Jun 28, 2016

Well, this doesn't work, because firewalld produces all manner of gnarliness, including flushing all NAT rules, which destroys all LXC communication paths, so back to the drawing board.

@qm2k
Copy link

qm2k commented Jul 9, 2016

Created new actions similar to iptables-* but with altered definition of <iptables> variable:
iptables = lxc-attach -n <container> -- iptables <lockingopt>
You should pass container variable to these rules, and you should install iptables package in the container. Not pretty, but works.

@davidfavor
Copy link
Author

qm2k wrote:

Created new actions similar to iptables-* but with altered definition of
|| variable:
|iptables = lxc-attach -n iptables |
You should pass container variable to them, and you should install
iptables package in the container. Not pretty, but works.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
http://links.davidfavor.com/wf/click?upn=npdP0-2FMHcGNgMeleDP-2B5C2OKSi7NbJV8-2Fxugocgfb1D-2FyKua6cSnyH9rcqxXR857O29L66uTIh3K38FExZXXJLqLhE1L1qPr9wj092eZUFM-3D_s5UH8bhnBaopYjthcNSRcWalBZYOotImKnZpIGt9Srf0QD-2BcZN81IZ3y0dH-2BjWNeIqx6WSZMTPi3hlwv-2B1SV6au61YwHMaTDXV1k63D5wvYR6-2FiyQGfwFLDfSmq7NZ-2FrM-2FSOp1VzEupVTf44jbMXzFEGyS1u0PvGM0y9Pje9QQtSBR5JuUSZ1QfTpFgUov9Qw671fod8lOBTitAkDQzqYhAPrHUk-2BLtj7EiEVWNYN6aoDZ-2FfTRF5XVLxhNwQ5esK3n4-2FXZylhNLuTQ6MWDI4HctoN-2F51DNr2z9l1VM9Dz2HxmgOLCSFsFlGafRYOsefLn2Inj0jBlBSfNAu-2B-2FSvNZg-3D-3D,
or mute the thread
http://links.davidfavor.com/wf/click?upn=npdP0-2FMHcGNgMeleDP-2B5C7AVBorP-2FKY4ck16dAhGxXUvybq1WQryduaQBV4jETF9bOxsaL67kReqmObHNab-2F-2Bol1jrNOI7N2J6I05A-2Fshk3z-2F2Jgk6Zg7GU11rjSEboWYCsxE-2B2NcfgESGHk7VjTXQ-3D-3D_s5UH8bhnBaopYjthcNSRcWalBZYOotImKnZpIGt9Srf0QD-2BcZN81IZ3y0dH-2BjWNeIqx6WSZMTPi3hlwv-2B1SV6au61YwHMaTDXV1k63D5wvYR6-2FiyQGfwFLDfSmq7NZ-2FrM-2FSOp1VzEupVTf44jbMXzFEGyS1u0PvGM0y9Pje9QQtSBR5JuUSZ1QfTpFgUov9QJtL-2BXehjgskBqJlr82pjsnVDvBrbdnOIELkz4gRa3XTdMdJNhoDKW7-2FhA-2B0H14Ak1NxOJC8WrRYY4JnFTZsZZPrXqOhUbewwM1lT7E3aweHypJdgQ4PO4cmAPUdKWtZIyyN1tXSl1iTgVh9UWe6nzA-3D-3D.

This is actually the same as running fail2ban inside each container.

Running fail2ban inside each container is likely better as attempting an attach,
requires first determining if container is running.

Running fail2ban inside each container also provides the perk of fail2ban rules
following the container, as it migrates/moves across machines, during it's lifetime.

@qm2k
Copy link

qm2k commented Jul 12, 2016

This is actually the same as running fail2ban inside each container.

Well, in my configuration I didn't want to run fail2ban with all dependencies, and also postfix with all dependencies, inside each container. If you want to ban IP on all containers simultaneously, you can do it by enumerating them with lxc-ls and xargs.

Also, I don't think stopped container can generate fail2ban events. And you can achieve portability with includes.

Don't get me wrong, I'd prefer a method of blocking incoming IPs on host, it's just that like you I didn't find one. Probably because the software switch on host is just that -- an L2 switch -- and it doesn't analyze L3 IP addresses at all. There's always an option of blocking IP addresses on some upstream router or nat, though.

@davidfavor
Copy link
Author

Just reading updates to this ticket + resolution I'm using matches suggestions.

If found running fail2ban inside each container seems best.

This allows custom fail2ban rules for each container's site(s).

All clients sites are extremely high traffic sites, so Bot Blocking has a high priority.

Different instances of custom fail2ban rules.

  1. Some sites target 100% paid traffic, so block Bad Bots + Good Bots - Google/Bing/Alexa, etc.

  2. Some sites target paid + natural traffic, so block Bad Bots + allow Good Bots.

Running fail2ban at host level means a single set of rules, so no way to offer clients custom rulesets.

Likely best approach is to always run fail2ban inside container with customer site(s) rules.

@ycharbi
Copy link

ycharbi commented Feb 17, 2020

Created new actions similar to iptables-* but with altered definition of <iptables> variable:
iptables = lxc-attach -n <conteneur> -- iptables <lockingopt>
You should pass conteneur variable to these rules, and you should install iptables package in the conteneur. Not pretty, but works.

Hello,
What you have described is exactly what I am trying to do, but I am not succeeding. I find that running F2B in every Container is clearly not a good solution (otherwise why make Containers instead of virtual machines?).

Could you please indicate more precisely the different sections to be modified and in which files?

Thank you for your help.

@qm2k
Copy link

qm2k commented Feb 18, 2020

What you have described is exactly what I am trying to do, but I am not succeeding.

Please write what you tried and what happened, otherwise it's going to be hard for me to help you.

Could you please indicate more precisely the different sections to be modified and in which files?

Here's one example, for postfix service in container postfix.
New lines in jail.local:

[DEFAULT]
action_mlw_lxc = iptables-multiport-lxc[name=%(__name__)s, container="%(container)s", bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
                 %(mta)s-lines-whois[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]

[postfix]
enabled = true
port = 25,465,587
logpath = /mnt/vars/postfix/log/mail.log
container = postfix
action = %(action_mlw_lxc)s                           

Note logpath pointing to mail log of a container as seen from host, the container property, and the new action.

The only difference of _lxc-suffixed action is in before property.

/etc/fail2ban$ diff -aur ./action.d/iptables-multiport{,-lxc}.conf
--- /etc/fail2ban/action.d/iptables-multiport.conf  2015-08-01 01:32:13.000000000 +0000
+++ /etc/fail2ban/action.d/iptables-multiport-lxc.conf      2016-07-05 16:26:48.367934705 +0000
@@ -6,7 +6,7 @@

 [INCLUDES]

-before = iptables-common.conf
+before = iptables-common-lxc.conf

 [Definition]

And the only difference of _lxc-suffixed common include is prefix to iptables property:

--- /etc/fail2ban/action.d/iptables-common.conf 2015-08-01 01:32:13.000000000 +0000
+++ /etc/fail2ban/action.d/iptables-common-lxc.conf     2016-07-05 16:26:40.599993044 +0000
@@ -10,7 +10,7 @@
[INCLUDES]
after = iptables-blocktype.local
-        iptables-common.local
+        iptables-common-lxc.local
 # iptables-blocktype.local is obsolet

 [Init]
@@ -61,4 +61,5 @@
 # Option:  iptables
 # Notes.:  Actual command to be executed, including common to all calls options
 # Values:  STRING
-iptables = iptables <lockingopt>
+iptables = lxc-attach -n <container> -- iptables <lockingopt>

(.local is specified but not being used in my configuration.)

@ycharbi
Copy link

ycharbi commented Feb 20, 2020

@qm2k
Thank you very much !
Your answer was the basis for solving my problem. I've run some tests and it seems to be working.

I modified the "iptables" command to handle the case when the container is off.

I think my modifications are improvable but for now, with the basic SSH rule, it works. I will test with Postfix as you have shown but I am very excited in advance.

Here are my modifications for those who might be interested:

cat /etc/fail2ban/jail.d/lxc.conf

[DEFAULT]
action_lxc = iptables-multiport-lxc[name=%(__name__)s, conteneur="%(conteneur)s", bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
action_mlw_lxc = iptables-multiport-lxc[name=%(__name__)s, conteneur="%(conteneur)s", bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
                 %(mta)s-lines-whois[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]

[postfix]
enabled = false
port = 25,465,587
logpath = /mnt/vars/postfix/log/mail.log
conteneur = postfix
action = %(action_mlw_lxc)s

[sshd-lxc-web]
enabled = true
port    = ssh
conteneur = lxc-web
logpath = /var/lib/lxc/%(conteneur)s/rootfs/var/log/auth.log
action = %(action_lxc)s
maxretry = 2
ignorecommand =
bantime  = 10m
findtime  = 10m
filter = sshd-lxc

[sshd-lxc-mail]
enabled = true
port    = ssh
conteneur = lxc-mail
logpath = /var/lib/lxc/%(conteneur)s/rootfs/var/log/auth.log
action = %(action_lxc)s
maxretry = 2
ignorecommand =
bantime  = 10m
findtime  = 10m
filter = sshd-lxc

diff -aur /etc/fail2ban/action.d/iptables-common{,-lxc}.conf

--- /etc/fail2ban/action.d/iptables-common.conf	2020-02-19 21:12:19.161146756 +0100
+++ /etc/fail2ban/action.d/iptables-common-lxc.conf	2020-02-20 20:14:59.012165630 +0100
@@ -73,7 +73,8 @@
 # Option:  iptables
 # Notes.:  Actual command to be executed, including common to all calls options
 # Values:  STRING
-iptables = iptables <lockingopt>
+iptables = bash -c "if [ $(lxc-info -n <conteneur> -s -H) == RUNNING ]; then lxc-attach -n <conteneur> -- iptables <lockingopt>
+iptablesfi = fi"
 
 
 [Init?family=inet6]

As you can see, I had to use some tricks to make sure that there are no errors when applying an F2B rule when an LXC container is switched off.
If this is the case, F2B applies the ban in its sqlite base but does nothing in the container. When starting the container, a manual reload of F2B launches the iptables command in the container.

I adapt this trick in the multiport file to close the "if" structure:
diff -aur /etc/fail2ban/action.d/iptables-multiport{,-lxc}.conf

--- /etc/fail2ban/action.d/iptables-multiport.conf	2018-01-18 14:49:01.000000000 +0100
+++ /etc/fail2ban/action.d/iptables-multiport-lxc.conf	2020-02-20 18:03:11.276776368 +0100
@@ -6,7 +6,7 @@
 
 [INCLUDES]
 
-before = iptables-common.conf
+before = iptables-common-lxc.conf
 
 [Definition]
 
@@ -14,23 +14,23 @@
 # Notes.:  command executed once at the start of Fail2Ban.
 # Values:  CMD
 #
-actionstart = <iptables> -N f2b-<name>
-              <iptables> -A f2b-<name> -j <returntype>
-              <iptables> -I <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>
+actionstart = <iptables> -N f2b-<name>; <iptablesfi>
+              <iptables> -A f2b-<name> -j <returntype>; <iptablesfi>
+              <iptables> -I <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>; <iptablesfi>
 
 # Option:  actionstop
 # Notes.:  command executed once at the end of Fail2Ban
 # Values:  CMD
 #
-actionstop = <iptables> -D <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>
-             <actionflush>
-             <iptables> -X f2b-<name>
+actionstop = <iptables> -D <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>; <iptablesfi>
+             <actionflush>; <iptablesfi>
+             <iptables> -X f2b-<name>; <iptablesfi>
 
 # Option:  actioncheck
 # Notes.:  command executed once before each actionban command
 # Values:  CMD
 #
-actioncheck = <iptables> -n -L <chain> | grep -q 'f2b-<name>[ \t]'
+actioncheck = <iptables> -n -L <chain> | grep -q 'f2b-<name>[ \t]'; <iptablesfi>
 
 # Option:  actionban
 # Notes.:  command executed when banning an IP. Take care that the
@@ -38,7 +38,7 @@
 # Tags:    See jail.conf(5) man page
 # Values:  CMD
 #
-actionban = <iptables> -I f2b-<name> 1 -s <ip> -j <blocktype>
+actionban = <iptables> -I f2b-<name> 1 -s <ip> -j <blocktype>; <iptablesfi>
 
 # Option:  actionunban
 # Notes.:  command executed when unbanning an IP. Take care that the
@@ -46,7 +46,7 @@
 # Tags:    See jail.conf(5) man page
 # Values:  CMD
 #
-actionunban = <iptables> -D f2b-<name> -s <ip> -j <blocktype>
+actionunban = <iptables> -D f2b-<name> -s <ip> -j <blocktype>; <iptablesfi>
 
 [Init]

However, it should be noted that the "actionstop" action does not seem to work. Each time the fail2ban service is restarted, a new "multiport dports 22" rule identical to the others is added to the "INPUT" chain. I will dig into this...

If you notice anything out of the ordinary about the way I do things, please do not hesitate to report it. I'm sure it will help someone (there are few results on this subject).

Encore merci !

@qm2k
Copy link

qm2k commented Feb 21, 2020

You reminded me about one important detail: something needs to create iptables rule chain f2b-postfix (and like) each time container is restarted. I'm doing this explicitly in container's rc.local, a better solution would be to use iptables-save on container shutdown and then restore as saved. Or, you can to restart the corresponding jail with fail2ban-client so that it could recreate its rule chain.

I modified the "iptables" command to handle the case when the container is off.

Cool, I was too lazy to do it and prefer to simply ignore error messages.
BTW you might be able to avoid the fi problem by using logical OR, like this (not tested):

[ $(lxc-info -n <conteneur> -s -H) != RUNNING ] || lxc-attach -n <conteneur> -- iptables <lockingopt>

However, it should be noted that the "actionstop" action does not seem to work. Each time the fail2ban service is restarted, a new "multiport dports 22" rule identical to the others is added to the "INPUT" chain. I will dig into this...

I didn't notice this problem here. First thing to check is fail2ban logs where output from all action commands is redirected.

@ycharbi
Copy link

ycharbi commented Feb 21, 2020

Thank you for your response.
I took note of your remarks and used iptables-persistent to keep the chain running at boot time. Here is its configuration file:
cat /etc/iptables/rules.v4

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:f2b-sshd-lxc-web - [0:0]
COMMIT

I used your modification on my condition and it's working wonders 👍.

--- /etc/fail2ban/action.d/iptables-common.conf	2020-02-19 21:12:19.161146756 +0100
+++ /etc/fail2ban/action.d/iptables-common-lxc.conf	2020-02-21 14:48:58.081002546 +0100
@@ -73,7 +73,7 @@
 # Option:  iptables
 # Notes.:  Actual command to be executed, including common to all calls options
 # Values:  STRING
-iptables = iptables <lockingopt>
+iptables = [ $(lxc-info -n <conteneur> -s -H) != RUNNING ] || lxc-attach -n <conteneur> -- iptables <lockingopt>
 
 
 [Init?family=inet6]
--- /etc/fail2ban/action.d/iptables-multiport.conf	2018-01-18 14:49:01.000000000 +0100
+++ /etc/fail2ban/action.d/iptables-multiport-lxc.conf	2020-02-21 14:22:34.415502555 +0100
@@ -6,7 +6,7 @@
 
 [INCLUDES]
 
-before = iptables-common.conf
+before = iptables-common-lxc.conf
 
 [Definition]

After these modifications, the duplication of rules that used to occur when restarting F2B no longer occurs! The problem is therefore solved. This was indeed due to the f2b-sshd-lxc-web chain not existing at the start of the Fail2ban service.

I'll continue my tests. If you are interested, here is the line I use to simulate a bad password in my auth.log to save time:

echo "$(LANG=en_us_8859_1 date +"%b %d %H:%M:%S") lxc-web sshd[413]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.150.55  user=root" >> /var/lib/lxc/lxc-web/rootfs/var/log/auth.log

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants