🔹iptables
Be careful with iptables rules, you might lock yourself out of remote machines.
In iptables, Default Policy Rules and the First Matching Rule Wins.
Remember to insert your rule at the beginning of the table or removing mismatching rules from previous line.
Kernel Configuration
to see all available network related kernel configurations for IPv4:
ls /proc/sys/net/ipv4/ -l | cut -d " " -f 10
Enable broadcast echo Protection
echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
Disable Source Routed Packets
echo "0" > /proc/sys/net/ipv4/conf/all/accept_source_route
Enable TCP SYN Cookie Protection
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
Disable ICMP Redirect Acceptance
echo "0" > /proc/sys/net/ipv4/conf/all/accept_redirects
Don't send Redirect Messages
echo "0" > /proc/sys/net/ipv4/conf/all/send_redirects
Drop Spoofed Packets
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo "1" > $f; done
Log packets with impossible addresses
echo "1" > /proc/sys/net/ipv4/conf/all/log_martians
Command Options
Tables options:
-t >>> set a table to operate opon (for firewalls often ‘filter’, for NAT config is ‘nat’)
-L >>> show config for a chain or all chains without name specification
-S >>> show rulses for a chain or all chains
-F >>> flush rules for a chain or all chains
-P [chain] [target] >>> set the default policy for a chain
-A [cahin]>>> specify a chain
-D [cahin] [rule] >>> delete a rule form a chain (by number or rule specification)
-I [chain] [num] [rule] >>> add new rule to a chain
-R [chain] [num] [rule] >>> replace an existing rule in a chain
default policies:
iptables -P [INPUT/OUTPUT/FORWARD] [DROP/REJECT/ACCEPT]
Matching criteria:
-m [name] >>> adds extended matching rules provided by module name
-p [protocol] >>> tcp, udp, udplite, icmp, esp, shtp, all
--sport >>> specify source port or 1:65535 for a port range
--dport >>> specify destination port or 1:65535 for a port range
-s >>> source address or 192.168.1.0/24 for a net block
-d >>> destiation address or 192.168.1.0/24 for a net block
-i >>> input interface only
-o >>> output interface only
--state >>> connection state: INVALID, NEW, ESTABLISHED, RELATED
-j [target] >>> action: ACCEPT, DROP, REJECT
-g [chain] >>> continue the process in another chain
-nL >>> show numeric IPs and ports
-nvL >>> more verbose output
Tables
By default there are three tables in the kernel that contain sets of rules.
The filter table is used for packet filtering
The nat table is used for address translation
The mangle table can be used for special-purpose processing of packets
Filter Table
Packet filtering is a bit more than packet forwarding. While packet forwarding uses only a routing table to make decisions, packet filtering also uses a list of rules. The kernel will inspect packets and decide based on these rules what to do with each packet.
The filter table in iptables has three chains (sets of rules). The INPUT chain is used for any packet coming into the system. The OUTPUT chain is for any packet leaving the system. And the FORWARD chain is for packets that are forwarded (routed) through the system.

