IPTables is a command-line utility that is the standard interface for controlling the firewall netfilter for Linux kernels. To use the IPTables utility you need superuser privileges (root).
netfilter is a set of system messages within the Linux kernel that allows kernel modules to register callback functions from the network stack. The registered callback function handles every packet passing through the network stack.
The firewall in Linux is controlled by iptables, which has IPv4 filtering functions
The # sign means that the command is executed as root. Open a console with root privileges beforehand - sudo -i on Debian-based systems or su on others.
*Show status.
# iptables -L -n -v
Sample output of the command for an inactive firewall:
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
For an active firewall:
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 state INVALID
394 43586 ACCEPT all -- * * 0.0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
93 17292 ACCEPT all -- br0 * 0.0.0.0.0/0 0.0.0.0/0
1 142 ACCEPT all -- lo * 0.0.0.0/0/0 0.0.0.0/0
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 0 ACCEPT all -- br0 br0 0.0.0.0/0 0.0.0.0/0
0 0 0 DROP all -- * * 0.0.0.0/0 0.0.0/0 state INVALID
0 0 0 TCPMSS tcp -- * * * 0.0.0.0/0 0.0.0.0/0 tcp flags:0x06/0x02 TCPMSS clamp to PMTU
0 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0/0 state RELATED,ESTABLISHED
0 0 0 wanin all -- -- vlan2 * 0.0.0.0/0 0.0.0.0/0
0 0 0 wanout all -- * vlan2 0.0.0.0/0 0.0.0.0/0
0 0 0 ACCEPT all -- br0 * 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 425 packets, 113K bytes)
pkts bytes target prot opt in out source destination
Chain wanin (1 references)
pkts bytes target prot opt in out source destination
Chain wanout (1 references)
pkts bytes target prot opt in out source destination
Where:
- L : Show list of rules.
- v : Show additional information. This option shows the interface name, options, TOS mask. It also displays suffixes 'K', 'M' or 'G'.
- n : Display IP address and port as numbers (without using a DNS server to define names. This will speed up the display).
**Display rule list with line numbers
# iptables -n -L -v --line-numbers
Approximate output:
Chain INPUT (policy DROP)
num target prot prot opt source destination
1 DROP all -- 0.0.0.0/0 0.0.0.0/0 state INVALID
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
4 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy DROP)
num target prot opt source destination
1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
2 DROP all -- 0.0.0.0/0 0.0.0.0/0 state INVALID
3 TCPMSS tcp -- 0.0.0.0/0 0.0.0.0/0 tcp flags:0x06/0x02 TCPMSS clamp to PMTU
4 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
5 wanin all -- 0.0.0.0/0 0.0.0.0/0
6 wanout all -- 0.0.0.0/0 0.0.0.0/0
7 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
Chain wanin (1 references)
num target prot opt source destination
Chain wanout (1 references)
num target prot opt source destination
You can use line numbers to add new rules.
**Display the INPUT or OUTPUT of a rule chain
# iptables -L INPUT -n -v
# iptables -L OUTPUT -n -v --line-numbers
*# Stop, start, restart the firewall
By the system itself:
# service ufw stop
# service ufw start
You can also use iptables commands to stop the firewall and remove all rules:
# iptables -F
# iptables -X
# iptables -t nat -F
# iptables -t nat -X
# iptables -t mangle -F
# iptables -t mangle -X
# iptables -P INPUT ACCEPT
# iptables -P OUTPUT ACCEPT
# iptables -P FORWARD ACCEPT
Where:
- F : Remove (flush) all rules.
- X : Remove the chain.
- t table_name : Select a table (nat or mangle) and delete all rules.
- P : Select the default action (such as DROP, REJECT, or ACCEPT).
*Remove firewall rules
To display the line number with existing rules:
# iptables -L INPUT -n --line-numbers
# iptables -L OUTPUT -n --line-numbers
# iptables -L OUTPUT -n --line-numbers | less
# iptables -L OUTPUT -n --line-numbers | grep 202.54.1.1
We get a list of IP addresses. Just look at the number on the left and remove the corresponding line. For example for number 3:
# iptables -D INPUT 3
Or find the source IP address (202.54.1.1) and remove it from the rule:
# iptables -D INPUT -s 202.54.1.1 -j DROP
Where:
- D : Remove one or more rules from the chain.
Add rule to the firewall.
To add one or more rules to a chain, we start by displaying a list using line numbers:
# iptables -L INPUT -n --line-numbers
Sample output:
Chain INPUT (policy DROP)
num target prot opt source destination
1 DROP all -- 202.54.1.1 0.0.0/0
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state NEW,ESTABLISHED
To insert a rule between line 1 and line 2:
# iptables -I INPUT 2 -s 202.54.1.2 -j DROP
Check if the rule has been updated:
# iptables -L INPUT -n --line-numbers
The output will go like this:
Chain INPUT (policy DROP)
num target prot prot opt source destination
1 DROP all -- 202.54.1.1 0.0.0/0
2 DROP all -- 202.54.1.2 0.0.0/0
3 ACCEPT all -- 0.0.0.0/0 0.0.0/0 state NEW,ESTABLISHED
**Save firewall rules
Through iptables-save:
# iptables-save > /etc/iptables.rules
*# Restore rules
Through iptables-restore
# iptables-restore < /etc/iptables.rules
*# Set default policies
To reset all traffic:
# iptables -P INPUT DROP
# iptables -P OUTPUT DROP
# iptables -P FORWARD DROP
# iptables -L -v -n
After the above commands no packets will leave this host.
# ping google.com
**Block only incoming connections
To drop all incoming packets not initiated by you, but allow outgoing traffic:
# iptables -P INPUT DROP
# iptables -P FORWARD DROP
# iptables -P OUTPUT ACCEPT
# iptables -A INPUT -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -L -v -n
Outgoing packets and those that have been remembered within established sessions are allowed.
# ping google.com
*# Reset isolated network addresses on the public network
# iptables -A INPUT -i eth1 -s 192.168.0.0/24 -j DROP
# iptables -A INPUT -i eth1 -s 10.0.0.0/8 -j DROP
List of IP addresses for isolated networks:
10.0.0.0/8 -j (A)
172.16.0.0/12 (B)
192.168.0.0/16 ©
224.0.0.0/4 (MULTICAST D)
240.0.0.0/5 (E)
127.0.0.0/8 (LOOPBACK)
** Blocking a specific IP address
To block burglar address 1.2.3.4:
# iptables -A INPUT -s 1.2.3.4 -j DROP
# iptables -A INPUT -s 192.168.0.0/24 -j DROP
Block incoming port requests.
To block all incoming port 80 requests:
# iptables -A INPUT -p tcp --dport 80 -j DROP
# iptables -A INPUT -i eth1 -p tcp --dport 80 -j DROP
To block a port 80 request from address 1.2.3.4:
# iptables -A INPUT -p tcp -s 1.2.3.4 --dport 80 -j DROP
# iptables -A INPUT -i eth1 -p tcp -s 192.168.1.0/24 --dport 80 -j DROP
**Block outgoing IP address requests
To block a certain domain, find out its address:
# host -t a facebook.com
Conclusion: facebook.com has address 69.171.228.40
Find the CIDR for 69.171.228.40:
# whois 69.171.228.40 | grep CIDR
Output:
CIDR: 69.171.224.0/19
Block access to 69.171.224.0/19:
# iptables -A OUTPUT -p tcp -d 69.171.224.0/19 -j DROP
You can also use the domain to block:
# iptables -A OUTPUT -p tcp -d www.fаcebook.com -j DROP
# iptables -A OUTPUT -p tcp -d -j DROP
Record the event and reset it.
To log packet traffic before resetting, let's add a rule:
# iptables -A INPUT -i eth1 -s 10.0.0.0/8 -j LOG --log-prefix "IP_SPOOF A: "
# iptables -A INPUT -i eth1 -s 10.0.0.0/8 -j DROP
Check the log (by default /var/log/messages):
# tail -f /var/log/messages
# grep -i --color 'IP SPOOF' /var/log/messages
# Record the event and reset it (with a limit on the number of entries).*
To avoid overfilling the partition with a bloated log, we will limit the number of entries using -m. For example, to record every 5 minutes a maximum of 7 lines:
# iptables -A INPUT -i eth1 -s 10.0.0.0/8 -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix "IP_SPOOF A: "
# iptables -A INPUT -i eth1 -s 10.0.0.0/8 -j DROP
**Reset or allow traffic from certain MAC addresses
# iptables -A INPUT -m mac --mac-source 00:0F:EA:91:04:08 -j DROP
## *allow only for TCP port # 8080 with mac address 00:0F:EA:91:04:07 ##
# iptables -A INPUT -p tcp --destination-port 22 -m mac --mac-source 00:0F:EA:91:04:07 -j ACCEPT
*Allow or deny ICMP Ping requests
Deny Icmp messages.
It is also good practice to forbid ICMP messages which might give out additional information about the host or be used to perform various malicious actions (e.g., modifying the routing table). Below is a table with a list of possible ICMP message types:
ICMP message types.
0 - echo reply (echo ping)
3 - destination unreachable
4 - source quench
5 - redirect
8 - echo request
9 - router advertisement
10 - router solicitation
11 - time-to-live exceeded
12 - IP header bad
13 - timestamp request (timestamp value request)
14 - timestamp reply (request for timestamp value)
15 - information request
16 - information reply (request for information)
17 - address mask request
18 - address mask reply (request for netmask)
As you can see, replying to some ICMP messages may lead to disclosure of some host information, while others may lead to modification of the routing table, so they should be forbidden.
Typically, ICMP messages 0, 3, 4, 11, and 12 are allowed out to the outside world, while only 3, 8, and 12 are allowed in. This is how it is implemented in different firewalls:
Deny dangerous ICMP messages.
iptables -A INPUT -p icmp --icmp-type 3,8,12 -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type 0,3,4,11,12 -j ACCEPT
To prohibit:
# iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
# iptables -A INPUT -i eth1 -p icmp --icmp-type echo-request -j DROP
Allow for certain networks/hosts:
# iptables -A INPUT -s 192.168.1.0/24 -p icmp --icmp-type echo-request -j ACCEPT
Allow only part of the ICMP requests:
### ** it is assumed that the default policy for inbound is set to DROP ** ###
# iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
# iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
# iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
## ** let us respond to the request ** ##
# # iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
- iptables -A INPUT -p icmp --icmp-type 3 -j ACCEPT
- iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT
-
iptables -A INPUT -p icmp --icmp-type 12 -j ACCEPT
-
iptables -A OUTPUT -i eth0 -p icmp --icmp-type 0 -j ACCEPT
**Open port range
# iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 7000:7010 -j ACCEPT
*Open a range of addresses
## allow connection to port 80 (Apache) if address range is 192.168.1.100 to 192.168.1.200 ##
# iptables -A INPUT -p tcp --destination-port 80 -m iprange --src-range 192.168.1.100-192.168.1.200 -j ACCEPT
## example for nat ##
# iptables -t nat -A POSTROUTING -j SNAT --to-source 192.168.1.20-192.168.1.25
Close or open standard ports.
Replace ACCEPT with DROP to block the port.
## ssh tcp port 22 ##
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -s 192.168.1.0/24 -m state --state NEW -p tcp --dport 22 -j ACCEPT
## cups (printing service) udp/tcp port 631 for local network ##
iptables -A INPUT -s 192.168.1.0/24 -p udp -m udp --dport 631 -j ACCEPT
iptables -A INPUT -s 192.168.1.0/24 -p tcp -m tcp --dport 631 -j ACCEPT
## time sync via NTP for local network (udp port 123) ##
iptables -A INPUT -s 192.168.1.0/24 -m state --state NEW -p udp --dport 123 -j ACCEPT
## tcp port 25 (smtp) ##
iptables -A INPUT -m state --state NEW -p tcp --dport 25 -j ACCEPT
# dns server ports ##
iptables -A INPUT -m state --state NEW -p udp --dport 53 -j ACCEPT
iptables -A INPUT -m state --state NEW -p tcp --dport 53 -j ACCEPT
## http/https www server port ##
iptables -A INPUT -m state --state NEW -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -m state --state NEW -p tcp --dport 443 -j ACCEPT
## tcp port 110 (pop3) ##
iptables -A INPUT -m state --state NEW -p tcp --dport 110 -j ACCEPT
## tcp port 143 (imap) ##
iptables -A INPUT -m state --state NEW -p tcp --dport 143 -j ACCEPT
## Samba file server for local network ##
iptables -A INPUT -s 192.168.1.0/24 -m state --state NEW -p tcp --dport 137 -j ACCEPT
iptables -A INPUT -s 192.168.1.0/24 -m state --state NEW -p tcp --dport 138 -j ACCEPT
iptables -A INPUT -s 192.168.1.0/24 -m state --state NEW -p tcp --dport 139 -j ACCEPT
iptables -A INPUT -s 192.168.1.0/24 -m state --state NEW -p tcp --dport 445 -j ACCEPT
## proxy server for local network ##
iptables -A INPUT -s 192.168.1.0/24 -m state --state NEW -p tcp --dport 3128 -j ACCEPT
## mysql server for local network ##
iptables -I INPUT -p tcp --dport 3306 -j ACCEPT
*Limit the number of concurrent connections to the server for one address
The connlimit module is used for restrictions. To allow only 3 ssh connections per client:
# iptables -A INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 3 -j REJECT
Set the number of HTTP requests to 20:
# iptables -p tcp --syn --dport 80 -m connlimit --connlimit-above 20 -connlimit-mask 24 -j DROP
Where:
- connlimit-above 3 : Specifies that the rule is valid only if the number of connections exceeds 3.
- connlimit-mask 24 : Specifies the network mask.