Access control using Fail2Ban and geoip

From munkjensen.net/wiki
Revision as of 10:12, 13 June 2017 by Admin (talk | contribs)
A flood of [ANY] queries started around 4 am. Configuration and tuning of Fail2Ban started around 8 am and was effectively banning DNS queries from ip's outside Denmark at 10 am.

Preface

This 'guide' explains how to make Debian block (silently drop) DNS requests using iptables to my Pi-Hole from anywhere in the world but Denmark. Of course you can change that so another country is allowed... or even a selection of countries ;-)

This Fail2ban configuration can raise an effective Geo-Fence for other server services, if configuration of the regular expression, the ports and logfile location is done properly ;-)

Geolookup

In order to do a geolookup from the command line, we have to get the GeoIP binary and database installed.

apt-get install geoip-bin geoip-database

Test it:

geoiplookup 159.20.6.38

should give you

GeoIP Country Edition: DK, Denmark

Fail2Ban

I assume Fail2ban is already installed and configured.

dnsmasq

The configuration will ban ip adresses from countries that is not included in the country_list found in the [init] section of the file /etc/fail2ban/action.d/iptables-pihole-geoip-fence.conf. If you dont want to totally block dns requests from countries not included in the 'country_list', you can use the regular expression that will filter all 'query[ANY]' requests. it is configured in the file /etc/fail2ban/filter.d/pihole-geoip.conf

Create a filter script: sudo vi /etc/fail2ban/filter.d/pihole-geoip.conf

# Fail2Ban filter file for Pi-Hole.
#

# This filter blocks attacks against PiHole (dnsmasq).
#

[Definition]

# This will filter all 'query' requests.
failregex = query\[.*\].* from <HOST>$

# This will filter all 'query[ANY]' requests.
#failregex = query\[ANY\].* from <HOST>$

#
# Author: [email protected]


Create an action script: sudo vi /etc/fail2ban/action.d/iptables-pihole-geoip-fence.conf

# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Modified by Yaroslav Halchenko for multiport banning
# Modified by [email protected] for pihole use.
#

[INCLUDES]

before = iptables-blocktype.conf

[Definition]

# Option:  actionstart
# Notes.:  command executed once at the start of Fail2Ban.
# Values:  CMD
#
actionstart = iptables -N f2b-<name>
              iptables -A f2b-<name> -j RETURN
              iptables -I <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>

# 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>
             iptables -F f2b-<name>
             iptables -X f2b-<name>

# Option:  actioncheck
# Notes.:  command executed once before each actionban command
# Values:  CMD
#
actioncheck = iptables -n -L <chain> | grep -q 'f2b-<name>[ \t]'

# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
#
actionban = IP=<ip> &&
            COUNTRY=$(geoiplookup $IP | egrep "<country_list>") && [ "$COUNTRY" ] ||
            (iptables -I f2b-<name> 1 -s <ip> -j <blocktype>)

# Option:  actionunban
# Notes.:  command executed when unbanning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
#
actionunban = IP=<ip> &&
              COUNTRY=$(geoiplookup $IP | egrep "<country_list>") && [ "$COUNTRY" ] ||
              (iptables -D f2b-<name> -s <ip> -j <blocktype>)

[Init]

# Option:  country_list
# Notes.:  List of exempted countries separated by pipe "|"
# Values:  STR  Default:
#
country_list = DK|Denmark

# Default name of the chain
#
name = pihole

# Option:  port
# Notes.:  specifies port to monitor
# Values:  [ NUM | STRING ]  Default:
#
port = 53

# Option:  protocol
# Notes.:  internally used by config reader for interpolations.
# Values:  [ tcp | udp | icmp | all ] Default: tcp
#
protocol = all

# Option:  chain
# Notes    specifies the iptables chain to which the fail2ban rules should be
#          added
# Values:  STRING  Default: INPUT
chain = INPUT

# Option:  blocktype
# Note:    This is what the action does with rules. This can be any jump target
#          as per the iptables man page (section 8). Common values are DROP
#          REJECT, REJECT --reject-with icmp-port-unreachable
# Values:  STRING
blocktype = DROP


Enable it by editing sudo vi /etc/fail2ban/jail.local

[DEFAULT]
maxretry = 3
bantime  = 900
destemail = fm@localhost

[pihole-geoip]
enabled  = true
port     = 53
protocol = udp
banaction = iptables-pihole-geoip-fence
filter   = pihole-geoip
logpath  = /var/log/pihole.log
bantime  = 604800  ; 1 week
findtime = 86400   ; 1 day
maxretry = 1

Restart Fail2Ban like this sudo service fail2ban restart

Hopefully it restarts without any errors... if you get errors in /var/log/fail2ban.log try to dum the config using the command fail2ban-client -d and hunt the bugs using this info.

