Iptables is a very useful linux firewall for protection and learning of how the ip packets transverse the linux system. Although the newer nftables is starting to gain popularity as well as ufw and firewalld due its simplicity as well as add GUI capabilities it is still good to learn iptables as still form the base of a lot of the packet filtering rules.

sudo apt install iptables iptables-persistent

Allow loopback connection.

sudo iptables -A INPUT -i lo -j ACCEPT

To accept all established TCP packets from incoming / INPUT. Both the state and ctstate perform similar function. ctstate is an extended function that allows you more granular control. So you just need to have either one in your iptables rule. Also depending on the kernel, some rumor is that state might be deprecated in favor of conntrack (ctstate).

sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
or
sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

Allow Incoming connection from SSH Client to SSH Server.

sudo iptables -A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

Allow Incoming connection to web server with (443) or without (80) ssl .

sudo iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

To only allow source machines from allowed source IP address to connect use the following command. Replace the ip address with your own ip.

sudo iptables -A INPUT -s 155.190.0.0/16 -j ACCEPT

To list the rules in iptables -L list the rules. -v version, -n shows app ip address and ports number. –line-numbers show the order of the rules in each chain.

sudo iptables -L -v -n --line-numbers

It is important to make sure that you have allowed the necessary management ports before you drop all incoming packets and turn on the firewall to avoid being lock out from your server.

Once you added the necessary incoming / INPUT allow/accepted traffic you can deny the rest.

sudo iptables -P INPUT DROP

Now is to turn on iptables. To make iptables persistent issue the following command.

sudo systemctl enable iptables

Next start the iptables.

sudo systemctl start iptables

Once that is done you can check the status by issuing the following command.

sudo systemctl status iptables

You can add in a logging for input traffic with custom tag with the following command.

sudo iptables -A INPUT -j LOG --log-prefix "\[IPT_"

Sample of the Configuration.

# Configure iptables to allow connection from loopback.
sudo iptables -A INPUT -i lo -j ACCEPT

#Configure iptables to accept pre-established packets.
sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# Configure the iptables to accept SSH connection default port is 22.
sudo iptables -A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT


# Configure the iptables to accept HTTP and HTTPS traffic on the default port 80 and 443.
sudo iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

# Block all other incoming packets
sudo iptables -P INPUT DROP

# Optional to log input packets with a custom prefix.
sudo iptables -A INPUT -j LOG --log-prefix "\[IPT_"

To save the iptables config use the netfilter-persistent save command.

sudo netfilter-persistent save

To limit number of packets per minute you can add in the following syntax.

sudo iptables -A INPUT -m limit --limit 10/min -j LOG --log-prefix "IPT_Deny"

Now if you are going to deny outgoing as well here are some of the rules that you might need.

Accept outgoing traffic to the loop back interface.

sudo iptables -A OUTPUT -o lo -j ACCEPT

To accept establish ssh packets to avoid accidentally locking yourself out. You can either accept all established tcp packet or specificed it for SSH only.

# For established SSH traffic only
sudo iptables -A OUTPUT -p tcp -m tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT

# or For all established TCP traffic.

sudo iptables -A OUTPUT -p tcp -m tcp -m conntrack --ctstate ESTABLISHED -j ACCEPT

Once you confirmed the configuration is done properly you can then issue the following command

sudo iptables -P OUTPUT -DROP