iptables: How to configure the Linux firewall to protect your server

iptables: How to configure the Linux firewall

iptables is the firewall used on Linux-based operating systems. Although in recent years we have nftables installed by default, you can still use the iptables syntax to configure the firewall in our operating system, such as Debian, Ubuntu and even the firewall of the router if it is based on Linux. Knowing iptables is very important to keep our local network protected from intrusions, this is because iptables will give us the possibility to allow or deny the traffic that we want. Today in this article we are going to explain how iptables works, and advanced usage examples.

Main features of iptables

iptables is software that is responsible for acting as a firewall or firewall on our network. It is a very important part of operating systems, and it is specifically designed to allow authorized access and block unauthorized access. A firewall establishes a point of control, both incoming and outgoing packets. In addition, it is very important to indicate that a firewall protects from traffic that crosses different networks, but it does not protect the local network from attacks that occur within the same subnet. .

iptables is the firewall included in Linux systems since version 2.4, therefore it is built-in by default in systems like Debian, Ubuntu, Linux Mint and many others, although currently nftables is used internally, because iptables is considered old, although today iptables is still widely used in the world of Linux system administration and also in the world of network administration.

This firewall has several tables created by default, with the aim of greatly facilitating the possibility of adding different chains and rules. A very important detail is that by default we have everything set to “accept”, that is, all traffic is allowed, there is no rule to deny traffic, therefore, at first this firewall is permissive, but we can change the default policy very easily and quickly.

Once we know the main characteristics, we are going to show you the operation and architecture of this firewall.

Operation and architecture

This firewall is based on rules that we will introduce one after another, its operation is based on applying rules that the firewall itself is responsible for executing. Although iptables may seem simple to use at first, if you want to do it in an advanced way, it is more complicated. Next, you can see a summary scheme of how iptables works.

The iptables structure is based on tables, many of which are already created by default. Inside the tables we have the strings, which we also have some created by default. Finally, inside the chains we have the different rules that we can configure. In the following photo you can see a small scheme of what the architecture of the firewall would look like:

By default we have a total of four tables:

  • filter table : it is the default table, if we do not define a table to add a rule, it will always go to the filter table. In this table we have a total of three default chains, depending on what interests us, we will have to use one chain or another: INPUT (these are the packets in the incoming direction, to the firewall itself), OUTPUT (they are the outgoing packets, from the server out), and FORWARD (used to filter packets going from one network interface to another).
  • Nat table: this table is responsible for doing the NAT, transforming the private IP into public and vice versa. Within NAT we have three chains: PREROUTING (alters packets before routing them, here DNAT or port forwarding is done), POSTROUTING (alters packets after routing them, here SNAT or MASQUERADE is done) and OUTPUT (packets generated by the firewall that the configured NAT will traverse).
  • Mangle table: this table is responsible for altering packets, it is where QoS is configured for quality of service, altering TCP headers, etc. In this table we have the five chains: PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING.
  • raw table – This table is not often used because packets travel without connection state. We have the chain PREROUTING and OUTPUT.

In the following image you can see a small summary of the chains that we have in the different tables:

The operation when adding a rule is as follows:

  • The rules that we add to the chains always have a target (-j in the rule).
  • When the firewall receives a packet, it checks if the packet matches a rule that we have enlisted. If it matches, the target command is executed, otherwise, it goes to the next rule until the end of the chain.
  • The rules are checked in a sequential order, from the first rule to the last. The order is very important, if we block everything first and then allow something more specific, we will block all traffic and the most specific rule will not be checked.
  • In the event that no rule satisfies the packet, then the policy of the chain that we have (global rule) will be used.

The objectives of the different rules are the following:

  • ACCEPT: accepts the packet and passes it to the next level, a web server, SSH, FTP etc.
  • DROP: blocks the packet and does not pass it to the next level.
  • QUEUE: is a special target, which passes the packet in a queue intended for user space processing. This can be used to run other external programs.
  • RETURN: has the same effect as if we had reached the end of the chain. If the rule was in one of the default chains, then the chain’s policy is executed. For a rule that is in a user-defined chain, it is exited, continuing through the chain before the jump, just after the rule it was jumped with.