Setting Default Policy
The most secure firewall policy would be to DROP everything and then specifically accept some traffic. A package that is dropped will not continue in any chain, and no warning or error will be sent anywhere.
The below commands lock down a computer. Do not execute these commands inside a remote SSH shell.
Remove any existing rules from all chains
iptables --flush
Specific tables can then be flushed using the -t
option:
iptables -t nat --flush
iptables -t mangle --flush
delete any user-defined chains.
iptables -X
iptables -t nat -X
iptables -t mangle -X
Resetting Default Policies and Stopping the Firewall:
ipbles -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
Allow Loopback Access
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# see the results
iptables -n -L -v --line-number
Allow ICMP echo (ping)
ICMP types:
use --icmp-type 8 for echo request only
type 0 → echo reply
type 3 → destination unreachable messages
type 5 → redirect messages
type 8 → echo request
type 11 → time exceeded messages
type 12 → parameter problem messages
iptables -A INPUT -p icmp --icmp-type any -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type any -j ACCEPT
Route Pings
The previous two lines do not allow other computers to route ping messages through your router, because it only handles INPUT and OUTPUT.
For routing of ping, you will need to enable it on the FORWARD chain. The following command enables routing of icmp messages between networks.
iptables -A FORWARD -p icmp --icmp-type any -j ACCEPT
Allow Established & Outbound Connections
The following commands will implement a policy to allow all outbound connections and all established TCP, UDP and ICMP connections:
# iptables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -p udp -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -p icmp -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A INPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A INPUT -p udp -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A INPUT -p icmp -m state --state ESTABLISHED,RELATED -j ACCEPT
Refuse spoofed Packets
Refuse spoofed packets pretending to be from the external interface's IP address.
iptables -A INPUT -i $INTERNET -s $IPADDR -j DROP
Refuse packets claiming to be from a Class A private network.
iptables -A INPUT -i $INTERNET -s $CLASS_A -j DROP
Refuse packets claiming to be from the loopback interface.
iptables -A INPUT -i $INTERNET -s $LOOPBACK -j DROP
Refuse malformed broadcast packets
iptables -A INPUT -i $INTERNET -s $BROADCAST_DEST -j LOG
iptables -A INPUT -i $INTERNET -s $BROADCAST_DEST -j DROP
iptables -A INPUT -i $INTERNET -d $BROADCAST_SRC -j LOG
iptables -A INPUT -i $INTERNET -d $BROADCAST_SRC -j DROP
Refuse directed broadcasts (Used to map networks and in Denial of Service attacks)
iptables -A INPUT -i $INTERNET -d $SUBNET_BASE -j DROP
iptables -A INPUT -i $INTERNET -d $SUBNET_BROADCAST -j DROP
Refuse limited broadcasts
iptables -A INPUT -i $INTERNET -d $BROADCAST_DEST -j DROP
Custom Rules
Inserting and replacing rules
iptables -I/-R INPUT [line number] -s 59.45.175.10 -j ACCEPT
iptables -I INPUT 1 -s 59.45.175.10 -j ACCEPT
iptables -R INPUT 1 -s 59.45.175.10 -j ACCEPT
blocking an IP
iptables -A INPUT -s IP-Address -j DROP
# works without ip tables
ip route add prohibit 192.168.30.83/32
allow a specific IP
iptables -I INPUT -p tcp -s XXX.XXX.XXX.XXX -j ACCEPT
iptables -I OUTPUT -p tcp -d XXX.XXX.XXX.XXX -j ACCEPT`
deleting a rule
iptables -D [chain name] [rule line number]
iptables -D INPUT 2
add connection tracking rules
iptables -A INPUT -j ACCEPT -m conntrack --ctstate ESTABLISHED,RELATED
iptables -A OUTPUT -j ACCEPT -m conntrack --ctstate ESTABLISHED,RELATED
Allowing a specific port
established and related connections
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
ssh
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --sport 22 -j ACCEPT
dns
iptables -A INPUT -p udp --sport 53 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A INPUT -p tcp --sport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
http/https
iptables -A INPUT -p tcp --sport 443 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp --sport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
Allowing access from a subnet
iptables -A INPUT -i eth1 -s 10.1.1.0/24 -p tcp -j ACCEPT
iptables -A OUTPUT -o eth1 -d 10.1.1.0/24 -p tcp -j ACCEPT
Logging
logging rules can apply anywhere in the table.
Don't put logging rules at the top of your table as the first rule, otherwise iptables will log EVERYTHING and will lead to a DoS condition if you dont have enough resource to store that data.
A best practice is to add logging rules at the end of the table as the last rule so anything that is not filtered by other rules will be logged.
add these at the end:
iptables -A INPUT -j LOG
iptables -A OUTPUT -j LOG
iptables -A FORWARD -j LOG
Rate Limiting
Protect against DDoS
Anti-DDoS Kernel Settings (sysctl.conf)
nano /etc/sysctl.conf
kernel.printk = 4 4 1 7
kernel.panic = 10
kernel.sysrq = 0
kernel.shmmax = 4294967296
kernel.shmall = 4194304
kernel.core_uses_pid = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
vm.swappiness = 20
vm.dirty_ratio = 80
vm.dirty_background_ratio = 5
fs.file-max = 2097152
net.core.netdev_max_backlog = 262144
net.core.rmem_default = 31457280
net.core.rmem_max = 67108864
net.core.wmem_default = 31457280
net.core.wmem_max = 67108864
net.core.somaxconn = 65535
net.core.optmem_max = 25165824
net.ipv4.neigh.default.gc_thresh1 = 4096
net.ipv4.neigh.default.gc_thresh2 = 8192
net.ipv4.neigh.default.gc_thresh3 = 16384
net.ipv4.neigh.default.gc_interval = 5
net.ipv4.neigh.default.gc_stale_time = 120
net.netfilter.nf_conntrack_max = 10000000
net.netfilter.nf_conntrack_tcp_loose = 0
net.netfilter.nf_conntrack_tcp_timeout_established = 1800
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 10
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 20
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 20
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 20
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 20
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 10
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.ip_no_pmtu_disc = 1
net.ipv4.route.flush = 1
net.ipv4.route.max_size = 8048576
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_congestion_control = htcp
net.ipv4.tcp_mem = 65536 131072 262144
net.ipv4.udp_mem = 65536 131072 262144
net.ipv4.tcp_rmem = 4096 87380 33554432
net.ipv4.udp_rmem_min = 16384
net.ipv4.tcp_wmem = 4096 87380 33554432
net.ipv4.udp_wmem_min = 16384
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_orphans = 400000
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rfc1337 = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_fack = 1
net.ipv4.tcp_ecn = 2
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 10
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.ip_forward = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.rp_filter = 1
These sysctl.conf settings help to maximize the performance of your server under DDoS as well as the effectiveness of the iptables rules.
IPtables Anti-DDoS Rules
Block New Packets That Are Not SYN:
iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
This blocks all packets that are new (don’t belong to an established connection) and don’t use the SYN flag. This rule is similar to the “Block Invalid Packets” one, but we found that it catches some packets that the other one doesn’t.
Block Uncommon MSS Values:
iptables -t mangle -A PREROUTING -p tcp -m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP
The above iptables rule blocks new packets (only SYN packets can be new packets as per the two previous rules) that use a TCP MSS value that is not common. This helps to block dumb SYN floods.
Block Packets With Bogus TCP Flags:
iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,URG URG -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,PSH PSH -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
The above ruleset blocks packets that use bogus TCP flags, ie. TCP flags that legitimate packets wouldn’t use.
Block Packets From Private Subnets (Spoofing):
iptables -t mangle -A PREROUTING -s 224.0.0.0/3 -j DROP
iptables -t mangle -A PREROUTING -s 169.254.0.0/16 -j DROP
iptables -t mangle -A PREROUTING -s 172.16.0.0/12 -j DROP
iptables -t mangle -A PREROUTING -s 192.0.2.0/24 -j DROP
iptables -t mangle -A PREROUTING -s 192.168.0.0/16 -j DROP
iptables -t mangle -A PREROUTING -s 10.0.0.0/8 -j DROP
iptables -t mangle -A PREROUTING -s 0.0.0.0/8 -j DROP
iptables -t mangle -A PREROUTING -s 240.0.0.0/5 -j DROP
iptables -t mangle -A PREROUTING -s 127.0.0.0/8 ! -i lo -j DROP
These rules block spoofed packets originating from private (local) subnets. On your public network interface you usually don’t want to receive packets from private source IPs.
These rules assume that your loopback interface uses the 127.0.0.0/8 IP space.
These five sets of rules alone already block many TCP-based DDoS attacks at very high packet rates.
With the kernel settings and rules mentioned above, you’ll be able to filter ACK and SYN-ACK attacks at line rate.
mitigate Ping of Death (ping flood):
iptables -t mangle -A PREROUTING -p icmp -j DROP
TCP connection attacks:
iptables -A INPUT -p tcp -m connlimit --connlimit-above 80 -j REJECT --reject-with tcp-reset
It rejects connections from hosts that have more than 80 established connections. If you face any issues you should raise the limit as this could cause troubles with legitimate clients that establish a large number of TCP connections.
Limit the new TCP connections that a client can establish per second:
iptables -A INPUT -p tcp -m conntrack --ctstate NEW -m limit --limit 60/s --limit-burst 20 -j ACCEPT
iptables -A INPUT -p tcp -m conntrack --ctstate NEW -j DROP
This can be useful against connection attacks, but not so much against SYN floods because the usually use an endless amount of different spoofed source IPs.
block fragmented packets:
iptables -t mangle -A PREROUTING -f -j DROP
Normally you don’t need those and blocking fragments will mitigate UDP fragmentation flood. But most of the time UDP fragmentation floods use a high amount of bandwidth that is likely to exhaust the capacity of your network card, which makes this rule optional and probably not the most useful one.
limits incoming TCP RST packets to mitigate TCP RST floods:
iptables -A INPUT -p tcp --tcp-flags RST RST -m limit --limit 2/s --limit-burst 2 -j ACCEPT
iptables -A INPUT -p tcp --tcp-flags RST RST -j DROP
Mitigating SYN Floods With SYNPROXY
SYNPROXY is a new target of iptables that has been added in Linux kernel version 3.12 and iptables 1.4.21. CentOS 7 backported the feature and it’s available in its 3.10 default kernel.
The purpose of SYNPROXY is to check whether the host that sent the SYN packet actually establishes a full TCP connection or just does nothing after it sent the SYN packet.
If it does nothing, it discards the packet with minimal performance impact.
Here are iptables SYNPROXY rules that help mitigate SYN floods that bypass our other rules:
iptables -t raw -A PREROUTING -p tcp -m tcp --syn -j CT --notrack
iptables -A INPUT -p tcp -m tcp -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
Per-IP packet limits
iptables -A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -m recent --set --name SSHLIMIT --rsource
iptables -A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -m recent --set --name SSHLIMIT --update --seconds 180 --hitcount 5 --name SSH --rsource -j DROP
Custom Chains
/iptables -N ssh-rules
iptables -A ssh-rules -s 18.130.0.0/16 -j ACCEPT
iptables -A ssh-rules -s 18.11.0.0/16 -j ACCEPT
iptables -A ssh-rules -j DROP
iptables -A INPUT -p tcp -m tcp --dport 22 -j ssh-rules
iptables -X ssh-rules
save/restore/persistent
Use iptables save to automatically implement these rules when the firewall is (re)started.
/etc/init.d/iptables save
or
iptables-save
iptables-save -f [output file]
iptables-restore [rules file]
make persistence after reboot:
sudo apt-get install iptables-persistent
iptables-save >/etc/iptables/rules.v4
ip6tables-save >/etc/iptables/rules.v6
iptables-save > /etc/iptables.conf
ip6tables-save > /etc/ip6tables.conf
pre-up iptables-restore < /etc/iptables.conf
pre-up ip6tables-restore < /etc/ip6tables.conf
adding a comment
-m comment --comment 'comment text'
example:
iptables -A INPUT -j ACCEPT -p tcp --dport 22 -m comment --comment 'ssh port 22'
NAT Masquerading
iptables -A FORWARD -m comment --comment "established traffic" -j ACCEPT -m conntrack --ctstate ESTABLISHED,RELATED
iptables -A FORWARD -j ACCEPT -i lan -o wan -m comment --comment "allow outbound traffic from lan"
iptables -t nat -L
iptables -t nat -A POSTROUTING -o wan -j MASQUERADE -m comment --comment "masquerade lan to wan"
apply ip forwarding for NAT:
echo 1 > /proc/sys/net/ipv4/ip_forward
port address translation
allow to reach a service over a firewall
iptables -t nat -A PREROUTING -p tcp --dport 22 -m comment --commnet "ssh PAT" -d [target ip] -j DNAT --to-destination [dest ip]
iptabes -A FORWARD -p tcp --dport 22 -d [dest ip] -j ACCEPT -m comment "ssh into dest"
Last updated