Drop versus Reject

Background

Many people advocate configuring packet filters with a mostly-closed policies that drop packets that they do not know to be safe. This leads to problems for users that are hard for them to diagnose while offering no additional security.

When a packet reaches the firewall, it is run against a set of rules. These rules may rely on existing state (eg. to match existing or related connections) or be stateless (eg. to match destination port 80). The rules determine an action to take for the packet, which can be one of:

ALLOW (aka ACCEPT)
Pemit a packet to traverse the firewall. This would be the behaviour if the firewall was not present.
REJECT
Prohibit a packet from passing. Send an ICMP destination-unreachable back to the source host [unless the icmp would not normally be permitted, eg. if it is to/from the broadcast address].
DROP (aka DENY, BLACKHOLE)
Prohibit a packet from passing. Send no response.

In the rules there is a choice of whether to REJECT or to DROP unwanted packets.When analysing this choice, we must consider negative and positive features for legitimate and illegitimate applications.

The big difference between REJECT and DROP is that REJECT results in an ICMP error being returned. What is this for? Let's look at excerpts from relevant standards document, STD0003 (RFC1122):

         3.2.2.1  Destination Unreachable: RFC-792

                  A Destination Unreachable message that is received MUST be
            reported to the transport layer.  The transport layer SHOULD
            use the information appropriately; for example, see Sections
            4.1.3.3, 4.2.3.9, and 4.2.4 below.  A transport protocol
            that has its own mechanism for notifying the sender that a
            port is unreachable (e.g., TCP, which sends RST segments)
            MUST nevertheless accept an ICMP Port Unreachable for the
            same purpose.
     
         4.2.3.9  ICMP Messages
 
            TCP MUST act on an ICMP error message passed up from the IP
            layer, directing it to the connection that created the
            error.  The necessary demultiplexing information can be
            found in the IP header contained within the ICMP message.

            o    Destination Unreachable -- codes 2-4
 
                 These are hard error conditions, so TCP SHOULD abort
                 the connection.
      

Legitimate users

Let's consider the user first:

By REJECTing unknown packets, TCP aborts the connection andthe application gets to know that the connection has failed after just one round-trip time. This allows the application attempting the connection to notify the user straight away.

DROPping the packet will just cause TCP to retry the connection until the threshold for retranmission is exceeded. This should be at least 100 seconds.

An experiment on Linux gives 0.01seconds for a REJECT to give an application error from a TCP connection, but 189 seconds for DROP.

Hostile users

Now let's consider hostile forces:

A common reason for using DROP rather than REJECT is to avoid giving away information about which ports are open, however, discarding packets gives away exactly as much information as the rejection.

With REJECT, you do your scan and categorise the results into "connection established" and "connection rejected".

With DROP, you categorise the results into "connection established" and "connection timed out".

The most trivial scanner will use the operating system "connect" call and will wait until one connection attempt is completed before starting on the next. This type of scanner will be slowed down considerably by dropping packets. However, if the attack sets a timeout of 5 seconds per connection attempt, it is possible to scan every reserved port (1..1023) on a machine in just 1.5 hours. Scans are always automated, and an attacker doesn't care that the result isn't immediate.

A more sophisticated scanner will send packets itself rather than relying on the operating system's TCP implementation. Such scanners are fast, efficient and indifferent to the choice of REJECT or DROP.

Hiding information about which ports are active requires making the server response indentical whether or not it offers a particular service. This is technically very difficult, and in some cases will be more error prone than actually providing the service!

Realistically, you could probably get away with accepting the connection for unknown ports, blackholing the data, then closing the connection after a timeout. However, that will cause problems with legitimate users if their application makes a connection to one of these ports.

Summary

REJECT DROP
Application connects to non-existent service Failure reported promptly to the user Applications pause for ages, then fail
Naïve network scanning with OS "connect" Scans are quick Scans are okay, provided that a timeout is set
Network scanning with a specialist program (eg. nmap) Scans are quick Scans are quick

Conclusion

DROP offers no effective barrier to hostile forces but can dramatically slow down applications run by legitimate users. DROP should not normally be used.

Update:

Sean Taylor emailed with an interesting counterposition:

A very thought provoking discussion. One scenario where drop has a significant advantage is if you are victim of a denial of service attack and have a highly asymmetric data connection (much faster download than upload) as is the case with DSL.

In this case dropping helps because the attacker may not overwhelm your download, but the ICMP responses may overwhelm your upload speed, meaning you will not be able to remotely log in and manage your network under attack, and legitimate traffic is completely blocked.

I'm sure there are more sophisticated ways to manage denial of service, but as part time admin. of a very small server with woeful uplink speed denial of service is the biggest problem I face these days.


Valid HTML 4.01! Valid CSS!

Peter Benie <peterb@chiark.greenend.org.uk>
Network