1. Overview

iptables is the command-line firewall program in Linux. It uses several policy chains for filtering network traffic. For example, the INPUT chain is for filtering incoming network traffic.

In addition to the policy chains, there are also built-in target rules. These built-in rules give a decision about the packet. The most common built-in target rules are ACCEPT, which lets the packet through, DROP, which filters it out by dropping it, and REJECT, which filters it out by rejecting it.

As we see, the DROP and REJECT target rules are similar to each other. They’re used for filtering out packets.

In this tutorial, we’ll discuss the differences between these two rules.

2. Example Setup

We’ll examine the behavior of REJECT and DROP using two hosts. The hosts are host1 and host2. Their IP addresses are 192.39.59.16 and 192.39.59.17, respectively.

Both hosts have no rules in any of the chains. Let’s verify it on one of the hosts using iptables:

$ iptables -L
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

The –L option of iptables lists the rules of the selected chain. Since we didn’t specify any specific chain, all chains were listed in the output.

We must have root privileges to use iptables.

We’ll use the ping and nc commands to communicate between the hosts.

3. Analysis of REJECT

We’ll examine REJECT using ICMP, TCP, and UDP protocols. First, let’s apply the REJECT rule on host1:

$ iptables –A INPUT –s 192.39.59.17 –j REJECT

The –A option of iptables is for appending rules to the specified chain. In this case, we appended the rule to the input chain using –A INPUT. That means we’re interested in the incoming traffic.

Additionally, the –s 192.39.59.17 part of the command specified that we’re only interested in the incoming traffic from the host with IP address 192.39.59.17. The –s option specifies the source IP address of incoming packets.

Finally, the –j REJECT part of the command implied that we want to apply the REJECT rule to the incoming packets from the host with IP address 192.39.59.17. The –j option specifies what we’ll do for the matching packets.

Since we only changed the rules in the INPUT chain, let’s check only the rules in the INPUT chain using iptables:

$ iptables –L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
REJECT     all  --  192.39.59.17         anywhere             reject-with icmp-port-unreachable

So, we appended the rule to the INPUT chain successfully.

3.1. Behavior in ICMP

Having applied the REJECT rule on host1, let’s ping host1 from host2:

$ ping –c 1 192.39.59.16
PING 192.39.59.16 (192.39.59.16) 56(84) bytes of data.
From 192.39.59.16 icmp_seq=1 Destination Port Unreachable

--- 192.39.59.16 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

We sent only one ICMP echo request to the destination host 192.39.59.16 using –c 1. However, we got a Destination Port Unreachable error immediately. This error indicates that we could reach the destination host, but we didn’t receive an ICMP echo reply. This is because of the REJECT rule we specified on host1.

The Destination Port Unreachable error is the default error for REJECT. It’s possible to change the type of error while appending the rule to the chain using iptables. We must use the –reject-with option of iptables. For example, if we had used the following command with –reject-with icmp-host-prohibited, we’d have received the Destination Host Prohibited error:

$ iptables –A INPUT –s 192.39.59.17 –j REJECT –-reject with icmp-host-prohibited

3.2. Behavior in TCP

We’ll use nc for analyzing the REJECT rule. First, let’s run nc on host1 as a server process:

$ nc –l 1234

The –l option of nc lets us run nc as a server process. It binds and listens for incoming connections on the specified TCP port. The default transport protocol used by nc is TCP. As a result of this command execution, we spawned a process waiting for TCP connections on host1 on port 1234.

Next, let’s run nc on host2:

$ nc 192.39.59.16 1234
Ncat: Connection refused.

Here, we tried to establish a TCP connection with the server process waiting on host1 on port 1234. But, we got a Connection refused error as soon as we ran the command. The behavior is as if there is no server process waiting for input on host1 on port 1234.

3.3. Behavior in UDP

We’ll analyze the behavior of REJECT for UDP protocol using nc. Let’s run nc on host1:

$ nc -u –l 1234

Here, the only difference from the TCP case is the –u option. This option tells nc to use UDP as the transmission protocol. The spawned process started to wait for UDP datagrams on UDP port 1234.

Now, let’s run nc on host2 for sending UDP datagrams to host1. First, we’ll use the –u option to tell nc to use UDP as the transmission protocol. All the other options are the same as the ones in the TCP communication:

$ nc –u 192.39.59.16 1234

This time, we didn’t get an immediate Connection refused error as in the case of TCP. nc waits for input. Now, let’s try to send a message from host2 to host1:

$ nc –u 192.39.59.16 1234
Hello host1
Ncat: Connection refused.

We got a Connection refused error when we tried to send the message Hello host1.

4. Analysis of DROP

Let’s examine DROP using ICMP, TCP, and UDP protocols. First, let’s delete the REJECT rule we had applied before on host1:

$ iptables –D INPUT –s 192.39.59.17 –j REJECT

The –D option of iptables deleted the rule we had previously appended.

Now, let’s apply the DROP rule on host1:

$ iptables –A INPUT –s 192.39.59.17 –j DROP

Let’s check the rules in the INPUT chain after applying DROP:

$ iptables –L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       all  --  192.39.59.17         anywhere

So, we’ve applied the DROP rule successfully.

4.1. Behavior in ICMP

Having applied the DROP rule on host1, let’s ping host1 from host2:

$ ping –c 1 192.39.59.16
PING 192.39.59.16 (192.39.59.16) 56(84) bytes of data.

--- 192.39.59.16 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

We sent only one ICMP request to the destination host 192.39.59.16 using –c 1. In this case, we didn’t get a response to the ICMP request. Our request simply timed out after a while.

4.2. Behavior in TCP

We’ll analyze the behavior of TCP while the DROP rule is in action. Let’s begin by running nc on host1:

$ nc –l 192.39.59.16 1234

As before, we spawned a process waiting for TCP connections on host1 on port 1234.

Now, let’s run nc on host2 again as before and try to send a message to host1:

$ nc 192.39.59.16 1234
Hello host1
Ncat: Connection timed out.

We received a Connection timed out error after a while. The message wasn’t sent to host1, either. The client process wasn’t successful in establishing a connection with the server process waiting on host1.

4.3. Behavior in UDP

We’ll analyze the behavior of UDP while the DROP rule is in action. Let’s run nc on host1 using the –u option in order for nc to use UDP as the underlying protocol:

$ nc –u –l 192.39.59.16 1234

Now, let’s run nc on host2 again using the –u option:

$ nc –u 192.39.59.16 1234

In this case, nothing happens. Both the server process on host1 and the client process on host2 wait. Let’s try to send a message from host2 to host1:

$ nc –u 192.39.59.16 1234
Hello host1

We didn’t get any errors, but the message wasn’t sent to the server on host1, either. The behavior looks as if the sent message was lost in the network.

5. Conclusion

In this article, we discussed the differences between the DROP and REJECT rules while using iptables. We examined them using the INPUT chain.

The REJECT rule immediately rejected the ICMP echo requests with a Destination Port Unreachable error**. On the other hand, for DROP, the ICMP echo request timed out after a while.**

While using TCP, we got an immediate Connection refused error in the case of REJECT. But, we got a Connection timed out error for DROP after a while.

Finally, while using UDP with the REJECT rule enabled, we received a Connection refused error when we tried to send a message from the client process to the server process. However, we didn’t get any errors in the case of DROP when we tried to send a message to the server process.