Setting up the basics
We like to use the iptables command in our scripts with the full path set, that is, instead of calling it as:
iptables
We use:
/sbin/iptables
We do this because we want to make sure our scripts are calling the right copy of iptables, in case we've installed some newer or experimental copy of the userland program. To make this easier, we also set it as a variable at the top of our firewall scripts in this manner:
IPTABLES="/sbin/iptables"
So in our scripts, if you see this:
$IPTABLES
That just short hand for /sbin/iptables or whatever the path is to your copy of IPTABLES. Change this variable to reflect the location that is appropriate for your system (i.e. /usr/local/bin/iptables).
How to set your default policy to a paranoid setting
$IPTABLES -P OUTPUT DROP $IPTABLES -P INPUT DROP $IPTABLES -P FORWARD DROP
Fixing MTU/MSS problems
$IPTABLES -A OUTPUT -o eth1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu $IPTABLES -A FORWARD -o eth1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
QOS tricks
#QOS tricks $IPTABLES -A PREROUTING -t mangle -p tcp --sport telnet -j TOS --set-tos Minimize-Delay $IPTABLES -A PREROUTING -t mangle -p tcp --sport ftp -j TOS --set-tos Minimize-Delay $IPTABLES -A PREROUTING -t mangle -p tcp --sport ftp-data -j TOS --set-tos Maximize-Throughput
Simple portscan detector Note: You will need to install the "recent" module for these rules to work. If you do not have the "recent" module installed, simply remove this section from these rules "-m recent --set". Remove that, and it should work.
$IPTABLES -N PORTSCAN
#portscan detection module
# NMAP FIN/URG/PSH
$IPTABLES -A INPUT -i all -p tcp --tcp-flags ALL FIN,URG,PSH -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags ALL FIN,URG,PSH -m recent --set -j PORTSCAN
# SYN/RST
$IPTABLES -A INPUT -i all -p tcp --tcp-flags SYN,RST SYN,RST -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags SYN,RST SYN,RST -m recent --set -j PORTSCAN
# SYN/FIN -- Scan(probably)
$IPTABLES -A INPUT -i all -p tcp --tcp-flags SYN,FIN SYN,FIN -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags SYN,FIN SYN,FIN -m recent --set -j PORTSCAN
# NMAP FIN Stealth
$IPTABLES -A INPUT -i all -p tcp --tcp-flags ALL FIN -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags ALL FIN -m recent --set -j PORTSCAN
# ALL/ALL Scan
$IPTABLES -A INPUT -i all -p tcp --tcp-flags ALL ALL -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags ALL ALL -m recent --set -j PORTSCAN
# NMAP Null Scan
$IPTABLES -A INPUT -i all -p tcp --tcp-flags ALL NONE -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags ALL NONE -m recent --set -j PORTSCAN
#XMAS
$IPTABLES -A INPUT -i all -p tcp --tcp-flags ALL URG,ACK,PSH,RST,SYN,FIN -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags ALL URG,ACK,PSH,RST,SYN,FIN -m recent --set -j PORTSCAN
$IPTABLES -A PORTSCAN -m limit --limit 1/second -j LOG --log-level info --log-prefix "PORTSCAN -- SHUN " --log-tcp-sequence --log-tcp-options --log-ip-options
$IPTABLES -A PORTSCAN -j DROP
Drop packets with bad flags
Note: You will need to install the "recent" module for these rules to work. If you do not have the "recent" module installed, simply remove this section from these rules "-m recent --set". Remove that, and it should work.
# Drop packets with bad tcp flags
$IPTABLES -N BAD_FLAGS
$IPTABLES -A INPUT -p tcp --tcp-option 64 -m recent --set -j BAD_FLAGS
$IPTABLES -A INPUT -p tcp --tcp-option 128 -m recent --set -j BAD_FLAGS
$IPTABLES -A BAD_FLAGS -m limit --limit 1/second -j LOG --log-level info --log-prefix "BAD_FLAGS -- SHUN " --log-tcp-sequence --log-tcp-options --log-ip-options
$IPTABLES -A BAD_FLAGS -j DROP
Drop packets with bad IP options set
Note: You will need to install the "recent" module for these rules to work. If you do not have the "recent" module installed, simply remove this section from these rules "-m recent --set". Remove that, and it should work.
$IPTABLES -N IPOPTS $IPTABLES -A INPUT -m ipv4options --ssrr -m recent --set -j IPOPTS $IPTABLES -A INPUT -m ipv4options --lsrr -m recent --set -j IPOPTS $IPTABLES -A INPUT -m ipv4options --rr -m recent --set -j IPOPTS $IPTABLES -A IPOPTS -j LOG --log-prefix "BAD IPOPTS SHUN " --log-tcp-sequence --log-tcp-options --log-ip-options -m limit --limit 1/second $IPTABLES -A IPOPTS -j DROP
Drop packets that are too small Note: You will need to install the "recent" module for these rules to work. If you do not have the "recent" module installed, simply remove this section from these rules "-m recent --set". Remove that, and it should work.
$IPTABLES -N SMALL $IPTABLES -A INPUT -p udp -m length --length 0:27 -m recent --set -j SMALL $IPTABLES -A INPUT -p tcp -m length --length 0:39 -m recent --set -j SMALL $IPTABLES -A INPUT -p icmp -m length --length 0:27 -m recent --set -j SMALL $IPTABLES -A INPUT -p 30 -m length --length 0:31 -m recent --set -j SMALL $IPTABLES -A INPUT -p 47 -m length --length 0:39 -m recent --set -j SMALL $IPTABLES -A INPUT -p 50 -m length --length 0:49 -m recent --set -j SMALL $IPTABLES -A INPUT -p 51 -m length --length 0:35 -m recent --set -j SMALL $IPTABLES -A INPUT -m length --length 0:19 -m recent --set -j SMALL $IPTABLES -A SMALL -m limit --limit 1/second -j LOG --log-level info --log-prefix "SMALL -- SHUN " --log-tcp-sequence --log-tcp-options --log-ip-options $IPTABLES -A SMALL -j DROP
Use simple atomic string matching to drop packets that are possible attacks
Note: You need the STRING patch for this work with your kernel and iptables.
$IPTABLES -N STRINGS #packets coming in $IPTABLES -A INPUT -p tcp --dport 22 -m string --string '"Version_Mapper"' -j STRINGS $IPTABLES -A FORWARD -p tcp --dport 22 -m string --string '"Version_Mapper"' -j STRINGS $IPTABLES -A INPUT -p tcp --dport 22 -m string --string '"/bin/sh"' -j STRINGS $IPTABLES -A INPUT -p tcp --dport 443 -m string --string "TERM=xterm" -j STRINGS $IPTABLES -A STRINGS -m recent --set -j DROP
A little trick to help hide your firewall from traceroute
Note: You may need the TTL patch for this work with your kernel and iptables.
$IPTABLES -N TTL $IPTABLES -t mangle -A PREROUTING -p UDP --dport 33434:33542 -j TTL --ttl-inc 1 $IPTABLES -A TTL -j ACCEPT
Reject all BOGUS packets
$IPTABLES -N BOGUS $IPTABLES -t filter -p all -A INPUT -m conntrack --ctstate INVALID -j BOGUS $IPTABLES -t filter -p all -A OUTPUT -m conntrack --ctstate INVALID -j BOGUS $IPTABLES -t filter -p all -A FORWARD -m conntrack --ctstate INVALID -j BOGUS #$IPTABLES -A BOGUS -m limit --limit 1/second -j LOG --log-level info --log-prefix "INVALID PACKET -- DROP " --log-tcp-sequence --log-tcp-options --log-ip-options $IPTABLES -A BOGUS -j REJECT
Note: We commented out the logging because on busy firewalls this can make some very noisy logging, but try turning it on to see how it works for you. With the logging turned off you will miss knowing about some attacks, although the firewall will still stop them.
Drop "unclean" packets
Note: We don't use these rules on our firewalls anymore. They are experimental, and may cause problems for you.
$IPTABLES -N DIRTY $IPTABLES -A INPUT -m unclean -j DIRTY $IPTABLES -A OUTPUT -m unclean -j DIRTY $IPTABLES -A FORWARD -m unclean -j DIRTY $IPTABLES -A DIRTY -m limit --limit 1/second -j LOG --log-level info --log-prefix "UNCLEAN PACKET -- DROP " --log-tcp-sequence --log-tcp-options --log-ip-options $IPTABLES -A DIRTY -j DROP
More advanced port scan detector
Note: You will need to install the PSD patch for iptables into your kernel for these to work.
$IPTABLES -N PSD
$IPTABLES -A INPUT -i eth+ -m psd -m limit --limit 5/minute -j PSD
$IPTABLES -A INPUT -i ipsec+ -m psd -m limit --limit 5/minute -j PSD
$IPTABLES -A INPUT -i tun+ -m psd -m limit --limit 5/minute -j PSD
$IPTABLES -A FORWARD -i eth+ -m psd -m limit --limit 5/minute -j PSD
$IPTABLES -A FORWARD -i ipsec+ -m psd -m limit --limit 5/minute -j PSD
$IPTABLES -A FORWARD -i tun+ -m psd -m limit --limit 5/minute -j PSD
$IPTABLES -A PSD -m limit --limit 1/second -j LOG --log-level info --log-prefix "PSD -- DROP " --log-tcp-sequence --log-tcp-options --log-ip-options
$IPTABLES -A PSD -j DROP
Block fragments
Note: These rules should never trip, if they do, something is seriously wrong with your firewall or you are not use any stateful rules - which means your firewall is configured incorrectly in most cases.
$IPTABLES -N NOFRAGS $IPTABLES -A OUTPUT -p ip -f -j NOFRAGS $IPTABLES -A INPUT -p ip -f -j NOFRAGS $IPTABLES -A FORWARD -p ip -f -j NOFRAGS $IPTABLES -A NOFRAGS -m limit --limit 1/second -j LOG --log-level info --log-prefix "Fragment -- DROP " --log-tcp-sequence --log-tcp-options --log-ip-options $IPTABLES -A NOFRAGS -j DROP
Detect and drop syn floods
$IPTABLES -N syn-flood $IPTABLES -A INPUT -i eth+ -p tcp --tcp-flags SYN,ACK,FIN,RST RST -j syn-flood $IPTABLES -A FORWARD -i eth+ -p tcp --tcp-flags SYN,ACK,FIN,RST RST -j syn-flood $IPTABLES -A syn-flood -m limit --limit 4/s --limit-burst 16 -j RETURN $IPTABLES -A syn-flood -m limit --limit 75/s --limit-burst 100 -j RETURN $IPTABLES -A syn-flood -j LOG --log-prefix "SYN FLOOD " --log-tcp-sequence --log-tcp-options --log-ip-options -m limit --limit 1/second $IPTABLES -A syn-flood -j DROP
Enforce SYN only connections on NEW connections
$IPTABLES -A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j LOG --log-prefix "New not syn:" $IPTABLES -A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j DROP $IPTABLES -A FORWARD -p tcp ! --syn -m conntrack --ctstate NEW -j LOG --log-prefix "New not syn:" $IPTABLES -A FORWARD -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
Send TCP resets for incoming AUTH connections
Note: This will help with "stalled" SMTP connections, IRC and other protocols that try to do an ident lookup against the host initiating the connection. This is a performance ruleset, and not specifically a security one.
$IPTABLES -A INPUT -p tcp -s any/0 --dport 113 -j REJECT --reject-with tcp-reset $IPTABLES -A FORWARD -p tcp -i eth+ -s any/0 --dport 113 -j REJECT --reject-with tcp-reset
Note: You will need to install the "recent" module for these rules to work. If you do not have the "recent" module installed, simply remove this section from these rules "-m recent --set". Remove that, and it should work.
Drop packets to "odd" ports
$IPTABLES -N ODDPORTS $IPTABLES -A INPUT -p udp --sport 2:21 -m recent --set -j ODDPORTS $IPTABLES -A INPUT -p udp --dport 2:21 -m recent --set -j ODDPORTS $IPTABLES -A INPUT -p tcp --dport 0 -m recent --set -j ODDPORTS $IPTABLES -A INPUT -p tcp --sport 0 -m recent --set -j ODDPORTS $IPTABLES -A FORWARD -i eth+ -p udp --dport 2:21 -m recent --set -j ODDPORTS $IPTABLES -A FORWARD -i eth+ -p tcp --dport 0 -m recent --set -j ODDPORTS $IPTABLES -A FORWARD -i eth+ -p tcp --sport 0 -m recent --set -j ODDPORTS $IPTABLES -A ODDPORTS -m limit --limit 1/second -j LOG --log-level info --log-prefix "ODDPORTS -- SHUN " --log-tcp-sequence --log-tcp-options --log-ip-options $IPTABLES -A ODDPORTS -j DROP
Ruleset to block repeat offenders
Note: This ruleset is "called" from other ruleset thru the use of the "-m recent" switch. You must have the "recent" module installed for these rules to work. Anywhere you have a DROP sequence (or REJECT) and want to add the offending IP into a temporarily list of offender hosts, just add the "-m recent" switch. Example follows after ruleset:
$IPTABLES -N OFFENDER $IPTABLES -A INPUT -p all -m recent --rcheck --seconds 300 -j OFFENDER $IPTABLES -A FORWARD -p all -m recent --rcheck --seconds 300 -j OFFENDER $IPTABLES -A OFFENDER -m limit --limit 1/second -j LOG --log-level info --log-prefix "OFFENDER -- SHUN " --log-tcp-sequence --log-tcp-options --log-ip-options $IPTABLES -A OFFENDER -j DROP
Example Use:
Note: You will need to install the "recent" module for these rules to work too. If you do not have the "recent" module installed, simply remove this section from these rules "-m recent --set". Remove that, and it should work.
$IPTABLES -N PORTSCAN
#portscan detection module
# NMAP FIN/URG/PSH
$IPTABLES -A INPUT -i all -p tcp --tcp-flags ALL FIN,URG,PSH -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags ALL FIN,URG,PSH -m recent --set -j PORTSCAN
# SYN/RST
$IPTABLES -A INPUT -i all -p tcp --tcp-flags SYN,RST SYN,RST -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags SYN,RST SYN,RST -m recent --set -j PORTSCAN
# SYN/FIN -- Scan(probably)
$IPTABLES -A INPUT -i all -p tcp --tcp-flags SYN,FIN SYN,FIN -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags SYN,FIN SYN,FIN -m recent --set -j PORTSCAN
# NMAP FIN Stealth
$IPTABLES -A INPUT -i all -p tcp --tcp-flags ALL FIN -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags ALL FIN -m recent --set -j PORTSCAN
# ALL/ALL Scan
$IPTABLES -A INPUT -i all -p tcp --tcp-flags ALL ALL -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags ALL ALL -m recent --set -j PORTSCAN
# NMAP Null Scan
$IPTABLES -A INPUT -i all -p tcp --tcp-flags ALL NONE -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags ALL NONE -m recent --set -j PORTSCAN
#XMAS
$IPTABLES -A INPUT -i all -p tcp --tcp-flags ALL URG,ACK,PSH,RST,SYN,FIN -m recent --set -j PORTSCAN
$IPTABLES -A FORWARD -i all -p tcp --tcp-flags ALL URG,ACK,PSH,RST,SYN,FIN -m recent --set -j PORTSCAN
$IPTABLES -A PORTSCAN -m limit --limit 1/second -j LOG --log-level info --log-prefix "PORTSCAN -- SHUN " --log-tcp-sequence --log-tcp-options --log-ip-options
$IPTABLES -A PORTSCAN -j DROP
Contributors to this page: Michael Shinn
.
Page last modified on Wednesday 23 of March, 2005 18:30:38 EST by Michael Shinn
.
The content on this page is licensed under the terms of the Got Root License.
