Search

Thursday, September 1, 2016

Centos 7 Network Hardening: How to Protect Your Server from Basic Network Attacks using IPTABLES Firewall

Linux iptables, included in Centos 7 distribution, provides a mechanism to block basic network attacks. This is a guide to set up basic iptables firewall rules to protect your server from some of the most common and simplest network attacks.



Since you are here reading this, I assume you already have iptables installed and running, i.e. the command systemctl status iptables produces an output similar to this:

iptables.service - IPv4 firewall with iptables
   Loaded: loaded (/usr/lib/systemd/system/iptables.service; enabled; vendor preset: disabled)
   Active: active (exited) since Mon 2016-08-22 23:37:19 UTC; 1 weeks 2 days ago
 Main PID: 598 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/iptables.service

Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.

Also disable the Centos 7 firewalld daemon. It attempts to provide an interface to manipulating iptables which I do not want and do not use at all.

# systemctl stop firewalld
# systemctl disable firewalld

The first step now is to examine your existing rules with line numbers.

# iptables -nL --line-numbers

If you have no rules defined, you will see empty lists:

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

Otherwise, if some rules are defined, you will see them with line numbers, as in the following example of what I see. Note: I use fail2ban and custom blocklist scripts; the following example includes the resulting rules.

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 110,995,143,993,587,465,4190 match-set f2b-dovecot src reject-with icmp-port-unreachable
2    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587,220,993,110,995 match-set f2b-postfix-sasl src reject-with icmp-port-unreachable
3    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587 match-set f2b-postfix src reject-with icmp-port-unreachable
4    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587 match-set f2b-sendmail-reject src reject-with icmp-port-unreachable
5    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587 match-set f2b-postfix-rbl src reject-with icmp-port-unreachable
6    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 587,465,25 match-set f2b-sendmail-auth src reject-with icmp-port-unreachable
7    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 8080 match-set f2b-squid src reject-with icmp-port-unreachable
8    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 22 match-set f2b-sshd-ddos src reject-with icmp-port-unreachable
9    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 22 match-set f2b-sshd src reject-with icmp-port-unreachable
10   ACCEPT     all  --  64.137.248.161       0.0.0.0/0
11   DROP       all  --  0.0.0.0/0            0.0.0.0/0            match-set blacklist src
12   DROP       all  --  0.0.0.0/0            0.0.0.0/0            match-set blacklistnet src
13   IP4BOGONS  all  --  0.0.0.0/0            0.0.0.0/0
14   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 110,995,143,993,587,465,4190 match-set f2b-dovecot src reject-with icmp-port-unreachable
15   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587 match-set f2b-sendmail-reject src reject-with icmp-port-unreachable
16   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587,220,993,110,995 match-set f2b-postfix-sasl src reject-with icmp-port-unreachable
17   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 587,465,25 match-set f2b-sendmail-auth src reject-with icmp-port-unreachable
18   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587 match-set f2b-postfix-rbl src reject-with icmp-port-unreachable
19   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 8080 match-set f2b-squid src reject-with icmp-port-unreachable
20   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587 match-set f2b-postfix src reject-with icmp-port-unreachable
21   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 22 match-set f2b-sshd-ddos src reject-with icmp-port-unreachable
22   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 22 match-set f2b-sshd src reject-with icmp-port-unreachable
23   ACCEPT     all  --  64.137.248.161       0.0.0.0/0
24   DROP       all  --  0.0.0.0/0            0.0.0.0/0            match-set block src
25   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp flags:!0x17/0x02 state NEW
26   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp flags:0x3F/0x3F
27   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp flags:0x3F/0x00
28   DROP       all  -f  0.0.0.0/0            0.0.0.0/0
29   ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
30   ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
31   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
32   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:23
33   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:25
34   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:53
35   ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:53
36   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:80
37   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:110
38   ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:123
39   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:143
40   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:443
41   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:465
42   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:587
43   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:993
44   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:995
45   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:4190
46   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:8080
47   ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:65514
48   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:65515
49   REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination
1    REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0

Chain IP4BOGONS (1 references)
num  target     prot opt source               destination
1    RETURN     all  --  10.0.0.0/8           0.0.0.0/0
2    RETURN     all  --  172.16.0.0/12        0.0.0.0/0
3    RETURN     all  --  192.168.0.0/16       0.0.0.0/0
4    DROP       all  --  0.0.0.0/0            0.0.0.0/0            match-set fullbogons-ipv4 src

In any case, we start by inserting a rule at the top of, i.e. line number 1, the ACCEPT list to drop fragmented packets. This blocks IP fragmentation exploits like IP fragment overlapped (teardrop), IP fragmentation buffer full, IP fragment overrun, IP fragment too many data-grams, IP fragment incomplete, IP Fragment Too Small and similar attacks. We use the -I switch with iptables to insert a rule at a position 1.

# iptables -I INPUT 1 -f -j DROP

Next, we stop Null Scans, which are basically a bunch of TCP packets with sequence number 0 and no flags set. Such packets are not used in proper network communications, and are used to find open ports or holes by hackers. The following command will insert the rule at the top of the ACCEPT table, pushing the existing rules down by one line.

# iptables -I INPUT 1 -p tcp --tcp-flags ALL NONE -j DROP

We next stop TCP "Christmas Tree" packets - unusual packets that have all flags set. These packets are used by hackers to explore the security and features of servers, and often provide clues to the underlying operating system because operating systems react differently to such packets. Again we insert this rule at the top (line number 1), pushing existing rules down.

# iptables -I INPUT 1 -p tcp --tcp-flags ALL ALL -j DROP

Finally we attempt to check TCP SYN Flood attacks by inserting a rule at the top.

# iptables -I INPUT 1 -p tcp ! --syn -m state --state NEW -j DROP

After executing these four commands, the first four rules in the ACCEPT change should show the resulting iptables firewall rules, followed by whatever other rules existed before.

# iptables -nL --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp flags:!0x16/0x02 state NEW
2    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp flags:0x3F/0x3F
3    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp flags:0x3F/0x00
4    DROP       all  -f  0.0.0.0/0            0.0.0.0/0
...
...
...

Making it permanent

We need to make the changes permanent, i.e. persistent across system restarts and reboots. On my server, iptables starts up on reboot using the default rules file /etc/sysconfig/iptables and then eventually other applications add what they need later on (e.g. a script I run to block of malware / attack sources based on publicly available blocklists, fail2ban jails created by fail2ban, etc.).

Therefore, I just saved the four rules in the default iptables system configuration file /etc/sysconfig/iptables


# ----------
# /etc/sysconfig/iptables
# Supratim Sanyal's Hobbyist Cloud VPS Server
#
# fail2ban and ip blocklist scripts add entries after boot, extending
# these initial startup filter rules
#
# See "Centos 7 Network Hardening: How to Protect Your Server from Basic Network Attacks using IPTABLES Firewall"
# at http://supratim-sanyal.blogspot.com/2016/09/centos-7-network-hardening-how-to_19.html
# ----------
#
#
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
#
# --
# Basic Network Exploit Protection from syn flood, nul, christmas and fragmented packets
# --
-A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j DROP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-A INPUT -f -j DROP
#
# --
# Allow related connections to come in for processes initiating outgoing connections
# --
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
#
# --
# Allow everything on localhost lo (127.0.0.1) interface
# --
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
#
# --
# Accept incoming connections on the following ports
# --
#
# --- SSH ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
#
# --- TELNET ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 23 -j ACCEPT
#
# --- SMTP ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT
#
# --- DNS: TCP and UDP ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 53 -j ACCEPT
-A INPUT -p udp -m udp --dport 53 -j ACCEPT
#
# --- HTTP ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
#
# --- POP ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 110 -j ACCEPT
#
# --- NTP ---
-A INPUT -p udp -m udp --dport 123 -j ACCEPT
#
# --- IMAP ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 143 -j ACCEPT
#
# --- HTTPS ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
#
# --- SMTPS ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 465 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 587 -j ACCEPT
#
# --- IMAP over SSL/TLS ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 993 -j ACCEPT
#
# --- POP3 over SSL/TLS ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 995 -j ACCEPT
#
# --- WEB PROXY (SQUID -> PRIVOXY -> TOR Proxy Chain) ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 8080 -j ACCEPT
#
# --- RSYSLOG ---
-A INPUT -p udp -m udp --dport 65514 -j ACCEPT
#
# --- STUNNEL (to RSYSLOG) ---
-A INPUT -p tcp -m state --state NEW -m tcp --dport 65515 -j ACCEPT
#
# --
# Reject everything else, including forwarding requests
# --
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
#
# --
# That's all, folks
# --
COMMIT
view raw iptables hosted with ❤ by GitHub
Finally, please make sure your /etc/sysctl.conf file has some server hardening parameters, including for securing your network. Here is mine.


# --
# /etc/sysctl.conf
# From "Centos 7 Network Hardening: How to Protect Your Server from Basic Network Attacks using IPTABLES Firewall"
# http://supratim-sanyal.blogspot.com/2016/09/centos-7-network-hardening-how-to_19.html
# --
# System default settings live in /usr/lib/sysctl.d/00-system.conf.
# To override those settings, enter new settings here, or in an /etc/sysctl.d/<name>.conf file
#
# For more information, see sysctl.conf(5) and sysctl.d(5).
net.ipv6.conf.all.disable_ipv6 = 1
# From https://highon.coffee/blog/security-harden-centos-7/
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.tcp_max_syn_backlog = 1280
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_timestamps = 0
# bump up size of tracked connections table
# helps in avoiding "nf_conntrack: table full, dropping packet" errors
net.netfilter.nf_conntrack_generic_timeout=120
net.netfilter.nf_conntrack_max = 524288
# misc
fs.suid_dumpable = 0
kernel.randomize_va_space = 2
kernel.exec-shield = 1
vm.overcommit_memory = 2
view raw sysctl.conf hosted with ❤ by GitHub



Starter /etc/sysconfig/iptables

You can use the following iptables as the starting point. Simply copy and put it into /etc/sysconfig/iptables and then adjust the ports that it opens up for the services your server provides.

# ----------------------------
# /etc/sysconfig/iptables
# Basic iptables initial rules for servers
# Protects from common attacks and opens up service ports to incoming connections
#
# See http://supratim-sanyal.blogspot.com/2016/09/centos-7-network-hardening-how-to_19.html
#
# Supratim Sanyal <supratim at riseup dot net>
# ----------------------------
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
#
# ---
# Basic network security - resist IP fragmentation, NULL scan, Christmas Tree and TCP SYN flood attacks - Supratim Sanyal
# See http://supratim-sanyal.blogspot.com/2016/09/centos-7-network-hardening-how-to_19.html
# ---
-I INPUT 1 -f -j DROP
-I INPUT 1 -p tcp --tcp-flags ALL NONE -j DROP
-I INPUT 1 -p tcp --tcp-flags ALL ALL -j DROP
-I INPUT 1 -p tcp ! --syn -m state --state NEW -j DROP
#
# ---
# Accept packets related to established connections (i.e. allow incoming connections to processes that initiated outgoing connections)
# ---
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
#
# ---
# Allow ping response
# ---
-A INPUT -p icmp -j ACCEPT
#
# ---
# Allow all traffic on localhost
# ---
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
#
# ---
# Open up incoming connections to servers on this box
# ---
#
# HECNET
-A INPUT -p udp -m udp --dport 4711 -j ACCEPT
#
# SSH
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
#
# Proxy Server
-A INPUT -p tcp -m tcp --dport 12345 -j ACCEPT
#
# SMTP
-A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
#
# ---
# Reject all other incoming and forwarding requests
# ---
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
#
# ---
# The End
# ---
#
COMMIT

No comments:

Post a Comment

"SEO" link builders: move on, your spam link will not get posted.

Note: Only a member of this blog may post a comment.

Recommended Products from Amazon