Skip to content

Instantly share code, notes, and snippets.

@mattia-beta
Last active April 27, 2024 22:00
Show Gist options
  • Star 77 You must be signed in to star a gist
  • Fork 27 You must be signed in to fork a gist
  • Save mattia-beta/bd5b1c68e3d51db933181d8a3dc0ba64 to your computer and use it in GitHub Desktop.
Save mattia-beta/bd5b1c68e3d51db933181d8a3dc0ba64 to your computer and use it in GitHub Desktop.
IPtables DDoS Protection for VPS
### 1: Drop invalid packets ###
/sbin/iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP
### 2: Drop TCP packets that are new and are not SYN ###
/sbin/iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
### 3: Drop SYN packets with suspicious MSS value ###
/sbin/iptables -t mangle -A PREROUTING -p tcp -m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP
### 4: Block packets with bogus TCP flags ###
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,URG URG -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,FIN FIN -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,PSH PSH -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL ALL -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
### 5: Block spoofed packets ###
/sbin/iptables -t mangle -A PREROUTING -s 224.0.0.0/3 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 169.254.0.0/16 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 172.16.0.0/12 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 192.0.2.0/24 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 192.168.0.0/16 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 10.0.0.0/8 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 0.0.0.0/8 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 240.0.0.0/5 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 127.0.0.0/8 ! -i lo -j DROP
### 6: Drop ICMP (you usually don't need this protocol) ###
/sbin/iptables -t mangle -A PREROUTING -p icmp -j DROP
### 7: Drop fragments in all chains ###
/sbin/iptables -t mangle -A PREROUTING -f -j DROP
### 8: Limit connections per source IP ###
/sbin/iptables -A INPUT -p tcp -m connlimit --connlimit-above 111 -j REJECT --reject-with tcp-reset
### 9: Limit RST packets ###
/sbin/iptables -A INPUT -p tcp --tcp-flags RST RST -m limit --limit 2/s --limit-burst 2 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --tcp-flags RST RST -j DROP
### 10: Limit new TCP connections per second per source IP ###
/sbin/iptables -A INPUT -p tcp -m conntrack --ctstate NEW -m limit --limit 60/s --limit-burst 20 -j ACCEPT
/sbin/iptables -A INPUT -p tcp -m conntrack --ctstate NEW -j DROP
### 11: Use SYNPROXY on all ports (disables connection limiting rule) ###
#/sbin/iptables -t raw -A PREROUTING -p tcp -m tcp --syn -j CT --notrack
#/sbin/iptables -A INPUT -p tcp -m tcp -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
#/sbin/iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
### SSH brute-force protection ###
/sbin/iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --set
/sbin/iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 10 -j DROP
### Protection against port scanning ###
/sbin/iptables -N port-scanning
/sbin/iptables -A port-scanning -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s --limit-burst 2 -j RETURN
/sbin/iptables -A port-scanning -j DROP
@alidasomi
Copy link

I add this rules
but it drop all my packets.
why?

@kodeine
Copy link

kodeine commented Jul 15, 2020

