> ## Content Index
> Fetch the complete content index at: https://blog.alphavps.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Iptables Essentials: The Ultimate Linux Firewall Configuration Guide
- URL: https://blog.alphavps.com/iptables-essentials-the-ultimate-linux-firewall-configuration-guide/
- Published: 2023-04-24T12:41:06.000Z
- Updated: 2026-03-09T10:47:25.000Z
- Author: Vladislav Peev
- Tags: Tutorials, Security, #series-linux-firewalls

**Iptables** is a powerful tool for managing network security on Linux systems. It allows you to filter and control the flow of your server's incoming and outgoing network traffic. It provides you with a layer of protection against unauthorized access and malicious attacks.

For this tutorial, we are going to use an AlmaLinux 8 VPS with a created sudo user.

---

## Core Concepts

**Iptables** organizes its rules into chains. Chains are sequences of rules that are executed in order. Each chain is associated with a specific type of traffic, such as incoming or outgoing traffic.

Each chain consists of a set of rules. A rule specifies the conditions under which it should be applied and the action to take for the related incoming or outgoing traffic when those conditions are met.

**Iptables** uses tables to organize its chains. Each table is associated with a specific type of traffic, such as TCP or UDP traffic.

**Iptables** defines three chains by default.

- **INPUT**: All packets that are addressed to your server.
- **OUTPUT**: All packets that are sent from your server.
- **FORWARD**: All traffic destined for other servers that is not created on your server.

**Iptables** also allows you to set default policies for each chain. These policies specify the action to take when traffic does not match any of the rules in the chain.

### IPv4 & IPv6

`iptables` only handles IPv4 traffic. For IPv6 traffic, you can use the `ip6tables` utility.

---

## Installing Iptables

In most cases, **Iptables** is already installed on your Linux system by default.  
To check if **Iptables** is installed on your Linux system, you can run the following command:

```
sudo iptables --version
```

If it is available on your system, you should receive a similar output:

```
iptables v1.8.4 (nf_tables)

```

Alternatively, it can be installed via the following commands:

### Debian/Ubuntu

```
sudo apt-get install iptables

```

### CentOS/Alma/Rocky

```
sudo yum install iptables
```

After installation, you can check the status of **Iptables** by running:

```
systemctl status iptables
```

You can start and enable **Iptables** by running:

```
systemctl start iptables
systemctl enable iptables
```

If you wish to stop and disable it, you can run:

```
sudo systemctl stop iptables
sudo systemctl disable iptables
```

---

## Persisting Iptables rules  

### Debian/Ubuntu

To save your rules and have them automatically applied at boot, you will need to install the Persistent Firewall Service.  
This can be done by running the following commands:

```
sudo apt update
sudo apt install iptables-persistent
```

You can now save your rules via the following command:

```
sudo /etc/init.d/iptables-persistent save
```

### CentOS/Alma/Rocky

For RHEL-based distributions, a similar service is provided - **Iptables Services.**  
It can be installed with the following commands:

```
sudo dnf update
sudo dnf install iptables-services
```

You can also run these commands with the `yum` package manager.

```
sudo yum update
sudo yum install iptables-services

```

After it is installed, you can now save your rules by running:

```
sudo /sbin/iptables-save > /etc/sysconfig/iptables
```

---

## Listing Rules

You can check your active firewall rules with the following commands:

**Listing by specification**

```
sudo iptables -S
```

Output:

```
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

```

The default policy for all of your chains will be to allow all incoming connections.

**Listing rules as tables**

```
sudo iptables -L
```

Output:

```
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

```

---

## Setting default policies

In **Iptables**, default policies are used to determine what action should be taken for traffic that does not match any of the rules in a given chain. 

The default policy can be set to one of the following actions:

- **ACCEPT**: Accept the traffic and let it pass through the chain.
- **DROP**: Drop the traffic without sending any response back to the source.
- **REJECT**: Reject the traffic and send an error response back to the source.

When traffic enters a chain, **Iptables** evaluates each rule in the chain in the order they are defined until it finds a rule that matches the traffic. If no rule matches the traffic, then the default policy for that chain is applied.

To set the default policy of a specific chain, you can use the command below and substitute the policy and chain names:

```
iptables -P "chain-name-here" "policy-name-here"
```

An example command is:

```
iptables -P INPUT DROP
```

NOTE: Setting the default policy for your INPUT chain to DROP is a common and secure practice. It is recommended to set it so, but in advance, you will need to specify rules, which allow incoming connection from trusted sources, for example, a specific IP or subnet. This way you will ensure that you will not lock yourself out of the VPS by setting the default policy for the INPUT chain directly to DROP.

