Configure Fail2Ban for a Docker Container – seifer.guru (2024)

Let’s say that you have a web server, such as NGINX or Apache, running within a Docker container, and functions as a reverse proxy for other web services deeper within your network.

Configure Fail2Ban for a Docker Container – seifer.guru (1)

It would be nice to have Fail2Ban configured on your public-facing NGINX server, right? Let’s walk through how to set this up. I’ll be focusing on NGINX in this article, but the Apache configurations shouldn’t be too difficult to retrofit.

Possible Configurations

There’s a number of ways that we might be able to accomplish this.

  1. Configure the NGINX container to have Fail2Ban built into the image.
  2. Configure a separate Fail2Ban container.
  3. Configure Fail2Ban on the Docker host.

Option #1 should be easy enough to accomplish, but maybe you don’t want to build out a pipeline to do so, or don’t have the resources. Option #2 sounds overly complicated, and will likely involve even-more-than-usual root access within a container (not a great idea). We have access to the Docker host in this scenario, so let’s go with option #3.

Configure Fail2Ban for a Docker Container – seifer.guru (2)

Configure NGINX Container Logging

In this example, let’s just map the NGINX logs to a volume mounted on the Docker host. You could work through syslog or journald for this, but it’s probably easiest to simply mount /var/log/WEBSERVER onto your Docker host.

# Something like this is a good start.
$ mkdir -p /opt/container_webservice/logs
$ docker run -d --name=nginx -v /opt/container_webservice/etc/:/etc/nginx/conf.d/nginx.conf:ro -v /opt/container_webservice/logs:/var/log/nginx:rw nginx

By mounting the NGINX log folder, the output will no longer be printed to whatever your container logging driver; it’ll go straight into the files, instead. However, normal NGINX startup info will still be printed to the Docker log.

$ docker run -ti --rm -v /var/lib/docker/persistent-volumes/test:/var/log/nginx:rw --name=test-nginx -p 8089:80 nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
^C
$

If you would like your different sites to get logged to different files, you’ll just have more integrations to do with Fail2Ban. You can set this with access_log and error_log options in the nginx.conf file.

Configuring Fail2Ban jail.local

Now that we know that Fail2Ban can read the log files output from the NGINX container, let’s install Fail2Ban on your Docker host.

# Debian based distros. Your mileage may vary.
$ sudo apt-get install fail2ban

# Enterprise Linux distros
$ sudo yum install fail2ban

Next, we need to configure your jails, and configure any subnets or individual IP addresses that need to be ignored. I won’t go into too much detail, since there’s a lot of resources out there on how to configure Fail2Ban jails.

You should end up with something like this for your /etc/fail2ban/jail.local file.

[DEFAULT]
ignoreip = 192.168.1.0/24
bantime = 600
maxretry = 3

[nginx-http-auth]
enabled = true
port = http,https

[nginx-limit-req]
enabled = true
port = http,https

[nginx-botsearch]
enabled = true
port = http,https
maxretry = 2

[php-url-fopen]
enabled = true
port = http,https

However, this isn’t a traditional install, is it? Let’s specify the volume path that we provided to the Docker container.

[DEFAULT]
ignoreip = 192.168.1.0/24
bantime = 600
maxretry = 3

[nginx-http-auth]
enabled = true
port = http,https
logpath = /opt/container_webservice/logs/error.log

[nginx-limit-req]
enabled = true
port = http,https
logpath = /opt/container_webservice/logs/error.log

[nginx-botsearch]
enabled = true
port = http,https
maxretry = 2
logpath = /opt/container_webservice/logs/error.log

[php-url-fopen]
enabled = true
port = http,https
logpath = /opt/container_webservice/logs/access.log

Awesome, we’re mostly done with the local configuration, now.

Banning Doesn’t Work Yet…

If we were to restart the Fail2Ban service, and trigger a banning event, we’d notice a firewall rule would be published properly by Fail2Ban, but it wouldn’t limit access properly.

$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
f2b-nginx-http-auth tcp -- anywhere anywhere multiport dports http,https

Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere

...

Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.17.0.8 tcp dpt:http

...

Chain f2b-nginx-http-auth (1 references)
target prot opt source destination
REJECT all -- 192.168.1.179 anywhere reject-with icmp-port-unreachable
RETURN all -- anywhere anywhere

Why are we experiencing this behavior, when it works just fine on a normal host? Well, that’s because this isn’t a normal install!

Normal system traffic traditionally comes across on the INPUT chain, while Docker container traffic is sent through the FORWARD chain. Reference

Let’s configure Fail2Ban to operate on the proper chain, then!

Banning on the FORWARD Chain

If you look in the default /etc/fail2ban/jail.conf file, you’ll probably see the default banaction = iptables-multiport value. Let’s take a look inside of this file.

Configure Fail2Ban for a Docker Container – seifer.guru (3)

You can see that the action is configured to point to <chain>. We could modify this file directly, but it’d likely break during an update, since Fail2Ban puts package maintained configurations in /etc/. You generally don’t want to do that as a package maintaner, but nonetheless…

Let’s look at what the <chain> value is set to in that iptables-common.conf file.

Configure Fail2Ban for a Docker Container – seifer.guru (4)

Bingo! Let’s make our changes, now. Let’s copy both files into a new set of configurations (that won’t be overwritten during package updates) that modify the FORWARD chain.

$ cd /etc/fail2ban/action.d
cat iptables-common.conf > iptables-common-forward.conf
sed -i 's/INPUT/FORWARD/g' iptables-common-forward.conf

