I have several HEAD queries a week that look like this (I assume that this is some kind hack attempt):
289 24133.787750 81.94.192.233 -> 95.85.35.251 HTTP 118 HEAD / HTTP/1.1
290 24133.987861 81.94.192.233 -> 95.85.35.251 TCP 118 [TCP Retransmission] 53341 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
291 24134.215884 81.94.192.233 -> 95.85.35.251 TCP 118 [TCP Retransmission] 53341 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
292 24134.442721 81.94.192.170 -> 95.85.35.251 TCP 118 [TCP Retransmission] 36843 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
293 24134.671833 81.94.192.233 -> 95.85.35.251 TCP 118 [TCP Retransmission] 53341 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
294 24135.583822 81.94.192.233 -> 95.85.35.251 TCP 118 [TCP Retransmission] 53341 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
295 24136.110698 81.94.192.170 -> 95.85.35.251 TCP 118 [TCP Retransmission] 36843 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
296 24137.411821 81.94.192.233 -> 95.85.35.251 TCP 118 [TCP Retransmission] 53341 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
297 24139.442873 81.94.192.170 -> 95.85.35.251 TCP 118 [TCP Retransmission] 36843 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
298 24141.063860 81.94.192.233 -> 95.85.35.251 TCP 118 [TCP Retransmission] 53341 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
299 24146.114817 81.94.192.170 -> 95.85.35.251 TCP 118 [TCP Retransmission] 36843 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
300 24148.375866 81.94.192.233 -> 95.85.35.251 TCP 118 [TCP Retransmission] 53341 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
301 24159.458755 81.94.192.170 -> 95.85.35.251 TCP 118 [TCP Retransmission] 36843 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
302 24162.983859 81.94.192.233 -> 95.85.35.251 TCP 118 [TCP Retransmission] 53341 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
303 24186.146998 81.94.192.170 -> 95.85.35.251 TCP 118 [TCP Retransmission] 36843 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
304 24192.231838 81.94.192.233 -> 95.85.35.251 TCP 118 [TCP Retransmission] 53341 → 80 [PSH, ACK] Seq=1 Ack=1 Win=29312 Len=5
305 24192.839296 95.85.35.251 -> 81.94.192.170 TCP 66 80 → 36843 [FIN, ACK] Seq=1 Ack=1 Win=14592 Len=0
306 24192.847089 81.94.192.170 -> 95.85.35.251 TCP 66 36843 → 80 [FIN, ACK] Seq=53 Ack=2 Win=29312 Len=0
307 24192.847545 95.85.35.251 -> 81.94.192.170 TCP 54 80 → 36843 [RST] Seq=2 Win=0 Len=0
I have this iptables entry to drop the HEAD request:
iptables -A INPUT -m string --string "HEAD " --algo bm --to 300 -j DROP
It doesn't seem to be being dropped because of the subsequent burst of [PSH, ACK] packets. Possibly the #305 [FIN, ACK] is the drop. What I want to do is stop or limit the [PSH, ACK] packets that are always after the HEAD request. I tried this, but it gave some sites a problem getting into my web pages:
iptables -A INPUT -p tcp --tcp-flags ALL SYN,ACK -j DROP
I thought I might try this:
iptables -A INPUT -p tcp -m multiport --dports 80,443 --tcp-flags ALL PSH,ACK -m limit --limit 10/s --limit-burst 2 -j DROP
but I would like some advise before I manage to block legitimit web page inquiries. Thanks.
A HEAD request is a completely valid HTTP request which simply returns the HTTP Headers without the actual content body.
Aside from the fact that HEAD requests are part of the HTTP standard, blocking them to deny potential attackers your HTTP header information is pointless because they could just as easily make a GET request and retrieve the same information. In fact, blocking HEAD requests could actually increase your bandwidth consumption because now the attackers have to make a full GET request rather than a low bandwidth HEAD request.
The reason you are seeing the TCP retransmissions is because you are dropping the HEAD request without sending any response back. The device which sent the HEAD thinks that its request never got through so it tries again...and again and again until the connection eventually times-out.
As you have already found out, dropping packets SYN, ACK packets is a terrible idea because you are breaking the TCP handshake and will prevent clients from connecting to your server. Dropping or rate limiting PSH, ACK packets is also not a good idea.
As long as you follow basic principles of security on your server, you should have no need to block access to HEAD requests and no matter what steps you take you will always see automated access attempts probing your server for weakness.
If you are insistent on dropping HEAD requests, your best bet would be to REJECT the requests with a TCP RST rather than silently dropping them. So rather than
-j DROP
, use-j REJECT --reject-with tcp-reset
. This will forcibly tear down the TCP connection.