Working with Iptables

Need Hosting? Try ours, it's fast, reliable and feature loaded with support you can depend on. View Plans

Setting up a good firewall is necessary for every system administrator to secure their operating system. Iptables is a command line tool that allows a linux system administrator to configure the tables provided by the linux kernel implemented within the Netfilter project.

Iptables is used to protect your server from unwanted traffic from the internet. There are many different firewall tools available that you can use to configure your firewall. Iptables is one of them included in most linux distributions by default.

Iptables uses a set of tables with different chains, chains contains set of built in rules or user defined rules.

There are three types of tables available in iptable:

FILTER Table : This is the default table that contains following chains"

INPUT : This is the default chain that originating to system. OUTPUT : This is the default chain that genrating from system. FORWARD : This is the default chain that routed through the system.

NAT Table : This table is used when packet tries to create a new connection. It has the following built in chains.

PREROUTING : This chain alters packets before routing. This is used to translate the destination ip address of the packets that matches the routing on the local machine. It is also used for destination NAT. OUTPUT : This chain is used for altering packets that is generated from local machine. POSTROUTING : This chain is used for altering packets after routing. This is used translate the source ip address of the packets that match the routing on the local machine.

MANGLE Table : This table is used for packet altering. Currently there are five chains available.

PREROUTING chain 2. OUTPUT chain 3. FORWARD chain 4. INPUT chain 5. POSTROUTING chain

In this tutorial, we will see different iptables tips and tricks to protect your server on Ubuntu 14.04.

Requirements

A CentOS-7 server

A Non-root user account with sudo privileges

Installing Iptables

By default firewalld is available on CentOS-7 to manage iptables, so you will need to disable firewalld and enable first. You can disable firewalld by running the following commands:

sudo systemctl stop firewalld

sudo systemctl mask firewalld

Now, install iptables by running the following command:

sudo yum install iptables-services

Enable the service to start at boot time by running the following commands:

sudo systemctl enable iptables

sudo systemctl enable ip6tables

You can start, ttop and restart the iptables by running the following command:

sudo systemctl start iptables

sudo systemctl stop iptables

sudo systemctl restart iptables

When you reboot the system and restart the iptable service, the existing rules will be flushed out, so you will need to run the following command whenever you add any rule.

sudo service iptables save

The above command will save iptables rules in /etc/sysconfig/iptables file by default and rules are applied or restored in case of iptables flushes out.

Displaying the Status of Your Firewall

To list all rules on filter table, run the following command:

sudo iptables -L

You should see the following output:

Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED ACCEPT icmp -- anywhere anywhere ACCEPT all -- anywhere anywhere ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh REJECT all -- anywhere anywhere reject-with icmp-host-prohibited Chain FORWARD (policy ACCEPT) target prot opt source destination REJECT all -- anywhere anywhere reject-with icmp-host-prohibited Chain OUTPUT (policy ACCEPT) target prot opt source destination

If you want to list ipatbles rules for specific tables like the nat table or mangle table, then run the following commands:

sudo iptables -L -t nat

sudo iptables -L -t mangle

You should see the following output:

Chain PREROUTING (policy ACCEPT) target prot opt source destination Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain POSTROUTING (policy ACCEPT) target prot opt source destination

If you want to list all the rules with more data, then run the following command:

sudo iptables -L -n -v

Output:

Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 250 19030 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 3 568 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain OUTPUT (policy ACCEPT 129 packets, 14800 bytes) pkts bytes target prot opt in out source destination

-L is used to list rules.

-v is used to list rules with detail information.

-n is used to display IP address and port in numeric format. This option speeds up the listing because it does not use DNS to resolve names.

You can also list all rules with line number by running the following command:

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

Output:

Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 296 22494 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 2 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 3 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 5 3 568 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain OUTPUT (policy ACCEPT 159 packets, 19056 bytes) num pkts bytes target prot opt in out source destination

If you want to list rules for specific chain like INPUT and OUTPUT, then run the following command:

sudo iptables -L INPUT -n -v sudo iptables -L OUTPUT -n -v

Set the Default Firewall Policies

You can block all incoming and outgoing traffic by running the following commands:

sudo iptables -P INPUT DROP

sudo iptables -P OUTPUT DROP

sudo iptables -P FORWARD DROP

After running above commands, you will not be able to connect anywhere.

To block all incoming / forwarded packets, but allow outgoing traffic, run the following commands:

sudo iptables -P INPUT DROP

sudo iptables -P FORWARD DROP

