Books / How To Secure A Linux Server / Chapter 4
Securing the Network
Firewall With UFW (Uncomplicated Firewall)
Call me paranoid, and you don’t have to agree, but I want to deny all traffic in and out of my server except what I explicitly allow. Why would my server be sending traffic out that I don’t know about? And why would external traffic be trying to access my server if I don’t know who or what it is? When it comes to good security, my opinion is to reject/deny by default, and allow by exception.
Of course, if you disagree, that is totally fine and can configure UFW to suit your needs.
Either way, ensuring that only traffic we explicitly allow is the job of a firewall.
How It Works
The Linux kernel provides capabilities to monitor and control network traffic. These capabilities are exposed to the end-user through firewall utilities. On Linux, the most common firewall is iptables. However, iptables is rather complicated and confusing (IMHO). This is where UFW comes in. Think of UFW as a front-end to iptables. It simplifies the process of managing the iptables rules that tell the Linux kernel what to do with network traffic.
UFW works by letting you configure rules that:
- allow or deny
- input or output traffic
- to or from ports
You can create rules by explicitly specifying the ports or with application configurations that specify the ports.
Goals
- all network traffic, input and output, blocked except those we explicitly allow
Notes
- As you install other programs, you’ll need to enable the necessary ports/applications.
Steps
-
Install ufw.
On Debian based systems:
sudo apt install ufw
-
Deny all outgoing traffic:
sudo ufw default deny outgoing comment 'deny all outgoing traffic'
Default outgoing policy changed to 'deny' (be sure to update your rules accordingly)
If you are not as paranoid as me, and don’t want to deny all outgoing traffic, you can allow it instead:
sudo ufw default allow outgoing comment 'allow all outgoing traffic'
-
Deny all incoming traffic:
sudo ufw default deny incoming comment 'deny all incoming traffic'
-
Obviously we want SSH connections in:
sudo ufw limit in ssh comment 'allow SSH connections in'
Rules updated Rules updated (v6)
-
Allow additional traffic as per your needs. Some common use-cases:
# allow traffic out on port 53 -- DNS sudo ufw allow out 53 comment 'allow DNS calls out' # allow traffic out on port 123 -- NTP sudo ufw allow out 123 comment 'allow NTP out' # allow traffic out for HTTP, HTTPS, or FTP # apt might needs these depending on which sources you're using sudo ufw allow out http comment 'allow HTTP traffic out' sudo ufw allow out https comment 'allow HTTPS traffic out' sudo ufw allow out ftp comment 'allow FTP traffic out' # allow whois sudo ufw allow out whois comment 'allow whois' # allow traffic out on port 68 -- the DHCP client # you only need this if you're using DHCP sudo ufw allow out 67 comment 'allow the DHCP client to update' sudo ufw allow out 68 comment 'allow the DHCP client to update'
Note: You’ll need to allow HTTP/HTTPS for installing packages and many other things.
-
Start ufw:
sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y Firewall is active and enabled on system startup
-
If you want to see a status:
sudo ufw status
Status: active To Action From -- ------ ---- 22/tcp LIMIT Anywhere # allow SSH connections in 22/tcp (v6) LIMIT Anywhere (v6) # allow SSH connections in 53 ALLOW OUT Anywhere # allow DNS calls out 123 ALLOW OUT Anywhere # allow NTP out 80/tcp ALLOW OUT Anywhere # allow HTTP traffic out 443/tcp ALLOW OUT Anywhere # allow HTTPS traffic out 21/tcp ALLOW OUT Anywhere # allow FTP traffic out Mail submission ALLOW OUT Anywhere # allow mail out 43/tcp ALLOW OUT Anywhere # allow whois 53 (v6) ALLOW OUT Anywhere (v6) # allow DNS calls out 123 (v6) ALLOW OUT Anywhere (v6) # allow NTP out 80/tcp (v6) ALLOW OUT Anywhere (v6) # allow HTTP traffic out 443/tcp (v6) ALLOW OUT Anywhere (v6) # allow HTTPS traffic out 21/tcp (v6) ALLOW OUT Anywhere (v6) # allow FTP traffic out Mail submission (v6) ALLOW OUT Anywhere (v6) # allow mail out 43/tcp (v6) ALLOW OUT Anywhere (v6) # allow whois
or
sudo ufw status verbose
Status: active Logging: on (low) Default: deny (incoming), deny (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- 22/tcp LIMIT IN Anywhere # allow SSH connections in 22/tcp (v6) LIMIT IN Anywhere (v6) # allow SSH connections in 53 ALLOW OUT Anywhere # allow DNS calls out 123 ALLOW OUT Anywhere # allow NTP out 80/tcp ALLOW OUT Anywhere # allow HTTP traffic out 443/tcp ALLOW OUT Anywhere # allow HTTPS traffic out 21/tcp ALLOW OUT Anywhere # allow FTP traffic out 587/tcp (Mail submission) ALLOW OUT Anywhere # allow mail out 43/tcp ALLOW OUT Anywhere # allow whois 53 (v6) ALLOW OUT Anywhere (v6) # allow DNS calls out 123 (v6) ALLOW OUT Anywhere (v6) # allow NTP out 80/tcp (v6) ALLOW OUT Anywhere (v6) # allow HTTP traffic out 443/tcp (v6) ALLOW OUT Anywhere (v6) # allow HTTPS traffic out 21/tcp (v6) ALLOW OUT Anywhere (v6) # allow FTP traffic out 587/tcp (Mail submission (v6)) ALLOW OUT Anywhere (v6) # allow mail out 43/tcp (v6) ALLOW OUT Anywhere (v6) # allow whois
Default Applications
ufw ships with some default applications. You can see them with:
sudo ufw app list
Available applications: AIM Bonjour CIFS DNS Deluge IMAP IMAPS IPP KTorrent Kerberos Admin Kerberos Full Kerberos KDC Kerberos Password LDAP LDAPS LPD MSN MSN SSL Mail submission NFS OpenSSH POP3 POP3S PeopleNearby SMTP SSH Socks Telnet Transmission Transparent Proxy VNC WWW WWW Cache WWW Full WWW Secure XMPP Yahoo qBittorrent svnserve
To get details about the app, like which ports it includes, type:
sudo ufw app info [app name]
sudo ufw app info DNS
Profile: DNS Title: Internet Domain Name Server Description: Internet Domain Name Server Port: 53
Custom Application
If you don’t want to create rules by explicitly providing the port number(s), you can create your own application configurations. To do this, create a file in /etc/ufw/applications.d
.
For example, here is what you would use for Plex:
cat /etc/ufw/applications.d/plexmediaserver
[PlexMediaServer] title=Plex Media Server description=This opens up PlexMediaServer for http (32400), upnp, and autodiscovery. ports=32469/tcp|32413/udp|1900/udp|32400/tcp|32412/udp|32410/udp|32414/udp|32400/udp
Then you can enable it like any other app:
sudo ufw allow plexmediaserver
iptables Intrusion Detection And Prevention with PSAD
Even if you have a firewall to guard your doors, it is possible to try brute-forcing your way in any of the guarded doors. We want to monitor all network activity to detect potential intrusion attempts, such has repeated attempts to get in, and block them.
How It Works
I can’t explain it any better than user FINESEC from https://serverfault.com/ did at: https://serverfault.com/a/447604/289829.
Fail2BAN scans log files of various applications such as apache, ssh or ftp and automatically bans IPs that show the malicious signs such as automated login attempts. PSAD on the other hand scans iptables and ip6tables log messages (typically /var/log/messages) to detect and optionally block scans and other types of suspect traffic such as DDoS or OS fingerprinting attempts. It’s ok to use both programs at the same time because they operate on different level.
And, since we’re already using UFW so we’ll follow the awesome instructions by netson at https://gist.github.com/netson/c45b2dc4e835761fbccc to make PSAD work with UFW.
Steps
-
Install psad.
On Debian based systems:
sudo apt install psad
-
Make a backup of psad’s configuration file
/etc/psad/psad.conf
:sudo cp --archive /etc/psad/psad.conf /etc/psad/psad.conf-COPY-$(date +"%Y%m%d%H%M%S")
-
Review and update configuration options in
/etc/psad/psad.conf
. Pay special attention to these:Setting Set To EMAIL_ADDRESSES
your email address(s) HOSTNAME
your server’s hostname ENABLE_PSADWATCHD
ENABLE_PSADWATCHD Y;
ENABLE_AUTO_IDS
ENABLE_AUTO_IDS Y;
ENABLE_AUTO_IDS_EMAILS
ENABLE_AUTO_IDS_EMAILS Y;
EXPECT_TCP_OPTIONS
EXPECT_TCP_OPTIONS Y;
Check the configuration file psad’s documentation at http://www.cipherdyne.org/psad/docs/config.html for more details.
-
Now we need to make some changes to ufw so it works with psad by telling ufw to log all traffic so psad can analyze it. Do this by editing two files and adding these lines at the end but before the COMMIT line.
Make backups:
sudo cp --archive /etc/ufw/before.rules /etc/ufw/before.rules-COPY-$(date +"%Y%m%d%H%M%S") sudo cp --archive /etc/ufw/before6.rules /etc/ufw/before6.rules-COPY-$(date +"%Y%m%d%H%M%S")
Edit the files:
/etc/ufw/before.rules
/etc/ufw/before6.rules
And add add this at the end but before the COMMIT line:
# log all traffic so psad can analyze -A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES] " -A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES] "
Note: We’re adding a log prefix to all the iptables logs. We’ll need this for seperating iptables logs to their own file.
For example:
... # log all traffic so psad can analyze -A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES] " -A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES] " # don't delete the 'COMMIT' line or these rules won't be processed COMMIT
-
Now we need to reload/restart ufw and psad for the changes to take effect:
sudo ufw reload sudo psad -R sudo psad --sig-update sudo psad -H
-
Analyze iptables rules for errors:
sudo psad --fw-analyze
[+] Parsing INPUT chain rules. [+] Parsing INPUT chain rules. [+] Firewall config looks good. [+] Completed check of firewall ruleset. [+] Results in /var/log/psad/fw_check [+] Exiting.
Note: If there were any issues you will get an e-mail with the error.
-
Check the status of psad:
sudo psad --Status
[-] psad: pid file /var/run/psad/psadwatchd.pid does not exist for psadwatchd on vm [+] psad_fw_read (pid: 3444) %CPU: 0.0 %MEM: 2.2 Running since: Sat Feb 16 01:03:09 2019 [+] psad (pid: 3435) %CPU: 0.2 %MEM: 2.7 Running since: Sat Feb 16 01:03:09 2019 Command line arguments: [none specified] Alert email address(es): [email protected] [+] Version: psad v2.4.3 [+] Top 50 signature matches: [NONE] [+] Top 25 attackers: [NONE] [+] Top 20 scanned ports: [NONE] [+] iptables log prefix counters: [NONE] Total protocol packet counters: [+] IP Status Detail: [NONE] Total scan sources: 0 Total scan destinations: 0 [+] These results are available in: /var/log/psad/status.out
Application Intrusion Detection And Prevention With Fail2Ban
UFW tells your server what doors to board up so nobody can see them, and what doors to allow authorized users through. PSAD monitors network activity to detect and prevent potential intrusions – repeated attempts to get in.
But what about the applications/services your server is running, like SSH and Apache, where your firewall is configured to allow access in. Even though access may be allowed that doesn’t mean all access attempts are valid and harmless. What if someone tries to brute-force their way in to a web-app you’re running on your server? This is where Fail2ban comes in.
How It Works
Fail2ban monitors the logs of your applications (like SSH and Apache) to detect and prevent potential intrusions. It will monitor network traffic/logs and prevent intrusions by blocking suspicious activity (e.g. multiple successive failed connections in a short time-span).
Goals
- network monitoring for suspicious activity with automatic banning of offending IPs
Notes
- As of right now, the only thing running on this server is SSH so we’ll want Fail2ban to monitor SSH and ban as necessary.
- As you install other programs, you’ll need to create/configure the appropriate jails and enable them.
Steps
-
Install fail2ban.
On Debian based systems:
sudo apt install fail2ban
-
We don’t want to edit
/etc/fail2ban/fail2ban.conf
or/etc/fail2ban/jail.conf
because a future update may overwrite those so we’ll create a local copy instead. Create the file/etc/fail2ban/jail.local
and add this to it after replacing[LAN SEGMENT]
and[your email]
with the appropriate values:[DEFAULT] # the IP address range we want to ignore ignoreip = 127.0.0.1/8 [LAN SEGMENT] # who to send e-mail to destemail = [your e-mail] # who is the email from sender = [your e-mail] # since we're using exim4 to send emails mta = mail # get email alerts action = %(action_mwl)s
Note: Your server will need to be able to send e-mails so Fail2ban can let you know of suspicious activity and when it banned an IP.
-
We need to create a jail for SSH that tells fail2ban to look at SSH logs and use ufw to ban/unban IPs as needed. Create a jail for SSH by creating the file
/etc/fail2ban/jail.d/ssh.local
and adding this to it:[sshd] enabled = true banaction = ufw port = ssh filter = sshd logpath = %(sshd_log)s maxretry = 5
cat << EOF | sudo tee /etc/fail2ban/jail.d/ssh.local [sshd] enabled = true banaction = ufw port = ssh filter = sshd logpath = %(sshd_log)s maxretry = 5 EOF
-
In the above we tell fail2ban to use the ufw as the
banaction
. Fail2ban ships with an action configuration file for ufw. You can see it in/etc/fail2ban/action.d/ufw.conf
-
Enable fail2ban:
sudo fail2ban-client start sudo fail2ban-client reload sudo fail2ban-client add sshd # This may fail on some systems if the sshd jail was added by default
-
To check the status:
sudo fail2ban-client status
Status |- Number of jail: 1 `- Jail list: sshd
sudo fail2ban-client status sshd
Status for the jail: sshd |- Filter | |- Currently failed: 0 | |- Total failed: 0 | `- File list: /var/log/auth.log `- Actions |- Currently banned: 0 |- Total banned: 0 `- Banned IP list:
Unban an IP
To unban an IP use this command:
fail2ban-client set [jail] unbanip [IP]
[jail]
is the name of the jail that has the banned IP and [IP]
is the IP address you want to unban. For example, to unaban 192.168.1.100
from SSH you would do:
fail2ban-client set sshd unbanip 192.168.1.100