Last active
September 21, 2023 07:34
-
-
Save valeriansaliou/9632580178e83da1dabce1bbe2cb6a76 to your computer and use it in GitHub Desktop.
HTTP/HTTPS DOS shield w/ IPTables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Those rules protect HTTP/HTTPS services for both IPv4 and IPv6 sources as such: | |
# 1. Prevent a /32 IPv4 or /64 IPv6 to open more than 10 HTTPS?/TCP connections per second (the limit is high, but this still shield against some attacks) — DROP TCP packets in this case, to avoid generating egress traffic sending a RST | |
# 2. Limit ingress bandwidth to HTTPS? services to 32KB/sec (adjust to your needs, in my case it is used to shield a WebSocket backend against incoming WebSocket message floods) | |
# 3. Limit the number of simultaneous ongoing connections to HTTPS? to 40 (also, high limit, adjust to your needs) | |
# The protections those rules offer: | |
# 1. Prevent crypto-DOS (ie. a client that proceed too many key exchanges and thus exhaust server CPU) | |
# 2. Prevent WebSocket floodings (eg. I use this for Socket.IO, which has no efficient way to rate-limit received messages before they get parsed) | |
# 3. Prevent ephemeral TCP port exhaustion due to a client holding too many TCP connections | |
# 4. Prevent IPv6 rotation attacks where a client that possesses a /64 IPv6 block (most hold a /5x or /6x block) uses different ephemeral IPv6 on this /64 subnet to bypass any /128 rate-limiter. It is always safer to rate-limit on the allocated block, hence the /64 (for IPv4 the issue doesn't exist, as IPv4 are expensive and thus people are allocated /32 blocks in 99% cases). | |
# IPTables (IPv4) | |
:FIREWALL | |
-A INPUT -i eth0 -p tcp -m tcp -m multiport --dports 80,443 -m state --state NEW -m hashlimit --hashlimit-above 10/sec --hashlimit-burst 20 --hashlimit-mode srcip --hashlimit-name http_rate -j DROP | |
-A INPUT -i eth0 -p tcp -m tcp -m multiport --dports 80,443 -m hashlimit --hashlimit-above 32kb/s --hashlimit-mode srcip --hashlimit-name http_bandwidth -j DROP | |
-A INPUT -i eth0 -p tcp -m tcp -m multiport --dports 80,443 -m connlimit --connlimit-above 40 --connlimit-mask 32 --connlimit-saddr -j REJECT --reject-with tcp-reset | |
# IPTables (IPv6) | |
:FIREWALL | |
-A INPUT -i eth0 -p tcp -m tcp -m multiport --dports 80,443 -m state --state NEW -m hashlimit --hashlimit-above 10/sec --hashlimit-burst 20 --hashlimit-mode srcip --hashlimit-name http_rate --hashlimit-srcmask 64 -j DROP | |
-A INPUT -i eth0 -p tcp -m tcp -m multiport --dports 80,443 -m hashlimit --hashlimit-above 32kb/s --hashlimit-mode srcip --hashlimit-name http_bandwidth --hashlimit-srcmask 64 -j DROP | |
-A INPUT -i eth0 -p tcp -m tcp -m multiport --dports 80,443 -m connlimit --connlimit-above 40 --connlimit-mask 64 --connlimit-saddr -j REJECT --reject-with tcp-reset |
@tszynalski done, fixed. Does it look good to your now?
Looks like -m hashlimit
comes after -m state
now, so it should be OK.
May I ask why did you not limit the bucket size?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for the feedback. I'll make the change today.