Files

This is the file/folder structure for Fail2Ban. I edited/created the files marked with an §

/etc/fail2ban/
     ├── action.d/
     │   └── iptables-pihole-geoip-fence.conf §
     ├── fail2ban.conf
     ├── filter.d/
     │   └── pihole-geoip.conf §
     ├── jail.conf
     └── jail.local §

lighttpd

This configuration will ban ip adresses from countries that is not included in the country_list located in the [init] section of the file /etc/fail2ban/action.d/iptables-pihole-adminweb-geoip-fence.conf if they try to access http://[your.domain]/admin and subfolders.

Create a filter script: sudo vi /etc/fail2ban/filter.d/pihole-geoip.conf

# Fail2Ban filter file for pihole.
#

# This filter find IP adresses that try to access the
# /admin folder and everything below, served by the lighttpd daemon.
#

[Definition]

# This will filter all GET and HEAD requests for /admin* in lighttpd.log
# Example line: 1496389170|123.123.123.123|cloud.pulspc.dk|GET /admin/api.php?overTimeData10mins HTTP/1.1|200|4901
#
failregex = ^\|<HOST>\|.*\|GET \/admin.*
            ^\|<HOST>\|.*\|HEAD \/admin.*

# This will filter all GET and HEAD requests for all GET requests
#
#failregex = ^\|<HOST>\|.*\|GET.*
#failregex = ^\|<HOST>\|.*\|HEAD.*

#
# Author: [email protected]


Create an action script: sudo vi /etc/fail2ban/action.d/iptables-pihole-adminweb-geoip-fence.conf

# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Modified by Yaroslav Halchenko for multiport banning
# Modified by [email protected] for pihole use.
#

[INCLUDES]

before = iptables-blocktype.conf

[Definition]

# Option:  actionstart
# Notes.:  command executed once at the start of Fail2Ban.
# Values:  CMD
#
actionstart = iptables -N f2b-<name>
              iptables -A f2b-<name> -j RETURN
              iptables -I <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>

# 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>
             iptables -F f2b-<name>
             iptables -X f2b-<name>

# Option:  actioncheck
# Notes.:  command executed once before each actionban command
# Values:  CMD
#
actioncheck = iptables -n -L <chain> | grep -q 'f2b-<name>[ \t]'

# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
#
actionban = IP=<ip> &&
            COUNTRY=$(geoiplookup $IP | egrep "<country_list>") && [ "$COUNTRY" ] ||
            (iptables -I f2b-<name> 1 -s <ip> -j <blocktype>)

# Option:  actionunban
# Notes.:  command executed when unbanning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
#
actionunban = IP=<ip> &&
              COUNTRY=$(geoiplookup $IP | egrep "<country_list>") && [ "$COUNTRY" ] ||
              (iptables -D f2b-<name> -s <ip> -j <blocktype>)

[Init]

# Option:  country_list
# Notes.:  List of exempted countries separated by pipe "|"
# Values:  STR  Default:
#
country_list = DK|Denmark

# Default name of the chain
#
name = ph-admweb

# Option:  port
# Notes.:  specifies port to monitor
# Values:  [ NUM | STRING ]  Default:
#
port = 53

# Option:  protocol
# Notes.:  internally used by config reader for interpolations.
# Values:  [ tcp | udp | icmp | all ] Default: tcp
#
protocol = all

# Option:  chain
# Notes    specifies the iptables chain to which the fail2ban rules should be
#          added
# Values:  STRING  Default: INPUT
chain = INPUT

# Option:  blocktype
# Note:    This is what the action does with rules. This can be any jump target
#          as per the iptables man page (section 8). Common values are DROP
#          REJECT, REJECT --reject-with icmp-port-unreachable
# Values:  STRING
blocktype = DROP


Enable it by editing/adding sudo vi /etc/fail2ban/jail.local

[pihole-adminweb-geoip]
enabled  = true
port     = 80,443
protocol = tcp
banaction = iptables-pihole-adminweb-geoip-fence
filter   = pihole-adminweb-geoip
logpath  = /var/log/lighttpd/access.log
bantime  = 604800  ; 1 week
findtime = 86400   ; 1 day
maxretry = 1

Restart Fail2Ban like this sudo service fail2ban restart

Hopefully it restarts without any errors... if you get errors in /var/log/fail2ban.log try to dum the config using the command fail2ban-client -d and hunt the bugs using this info.

Files

This is the file/folder structure for Fail2Ban. I edited/created the files marked with an §

/etc/fail2ban/
     ├── action.d/
     │   └── iptables-pihole-adminweb-geoip-fence.conf §
     ├── fail2ban.conf
     ├── filter.d/
     │   └── pihole-adminweb-geoip.conf §
     ├── jail.conf
     └── jail.local §

Reference