DROP versus REJECT a packet

Here's a brief overview of how the Linux kernel manages traffic,  being Traffic Shaping, Traffic Scheduling or Traffic Policing and what is the difference from the kernel perspective when dropping or rejecting a packet.

First, here's the difference between the 3:
  • Traffic Shaping - controls the rate of transmission of packets. Shaping can be used to lower the bandwidth  and to smooth out traffic spikes.
  • Traffic Scheduling - is used to reorder packets. This is used to give priority to interactive traffic e.g SSH. 
  • Traffic Policing - controls the arrival of packets. This is achieved by tagging packets so that iptables can act on them for example.
The lower 2 OSI network layers are usually implemented in hardware and the device driver and the rest of the higher layers are implemented in software inside the kernel.

So let's look at what happens when a packet arrives and is received by the NIC:

The NIC's firmware or kernel driver handles all layers 1 and layer 2 requests. Some filtering and error checking/correction can happen at these levels. The kernel generally is not involved much at the Physical and the Link layers. Once the NIC has received the packet it notifies the kernel via an interrupt - IRQ. The kernel uses the NIC device driver to transfer the IP packet from the NIC’s buffers to the host’s memory The packet is placed at the end of a queue (rx_ring) which holds the packet until it can be processed by the kernel. The queue has a maximum size it can grow to. If the queue becomes full all subsequent packets are discarded.  Once the packet is in the queue, it will eventually be processed by the kernel. The packet will be examined and converted to a manageable data structure, for easy access to various fields. Similarly for outgoing packets, after the kernel network code at layer 3 is done the IP packet is placed in an outgoing queue. An IRQ is then sent to the NIC to tell it that a packet is available. When the NIC is ready the packet is processed by the NIC’s device driver at layer 2 and removed from the queue,then loaded into the NIC’s memory

By changing the order of the packets in the queues and by adding a delay before making an outgoing packet available to a NIC the kernel can implement Traffic Shaping and Scheduling. This is available through user-space tools like the iproute2 where using commands like tc and ip one can setup different queuing and scheduling disciplines. I'll demonstrate this in a different article.

When the kernel receives a network packet, being part of an existing connection or not it can take the following 3 actions:

ALLOW/ACCEPT-  Permit a packet to be processes.
REJECT  - Prohibit a packet from passing and send an ICMP destination-unreachable response back to the client.
DROP - Prohibit a packet from passing and do not send a response back to the client.

By REJECT-ing a packet, TCP aborts the connection by sending a RST packet back, and the client application knows that the connection has failed after just one round-trip time. This allows the application attempting the connection to act on that reject, e.g retry the connection, or send some sort of notification. This is usually a "nicer" way to refuse a packet, but bare in mind that if this is a DDoS your server will have to respond to each request with a reset.

DROP-ping a packet on the other hand will cause TCP to retry the connection until a threshold for re-transmission is exceeded, which can take a long time (a timeout of 100+ seconds). Nothing is sent back to the client in this case.

You can test this on Linux, but the results I got  were 10 milliseconds  for a REJECT to give an application error from a TCP connection and 165 seconds for DROP.

As you can see both of the two options are viable, just consider your use case. iptables offers both methods to deny a request.