Configuring the iptables Firewall
Iptables is a firewall for Linux operating systems that controls how network traffic passes through. When someone tries to connect to the server (or the server sends a request), iptables checks the chain of rules for that particular connection and applies the configured settings.
Iptables is installed by default in all modern Linux distributions.
Chain types
There are three types of iptables chains: INPUT, OUTPUT and FORWARD.
- INPUT — this chain is used to handle incoming connections.
- OUTPUT — used for outgoing connections.
- FORWARD — used to handle transit traffic, for example on a router. If you are not configuring routing, you will not need rules of this type.
A chain is an ordered set of rules. Each rule includes a criterion (for example, the packet's source IP address) and an action to apply to a packet that matches this criterion (for example, "allow"). If no criterion is specified, the rule applies to all packets.
When deciding what to do with a packet, iptables goes through the corresponding chain from the top of the rule list, checking the rules one by one until it finds a match. If no match is found (the connection does not match any of the rules you created), the default rule is applied.
When configuring iptables rules, keep in mind that for many ports, a connection must be established and a response received for data to be transferred successfully. Also be careful not to accidentally lock yourself out: for example, a remote SSH connection to the server is also an incoming connection.
Connection actions
There are three types of actions that can be applied to connections:
Accept — allow the connection.
Drop — ignore (block) the connection without notifying the source that it was blocked. This is recommended for handling traffic on internet-facing ports, since attackers get minimal information when scanning ports.
Reject — reject the connection and notify the source of the request that it was blocked. By default, an "icmp-port-unreachable" response packet is sent, but you can also configure the message (for example, "icmp-host-unreachable", "icmp-net-prohibited", "icmp-host-prohibited" and others).
Configuring rules
In this article, the general format for configuring rules is as follows:
iptables action chain rule
We omit the table from this format because we are covering the main filter table, which iptables commands use by default. There is no need to specify this table explicitly.
Action in this context is the operation to perform on the rule (for example, add or delete it).
Examples of available iptables actions:
- -A — append a rule to the chain;
- -I — insert a rule into the chain at a specified position;
- -D — delete a rule;
- -F — delete all rules;
- -L — list all rules in the current chain;
- -P — set the default policy.
Additional options:
- -p — specify the packet protocol;
- -s — specify the packet's source IP address;
- -j — specify how to handle the packet (allow, block, etc.).
Viewing existing rules
To list all rules, use the following command:
iptables -L
Or a command with more detailed output:
iptables -L -n -v
You can also view the rules for a specific chain, for example the INPUT chain:
iptables -L INPUT
Default rules
If none of the rules you created matches an incoming packet, the default rule is applied.
To view the default rules, run the following command:
iptables -L | grep policy
If you have not changed the default policy, all chains are initially set to allow.
To set the default rule, use the -P option, for example:
iptables -P FORWARD DROP
Configuration examples
To add a rule to an existing chain, run the command:
iptables -A
If you need to place a rule somewhere other than the end of the list, you can use the following command format and specify the rule's position in the list:
iptables -I chain number rule
For example, the following rule will be the first in the INPUT chain:
iptables -I INPUT 1 --dport 80 -j ACCEPT
To block all incoming connections from a specific IP:
iptables -A INPUT -s 1.2.3.4 -j DROP
To block connections from a specific subnet:
iptables -A INPUT -s 1.2.3.4/24 -j DROP
You can specify either an IP address or a host as the source. For example, to deny all connections from test.domain.ru:
iptables -A INPUT -s test.domain.ru -j DROP
To deny connections from hosts other than test.domain.ru:
iptables -A INPUT ! -s test.domain.ru -j DROP
To allow access to port 25 (SMTP) for everyone:
iptables -A INPUT -m state --state NEW -p tcp --dport 25 -j ACCEPT
To block port 25 (SMTP) for everyone (just replace ACCEPT with DROP):
iptables -A INPUT -m state --state NEW -p tcp --dport 25 -j DROP
To open the Apache ports to everyone:
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
To allow access to port 3306 (MySQL) for a specific IP:
iptables -A INPUT -s 1.2.3.4 -p tcp -m tcp --dport 3306 -j ACCEPT
To set up logging:
iptables -A INPUT -p tcp -m multiport --dports 22,53,8080,139,445 -j LOG --log-level INFO --log-prefix "New connection from 1.2.3.4/24:"
iptables -A INPUT -s 1.2.3.4/24 -m multiport --dports 22,8080,139,445 -j ACCEPT
With this configuration, every new connection to the server from the 1.2.3.4/24 subnet will be recorded in the log.
To protect against common attacks, you can add the following settings:
To block all "invalid" packets:
iptables -A INPUT -m state --state INVALID -j DROP
To block null packets:
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
To protect against SYN flood attacks:
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
iptables -A OUTPUT -p tcp ! --syn -m state --state NEW -j DROP
To block fragmented packets and protect against ping floods:
iptables -A INPUT -p icmp --fragment -j LOG --log-prefix "ping flooding"
iptables -A INPUT -p icmp --fragment -j DROP
To block ping:
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
iptables -A INPUT -i eth0 -p icmp --icmp-type echo-request -j DROP
To allow ping from specific addresses:
iptables -A INPUT -s 1.2.3.4 -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -s 1.22.33.44 -p icmp --icmp-type echo-request -j ACCEPT
To limit the number of simultaneous connections (connlimit) to port 80 to 5:
iptables -A INPUT -p tcp -m tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -m connlimit --connlimit-above 5 --connlimit-mask 32 -j DROP
Saving changes
To make sure the rules you created stay in effect even after a system reboot, you need to save them.
On CentOS, use the following command:
/sbin/service iptables save
If you use Debian or Ubuntu, it is recommended to install the iptables-persistent package to save the rules. You can install it with the following command:
apt install iptables-persistent
During installation, you will be asked whether to save the current rules. Answer "Yes".
After changing the iptables rules, save them by running the command:
netfilter-persistent save
Deleting rules
To delete a specific rule, use the -D option, for example:
iptables -D INPUT -s 1.2.3.4 -j DROP
To delete all rules, run the following command:
iptables -F
To delete the rules for a specific chain, run the command:
iptables -F INPUT