---

## Setting rules  

To set **Iptables** rules, you can use the following generic command:

```
iptables -A "chain-name-here" [options] -j <target>

```

You will need to specify the name of the chain you want to add the rule to, `[options]` are the match criteria you want to use to filter traffic, and `<target>` is the action to take for the matching traffic.

Some common options that can be used to specify the match criteria are:

- `-s <source>`: Match traffic from a specific source IP address or network.
- `-d <destination>`: Match traffic to a specific destination IP address or network.
- `-p <protocol>`: Match traffic with a specific protocol, such as TCP or UDP.
- `--dport <port>`: Match traffic with a specific destination port.
- `--sport <port>`: Match traffic with a specific source port.

  
You will notice the `-A` flag added just after `iptables`.  
The `-A` and `-I` options in **Iptables** are used to add rules to a chain, but they differ in how they add the rule to the chain.

The `-A` option adds the rule to the end of the chain, which means it will be evaluated after all the existing rules in the chain. This is useful for appending rules to a chain when you want to add a new rule without disturbing the existing rules.

The `-I` option, on the other hand, inserts the rule at a specific position in the chain. You can specify the position by using an index number, where 1 is the first rule in the chain, 2 is the second rule, and so on. This is useful when you want to add a new rule at a specific position in the chain.

Some real example commands are:

```
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -I INPUT 2 -p tcp --dport 22 -j ACCEPT

```

The first command allows incoming connections on port 80 /HTTP/ and appends the rule at the end of the chain.

The second command allows incoming ssh connection on the default ssh port /22/. The rule is inserted at the second position via the `-I 2` options. If the position is not specified, it will default to `1`.

---

## Common commands

###   
Allowing Loopback connections

Loopback connections are used for communication between processes running on the same host. By allowing loopback connections, you can enable important services and applications that rely on loopback communication to function properly.

You can allow them with the following commands:

```
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT
```

### Allowing Established and Related connections

When a new connection is established, it consists of both incoming and outgoing traffic. The incoming traffic is a response to outgoing traffic that was sent by the system initiating the connection.

- **Incoming connections**

By allowing established and related incoming connections, you can enable responses to return to the initiating system and complete the connection.

You can enable incoming connections with the following command:

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

- **Outgoing connections**

By allowing established and related outgoing connections, you can enable the system to initiate new connections and communicate with other machines on the internet.

You can enable outgoing connections with the following command:

```
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
```

### Dropping Invalid Packets

Dropping invalid packets is an important security measure that can help protect your system. Invalid packets are packets that do not match any known or expected protocol or do not have valid header information.

You can do this by running:

```
sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

```

### Blocking specific connections

You can block connections from specific IP addresses or whole subnets in **Iptables** by creating rules that match traffic from those addresses or subnets. You can either **DROP** it or **REJECT** it.

**NOTE**: These rules are necessary only if you have left your default policies to ACCEPT, which is not the recommended way. A common practice is to set your default policies to REJECT/DROP and instead allow access from trusted sources. You can set the default policy of the INPUT chain to DROP with the following command:

```
iptables -P INPUT DROP
```

- **Block incoming connections from a specific IP address:**

```
sudo iptables -A INPUT -s "ip-address-here" -j DROP
```

or

```
sudo iptables -A INPUT -s "ip-address-here" -j REJECT
```

- **Blocking incoming connection to a specific network interface:**

```
iptables -A INPUT -i eth0 -s "ip-address-here" -j DROP
```

- **Block traffic from a specific subnet**:

```
iptables -A INPUT -s "ip-address-subnet-here"/"prefix-length" -j DROP
```

or

```
iptables -A INPUT -s "ip-address-subnet-here"/"prefix-length" -j REJECT
```

- **Block traffic to a specific port**

```
iptables -A INPUT -p tcp --dport "port-number-here" -j DROP
```

You can also block traffic to a port only for a specific IP address or subnet.

```
iptables -A INPUT -s "ip-address-here" -p tcp --dport "port-number-here" -j DROP
```

- **SSH**

Blocking SSH access is a common security measure to prevent unauthorized access to your system through SSH.

Of course, it's a bad idea to directly block SSH connections - this will sever your connection and lock you out. You will certainly need to take the necessary precautions. You will need to allow incoming SSH connection for a specific IP address or subnet. This can be done with the following commands:

```
iptables -A INPUT -p tcp -s "ip-address-here" --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -s "ip-address-subnet-here"/"prefix-length" --dport 22 -j ACCEPT
```

To block connections, use the following command:

```
iptables -A INPUT -p tcp --dport 22 -j DROP
```

