ANALYSIS

To better understand the difference between DROP and REJECT, let’s look at three scenarios in detail:

  • Scenario 1: a request to an open port without a service behind it
  • Scenario 2: a request to a port which is blocked by REJECT
  • Scenario 3: a request to a port which is blocked by DROP

The requesting system (the client) is 192.168.99.1, a Linux system with kernel 5.19.0.
The responding system (the server) is 192.168.50.1, operated by Ubuntu 22.04.1 LTS with kernel 5.15.

To generate the request, we use netcat against port 80 of the server. We analyze the communication with Wireshark.

SCENARIO 1: REQUEST TO AN OPEN PORT WITH NO SERVICE BEHIND

nc -v 192.168.50.1 80

Scenario 1: request to an open port without a service behind it
The client sends a tcp handshake packet with the [SYN] flag set. The server responds with a tcp packet in which the flags [RST] and [ACK] are set. There is no service behind the server port that could respond. The client is informed of this by the server with [RST]. The communication is now completed and terminated after one transmitted tcp packet.

SCENARIO 2: REQUEST TO A PORT FIREWALLED BY REJECT

For this scenario we block tcp port 80 on the server with netfilter REJECT:

~# nft flush table inet filter
~# nft add rule inet filter input tcp dport 80 reject
~# nft list ruleset -a
table inet filter {
	chain input {
		type filter hook input priority 0; policy accept;
		tcp dport http reject # handle 4
	}

	chain forward {
		type filter hook forward priority 0; policy accept;
	}

	chain output {
		type filter hook output priority 0; policy accept;
	}
}


We start with our request, as we have done before.

nc -v 192.168.50.1 80

Scenario 2: request to a port, firewalled by REJECT
The client sends a tcp handshake packet with the [SYN] flag set. This time, the server does not respond with a tcp [RST], but with an icmp packet type 3, Code 3 ((Destination unreachable / Port unreachable). The client is informed that the server is actively blocking this port. The communication is terminated after one sent icmp packet.

SCENARIO 3: REQUEST TO A PORT FIREWALLED BY DROP

We are coming to the interesting part. But first, lets prepare our server and block the tcp port 80 with DROP:

~# nft flush table inet filter
~# nft add rule inet filter input tcp dport 80 drop
~# nft list ruleset -a
table inet filter {
	chain input {
		type filter hook input priority 0; policy accept;
		tcp dport http drop # handle 5
	}

	chain forward {
		type filter hook forward priority 0; policy accept;
	}

	chain output {
		type filter hook output priority 0; policy accept;
	}
}


We restart our request and monitor the transmission with Wireshark.

nc -v 192.168.50.1 80

Scenario 3: request to a port firewalled by DROP
The client sends a tcp handshake packet with the [SYN] flag set. The server never responds with anything. Therefore, the client suspects transmission problems and sends the packet again and again. Depending on the operating system, this is continued for up to 240 seconds. Most modern operating systems will stop the request after 120 seconds.

CONCLUSION

As we can see, using the DROP method is the least efficient way to handle incoming requests. The long timeout for retransmission and the unnecessary data sent can add up to a reasonable network load. Especially if the DROP rule is applied to common ports like HTTPS.

There is no information hiding advantage to DROP, if the server provides at least one public service. You may be able to get all tcp-specific information from this single open port. Admittedly, reflection attacks are possible if DROP is not used, but again, attacks of this kind would work with any open port for any public service on the server.

If the server offers public services, we recommend using REJECT for common high traffic ports and DROP for everything else.