This short tutorial will guide you to a classic configuration of a web-server, including HTTP HTTPS and SSH.

Install and run

First install iptables with :

$ dnf install iptables-services

Then run and enable the service, so that it is loaded on each start :

$ systemctl start iptables
$ systemctl enable iptables
$ systemctl status iptables

The last command should display the status of the service : activate.

Configuration

Iptables configuration file is located at /etc/sysconfig/iptables-config and rules are saved in /etc/sysconfig/iptables. To update the configuration you can either :

  • Modify /etc/sysconfig/iptables and reload the service to activate the changes.
  • Use the command line to update rules in live.
Display all rules with line numbers
$ iptables --line-numbers -n -L
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 
Flush all the rules
$ iptables -F
Append a rule
$ iptables -A INPUT -p tcp -m tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
  • -A INPUT : append a rule to the INPUT target.
  • -p tcp : apply the rule to tcp packets.
  • -m tcp : use the tcp module.
  • --dport 443 : destination port 443 (HTTPS), this option is linked to the -m tcp option.
  • -m state : use the state module to track connections states.
  • --state NEW,ESTABLISHED : apply the rule for newly/already established connections.
  • -j ACCEPT : accept the packet if it matches the rule.
Set default chain policy
$ iptables -P INPUT DROP

Any packet in INPUT will be dropped (no error message sent back), if no rule matches.

Delete a rule
$ iptables -D INPUT 4

Rule number 4 in the INPUT chain policy will be deleted.

Configuration scenarios

Before setting all the targets (INPUT, OUTPUT, FORWARD) to DROP as a default rule, we will need to add some defaults rules, otherwise the connection with the server will be dropped and you will have to recover access with an emergency procedure, like chroot.

When configuring iptables for the first time, it is usual to lose access to your remote server, it happened to me several times ! My best advice is that you should try to guess how each change is going to affect your connection with the remote host. To guarantee an access to SSH, make sure you can connect on the SSH port (INPUT rule) and that the server can answer to this incoming packet (OUTPUT rule + state).

Ping

# allow incoming ping and the corresponding reply
$ iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
$ iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT

# allow ping from the server to the outside
$ iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
$ iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT

HTTP, HTTPS, SSH

Now we can set a list of rules for the INPUT target:

$ iptables -A INPUT -p tcp -m tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
$ iptables -A INPUT -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
$ iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

# or simply

$ iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -m state --state NEW,ESTABLISHED -j ACCEPT

By using the state module, we can keep track of connection states, only newly established or already established connections are accepted. On the same logic, we can build the rules for the OUTPUT target:

$ iptables -A OUTPUT -p tcp -m tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT
$ iptables -A OUTPUT -p tcp -m tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
$ iptables -A OUTPUT -p tcp -m tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

# or simply

$ iptables -A OUTPUT -p tcp -m multiport --sports 22,80,443 -m state --state ESTABLISHED -j ACCEPT

Final iptables configuration file:

-A INPUT -m state --state ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m multiport --dports 22,80,443 -m state --state NEW -j ACCEPT

# Ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT

# DNS over tcp/udp
-A INPUT -p udp -m udp --sport 53 -j ACCEPT
-A INPUT -p tcp -m tcp --sport 53 -j ACCEPT
-A INPUT -i lo -j ACCEPT

# Forward from eth1 to eth0
-A FORWARD -i eth1 -o eth0 -j ACCEPT

-A OUTPUT -m state --state ESTABLISHED -j ACCEPT
# The server sometimes needs to initiate requests (call to API, system packet manager)
-A OUTPUT -p tcp -m multiport --dports 80,443 -m state --state NEW -j ACCEPT
-A OUTPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A OUTPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A OUTPUT -p udp -m udp --dport 53 -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 53 -j ACCEPT

# RTM for kimsufi server
-A OUTPUT -p udp -m udp --dport 6100:6200 -j ACCEPT
-A OUTPUT -o lo -j ACCEPT

A list of useful command to manage the iptables service :

$ systemctl start iptables
$ systemctl restart iptables
$ systemctl stop iptables

# run iptables automatically
$ systemctl enable iptables
$ systemctl disable iptables