Once we know how it works and its architecture, we are going to see different commands to carry out different actions.

 

Essential commands to use iptables

The first thing that we must take into account when configuring this firewall is that we need superuser permissions to carry out the different orders. It is absolutely necessary for them to run, otherwise it won’t work. The following commands do not have “sudo” because we assume that you are already superuser (sudo su).

In the latest versions of Linux it is not possible to stop the iptables service, in order to allow all network traffic and leave the firewall with the default parameters, we have to execute the following commands:

  • sudo iptables -F
  • sudo iptables -X
  • sudo iptables -t nat -F
  • sudo iptables -t nat -X
  • sudo iptables -t mangle -F
  • sudo iptables -t mangle -X
  • sudo iptables -P INPUT ACCEPT
  • sudo iptables -P FORWARD ACCEPT
  • sudo iptables -P OUTPUT ACCEPT

Once we have done this, we will have the firewall “reset” and allow everything. Now that we know how to reset it, let’s see the different commands.

 

View current tables

If you want to see the content of the different chains and rules that we have in a certain table, then you can see what they would look like:

  • iptables -t filter –list
  • iptables -t mangle –list
  • iptables -t nat –list
  • iptables -t raw –list

 

Main arguments and what they are for

  • -t, –table table Select the table we want
  • -A, –append chain rule-specification We add a new rule in a certain chain
  • -C, –check chain rule-specification We check that there is a certain rule in a certain chain
  • -D, –delete chain rule-specification We delete the rule that we put in a certain chain
  • -D, –delete chain rulenum We delete the rule number X in a certain chain
  • -I, –insert chain [rulenum] rule-specification We insert a new chain with a number in a certain table
  • -R, –replace chain rulenum rule-specification Replaces a given chain in a table, used to move the number.
  • -L, –list [chain] Show the list of rules of a chain
  • -F, –flush [chain] Flush all rules from a given chain.
  • -Z, –zero [chain [rulenum]] Sets the counters of a given rule to 0.
  • -N, –new-chain chain We create a new chain in a certain table
  • -X, –delete-chain [chain] We delete a certain chain (empty) in a certain table
  • -P, –policy chain target We apply the default policy, it is fulfilled when no rule of the chains is fulfilled.
  • -E, –rename-chain old-chain new-chain Rename a previously added chain
  • -h, show help
  • -v, –verbose Output used in conjunction with –L, to display more information than the –L command provides.
  • -n, –numeric IP addresses and port numbers will appear as numbers. For example, if we filter port 80, with the typical –L www will appear, and not 80.
  • -x, –exact Show the exact value of the packet and byte counter, instead of using K, M, or G for the values.
  • –line-numbers When showing the list of rules, it will show the exact number of the rule. Ideal for using –D and the number (delete) or –I to introduce before or after said rule.

 

Main conditions

  • -p , –protocol protocol. Filter the packet by protocol, the specified protocol can be: tcp, udp, Idplite, icmp, esp, ah, sctp.
  • -s , –source address[/mask][,…] Source IP address of the packet. We can have an IP or a subnet (indicating the mask in CIDR format). We can also put host names (domains, websites etc), but it is a bad idea because it is not efficient. Multiple source addresses can be specified, (192.168.1.1,192.168.1.2) but it will create different rules to satisfy them.
  • -d , –destination address[/mask][,…] Destination IP address of the packet. It behaves exactly like -s.
  • -m , –match match. Specifies if we want to call the extended modules of iptables, to perform certain actions such as:
    • Put multiple source and destination ports (multiport module).
    • Control connections (conntrack module).
    • Avoid brute force (recent module, ideal for SSH).
    • Limit the number of connections (modulo limit and connlimit).
    • IP address range (iprange).
  • -j , –jump target. Specifies the objective of the rule, if we want to accept, deny and even forward the packet to another chain for further treatment. Always in any rule we will have a -j to tell it what we want to do. If we don’t add a –j, the rule will be added and it will count the packets, but it won’t do anything. If we use -j to forward to another chain, once the other chain has finished, it will return to the original.
  • -g , –goto chain. It is used to forward the traffic to another chain, but unlike jump, it will not go back to the original chain where it came in.
  • -i , –in-interface name. Name of the interface through which a packet is received. It only works for input strings like INPUT, FORWARD, and PREROUTING. If we put It means all but that interface. If we put a + at the end of the name, any interface with the beginning of the name will grab it for checking. Let’s imagine eth0, eth1 and eth2. If we want to put all three, simply putting eth+ is enough.
  • -o , –out-interface name. Name of the interface through which a packet leaves. It is only valid for output strings such as OUTPUT, FORWARD, and POSTROUTING.

 

