Iptables is highly versatile and accepts direct commands from the user who can load and unload rules according to the need.
This tutorial shows how to protect a web server, forward connections to internal IP addresses from our LAN, and offer specific services to whitelisted IP addresses only.
Note: This Iptables tutorial was first released two years ago and updated on 23/05/2021 with improved examples and better quality screenshots.
How to install
Iptables are omitted by default in distributions that incorporate Nftables.
To install Iptables on Debian based Linux distributions, run the following command:
Opening HTTP and HTTPS ports
First of all, let’s add all ACCEPT policies starting with the webserver.
Note: If you create a script with rules, you don’t need to use sudo.
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
To see added rules run “iptables -L”
Where:
Iptables = calls the program
-A = adds a rule
INPUT = incoming traffic
-p = protocol
–ddport = destination port
-j = specify the “target”; the target is the type of policy: ACCEPT, DROP, REJECT (Built-in)…
Iptables -L = lists all iptables loaded rules (Iptables -L -v = the same with verbosity.)
In the example above, we instruct Iptables to add a rule for incoming traffic through TCP protocol and ports 80 (http) and 443 (https) to be accepted.
We can change the command to accept the connection only from a specific IP by adding the parameter “-s”:
Where:
s = source
You can also test your firewall with nmap:
Note: In the example above, port 443 isn’t shown because the server has not an SSL certificate adequately configured.
Note: For more information on Nmap, you can read this.
Protecting your server with Iptables:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
#Open SSH Port Service
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
Where the new parameters are:
-m means “match” and is used to call Iptables extensions like conntrack, which is not part of iptables core functions.
conntrack = Allows tracking information on connections like specific addresses or, in this case, the state of the connection. This must be used carefully since many rules to defend servers from some attacks use conntrack while the hardware limits its use, and such limitation can be used to overload the server’s resources.
-ctstate = determines the state of the rule to match; the possible states are: NEW, ESTABLISHED, RELATED and INVALID.
to access iptables -A INPUT -p tcp -s X.X.X.X --dport 22 -m conntrack --ctstate NEW,
ESTABLISHED -j ACCEPT
#Protect your SSH Service against brute force attacks by limiting connection attempts
Iptables -A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j 22-test
Iptables -A 22-test -m recent --name CONNECTIONS --set --mask 255.255.255.255 --rsource
Iptables -A 22-test -m recent --name CONNECTIONS --rcheck --mask 255.255.255.255
--rsource --seconds 30 --hitcount 3 -j 22-protection
Iptables -A 22-test -j ACCEPT
Iptables -A 22-protection -j DROP
Where:
In the first liNe, our rule says “-m conntrack –ctstate NEW,” which means if the connection is new, then pass to the rule “22-test”.
The second line says packets netmask 255.255.255.255 are named as CONNECTIONS.
The third line says if a CONNECTIONS is over 3 times within 30 seconds, the firewall continues applying the chain 22-protection. The fourth line says if the CONNECTIONS weren’t seen over 3 times within 30 seconds, they could be accepted.
The fifth line, which belongs to the 22-protection chain, says to drop CONNECTIONS if they seem to be over 3 times within 30 seconds.
Now to end, let’s refuse all unawolled incoming connections and let’s allow all outgoing traffic:
iptables -P INPUT DROP
P refers to the chain policy; remember the target is the policy, ACCEPT, DROP, REJECT. In this case, we are saying the default policy for outgoing traffic is to accept, and the default policy for incoming traffic is to refuse unless we specified something different in previous rules. This is a very basic firewall that does not include rules for many attacks, for learning purposes and not for production; at the end of the article, I attach a firewall I used for production on a server; it has comments explaining each rule.
FORWARDING A CONNECTION TO A SPECIFIC PORT TO A SPECIFIC IP ADDRESS
This is also very useful for desktop users who want to enroute a connection through a specific device; it can be useful even for gamers; usually, we do it from the router settings but let’s assume the routing device is running Iptables.
iptables -A POSTROUTING -t nat -p tcp -j SNAT --to-source X.X.X.X
The rules above invoke NAT (Network Address Translation) to specify connections through protocol TCP to the address X.X.X.X, and port 8080 will be redirected to address Y.Y.Y.Y, port 80. The second rule specifies replies must be sent to the source address (X.X.X.X). We can use these rules to allow access to an IP camera, enable online gaming with external networks, etc.
This tutorial was meant to introduce beginners to Iptables and only explains a limited number of basics. Below you can see a sample of a well-planned firewall used for a production server; it includes some of the rules we already saw to more complex rules to prevent DDoS, among other types of attacks.
Bonus: Sample of production firewall
#---- Enable bad error message protection
enable /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
#---- Turn on reverse path filtering. Safer, but breaks asymmetric routing and/or IPSEC
enable /proc/sys/net/ipv4/conf/*/rp_filter
#---- Don't accept source routed packets. Source routing is rarely used for legitimate
purposes disable /proc/sys/net/ipv4/conf/*/accept_source_route
#---- Disable ICMP redirect acceptance which can be used to alter your routing tables
disable /proc/sys/net/ipv4/conf/*/accept_redirects
#---- As we don't accept redirects, don't send Redirect messages either
disable /proc/sys/net/ipv4/conf/*/send_redirects
#---- Ignore packets with impossible addresses
disable /proc/sys/net/ipv4/conf/*/log_martians
#---- Protect against wrapping sequence numbers and aid round trip time measurement
enable /proc/sys/net/ipv4/tcp_timestamps
#---- Help against syn-flood DoS or DDoS attacks using particular choices of initial
TCP sequence numbers enable /proc/sys/net/ipv4/tcp_syncookies
#---- Use Selective ACK which can be used to signify that specific packets are missing
disable /proc/sys/net/ipv4/tcp_sack
modprobe nf_conntrack_ipv4
modprobe nf_nat
# modprobe nf_conntrack_ipv6
# modprobe nf_conntrack_amanda
# modprobe nf_nat_amanda
modprobe nf_conntrack_h323
modprobe nf_nat_h323
modprobe nf_conntrack_ftp
modprobe nf_nat_ftp
# modprobe nf_conntrack_netbios_ns
# modprobe nf_conntrack_irc
# modprobe nf_nat_irc
# modprobe nf_conntrack_proto_dccp
# modprobe nf_nat_proto_dccp
modprobe nf_conntrack_netlink
# modprobe nf_conntrack_pptp
# modprobe nf_nat_pptp
# modprobe nf_conntrack_proto_udplite
# modprobe nf_nat_proto_udplite
# modprobe nf_conntrack_proto_gre
# modprobe nf_nat_proto_gre
# modprobe nf_conntrack_proto_sctp
# modprobe nf_nat_proto_sctp
# modprobe nf_conntrack_sane
modprobe nf_conntrack_sip
modprobe nf_nat_sip
# modprobe nf_conntrack_tftp
# modprobe nf_nat_tftp
# modprobe nf_nat_snmp_basic
#Now we can start adding selected services to our firewall filter. The first such thing
is a localhost interface iptables -A INPUT -i lo -j ACCEPT
#We told the firewall to take all incoming packets with tcp flags NONE and just DROP them.
iptables -A INPUT -p tcp ! -m conntrack --ctstate NEW -j DROP
#We tell iptables to add (-A) a rule to the incoming (INPUT)- SSH works on port 50683
instead 22.
iptables -A INPUT -p tcp -m tcp --dport 50683 -j ACCEPT
iptables -A INPUT -p tcp -m tcp -s specific ip --dport 50683 -j ACCEPT
iptables -A INPUT -p tcp -m tcp -s specific ip --dport 50683 -j ACCEPT
iptables -A INPUT -p tcp -m tcp -s specific ip --dport 50683 -j ACCEPT
iptables -A INPUT -p tcp --dport 50683 -m conntrack --ctstate NEW -m recent --set
--name SSH -j ACCEPT
iptables -A INPUT -p tcp --dport 50683 -m recent --update --seconds 60 --hitcount 4
--rttl --name SSH -j LOG --log-prefix "SSH_brute_force "
iptables -A INPUT -p tcp --dport 50683 -m recent --update --seconds 60 --hitcount 4
--rttl --name SSH -j DROP
iptables -A INPUT -p tcp --dport 50683 -m conntrack --ctstate NEW -m recent --set
--name SSH
iptables -A INPUT -p tcp --dport 50683 -m conntrack --ctstate NEW -j SSH_WHITELIST
iptables -A INPUT -p tcp --dport 50683 -m conntrack --ctstate NEW -m recent --update
--seconds 60 --hitcount 4 --rttl --name SSH -j ULOG --ulog-prefix SSH_bru
iptables -A INPUT -p tcp --dport 50683 -m conntrack --ctstate NEW -m recent --update
--seconds 60 --hitcount 4 --rttl --name SSH -j DROP
#Now I allow imap,and smtp.
-A INPUT -p tcp --dport 25 -j ACCEPT
# Allows pop and pops connections
-A INPUT -p tcp --dport 110 -j ACCEPT
-A INPUT -p tcp --dport 995 -j ACCEPT
############ IMAP & IMAPS ############
-A INPUT -p tcp --dport 143 -j ACCEPT
-A INPUT -p tcp --dport 993 -j ACCEPT
########### MYSQL ###################
iptables -A INPUT -i eth0 -p tcp -m tcp --dport 3306 -j ACCEPT
########## R1soft CDP System ###############
iptables -A INPUT -p tcp -m tcp -s specific ip --dport 1167 -j ACCEPT
############### outgoing ###################
iptables -I INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
### Allow ongoing, block incoming not defined ###
iptables -P OUTPUT ACCEPT
iptables -P INPUT DROP
iptables -L -n
iptables-save | tee /etc/iptables.test.rules
iptables-restore < /etc/iptables.test.rules
#service iptables restart