#!/bin/sh # LAN_IP="192.168.11.34/24" LAN_BCAST_ADRESS="192.168.11.255/24" LAN_IFACE="eth0" LO_IFACE="lo" LO_IP="127.0.0.1/32" INET_IP="65.207.72.194/28" INET_IFACE="eth1" FW="/sbin/iptables" PERL="/usr/bin/perl" # # Default log level to kern.notice # LOG_LEVEL="kern.notice" # # Reserved networks # RESERVED_NET=" 0.0.0.0/8 1.0.0.0/8 2.0.0.0/8 \ 5.0.0.0/8 \ 7.0.0.0/8 \ 23.0.0.0/8 \ 27.0.0.0/8 \ 31.0.0.0/8 \ 36.0.0.0/8 37.0.0.0/8 \ 39.0.0.0/8 \ 41.0.0.0/8 42.0.0.0/8 \ 58.0.0.0/8 59.0.0.0/8 60.0.0.0/8 \ 67.0.0.0/8 68.0.0.0/8 69.0.0.0/8 70.0.0.0/8 71.0.0.0/8 72.0.0.0/8 73.0.0.0/8 \ 74.0.0.0/8 75.0.0.0/8 76.0.0.0/8 77.0.0.0/8 78.0.0.0/8 79.0.0.0/8 80.0.0.0/8 \ 81.0.0.0/8 82.0.0.0/8 83.0.0.0/8 84.0.0.0/8 85.0.0.0/8 86.0.0.0/8 87.0.0.0/8 \ 88.0.0.0/8 89.0.0.0/8 90.0.0.0/8 91.0.0.0/8 92.0.0.0/8 93.0.0.0/8 94.0.0.0/8 \ 95.0.0.0/8 96.0.0.0/8 97.0.0.0/8 98.0.0.0/8 99.0.0.0/8 100.0.0.0/8 101.0.0.0/8 \ 102.0.0.0/8 103.0.0.0/8 104.0.0.0/8 105.0.0.0/8 106.0.0.0/8 107.0.0.0/8 \ 108.0.0.0/8 109.0.0.0/8 110.0.0.0/8 111.0.0.0/8 112.0.0.0/8 113.0.0.0/8 \ 114.0.0.0/8 115.0.0.0/8 116.0.0.0/8 117.0.0.0/8 118.0.0.0/8 119.0.0.0/8 \ 120.0.0.0/8 121.0.0.0/8 122.0.0.0/8 123.0.0.0/8 124.0.0.0/8 125.0.0.0/8 \ 126.0.0.0/8 127.0.0.0/8 \ 197.0.0.0/8 \ 201.0.0.0/8 \ 219.0.0.0/8 220.0.0.0/8 221.0.0.0/8 222.0.0.0/8 223.0.0.0/8 \ 240.0.0.0/8 241.0.0.0/8 242.0.0.0/8 243.0.0.0/8 244.0.0.0/8 245.0.0.0/8 \ 246.0.0.0/8 247.0.0.0/8 248.0.0.0/8 249.0.0.0/8 250.0.0.0/8 251.0.0.0/8 \ 252.0.0.0/8 253.0.0.0/8 254.0.0.0/8 255.0.0.0/8" ######### # Load all required IPTables modules # # # Adds some iptables targets like LOG, REJECT and MASQUARADE. # modprobe ip_tables modprobe ip_conntrack modprobe ipt_state modprobe ipt_limit modprobe iptable_mangle modprobe iptable_nat modprobe ip_conntrack modprobe ip_conntrack_ftp modprobe ipt_LOG modprobe ipt_REJECT modprobe ipt_MASQUERADE modprobe ipt_string # # Flush everything # echo "Flushing Everything..." $FW -P INPUT DROP $FW -P OUTPUT DROP $FW -P FORWARD DROP $FW -F INPUT $FW -F OUTPUT $FW -F FORWARD echo "Deleting user chains..." for chain in `$FW -L -n | \ $PERL -ane 'print "$F[1]\n" if (($F[0] eq 'Chain')&&($F[1]!~/INPUT|OUTPUT|FORWARD/))'` ; do $FW -F $chain done for chain in `$FW -L -n | \ $PERL -ane 'print "$F[1]\n" if (($F[0] eq 'Chain')&&($F[1]!~/INPUT|OUTPUT|FORWARD/))'` ; do $FW -X $chain done # # Block spoofing on interfaces # if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ]; then echo -n "Setting up IP spoofing protection..." for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f ; done echo "done." else echo DANGER: PROBLEMS SETTING UP IP SPOOFING PROTECTION. fi #------------------------------------------------------------------ # # Set up keep_state table for state matching # echo "Creating keep_state.." $FW -N keep_state $FW -F keep_state $FW -A keep_state -m state --state INVALID -j DROP $FW -A keep_state -m unclean -j DROP $FW -A keep_state -m state --state RELATED,ESTABLISHED -j ACCEPT #-------------------------------------------------------------- # # Set up check_flags to look for weirdness # echo "Creating check_flags.." $FW -N check_flags $FW -F check_flags # # NMAP FIN/URG/PSH $FW -A check_flags -p tcp --tcp-flags ALL FIN,URG,PSH -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "ipfw NMAP-XMAS:" --log-tcp-options --log-ip-options $FW -A check_flags -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP # # SYN/RST $FW -A check_flags -p tcp --tcp-flags SYN,RST SYN,RST -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "ipfw SYN/RST:" --log-tcp-options --log-ip-options $FW -A check_flags -p tcp --tcp-flags SYN,RST SYN,RST -j DROP # # SYN/FIN -- Scan(probably) $FW -A check_flags -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "ipfw SYN/FIN:" --log-tcp-options --log-ip-options $FW -A check_flags -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP # # Slow down other types of port scans to cause script kiddy annoyance $FW -A check_flags -m limit --limit 5/second -p tcp --tcp-flags ALL RST -j ACCEPT $FW -A check_flags -m limit --limit 5/second -p tcp --tcp-flags ALL FIN -j ACCEPT $FW -A check_flags -m limit --limit 5/second -p tcp --tcp-flags ALL SYN -j ACCEPT #---------------------------------------------------------- # # deny_ports # # ## TCP ## # 111 Sunrpc (rpc.statd vulnerability in some Linux may be exploited) # 137:139 Netbios/SMB # 1500 ssdp, exploit of XP Remote PnP flaw # 2049 NFS # 5000 commplex-main?, exploit of XP Remote PnP flaw # 6000:6063 X # 20034 Netbus 2 Pro # 12345:12346 Netbus # 27374 SubSeven Trojan for Win 95/98 scan this port by default # 27665,27444,31335 Trinoo # 10498,12754 Mstream # # ## UDP ## # 2049 NFS # 31337 BO2k # 27444,31335 Trinoo # 10498 mstream # echo "Creating deny_ports.." $FW -N deny_ports $FW -F deny_ports # # 137 is a netbios nameserver lookup. It often happens when we hit an external Windows based website # and should be considered a non-problematic probe that we can just ignore. # $FW -A deny_ports -p tcp --dport 137 -j DROP $FW -A deny_ports -p udp --dport 137 -j DROP DENIED_PORTS_TCP="111 138 139 1500 2049 5000 6000:6063 20034 12345:12346 27374 27665 27444 31335 10498 12754 32768 32769 32770 8200 8201" for PORT in $DENIED_PORTS_TCP; do $FW -A deny_ports -p tcp --dport $PORT -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "ipfw DENIED:" --log-tcp-options --log-ip-options $FW -A deny_ports -p tcp --sport $PORT -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "ipfw DENIED:" --log-tcp-options --log-ip-options $FW -A deny_ports -p tcp --dport $PORT -j DROP $FW -A deny_ports -p tcp --sport $PORT -j DROP done DENIED_PORTS_UDP="111 138 139 1500 2049 5000 31337 27444 31335 32768 32769 32777 8200 8201 10498" for PORT in $DENIED_PORTS_UDP; do $FW -A deny_ports -p udp --dport $PORT -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "ipfw DENIED:" --log-tcp-options --log-ip-options $FW -A deny_ports -p udp --sport $PORT -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "ipfw DENIED:" --log-tcp-options --log-ip-options $FW -A deny_ports -p udp --dport $PORT -j DROP $FW -A deny_ports -p udp --sport $PORT -j DROP done #----------------------------------------------------- # # allow ports # # TCP: domain ssh smtp tls/ssl (hold off on www until apache gets set up) # UDP: domain ntp # echo "Creating accept_ports" $FW -N allow_ports $FW -F allow_ports TCP_PORTS="22 25 53 80 123 443 563 580 1865 2514" for PORT in $TCP_PORTS; do $FW -A allow_ports -m state --state NEW -p tcp --dport $PORT -j ACCEPT done UDP_PORTS="53 80 123 563 580 1865 2514" for PORT in $UDP_PORTS; do $FW -A allow_ports -m state --state NEW -p udp --dport $PORT -j ACCEPT done # # Also allow source port DNS UDP traffic # $FW -A allow_ports -m state --state NEW -p udp --sport 53 -j ACCEPT # # Allow source port smpt traffic (slow closing hotmail/Exchange connections?) # $FW -A allow_ports -p tcp --sport 25 -j ACCEPT # # Allow source port http traffic (not sure why packets escaped keep_state) # $FW -A allow_ports -p tcp --sport 80 -j ACCEPT # # reject ident with extreme prejudice # $FW -A allow_ports -p tcp --dport 113 -j REJECT --reject-with tcp-reset #------------------------------------------------ # # src_egress table # echo "Creating src_egress.." $FW -N src_egress $FW -Z src_egress ## Class A Reserved $FW -A src_egress -s 10.0.0.0/8 -j DROP ## Class B Reserved $FW -A src_egress -s 172.16.0.0/12 -j DROP ## Class C Reserved $FW -A src_egress -s 192.168.0.0/16 -j DROP ## Class D Reserved $FW -A src_egress -s 224.0.0.0/4 -j DROP ## Class E Reserved $FW -A src_egress -s 240.0.0.0/5 -j DROP for NET in $RESERVED_NET; do $FW -A src_egress -s $NET -j DROP done #----------------------------------------------- # # mangle_output # # # Mangle values of packets created locally. Only TOS values are mangled right # now. Most of these settings are RFC 1060/1349 suggested. # # TOS stuff: # Minimize-Delay 16 (0x10) # Maximize-Throughput 8 (0x08) # Maximize-Reliability 4 (0x04) # Minimize-Cost 2 (0x02) # Normal-Service 0 (0x00) # # Note: I'd use hex values instead of symbolic, but it appears this version of iptables # (1.2.3) gets its panties in a bunch over anything but... go figure. # echo "Creating mangle_output" $FW -t mangle -N mangle_output $FW -t mangle -F mangle_output $FW -t mangle -A mangle_output -p tcp --dport 20 -j TOS --set-tos Maximize-Throughput $FW -t mangle -A mangle_output -p tcp --dport 21 -j TOS --set-tos Minimize-Delay $FW -t mangle -A mangle_output -p tcp --dport 22 -j TOS --set-tos Minimize-Delay $FW -t mangle -A mangle_output -p tcp --dport 23 -j TOS --set-tos Minimize-Delay $FW -t mangle -A mangle_output -p tcp --dport 25 -j TOS --set-tos Minimize-Delay $FW -t mangle -A mangle_output -p tcp --dport 53 -j TOS --set-tos Minimize-Delay $FW -t mangle -A mangle_output -p udp --dport 53 -j TOS --set-tos Minimize-Delay $FW -t mangle -A mangle_output -p tcp --dport 80 -j TOS --set-tos Maximize-Throughput #--------------------------------------------- # # mangle_prerouting # # Likewise but for routed packets through the firewall. # echo "Creating mangle_prerouting.." $FW -t mangle -N mangle_prerouting $FW -t mangle -F mangle_prerouting $FW -t mangle -A mangle_prerouting -p tcp --dport 20 -j TOS --set-tos Maximize-Throughput $FW -t mangle -A mangle_prerouting -p tcp --dport 21 -j TOS --set-tos Minimize-Delay $FW -t mangle -A mangle_prerouting -p tcp --dport 22 -j TOS --set-tos Minimize-Delay $FW -t mangle -A mangle_prerouting -p tcp --dport 23 -j TOS --set-tos Minimize-Delay $FW -t mangle -A mangle_prerouting -p tcp --dport 25 -j TOS --set-tos Minimize-Delay $FW -t mangle -A mangle_prerouting -p tcp --dport 53 -j TOS --set-tos Minimize-Delay $FW -t mangle -A mangle_prerouting -p udp --dport 53 -j TOS --set-tos Minimize-Delay $FW -t mangle -A mangle_prerouting -p tcp --dport 80 -j TOS --set-tos Maximize-Throughput #------------------------------------------------------------------------------ # Firewall input chains #------------------------------------------------------------------------------ # # External interface # echo "Creating external_input.." $FW -N external_input $FW -F external_input $FW -A external_input -i eth1 -p tcp -j check_flags $FW -A external_input -i eth1 -p ! icmp -j deny_ports # # Nimda blocking first before we allow port 80 acceptance # $FW -A external_input -i eth1 -p tcp --dport 80 -m string --string "/cmd.exe" -m state --state ESTABLISHED -j REJECT --reject-with tcp-reset $FW -A external_input -i eth1 -p tcp --dport 80 -m string --string "/root.exe" -m state --state ESTABLISHED -j REJECT --reject-with tcp-reset $FW -A external_input -i eth1 -p tcp --dport 80 -m string --string "/Admin.dll" -m state --state ESTABLISHED -j REJECT --reject-with tcp-reset # # Now allow certain ports # $FW -A external_input -i eth1 -p ! icmp -j allow_ports #------------------------------------------------------------------------------ # Main #------------------------------------------------------------------------------ # # internal interfaces # echo "Opening up internal interfaces" $FW -A INPUT -i lo -j ACCEPT $FW -A INPUT -i eth0 -j ACCEPT # # Turn on Masquerade # $FW -t nat -A POSTROUTING -s 192.168.11.0/24 -j MASQUERADE # # Allow most icmp (except redirects) # echo "Setting up icmp filtering..." # (done in kernel on the interface) $FW -A INPUT -p icmp --icmp-type redirect -j DROP $FW -A INPUT -p icmp -j ACCEPT # # INPUT on the external interface # echo "Opening up external INPUT.." ## Filter out Reserved/Private IP addresses based on source IP. $FW -A INPUT -i eth1 -j src_egress ## Jump to our EXTERNAL_INPUT Chain. $FW -A INPUT -i eth1 -j external_input ## DROP/ACCEPT packets based on the state of the connection. $FW -A INPUT -i eth1 -j keep_state #-------------------------------------- # OUTPUT #------------------------------------- # # mangle table for output # echo "Opening up output.." $FW -t mangle -A OUTPUT -o eth1 -j mangle_output $FW -t mangle -A PREROUTING -i eth0 -j mangle_prerouting $FW -A OUTPUT -j ACCEPT # # LOG and DROP TCP packets with no flags set. # Possible NULL scan. # $FW -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "ipfw NULLSCAN:" --log-tcp-options --log-ip-options $FW -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP $FW -A OUTPUT -j ACCEPT #-------------------------------------------------- # FORWARD #-------------------------------------------------- echo "Opening up forward..." $FW -A FORWARD -s 192.168.11.0/24 -j ACCEPT $FW -A FORWARD -j keep_state #--------------------------------------- # # Final set of rules, reject and log the leftover packets # $FW -A INPUT -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "ipfw INP:" --log-tcp-options --log-ip-options $FW -A OUTPUT -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "ipfw OUT:" --log-tcp-options --log-ip-options $FW -A FORWARD -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "ipfw FWD:" --log-tcp-options --log-ip-options #------------------------------------------------------------------------------------------ # End Firewall. # # Begin kernel tweaks #------------------------------------------------------------------------------------------ # # Turn on forwarding # echo "1" > /proc/sys/net/ipv4/ip_forward # # Local port range for TCP/UDP connections # if [ -e /proc/sys/net/ipv4/ip_local_port_range ]; then echo -e "32768\t61000" > /proc/sys/net/ipv4/ip_local_port_range fi # # Ignore any broadcast icmp echo requests # if [ -e /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts ]; then echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts fi # # Log packets with impossible addresses to kernel log. # if [ -e /proc/sys/net/ipv4/conf/all/log_martians ]; then echo "1" > /proc/sys/net/ipv4/conf/all/log_martians fi # # Disable ICMP redirects on eth1 # if [ -e /proc/sys/net/ipv4/conf/$EXTERNAL/accept_redirects ]; then echo "0" > /proc/sys/net/ipv4/conf/$EXTERNAL/accept_redirects fi