Create an iptables firewall using custom chains that will be used to control incoming and outgoing traffic.
Create an iptables firewall that will allow already established connections, incoming ssh for given source addresses, outgoing icmp, ntp, dns, ssh, http, and https.
# Flush rules and delete custom chains iptables -F iptables -X # Define chain to allow particular source addresses iptables -N chain-incoming-ssh iptables -A chain-incoming-ssh -s 192.168.1.148 -j ACCEPT iptables -A chain-incoming-ssh -s 192.168.1.149 -j ACCEPT iptables -A chain-incoming-ssh -j DROP # Define chain to allow particular services iptables -N chain-outgoing-services iptables -A chain-outgoing-services -p tcp --dport 53 -j ACCEPT iptables -A chain-outgoing-services -p udp --dport 53 -j ACCEPT iptables -A chain-outgoing-services -p tcp --dport 123 -j ACCEPT iptables -A chain-outgoing-services -p udp --dport 123 -j ACCEPT iptables -A chain-outgoing-services -p tcp --dport 80 -j ACCEPT iptables -A chain-outgoing-services -p tcp --dport 443 -j ACCEPT iptables -A chain-outgoing-services -p tcp --dport 22 -j ACCEPT iptables -A chain-outgoing-services -p icmp -j ACCEPT iptables -A chain-outgoing-services -j DROP # Define chain to allow established connections iptables -N chain-states iptables -A chain-states -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A chain-states -p udp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A chain-states -p icmp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A chain-states -j RETURN # Drop invalid packets iptables -A INPUT -m conntrack --ctstate INVALID -j DROP # Accept everything on loopback iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT # Accept incoming/outgoing packets for established connections iptables -A INPUT -j chain-states iptables -A OUTPUT -j chain-states # Accept incoming ICMP iptables -A INPUT -p icmp -j ACCEPT # Accept incoming SSH iptables -A INPUT -p tcp --dport 22 -j chain-incoming-ssh # Accept outgoing iptables -A OUTPUT -j chain-outgoing-services ## Drop everything else iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP
List all firewall rules to verify that executed commands are applied as desired.
$ sudo iptables -L -v -n
Chain INPUT (policy DROP 2 packets, 92 bytes) pkts bytes target prot opt in out source destination 0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID 1 29 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 190 15639 chain-states all -- * * 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 1 60 chain-incoming-ssh tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 Chain FORWARD (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 1 29 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0 150 39893 chain-states all -- * * 0.0.0.0/0 0.0.0.0/0 1 62 chain-outgoing-services all -- * * 0.0.0.0/0 0.0.0.0/0 Chain chain-incoming-ssh (1 references) pkts bytes target prot opt in out source destination 0 0 ACCEPT all -- * * 192.168.1.148 0.0.0.0/0 1 60 ACCEPT all -- * * 192.168.1.149 0.0.0.0/0 0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 Chain chain-outgoing-services (1 references) pkts bytes target prot opt in out source destination 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53 1 62 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:123 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:123 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 Chain chain-states (2 references) pkts bytes target prot opt in out source destination 335 55240 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED 1 78 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED 4 214 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
I have used RETURN
target for chain-states
so the packet would continue its passage through the firewall.
Editing address list
List firewall rules in the source address list.
$ sudo iptables -n --list chain-incoming-ssh --line-numbers
Chain chain-incoming-ssh (1 references) num target prot opt source destination 1 ACCEPT all -- 192.168.1.148 0.0.0.0/0 2 ACCEPT all -- 192.168.1.149 0.0.0.0/0 3 DROP all -- 0.0.0.0/0 0.0.0.0/0
Remove the first entry.
sudo iptables -D chain-incoming-ssh 1
Add a new rule at the beginning of the chain.
$ sudo iptables -I chain-incoming-ssh 1 -s 192.168.1.140 -j ACCEPT
Add new rule just one before last entry.
$ sudo iptables -I chain-incoming-ssh 3 -s 192.168.1.150 -j ACCEPT
List firewall rules in the source address list.
$ sudo iptables -n --list chain-incoming-ssh --line-numbers Chain chain-incoming-ssh (1 references) num target prot opt source destination 1 ACCEPT all -- 192.168.1.140 0.0.0.0/0 2 ACCEPT all -- 192.168.1.149 0.0.0.0/0 3 ACCEPT all -- 192.168.1.150 0.0.0.0/0 4 DROP all -- 0.0.0.0/0 0.0.0.0/0
Additional notes
You can inspect a particular chain using the following command.
$ sudo iptables -n --list chain-outgoing-services
Chain chain-outgoing-services (1 references) target prot opt source destination ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:53 ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:53 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:123 ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:123 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 DROP all -- 0.0.0.0/0 0.0.0.0/0
You can also use it inside a shell script to perform different actions depending on its existence.
iptables --list chain-outgoing-services &>/dev/null if [ "$?" -eq "0" ]; then iptables -F chain-outgoing-services else iptables -N chain-outgoing-services fi