Conditions only if you use TCP or UDP

If you use the TCP or UDP protocol, you may want to filter by source and/or destination port number, then you have the two arguments that you can use:

  • –sport –source-port. Select source ports to allow or deny. If we use ! excludes.
  • –dport –destination-port. Select destination ports to allow or deny. If we use ! excludes.

There are many more conditions for an advanced configuration of the firewall, but we have already listed the elementary ones.

 

Set the default policy

Policies are used so that when a rule is not found within the chain, the default policy is executed. The default policy for all chains is ACCEPT, but there are two options: ACCEPT or DROP

-P, –policy chain target

Examples:

  • iptables -P INPUT DROP
  • iptables -P FORWARD DROP
  • iptables -P OUTPUT DROP

With this we will run out of internet, so next we must start creating permissive rules.

Below, you can see all the policies we have in the different tables:

  • iptables -t filter -P (INPUT | OUTPUT | FORWARD) (ACCEPT | DROP)
  • iptables -P (INPUT | OUTPUT | FORWARD) (ACCEPT | DROP)
  • iptables -t mangle -P (INPUT | OUTPUT | FORWARD | PREROUTING | POSTROUTING) (ACCEPT | DROP)

 

View firewall status

The -L parameter shows the rules that we have configured. V allows you to receive more information about the connections and N returns the IP addresses and their corresponding ports without going through a DNS server.

  • iptables -L -n -v

This is one of the most important commands to see the status of the firewall.

 

Modules (-m match) of iptables

 

multi-port

It is an extension of iptables that gives us the possibility of grouping similar rules with different TCP and UDP ports in one. Multiport allows you to put several ports skipped, and also several ports in a row, the maximum is 15 port arguments. Example:

  • iptables –A INPUT –p tcp –m multiport –dports 80,81,1000:1200 –j ACCEPT

Thanks to this module, we have the possibility to use several ports in the same rule.

 

iprange

iprange allows us to put several source or destination IP addresses at once, without the need to put dozens of rules. It also allows you to put both source and destination IP, the syntax is as follows:

  • [!]–src-range ip-ip
  • [!]–dst-range ip-ip

The operation of this rule is quite simple, we simply put the start IP and the end IP.

 

Limit

The connlimit module is responsible for restricting the number of simultaneous connections made by an IP address, it is ideal for limiting the number of connections to avoid DoS.

  • –connlimit-upto n . We check if the number of connections is equal to or less than N (then we can allow or deny).
  • –connlimit-above n . We check if the number of connections is greater than N (then we can allow or deny).
  • –connlimit-mask prefix_length . We mark by subnet range (it is the same as a host making 2 connections, two hosts on the same subnet making 1 connection each).
  • –connlimit-saddr . Apply the limitation to the source group, it is the default if nothing is specified.
  • –connlimit-daddr . Applies the limitation to the target group.

For example, let’s say we want to allow only two SSH connections per client:

  • iptables -A INPUT -p tcp –dport 22 -m connlimit –connlimit-above 2 -j DROP

However, we can make the complementary rule, putting an accept up to 2 connections.

 

conntrack