If your SSH service is running on a custom port, simply replace "22" with it.

- **HTTP/HTTPS**

Blocking both HTTP and HTTPS requests can be done by creating rules that block incoming traffic to port 80 and port 443.

It's important to note that blocking HTTP and HTTPS requests can also prevent legitimate users from accessing your website.

Of course, this is a decision that depends on your use case. You most likely will need to specify an IP address or subnet, which be allowed to connect to these ports. You will need to either do this in advance or insert the rule before the DROP rule above (via the -I flag).

```
iptables -A INPUT -p tcp -m multiport --dports 80,443 -s "ip-address-here" -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 80,443 -s "ip-address-subnet-here"/"prefix-length" -j ACCEPT

```

or

```
iptables -I INPUT 1 -p tcp -m multiport --dports 80,443 -s "ip-address-here" -j ACCEPT
iptables -I INPUT 1 -p tcp -m multiport --dports 80,443 -s "ip-address-subnet-here"/"prefix-length" -j ACCEPT
```

Connections can be blocked via:

```
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j DROP
```

### Allowing specific connections

As previously mentioned, an appropriate and secure approach would be to set your default policies to DROP or REJECT and allow connections to either specific ports or from trusted sources - a known IP address or subnet.  
The implementation of this will highly depend on your own requirements.  
You can set the default policy of the INPUT chain to DROP with the following command:

```
iptables -P INPUT DROP
```

- **Allowing incoming connections from a specific IP address:**

```
iptables -I INPUT -s "ip-address-here" -j ACCEPT

```

- **Allow incoming connections from a specific subnet**:

```
iptables -I INPUT -s "ip-address-subnet-here"/"prefix-length" -j ACCEPT
```

- **Allow connections to a specific port**

```
iptables -A INPUT -p tcp --dport "port-number-here" -j ACCEPT
```

- **Allow connections to a specific port only from trusted sources**

```
iptables -A INPUT -s "ip-address-here" -p tcp --dport "port-number-here" -j ACCEPT
iptables -A INPUT -s "ip-address-subnet-here"/"prefix-length" -p tcp --dport "port-number-here" -j ACCEPT
```

- **SSH**

You can allow SSH connection via the following command:

```
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT

```

The second command actually enables outgoing SSH connections for already established connections, which is mandatory if your OUTPUT policy is also set to DROP/REJECT. After all, the connection is two-way communication.

If your SSH port is not the default one, specify it by replacing `22` with it.

It is highly advisable to enable SSH connections only from trusted sources.  
You can do this with these:

 **Specific IP Address**:

```
sudo iptables -A INPUT -p tcp -s "ip-address-here" --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
```

 **Specific Subnet**:

```
sudo iptables -A INPUT -p tcp -s "ip-address-subnet-here"/"prefix-length" --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
```

 **Outgoing SSH**

Outgoing SSH connections can be enabled by running:

```
sudo iptables -A OUTPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT

```

- **HTTP/HTTPS**

You can allow both HTTP and HTTPS traffic by creating a rule that allows both ports (80 & 443):

```
sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate ESTABLISHED -j ACCEPT

```

The second command is only necessary if the OUTPUT chain default policy is set to REJECT or DROP.

**Specific IP Address:**

```
iptables -A INPUT -p tcp -s "ip-address-here" -m multiport --dports 80,443 -j ACCEPT
sudo iptables -A OUTPUT -p tcp -s "ip-address-here" -m multiport --dports 80,443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
```

**Specific Subnet:**

```
iptables -A INPUT -p tcp -s "ip-address-subnet-here"/"prefix-length" -- -m multiport --dports 80,443 -j ACCEPT
sudo iptables -A OUTPUT -p tcp -s "ip-address-subnet-here"/"prefix-length" -- -m multiport --dports 80,443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
```

---

## Deleting rules

**Iptables** rules can be deleted by using the `iptables -D` command. You will need to point out the chain name and the rule specification. 

The rules can be specified in two different ways.  
You can either determine by its specification, for example:

```
sudo iptables -D INPUT -m conntrack --ctstate INVALID -j DROP
```

or you can determine the rule by its rule number.  
An example would be:

```
sudo iptables -D INPUT 2

```

You can determine a rule's number via the following command:

```
sudo iptables -L --line-numbers
```

### Flushing Chains

You are able to delete all rules in a chain by flushing it. 

To flush all chains at once, run the following command:

```
sudo iptables -F

```

To only flush a specific chain, you can specify the chain just after the command above. You can do this by using any of these three:

```
sudo iptables -F INPUT
sudo iptables -F OUTPUT
sudo iptables -F FORWARD

```