sudo iptables -P OUTPUT ACCEPT

sudo iptables -A INPUT -m state --state NEW,ESTABLISHED -j ACCEPT

Now, check the firewall status by running the following command:

sudo iptables -L -v -n

Output:

Chain INPUT (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 33 2444 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state NEW,ESTABLISHED Chain FORWARD (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain OUTPUT (policy ACCEPT 3 packets, 328 bytes) pkts bytes target prot opt in out source destination

Block by IP Address

If you want to block specific IP address (192.168.1.34), then run the following command:

sudo iptables -A INPUT -s 192.168.1.34 -j DROP

Where you need to change 192.168.1.34 as you wish. The -A option appends the rule in the end of the selected chain.

The DROP option drops the packet without responding any acknowledgement.

If you want to block only TCP traffic from that specific IP address then run the following command:

sudo iptables -A INPUT -p tcp -s 192.168.1.34 -j DROP

If you want to block multiple source IP address like 192.168.1.20, 192.168.0.23, 10.11.1.2, then run the following command:

sudo iptables -A INPUT -s 192.168.1.20,192.168.0.23,10.11.1.2 -j DROP

To block specific IP address range, run the following command:

sudo iptables -A INPUT -s 192.168.0.0/24 -j DROP

If you no longer want to block requests from specific IP address, then you can delete the blocking rule with the following command:

sudo iptables -D INPUT -s 192.168.1.34 -j DROP

The -D option deletes one or more rules from the selected chain.

Block Ports in Iptables

Sometimes you will need to block incoming and outgoing connections on a specific port. If you want to block outgoing connection on port 22, then run the following command:

sudo iptables -A OUTPUT -p tcp --dport 22 -j DROP

To allow incoming connections on port 22, run the following command:

sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

Where you will change the 22 with the actual port as you wish to allow. If you want to block UDP traffic instead TCP, then simply run the following command:

sudo iptables -A INPUT -p udp --dport 22 -j ACCEPT

If you want to allow multiple port like 80, 25 and 443, then use multiport option as below:

sudo iptables -A INPUT -p tcp -m multiport --dports 25,80,443 -j ACCEPT

For outgoing connections, run the following command:

sudo iptables -A OUTPUT -p tcp -m multiport --dports 25,80,443 -j ACCEPT

If you can also limit the certain connections for specific port to specific network. For example if you want to allow outgoing connections on port 80 to network 192.168.0.1/24, then run the following command:

sudo iptables -A OUTPUT -p tcp -d 192.168.0.1/24 --dport 80 -j ACCEPT

To block all service requests on port 80, run the following command:

sudo iptables -A INPUT -p tcp --dport 80 -j DROP

To block port 80 only for an ip address 192.168.1.10, run the following command:

sudo iptables -A INPUT -p tcp -s 192.168.1.10 --dport 80 -j DROP

To block outgoing traffic to network 192.168.0.1/24 from interface eth1, then run the following command:

sudo iptables -A OUTPUT -o eth1 -d 192.168.1.0/24 -j DROP

Block or Accept Traffic from a Mac Address

If you wan to block all incomming connections from specific MAC address, then run the following command:

sudo iptables -A INPUT -m mac --mac-source 01:0P:BA:91:14:08 -j DROP

If you want to accept traffic for TCP port 22 from specific MAC address, then run the following command:

sudo iptables -A INPUT -p tcp --destination-port 22 -m mac --mac-source 01:0P:BA:91:14:08 -j ACCEPT

Log and Drop Packets

If you want to log and block IP spoofing on specific interface, then run the following commands:

sudo iptables -A INPUT -i eth1 -j LOG --log-prefix "IP_SPOOF A: "

sudo iptables -A INPUT -i eth1 -j DROP

The messages are logged in to file /var/log/messages, you can see by running the following command:

sudo tail -f /var/log/messages

Open Common Ports

To open NTP port for time syncing for specific network, run:

sudo iptables -A INPUT -s 192.168.20.0/24 -m state --state NEW -p udp --dport 123 -j ACCEPT

To open SMTP port for mail, run:

sudo iptables -A INPUT -m state --state NEW -p tcp --dport 25 -j ACCEPT

To allow HTTP and HTTPS for all, run:

sudo iptables -A INPUT -m state --state NEW -p tcp --dport 80 -j ACCEPT

sudo iptables -A INPUT -m state --state NEW -p tcp --dport 443 -j ACCEPT

To allow printing service for specific network, run:

sudo iptables -A INPUT -s 192.168.20.0/24 -p udp -m udp --dport 631 -j ACCEPT

sudo iptables -A INPUT -s 192.168.20.0/24 -p tcp -m tcp --dport 631 -j ACCEPT

To open POP3 and IMAP port, run:

sudo iptables -A INPUT -m state --state NEW -p tcp --dport 110 -j ACCEPT

sudo iptables -A INPUT -m state --state NEW -p tcp --dport 143 -j ACCEPT

To allow Samba file server to specific network, run:

sudo iptables -A INPUT -s 192.168.20.0/24 -m state --state NEW -p tcp --dport 137 -j ACCEPT

sudo iptables -A INPUT -s 192.168.20.0/24 -m state --state NEW -p tcp --dport 138 -j ACCEPT

sudo iptables -A INPUT -s 192.168.20.0/24 -m state --state NEW -p tcp --dport 139 -j ACCEPT

sudo iptables -A INPUT -s 192.168.20.0/24 -m state --state NEW -p tcp --dport 445 -j ACCEPT

To allow access for mysql, run:

sudo iptables -I INPUT -p tcp --dport 3306 -j ACCEPT

Advanced Iptable Rules

If you want to limit number of concurrent connections establish from single IP address on specific port, then run the following command:

sudo iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 3 -j REJECT

The above command allows only 3 connections on port 80 per client. You can change the port number as your need.

If you want to allow only established and related incoming traffic for incomming connections, run the following command:

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

For outgoing connections, run the following command:

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

If you want to block email sending from your system, then you can do this by blocking outgoing ports on SMTP:

sudo iptables -A OUTPUT -p tcp --dports 25,465,587 -j REJECT

Sometimes you will need to forward traffic to another port. You can do this by running the following command:

sudo iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 8080

The above command forwards all incoming traffic on interface eth1 from port 80 to port 8080. You may change the ports with your need.

If you want to share internet, you will need to set FORWARD chain to ACCEPT target by running the following command:

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

sudo iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

Next, you need to enable IP masquerading for your WAN interface on NAT table.

You can do this by running the following command:

sudo iptables -t nat -I POSTROUTING -o wan0 -j MASQUERADE

Delete Iptable Rules

If you want to delete all iptable rules, run the following command:

sudo iptables -F

To delete chain, run the following command:

sudo iptables -X

You can delete chains from specific table like nat and mangle table by running the following command:

sudo iptables -t nat -F

sudo iptables -t mangle -F

You can also delete iptable rules by line number.

First, display all rules for INPUT chain with line number run the following command:

sudo iptables -L INPUT -n --line-numbers

Output:

Chain INPUT (policy DROP) num target prot opt source destination 1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 2 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 5 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited 6 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state NEW,ESTABLISHED

In the above output, you can see the list of all rules with line number.

Now, to delete line number 5, run the following command:

sudo iptables -D INPUT 5

Testing Iptable Rules

You can list all open port on your system by running the following command:

sudo netstat -tulpn

Output:

Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 819/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1445/master udp 0 0 0.0.0.0:5353 0.0.0.0:* 573/avahi-daemon: r udp 0 0 0.0.0.0:34090 0.0.0.0:* 573/avahi-daemon: r udp 0 0 127.0.0.1:323 0.0.0.0:* 586/chronyd udp 0 0 0.0.0.0:58329 0.0.0.0:* 2327/dhclient udp 0 0 0.0.0.0:68 0.0.0.0:* 2327/dhclient

You can see that port 22 and 25 are open.

To check whether iptables allowing access to the port 22 from outside or not by running the following command:

sudo iptables -L INPUT -v -n | grep 22

Output:

0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22

You can also use the telnet command to see if firewall allows to connect to port 22. On remote machine, run the following command:

telnet server-ip-address 22

You should see the following output:

Trying 192.168.43.7... Connected to 192.168.43.7. Escape character is '^]'. SSH-2.0-OpenSSH_6.6.1

You can also use nmap command to check whether port 22 allow or not:

On remote machine, run the following command:

sudo nmap -sS -p 22 server-ip-address

Output: ``` language-bash Starting Nmap 6.40 ( http://nmap.org ) at 2016-08-17 14:25 IST Nmap scan report for centOS-7 (192.168.43.7) Host is up (0.00082s latency). PORT STATE SERVICE 22/tcp open ssh MAC Address: 08:00:27:8C:3F:C6 (Cadmus Computer Systems)

Nmap done: 1 IP address (1 host up) scanned in 0.58 seconds