This module is used to track the connections, it is used to manage the input and output of packets before and after the establishment of the connection. Within this module there are several options, but the most important is -ctstate which allows us to accept or deny different types of packets. Within ctstate we have several states, the following stand out:

  • INVALID: The packet received is invalid and does not belong to any connection.
  • NEW: New connections that are made, or that is associated with a connection that is not yet bidirectional.
  • ESTABLISHED: Established connections, they go through NEW first since they have had a response
  • RELATED: A packet that is related to, but is not part of, an existing connection, such as passive FTP.

Let’s imagine that we want to access any site, however, we do not want absolutely no one to access us.

  • iptables –P INPUT DROP
  • iptables -A INPUT -m conntrack –ctstate ESTABLISHED,RELATED -j ACCEPT

 

Limit

The limit module allows us to limit both traffic and the number of logs to write to the syslog as connection attempts. It has two main arguments:

  • –limit N . This argument specifies the maximum number of average matches per second (N/s), minute (N/m), hour (N/h), or day (N/d) to allow. N specifies the number
  • –limit-burst N . Indicates the longest burst that can occur before checking the limit –limit.

The default value if nothing is specified is 3 matches per hour, in bursts of 5. Imagine the following rule: “iptables -A INPUT -m limit -j LOG”, the operation is as follows:

  • The first time this rule is hit, the first five packets are logged.
  • Afterwards, it will be twenty minutes before a packet is re-registered with this rule (3 matches between 60 minutes equals 20 minutes, since it is AVERAGE).
  • Also, every twenty minutes that passes without a packet reaching the rule, the burst will retrieve a packet.
  • If nothing happens for 100 minutes, the burst will be fully recharged; then back to the initial situation.

 

Recent

The recent module is used to limit the number of connections per second at the IP level, this is ideal to protect us from attacks on the SSH port because an attacker will try multiple passwords. For example, if we want to protect our SSH, we could run the following rule:

  • iptables -A INPUT -p tcp –dport 22 -m conntrack –ctstate NEW -m recent –set –name ssh –rsource
  • iptables -A INPUT -p tcp –dport 22 -m state –state NEW -m recent –rcheck –seconds 60 –hitcount 4 –name ssh –rsource -j DROP

This rule allows only four connection attempts within 60 seconds, it is a “sliding” window.

 

NAT

This firewall is also responsible for NATing our connection. To make the NAT of our public IP (or interface that has this public IP), we must put:

  • Static SNAT: iptables -t nat -A POSTROUTING -s 192.168.1.0/24 –o eth1 -j SNAT –to IP_eth1
  • Dynamic SNAT: iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 -j MASQUERADE

The normal thing is to use MASQUERADE to do NAT regardless of the IP address that the physical or logical interface has.

To open ports we have to add a rule in the PREROUTING chain of the NAT table.

  • iptables -t nat -A PREROUTING -i eth1 -p tcp –dport 22 -j DNAT –to-destination 192.168.1.1

The PREROUTING table also allows us to modify the ports on the fly, so that if we receive packets on port 2121, we can transform it to 21.

  • iptables -t nat -A PREROUTING -i eth1 -p tcp –dport 2121 -j DNAT –to-destination 192.168.1.1:21

Once we know this firewall in detail, we are going to see the basic examples of use and also the most advanced ones.

 

Basic usage examples

This firewall is very complete and we have hundreds of commands that we can execute to perform different actions. In this article we are going to give you some easy-to-understand examples for a first approach to this firewall.

Block the IP address 192.168.1.10 from making any communication to our server:

  • iptables -A INPUT –s 192.168.1.10 –j DROP

Block IP addresses 192.168.1.20, 192.168.1.30, 192.168.1.40, 192.168.1.50 from making any communication to our server:

  • iptables -A INPUT –s 192.168.1.20,192.168.1.30,192.168.1.40,192.168.1.50 –j DROP

Block the entire 192.168.2.0/24 subnet from making any communication to our server, except for the 192.168.2.20 IP address, which would be allowed:

  • iptables –A INPUT –s 192.168.2.20 –j ACCEPT
  • iptables –A INPUT –s 192.168.2.0/24 –j DROP