6: Drop ICMP (you usually don't need this protocol)

/sbin/iptables -t mangle -A PREROUTING -p icmp -j DROP

is suppose to reject ping from outside? i am still able to ping server from outside.

@Gabitzuu
Copy link

@kodeine yes, it drops the outside ping

@pavpd
Copy link

pavpd commented Sep 25, 2020

I add this rules
but it drop all my packets.
why?

i ssh'd into my modem and im trying to make it filter ddos better. i am scared of bricking it lol, assuming you fixed your issue, are you sure this script made you drop all packets?

@daryll-swer
Copy link

daryll-swer commented Apr 20, 2021

Blocking ICMP blindly does not provide security and it breaks PMTUD along with Time Exceeded etc, don't give such advice @mattia-beta. The right thing to do is allow some ICMP while blocking the rest or just rate limit ICMP. Not to mention IPv6 is even more strict about ICMP.

An improvement is to switch from mangle to raw, which will drop at line rate as those connections never enter conntrack.

Source:

  1. https://blog.paessler.com/disabling-icmp-and-snmp-wont-increase-security-but-will-impact-network-monitoring
  2. https://ccie-or-null.net/2012/02/13/dont-block-icmp/
  3. http://shouldiblockicmp.com/
  4. https://www.ietf.org/rfc/rfc4890.txt
  5. https://help.mikrotik.com/docs/display/ROS/Building+Advanced+Firewall
  6. https://help.mikrotik.com/docs/pages/viewpage.action?pageId=28606504

Copy link

ghost commented May 2, 2021

thanks for sharing

Copy link

ghost commented May 2, 2021

Where are iptables rules located
ubuntu 20.04

Copy link

ghost commented May 2, 2021

I ran this as a shell script on my VPS
Is this correct?

@daryll-swer
Copy link

I ran this as a shell script on my VPS
Is this correct?

As I stated before, there are some flaws. I created my own rules from scratch which is what I use on actual routers based on IETF specs, best networking practices etc.

Change interface names to match your own

###eth1 & lo (loopback) is LAN interface###

iptables -A INPUT -m comment -m conntrack --ctstate ESTABLISHED,RELATED,UNTRACKED -j ACCEPT --comment "accept established,related,untracked"
iptables -A INPUT -m comment -p tcp -m tcp --dport 22 -j ACCEPT --comment "Accept SSH port"
iptables -A INPUT -m comment -i lo -j ACCEPT --comment "Accept local traffic lo"
iptables -A INPUT -m comment -i eth1 -j ACCEPT --comment "Accept local traffic eth1"
iptables -A INPUT -m comment -m conntrack --ctstate INVALID -j DROP --comment "drop invalid"
iptables -A INPUT -m comment -p icmp -j ACCEPT --comment "accept ICMP after RAW"
iptables -A INPUT -m comment -j DROP --comment "drop everything else"
iptables -A FORWARD -m comment -m conntrack --ctstate ESTABLISHED,RELATED,UNTRACKED -j ACCEPT --comment "accept established,related, untracked"
iptables -A FORWARD -m comment -m policy --pol ipsec --dir in -j ACCEPT --comment "accept in ipsec policy"
iptables -A FORWARD -m comment -m policy --pol ipsec --dir out -j ACCEPT --comment "accept out ipsec policy"
iptables -A FORWARD -m comment -m conntrack --ctstate INVALID -j DROP --comment "drop invalid"
iptables -A FORWARD -m comment -d "0.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 10.0.0.0/8, 169.254.0.0/16, 127.0.0.0/8, 224.0.0.0/4, 198.18.0.0/15, 192.0.0.0/24, 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24, 100.64.0.0/10, 240.0.0.0/4, 192.88.99.0/24, 255.255.255.255" -i eth1 -o eth0 -j DROP --comment "Drop tries to reach not public addresses from LAN eth1"
iptables -A FORWARD -m comment -d "0.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 10.0.0.0/8, 169.254.0.0/16, 127.0.0.0/8, 224.0.0.0/4, 198.18.0.0/15, 192.0.0.0/24, 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24, 100.64.0.0/10, 240.0.0.0/4, 192.88.99.0/24, 255.255.255.255" -i lo -o eth0 -j DROP --comment "Drop tries to reach not public addresses from LAN lo"
iptables -A FORWARD -m comment -m conntrack -i eth0 -o eth1 ! --ctstate DNAT -j DROP --comment "drop all from WAN not DSTNATed for eth1"

###Create chains for RAW table###
iptables -t raw -N chain-icmp
iptables -t raw -N chain-bad_tcp

###Loopback is need for DNS resolver on Cloud VMs so 127.0.0.0/8 is not part of bad src/dst IPs###
iptables -t raw -A PREROUTING -m comment -s "192.0.0.0/24, 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24, 240.0.0.0/4" -j DROP --comment "drop bad src IPs"
iptables -t raw -A PREROUTING -m comment -d "192.0.0.0/24, 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24, 240.0.0.0/4" -j DROP --comment "drop bad dst IPs"
iptables -t raw -A PREROUTING -m comment -s 255.255.255.255 -j DROP --comment "drop bad_src_ipv4"
iptables -t raw -A PREROUTING -m comment -d 0.0.0.0/8 -j DROP --comment "drop bad_dst_ipv4"
iptables -t raw -A PREROUTING -m comment -s "0.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 10.0.0.0/8, 169.254.0.0/16, 127.0.0.0/8, 224.0.0.0/4, 198.18.0.0/15, 192.0.0.0/24, 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24, 100.64.0.0/10, 240.0.0.0/4, 192.88.99.0/24, 255.255.255.255" -i eth0 -j DROP --comment "drop non global from WAN"
iptables -t raw -A PREROUTING -m comment -d "10.122.32.0/20, 10.7.0.0/24" -i eth0 -j DROP --comment "drop forward to local lan from WAN"
iptables -t raw -A PREROUTING -m comment -p udp -m udp -m multiport --ports 0 -j DROP --comment "drop bad UDP"
iptables -t raw -A PREROUTING -m comment -p icmp -j chain-icmp --comment "jump to ICMP chain"
iptables -t raw -A PREROUTING -m comment -p tcp -m tcp -j chain-bad_tcp --comment "jump to TCP chain"
iptables -t raw -A PREROUTING -m comment -i eth1 -j ACCEPT --comment "accept everything else from LAN eth1"
iptables -t raw -A PREROUTING -m comment -i lo -j ACCEPT --comment "accept everything else from LAN lo"
iptables -t raw -A PREROUTING -m comment -i eth0 -j ACCEPT --comment "accept everything else from WAN"
iptables -t raw -A PREROUTING -m comment -j DROP --comment "drop the rest"
iptables -t raw -A chain-icmp -m comment -p icmp -m icmp --icmp-type echo-reply -j ACCEPT --comment "echo reply"
iptables -t raw -A chain-icmp -m comment -p icmp -m icmp --icmp-type network-unreachable -j ACCEPT --comment "net unreachable"
iptables -t raw -A chain-icmp -m comment -p icmp -m icmp --icmp-type host-unreachable -j ACCEPT --comment "host unreachable"
iptables -t raw -A chain-icmp -m comment -p icmp -m icmp --icmp-type protocol-unreachable -j ACCEPT --comment "protocol unreachable"
iptables -t raw -A chain-icmp -m comment -p icmp -m icmp --icmp-type port-unreachable -j ACCEPT --comment "port unreachable"
iptables -t raw -A chain-icmp -m comment -p icmp -m icmp --icmp-type fragmentation-needed -j ACCEPT --comment "host unreachable fragmentation required"
iptables -t raw -A chain-icmp -m comment -p icmp -m icmp --icmp-type echo-request -j ACCEPT --comment "echo request"
iptables -t raw -A chain-icmp -m comment -p icmp -m icmp --icmp-type time-exceeded -j ACCEPT --comment "time exceeded"
iptables -t raw -A chain-icmp -m comment -p icmp -m icmp --icmp-type parameter-problem -j ACCEPT --comment "allow parameter bad"
iptables -t raw -A chain-icmp -m comment -p icmp -m icmp --icmp-type any -j DROP --comment "drop other icmp"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags SYN,RST SYN,RST -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags FIN,RST FIN,RST -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags FIN,ACK FIN -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags ACK,URG URG -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags ACK,FIN FIN -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags ACK,PSH PSH -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags ALL ALL -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags ALL NONE -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP --comment "TCP flag filter"
iptables -t raw -A chain-bad_tcp -m comment -p tcp -m tcp -m multiport --ports 0 -j DROP --comment "TCP port 0 drop"

##################################ip6tables rules##################################
ip6tables -A INPUT -m comment -m conntrack --ctstate ESTABLISHED,RELATED,UNTRACKED -j ACCEPT --comment "accept established,related,untracked"
ip6tables -A INPUT -m comment -m conntrack --ctstate INVALID -j DROP --comment "drop invalid"
ip6tables -A INPUT -m comment -p icmpv6 -j ACCEPT --comment "accept ICMPv6"
ip6tables -A INPUT -m comment -p udp -m udp -m multiport --ports 33434:33534 -j ACCEPT --comment "accept UDP traceroute"
ip6tables -A INPUT -m comment -p udp -m udp -s fe80::/10 --dport 546 -j ACCEPT --comment "accept DHCPv6-Client prefix delegation"
ip6tables -A INPUT -m comment -s fe80::/16 -i eth0 -j DROP --comment "dropLocalLink_from_public"
ip6tables -A INPUT -m comment -s "fd12:672e:6f65:8899::/64, fe80::/16, ff02::/16" -j ACCEPT --comment "allow allowed addresses"
ip6tables -A INPUT -m comment -p udp -m udp -m multiport -j ACCEPT --dports 500,4500 --comment "accept IKE"
ip6tables -A INPUT -m comment -m ah -j ACCEPT --comment "accept ipsec AH"
ip6tables -A INPUT -m comment -p esp -j ACCEPT --comment "accept ipsec ESP"
ip6tables -A INPUT -m comment -m policy --pol ipsec --dir in -j ACCEPT --comment "accept all that matches ipsec policy"
ip6tables -A INPUT -m comment -i eth1 -j ACCEPT --comment "accept all not coming from LAN's interface list/subnets eth1"
ip6tables -A INPUT -m comment -i lo -j ACCEPT --comment "accept all not coming from LAN's interface list/subnets lo"
ip6tables -A INPUT -m comment -j DROP --comment "drop everything else"
ip6tables -A FORWARD -m comment -m conntrack --ctstate ESTABLISHED,RELATED,UNTRACKED -j ACCEPT --comment "accept established,related, untracked"
ip6tables -A FORWARD -m comment -m conntrack --ctstate INVALID -j DROP --comment "drop invalid"
###Loopback is need for DNS resolver on Cloud so ::1/128 is not part of bad src and dst###
ip6tables -A FORWARD -m comment -s "::/128, fec0::/10, ::ffff:0.0.0.0/96, ::/96, 100::/64, 2001:db8::/32, 2001:10::/28, 3ffe::/16, ::224.0.0.0/100, ::127.0.0.0/104, ::/104, ::255.0.0.0/104, 2001::/23" -j DROP --comment "drop packets with bad src ipv6"
ip6tables -A FORWARD -m comment -d "::/128, fec0::/10, ::ffff:0.0.0.0/96, ::/96, 100::/64, 2001:db8::/32, 2001:10::/28, 3ffe::/16, ::224.0.0.0/100, ::127.0.0.0/104, ::/104, ::255.0.0.0/104, 2001::/23" -j DROP --comment "drop packets with bad dst ipv6"
ip6tables -A FORWARD -m comment -s "fe80::/10, ff00::/8" -j DROP --comment "drop bad forward IPs"
ip6tables -A FORWARD -m comment -d "fe80::/10, ff00::/8" -j DROP --comment "drop bad forward IPs"
ip6tables -A FORWARD -m comment -p icmpv6 -m hl --hl-eq 1 -j DROP --comment "rfc4890 drop hop-limit=1"
ip6tables -A FORWARD -m comment -p icmpv6 -j ACCEPT --comment "accept ICMPv6"
ip6tables -A FORWARD -m comment -s "fd12:672e:6f65:8899::/64, fe80::/16, ff02::/16" ! -i eth0 -j ACCEPT --comment "local clients to public"
ip6tables -A FORWARD -m comment -p hip -j ACCEPT --comment "accept HIP"
ip6tables -A FORWARD -m comment -p udp -m udp -m multiport -j ACCEPT --dports 500,4500 --comment "accept IKE"
ip6tables -A FORWARD -m comment -m ah -j ACCEPT --comment "accept ipsec AH"
ip6tables -A FORWARD -m comment -p esp -j ACCEPT --comment "accept ipsec ESP"
ip6tables -A FORWARD -m comment -m policy --pol ipsec --dir in -j ACCEPT --comment "accept all that matches ipsec policy"
ip6tables -A FORWARD -m comment -i eth1 -j ACCEPT --comment "accept all not coming from LAN's interface list/subnets eth1"
ip6tables -A FORWARD -m comment -i lo -j ACCEPT --comment "accept all not coming from LAN's interface list/subnets lo"
ip6tables -A FORWARD -m comment -j DROP --comment "drop everything else"
ip6tables -t raw -A PREROUTING -m comment -s "::/128, fec0::/10, ::ffff:0.0.0.0/96, ::/96, 100::/64, 2001:db8::/32, 2001:10::/28, 3ffe::/16, ::224.0.0.0/100, ::127.0.0.0/104, ::/104, ::255.0.0.0/104, 2001::/23" -j DROP --comment "drop bad src IPs"
ip6tables -t raw -A PREROUTING -m comment -d "::/128, fec0::/10, ::ffff:0.0.0.0/96, ::/96, 100::/64, 2001:db8::/32, 2001:10::/28, 3ffe::/16, ::224.0.0.0/100, ::127.0.0.0/104, ::/104, ::255.0.0.0/104, 2001::/23" -j DROP --comment "drop bad dst IPs"
ip6tables -t raw -A PREROUTING -m comment -s "::/128, ff00::/8" -j DROP --comment "drop bad src IPs"
ip6tables -t raw -A PREROUTING -m comment -d ::/128 -j DROP --comment "drop bad dst IPs"
ip6tables -t raw -A PREROUTING -m comment -s "100::/64, 2001::/32, 2001:2::/48, fc00::/7" -i eth0 -j DROP --comment "drop non global from WAN"
ip6tables -t raw -A PREROUTING -m comment -d ff02::/16 -j ACCEPT --comment "accept local multicast scope"
ip6tables -t raw -A PREROUTING -m comment -d ff00::/8 -j DROP --comment "drop other multicast destinations"
ip6tables -t raw -A PREROUTING -m comment -i eth1 -j ACCEPT --comment "accept everything else from LAN eth1"
ip6tables -t raw -A PREROUTING -m comment -i lo -j ACCEPT --comment "accept everything else from LAN lo"
ip6tables -t raw -A PREROUTING -m comment -i eth0 -j ACCEPT --comment "accept everything else from WAN"
ip6tables -t raw -A PREROUTING -m comment -j DROP --comment "drop the rest"```

Copy link

ghost commented May 2, 2021

What kind of attack can block?
https://www.stressthem.to/
I tested my server with this website but attack reaches the server

@kv4X
Copy link

kv4X commented May 6, 2021

What kind of attack can block?
https://www.stressthem.to/
I tested my server with this website but attack reaches the server

You can analyze attack with tcpdump, view ips or packets which reaching server and block them.

Copy link

ghost commented May 7, 2021

What kind of attack can block?
https://www.stressthem.to/
I tested my server with this website but attack reaches the server

You can analyze attack with tcpdump, view ips or packets which reaching server and block them.

How can block udp?

@diyaa59
Copy link

diyaa59 commented Feb 24, 2022

I am not sure if you are aware, but dropping all ICMP traffic is such a horrible idea. I would rate limit ICMP traffic and not completely drop it. There are some ICMP traffic that are required for network functionality!

@ivansalloum
Copy link

You don't need rule 4 (Block packets with bogus TCP flags) since you have rule 2 (Drop TCP packets that are new and are not SYN). You have a redundant in your configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment