overview edit doc new doc remove

Jan 26, 2018

Iptables

How it works

Iptables are used to set up, maintain, and inspect the tables of IPv4 packet filter rules in the Linux kernel, it operates by comparing network traffic against a set of rules. These rules are organized into groups called chains. A chain is a set of rules that a packet is checked against sequentially. When the packet matches one of the rules, it executes the associated action.

NOTE: If a packet matches a rule it will not be checked against remaining rules in the chain.

Iptables is only for IPv4, if you want to configure IPv6 you need ip6tables. In the future iptables will be replaced by nftables.

Chains

INPUT

This chain handles all packets that are addressed to your server.

OUTPUT

This chain contains rules for traffic created by your server.

FORWARD

This chain is used to deal with traffic destined for other servers that are not created on your server. This chain is basically a way to configure your server to route requests to other machines.

Implementation

Discover ports being used

# netstat -4plunt
# ss -tulpna

Iptables commands

Show all active rules:

# iptables -S
# iptables -L --line-numbers

Checking the status of IPTables / Firewall. Options “-L” (List ruleset), “-v” (Verbose) and “-n” (Displays in numeric format).

# iptables -L -n -v

Flush iptables:

# iptables -F

Look at the INPUT chain:

# iptables -L INPUT

Create iptables config file

Create a file /etc/iptables.firewall.rules and append rules to it, next you find 2 examples of the config file.

Iptables V1

########################STRONG IPTABLES FILE########################

*filter

-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT -d 127.0.0.0/8 -j REJECT

# accept all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# allow all outbound traffic - you can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT

# allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL).
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT
-A INPUT -p tcp --dport 5000 -j ACCEPT
-A OUTPUT -p tcp --dport 5000 -j ACCEPT

# allow OpenVPN
#-A INPUT -p tcp --dport 1194 -j ACCEPT
#-A INPUT -p udp --dport 1194 -j ACCEPT

# allow DNS
-A OUTPUT -p udp -m udp --dport 53 -j ACCEPT

#####################MAIL SERVER#####################
#
# allows SMTP access
#-A INPUT -p tcp --dport 25 -j ACCEPT
#-A INPUT -p tcp --dport 465 -j ACCEPT
#-A INPUT -p tcp --dport 587 -j ACCEPT
#
# allows pop and pops connections
# -A INPUT -p tcp --dport 110 -j ACCEPT
# -A INPUT -p tcp --dport 995 -j ACCEPT
#
# allows imap and imaps connections
#-A INPUT -p tcp --dport 143 -j ACCEPT
#-A INPUT -p tcp --dport 993 -j ACCEPT
#
#####################MAIL SERVER#####################

# block mysql other then 192.168.0.0
-A INPUT -p tcp -s 192.168.0.0/24 --dport 3306 -m state --state NEW,ESTABLISHED -j ACCEPT

# allow SSH connections
# the -dport number should be the same port number you set in sshd_config
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
-A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

# allow ping
-A INPUT -p icmp --icmp-type echo-request -j ACCEPT

# for SMURF attack protection
-A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP
-A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP

# droping all invalid packets
-A INPUT -m state --state INVALID -j DROP
-A FORWARD -m state --state INVALID -j DROP
-A OUTPUT -m state --state INVALID -j DROP

# protecting portscans
# attacking IP will be locked for 24 hours (3600 x 24 = 86400 Seconds)
# this can make your server crash, use at own risk
-A INPUT -m recent --name portscan --rcheck --seconds 86400 -j DROP
-A FORWARD -m recent --name portscan --rcheck --seconds 86400 -j DROP

# remove attacking IP after 24 hours
-A INPUT -m recent --name portscan --remove
-A FORWARD -m recent --name portscan --remove

# these rules add scanners to the portscan list, and log the attempt.
-A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "portscan:"
-A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP

# block bad ports
-A INPUT -p tcp -m multiport --dport 135,136,137,138,139,445 -j DROP
-A INPUT -p udp -m multiport --dport 135,136,137,138,139,445 -j DROP

# block DDoS
# maximum 25 connection per minute
-A INPUT -p tcp --dport 80 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT
-A INPUT -p tcp --dport 443 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT

# log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# block null packets
-A INPUT -p tcp --tcp-flags ALL NONE -j DROP

# block Syn-flood packets
-A INPUT -p tcp ! --syn -m state --state NEW -j DROP

# block XMAS packets
-A INPUT -p tcp --tcp-flags ALL ALL -j DROP

# drop all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

iptables V2

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:TCP - [0:0]
:UDP - [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -d 127.0.0.0/8 -j REJECT 
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP

# allow HTTP and HTTPS connections.
# port 5000 is for reverse proxied python apps
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT
-A INPUT -p tcp --dport 5000 -j ACCEPT

# accept ICMP
-A INPUT -p icmp -j ACCEPT

# block mysql other then 192.168.0.0
-A INPUT -p tcp -s 192.168.0.0/24 --dport 3306 -m state --state NEW,ESTABLISHED -j ACCEPT

# allow SSH connections
# the -dport number should be the same port number you set in sshd_config
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

# block DDoS
# maximum 25 connection per minute
-A INPUT -p tcp --dport 80 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT 
-A INPUT -p tcp --dport 443 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT

# log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# block Syn-flood packets
-A INPUT -p tcp ! --syn -m state --state NEW -j DROP

# syn scans blocking
-I TCP -p tcp -m recent --update --seconds 60 --name TCP-PORTSCAN -j REJECT --reject-with tcp-reset
#-D INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -p tcp -m recent --set --name TCP-PORTSCAN -j REJECT --reject-with tcp-reset

-I UDP -p udp -m recent --update --seconds 60 --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable
#-D INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p udp -m recent --set --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable

#-D INPUT -j REJECT --reject-with icmp-proto-unreachable
-A INPUT -j REJECT --reject-with icmp-proto-unreachable

# drop everything else
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

Save and activate

Activate the firewall rules by entering the following command:

# iptables-restore < /etc/iptables.firewall.rules

Or you can install iptables-persistent and issue the following command after you have setup all your rules.

# service netfilter-persistent save

To enable on boot, make a script /etc/network/if-pre-up.d/firewall add the following to it:

#!/bin/sh
/sbin/iptables-restore < /etc/iptables.firewall.rules

And make it executable.

1