cat iptables-multiport.conf > iptables-multiport-forward.conf
sed -i 's/iptables-common.conf/iptables-common-forward.conf/g' iptables-multiport-forward.conf

The final step here is to reconfigure our /etc/fail2ban/jail.local file to use our new banaction for each jail we want to configure.

[DEFAULT]
ignoreip = 192.168.1.0/24
bantime = 600
maxretry = 3

[nginx-http-auth]
enabled = true
port = http,https
logpath = /opt/container_webservice/logs/error.log
banaction = iptables-multiport-forward

[nginx-limit-req]
enabled = true
port = http,https
logpath = /opt/container_webservice/logs/error.log
banaction = iptables-multiport-forward

[nginx-botsearch]
enabled = true
port = http,https
maxretry = 2
logpath = /opt/container_webservice/logs/error.log
banaction = iptables-multiport-forward

[php-url-fopen]
enabled = true
port = http,https
logpath = /opt/container_webservice/logs/access.log
banaction = iptables-multiport-forward

Now let’s restart Fail2Ban.

systemctl restart fail2ban.service

Validating FORWARD Chain Behavior

We should now have different behavior through iptables than we had before. Trigger a ban, and let’s review the firewall rules this time.

$ sudo iptables -L
Chain INPUT (policy ACCEPT)

Chain FORWARD (policy DROP)
target prot opt source destination
f2b-nginx-http-auth tcp -- anywhere anywhere multiport dports http,https
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere

...

Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.17.0.7 tcp dpt:http

...

Chain f2b-nginx-http-auth (1 references)
target prot opt source destination
REJECT all -- 192.168.1.179 anywhere reject-with icmp-port-unreachable
RETURN all -- anywhere anywhere

Great! We can see that our f2b-nginx-http-auth rule has moved down from the INPUT chain to the FORWARD chain.

Now, if you read that Docker and iptables article I previously linked, it states that any custom rules to be applied before routing to a Docker container should be added to the DOCKER-USER chain. It’s not too big of a deal in this case, since Fail2Ban should always insert itself at the top of whatever firewall chain it’s operating within, but feel free to change your configurations above to honor this.

Thanks for reading. I hope this was useful!

Configure Fail2Ban for a Docker Container – seifer.guru (2024)

References

Top Articles
Ordering Prepared Thanksgiving Dinner To Go from Safeway - Super Safeway
The 5 Best Pre-Made Thanksgiving Dinners For A Memorable Meal Sans Stress
Www.mytotalrewards/Rtx
The UPS Store | Ship & Print Here > 400 West Broadway
Euro (EUR), aktuální kurzy měn
Mate Me If You May Sapir Englard Pdf
Valley Fair Tickets Costco
Costco The Dalles Or
Beautiful Scrap Wood Paper Towel Holder
Cumberland Maryland Craigslist
Ribbit Woodbine
Stolen Touches Neva Altaj Read Online Free
Skip The Games Norfolk Virginia
อพาร์ทเมนต์ 2 ห้องนอนในเกาะโคเปนเฮเกน
Hartland Liquidation Oconomowoc
U/Apprenhensive_You8924
Lcwc 911 Live Incident List Live Status
Lowe's Garden Fence Roll
Cocaine Bear Showtimes Near Regal Opry Mills
My Homework Lesson 11 Volume Of Composite Figures Answer Key
Drift Boss 911
Sea To Dallas Google Flights
Tu Pulga Online Utah
Best Nail Salons Open Near Me
R. Kelly Net Worth 2024: The King Of R&B's Rise And Fall
Shadbase Get Out Of Jail
Papa Johns Mear Me
Table To Formula Calculator
Penn State Service Management
Stephanie Bowe Downey Ca
3 Ways to Format a Computer - wikiHow
Pixel Combat Unblocked
Ilabs Ucsf
Fastpitch Softball Pitching Tips for Beginners Part 1 | STACK
Craigslist Gigs Norfolk
Jambus - Definition, Beispiele, Merkmale, Wirkung
Craigslist Ludington Michigan
Gvod 6014
Flags Half Staff Today Wisconsin
Indio Mall Eye Doctor
Birmingham City Schools Clever Login
The Attleboro Sun Chronicle Obituaries
Courtney Roberson Rob Dyrdek
'The Nun II' Ending Explained: Does the Immortal Valak Die This Time?
Theater X Orange Heights Florida
Kaamel Hasaun Wikipedia
Lesly Center Tiraj Rapid
Lebron James Name Soundalikes
SF bay area cars & trucks "chevrolet 50" - craigslist
Cryptoquote Solver For Today
Lira Galore Age, Wikipedia, Height, Husband, Boyfriend, Family, Biography, Net Worth
Www.card-Data.com/Comerica Prepaid Balance
Latest Posts
Article information

Author: Fredrick Kertzmann

Last Updated:

Views: 6291

Rating: 4.6 / 5 (66 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Fredrick Kertzmann

Birthday: 2000-04-29

Address: Apt. 203 613 Huels Gateway, Ralphtown, LA 40204

Phone: +2135150832870

Job: Regional Design Producer

Hobby: Nordic skating, Lacemaking, Mountain biking, Rowing, Gardening, Water sports, role-playing games

Introduction: My name is Fredrick Kertzmann, I am a gleaming, encouraging, inexpensive, thankful, tender, quaint, precious person who loves writing and wants to share my knowledge and understanding with you.