Block the IP address of 192.168.4.50 so that we cannot make any communication:

  • iptables –A OUTPUT –d 192.168.4.50 –j DROP

Block the IP addresses 192.168.4.51 and 192.168.4.52 so that we cannot make any communication:

  • iptables –A OUTPUT –d 192.168.4.51,192.168.4.52 –j DROP

Block access to www.google.es from iptables:

  • iptables –A OUTPUT –d www.google.es –j DROP

We want to block access to our server from the MAC 00:01:02:03:04:05, and the rest allow everything:

  • iptables -A INPUT -m mac –mac-source 00:01:02:03:04:05 -j DROP

We want to allow access to our server to the MAC address MAC 00:01:02:03:04:06, and the rest deny everything:

  • iptables -A INPUT -m mac –mac-source 00:01:02:03:04:05 -j ACCEPT
    iptables -A INPUT -j DROP

Block the IP address 192.168.1.10 for pinging from our our server:

  • iptables -A INPUT -s 192.168.1.10 -p icmp -j DROP

Block IP addresses 192.168.1.20, 192.168.1.30, 192.168.1.40, 192.168.1.50 from PINGing our server (in a single rule):

  • iptables -A INPUT -s 192.168.1.20,192.168.1.30,192.168.1.40,192.168.1.50 -p icmp -j DROP

Block the entire 192.168.2.0/24 subnet so that they do not PING our server, except for the IP address 192.168.2.20, which would be allowed:

  • iptables -A INPUT -s 192.168.2.20 -p icmp -j ACCEPT
    iptables -A INPUT -s 192.168.2.0/24 -p icmp -j DROP

Block the IP address of 192.168.4.50 so that we cannot ping it.

  • iptables -A OUTPUT -d 192.168.4.50 -p icmp -j DROP

Block the IP addresses 192.168.4.51 and 192.168.4.52 so that we cannot ping them.

  • iptables -A OUTPUT -d 192.168.4.51,192.168.4.52 -p icmp -j DROP

Block access to www.google.es from iptables.

  • iptables -A OUTPUT -d www.google.es -p icmp -j DROP

As you can see, the operation is quite simple with the rules based on IP with origin and destination. We could also use the iprange module to configure a range of IPs:

Block a range of IP addresses from 192.168.5.1 to 192.168.5.50 from being able to ping from our server.

  • iptables -A OUTPUT -m iprange –dst-range 192.168.5.1-192.168.5.50 -p icmp -j DROP

We can also filter the ICMP protocol in a more advanced way. Let’s imagine we have a user who wants to be able to ping any host, but doesn’t want ANYONE to be able to ping him. How can we do it with iptables if PING itself has bidirectional communication?

  • iptables -A INPUT -s IP -p icmp –icmp-type echo-request -j DROP

Block any incoming access through the eth0 interface (only), thus allowing eth1 access.

  • iptables -A INPUT -i eth0 -j DROP
  • iptables -A INPUT -i eth1 -j ACCEPT

Block outgoing traffic on the eth0 interface (only), thus allowing eth1 access.

  • iptables -A OUTPUT -o eth0 -j DROP
  • iptables -A OUTPUT -o eth1 -j ACCEPT

Allow any incoming and outgoing traffic on eth0, and deny any incoming or outgoing traffic on eth1.

  • iptables -A INPUT -i eth0 -j ACCEPT
  • iptables -A OUTPUT -o eth0 -j ACCEPT
  • iptables -A INPUT -i eth1 -j DROP
  • iptables -A OUTPUT -o eth1 -j DROP

If you want to start seeing how the TCP and UDP protocol works, here are some examples:

Block web access to www.google.es and allow everything else (ping) for example.

  • iptables -A OUTPUT -d www.google.es -p tcp –dport 80 -j DROP

Block FTP access to any IP or domain, and allow everything else.

  • iptables -A OUTPUT -p tcp –dport 21 -j DROP

Block SSH access to IP 192.168.1.50, and allow everything else.

  • iptables -A OUTPUT -d 192.168.1.50 -p tcp –dport 22 -j DROP

