Securing Webservers - FirewallD Deployment on Debian 9
Changing the SSH Port
Once the system is updated, open the SSH configuration file and find the lines that specify the SSH port.
nano /etc/ssh/sshd_config
#Port 22
Uncomment the relevant line by removing the # sign and change the default port 22 to the one that you want to use. Save the changes and exit. Now, restart the SSH service for the changes to take effect:
service sshd restart
netstat -tunlp |grep ssh
Install Firewalld on Debian
apt-get update && apt-get upgrade -y
apt -y install firewalld
firewall-cmd --state
firewall-cmd --list-all
Setup
Before continuing you need to check what ports are in use on your server:
netstat -lntup
We can add all relevant service presets with:
firewall-cmd --add-service={http,https,smtp,imap} --permanent --zone=public
To add specialized ports run:
firewall-cmd --permanent --zone=public --add-port=5601/tcp
firewall-cmd --permanent --zone=public --add-port=9200/tcp
firewall-cmd --permanent --zone=public --add-port=7777/tcp
firewall-cmd --permanent --zone=public --add-port=7779/tcp
firewall-cmd --permanent --zone=public --add-port=5601/tcp
firewall-cmd --permanent --zone=public --add-port=9200/tcp
firewall-cmd --permanent --zone=public --add-port=9300/tcp
firewall-cmd --permanent --zone=public --add-port=7777/tcp
firewall-cmd --permanent --zone=public --add-port=7779/tcp
firewall-cmd --permanent --zone=public --add-port=32139/tcp
firewall-cmd --reload
firewall-cmd --list-all
Docker
To actively reject traffic to a specific port:
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 port port="9200" protocol="tcp" reject'
firewall-cmd --reload
BUT Docker will override this! Make sure to bind all ports that you don't want to be open to the internet to localhost!
Example docker-compose.yml
:
ports:
- '127.0.0.1:9200:9200'
- '127.0.0.1:9300:9300'
Prevent Bruteforce SSH attacks
Reject new incoming ipv4 connections when more than 2 attempts per minute are made. It will also log a message about this:
firewall-cmd --add-rich-rule='rule family="ipv4" service name="ssh" log prefix="SSH Bruteforce:" level="warning" limit value="2/m" accept limit value="2/m"' --permanent
If you have both ipv4 and ipv6 configured you’ll probably want the more generic version:
firewall-cmd --add-rich-rule='rule service name="ssh" log prefix="SSH Bruteforce:" level="warning" limit value="2/m" accept limit value="2/m"' --permanent
Create a Blacklist
firewall-cmd --permanent --new-ipset=blacklist --type=hash:net --option=family=inet --option=hashsize=4096 --option=maxelem=200000
–permanent
= use to make changes to the permanent configuration–new-ipset
= name of the new IP/net blacklist–type
= storage hash type, "net" is for subnets, while "ip" for individual ip addresses–option=family
= IPv4 or IPv6 network, inet is for IPv4–option=hashsize
= the initial hash size of the list–option=maxelem
= max number of elements
wget https://www.ipdeny.com/ipblocks/data/aggregated/ru-aggregated.zone
Populate the blacklist:
firewall-cmd --permanent --ipset=blacklist --add-entries-from-file=./ru-aggregated.zone
To add individual IP addresses or net blocks by yourself:
firewall-cmd --permanent --ipset=blacklist --add-entry=4.46.116.112
firewall-cmd --ipset=blacklist --add-entry=4.46.116.112
Redirect the blacklist to the drop zone
firewall-cmd --permanent --zone=drop --add-source=ipset:blacklist
firewall-cmd --reload
Block and Enable ICMP
firewall-cmd --zone=public --query-icmp-block=echo-reply
If you get "no", that means there isn’t any icmp block applied, let’s enable (block) icmp.
firewall-cmd --zone=public --add-icmp-block=echo-reply
Lockdown Rules
It’s possible to change the firewalld rules by any local applications, which have the root privileges. To avoid making changes to firewalld rules, we have to put a lock-down in ‘firewalld.conf‘ file. This mostly used to protect the firewalld from any unwanted rules changes by any applications.
nano /etc/firewalld/firewalld.conf
Lockdown=yes
firewall-cmd --reload
firewall-cmd --query-lockdown
To On/Off lockdown mode, use the following combination.
firewall-cmd --lockdown-on
firewall-cmd --lockdown-off
How to Reset when things go Wrong
Delete your Zone Settings:
rm -rf /etc/firewalld/zones
Using the below set of commands you will set accept rule for all types of connections.
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
This will confirm, iptables gonna accept all requests for all types of connections.
Using below set of commands, delete your currently configured rules from iptables.
iptables -F INPUT
iptables -F OUTPUT
iptables -F FORWARD
Or you can do it in single command:
iptables -F
That’s it! Your iptables are reset to default settings i.e. accept all!
fail2ban-firewalld
Configure fail2ban (see below) to block hosts via firewalld.
apt-get install fail2ban
fail2ban
fail2ban is a daemon to ban hosts that cause multiple authentication errors.
fail2ban will monitor the SystemD journal to look for failed authentication attempts for whichever jails have been enabled. After the number of failed attempts specified it will add a firewall rule to block that specific IP address for an amount of time configured.
Start by installing the package on your system - Debian, Ubuntu or on Centos through EPEL.
The jail.conf file will enable Fail2ban for SSH by default for Debian and Ubuntu, but not CentOS. All other protocols and configurations (HTTP, FTP, etc.) are commented out. If you want to change this, create a jail.local for editing:
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Once installed the next step is to configure a jail (a service you want to monitor and ban at whatever thresholds you’ve set). By default IPs are banned for 1 hour. The best practice is to override the system defaults using _.local files instead of directly modifying the _.config files:
# cat /etc/fail2ban/jail.local
[DEFAULT]
# "bantime" is the number of seconds that a host is banned.
bantime = 1d
# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime = 1h
# "maxretry" is the number of failures before a host get banned.
maxretry = 5
After 5 attempts within the last hour the IP will be blocked for 1 day.
The next step is to configure a jail. In this tutorial sshd is shown but the steps are more or less the same for other services. Create a configuration file inside /etc/fail2ban/jail.d
:
# cat /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true
port = ssh
You can change the port there to the value you have chosen in step 1:
[sshd]
port = ssh,sftp,12345
logpath = %(sshd_log)s
backend = %(sshd_backend)s
Next enable and start the fail2ban service.
systemctl enable --now fail2ban
systemctl status fail2ban
to check the status of fail2ban and make sure the jail is enabled enter:
fail2ban-client status
Status
|- Number of jail: 1
`- Jail list: sshd
fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 8
| |- Total failed: 4399
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
|- Currently banned: 101
|- Total banned: 684
`- Banned IP list: ...
tail -f /var/log/fail2ban.log
Check IP address geo location and add country ban lists where necessary whois ip-addrss | grep -i country
.
Unbanning an IP Address
In order to remove an IP address from the banned list, parameter IPADDRESS is set to appropriate IP which needs unbanning. The name "sshd" is the name of the jail, in this case the "sshd" jail that we configured above. The following command does the job.
fail2ban-client set sshd unbanip IPADDRESS
Resetting fail2ban
service fail2ban stop
truncate -s 0 /var/log/fail2ban.log
rm /var/lib/fail2ban/fail2ban.sqlite3
service fail2ban restart