Skip to content

Instantly share code, notes, and snippets.

@valeriansaliou
Last active September 21, 2023 07:34
Show Gist options
  • Save valeriansaliou/9632580178e83da1dabce1bbe2cb6a76 to your computer and use it in GitHub Desktop.
Save valeriansaliou/9632580178e83da1dabce1bbe2cb6a76 to your computer and use it in GitHub Desktop.
HTTP/HTTPS DOS shield w/ IPTables
# 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
@valeriansaliou
Copy link
Author

Thanks for the feedback. I'll make the change today.

@valeriansaliou
Copy link
Author

@tszynalski done, fixed. Does it look good to your now?

@tszynalski
Copy link

Looks like -m hashlimit comes after -m state now, so it should be OK.

@Mecanik
Copy link

Mecanik commented Nov 13, 2022

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