Block Telnet access to the 192.168.2.0 subnet, and allow everything else.

  • iptables -A OUTPUT -d 192.168.2.0/24 -p tcp –dport 23 -j DROP

Block 192.168.1.50 access to our web server.

  • iptables -A INPUT -s 192.168.1.50 -p tcp –dport 80 -j DROP

Block 192.168.1.150 and 192.168.1.151 access to our SSH server.

  • iptables -A INPUT -s 192.168.1.150,192.168.1.151 -p tcp –dport 22 -j DROP

Block access of the entire 192.168.2.0/24 subnet to our telnet service

  • iptables -A INPUT -s 192.168.2.0/24 -p tcp –dport 23 -j DROP

Block everyone’s access to the OpenVPN server, except for the IP address 77.77.77.77 which is allowed.

  • iptables -A INPUT -s 77.77.77.77 -p tcp –dport 1194 -j ACCEPT
  • iptables -A INPUT -p tcp –dport 1194 -j DROP

Block DNS access to 8.8.8.8 and allow everything else (ping) for example.

  • iptables -A OUTPUT -d 8.8.8.8 -p tcp –dport 53 -j DROP
  • iptables -A OUTPUT -d 8.8.8.8 -p udp –dport 53 -j DROP

Block access to port 1194 to any IP or domain, and allow everything else.

  • iptables -A INPUT -p udp –dport 1194 -j DROP

We have a DNS server on our server. We want only computers on the 192.168.1.0/24 subnet to be able to communicate with it, and block all other access.

  • iptables -A INPUT -s 192.168.1.0/24 -p tcp –dport 53 -j ACCEPT
  • iptables -A INPUT -s 192.168.1.0/24 -p udp –dport 53 -j ACCEPT
  • iptables -A INPUT -p tcp –dport 53 -j DROP
  • iptables -A INPUT -p udp –dport 53 -j DROP

Block access to our web server, from the IP range 192.168.100.0/24, coming from the eth0 interface.

  • iptables -A INPUT -s 192.168.100.0/24 -i eth0 -p tcp –dport 80 -j DROP

Block access to our ssh server, from the IP range 192.168.100.0/24, coming from the eth1 interface.

  • iptables -A INPUT -s 192.168.100.0/24 -i eth1 -p tcp –dport 22 -j DROP

 

Advanced Usage Examples

If you want to learn more about iptables, here are some examples where we make use of the connlimit module.

Allow only 10 Telnet connections per client.

  • iptables -A INPUT -p tcp –dport 23 -m connlimit –connlimit-above 10 –connlimit-mask 32 -j DROP

Deny up to connection number 5 on the web made by a client (it doesn’t make much sense but it’s an example).

  • iptables -A INPUT -p tcp –dport 80 -m connlimit –connlimit-upto 5 –connlimit-mask 32 -j DROP

Allow only 10 Telnet connections per client (do it differently than above).

  • iptables -A INPUT -p tcp –dport 23 -m connlimit –connlimit-upto 10 –connlimit-mask 32 -j ACCEPT
  • iptables -A INPUT -p tcp –dport 23 -j DROP

Only allow 10 web connections in the 10.0.0.0/8 IP range, and deny if it exceeds this number.

  • iptables -A INPUT -s 10.0.0.0/8 -p tcp –dport 80 -m connlimit –connlimit-above 10 –connlimit-mask 8 -j DROP

Allow only 20 HTTP connections for each client, as soon as it is exceeded we send a TCP Reset.

  • iptables -A INPUT -p tcp –dport 80 -m connlimit –connlimit-above 20 –connlimit-mask 32 -j REJECT –reject-with tcp-reset

Or this way:

  • iptables -A INPUT -p tcp –syn –dport 80 -m connlimit –connlimit-above 20 –connlimit-mask 32 -j REJECT –reject-with tcp-reset

As you can see, this firewall is really complete and we can do a lot of very advanced configuration, to control all incoming and outgoing connections in detail.