#!/bin/sh #version 2.0 september 2005 By Hans-Cees Speel. # description: Iptables script for esmith 7 server (contribs.org) as server-gateway. #This script does not include PPTP nor ipsec!! #reason to write this script: I want to be in control of my server, so I want my ipnat rules. #I want to log about everything so I can see if something weird is there. #This script first wipes out all existing iptables lines and use this script only. #This script uses masquerading from an internal network to the internet #using the outside ip address of the server. #First you have to understand how packet traverse the filters with iptables: # +------------+ +---------+ +-------------+ #Packet -| PREROUTING |--- routing-----| FORWARD |-------+-------| POSTROUTING |- Packets #input +------------+ decision +-­-------+ | +-------------+ out # | | # +-------+ +--------+ # | INPUT |---- Local process -| OUTPUT | # +-------+ +--------+ # used from http://lartc.org/howto/lartc.cookbook.fullnat.intro.html #These are the traffic flows: #I) for traffic in and out the firewall itsself, both from internet and from lan # In: first prerouting, then input. # Out: first output then postrouting #II) for traffic from the internal masqueraded network to the internet and back: # Out: first prerouting, then forward and then postrouting. # In: first prerouting then forward and then postrouting. ##For this script: ###In short: #not allowed is: #udp from lan to internet, except 123. Lan dns resolving must be on this server. #tcp port 135,139,445,2049,1433,17300,6588 from lan to internet #tcp from internet to server except on ports T80,25 U53 ##as a conclusion not possible: pptp (gre) ipsec (isa-kmp or IKE [udp 500] and esp) ##allowed is: #all tcp from lan to internet #all tcp and udp from server to internet #all on local interface lo ##logged is: #all syns and udp from server to internet #all syns and udp from internet to server #all syns from lan to internet ### ###In long: #Logging in /vasr/log/messages means: #WrongIcmpFilter: icmp input blocked OR #WrongIcmpFilter: icmp output blocked OR #WrongStateFilter: something in forward chain goes wrong (impossible in theory) #AcceptServicesIn: internet to firewall T(25,80,53) U(53) #AcceptInLan: accept input from lan not: related,established, udp(53,123,137,138) #DropInputInternet: drop input from internet to firewall NOT ports Tcp(445,1433,135,4444,17300) UDP(137,1434) #OutputSynAccept: firewall Tcp syns to internet except multicast #OutputUdpAccept: firewall udp to internet except U(53,123) #DropTcpFlags: from anywhere to firewall (prerouting) with wrong tcp flags #DropTcpForward: (forward) from lan to internet T(135,139,445,2049,1433,17300,6588) #DropUdpForward: (forward) from lan to internet U(all but 53,123) #AcceptSynForward: all syns from lan to internet #SynFloodDrop Too many syns/sec (disabled, prerouting) #Not logged is: #Local interface lo traffic #Lan to firewall traffic related,established or udp(53,123,137,138) #Internet to firewall Tcp(445,1433,135,4444,17300), state related,established UDP(137,1434) multicast #firewall to internet multicast udp 53,123 and Tcp state related,established #lan to internet U(53 123) #lan to internet, Tcp state established ###################Overview chains and logging short and in full ################ ###################################Chains and logging used, short version############################## # +------------+ +---------+ +-------------+ #Packet -| PREROUTING |--- routing-----| FORWARD |-------+-------| POSTROUTING |- Packets # 1. (nat table) tcp-flags 1. T port 135,139,445,2049,1433,17300,6588 # --> CHAIN: denylognat LOG: DropTcpForward & drop # 1.1 drop&LOG: DropTcpFlags 3. Accept -dpt&src udp 53,123 1. All out of Ext --> # 3. Disabled: 5. UDP all LOG:DropUdpForward & drop chain: MASQUERADE # syn --> CHAIN: synflood 7. Disabled: don't log port 80 syns # 3.2 LOG: SynFloodDrop &drop 8. Tcp syns out of Ext LOG: AcceptSynForward # 4. Disabled: redirect 9. rest --> CHAIN: StatefulForwardFilter # port 80 to 3280 (squid) 9.1 accept state established,related & new from lan # 5. default: accept 9.3 rest -> CHAIN: denylog (LOG: WrongIcmpFilter &drop) # #input +------------+ decision +-­-------+ | +-------------+ out # | | # +-------+ +--------+ # | INPUT |---- Local process -| OUTPUT | # 1. icmp->CHAIN icmpInOut 1. icmp -> CHAIN: icmpInOut # 1.x Accept some 1.x Accept some # 1.7.1 CHAIN denylog 1.7.1 CHAIN denylog # 1.7.2 drop &LOG: WrongIcmpFilter 1.7.2 drop &LOG: WrongIcmpFilter # 2. Interface lo yes 2. Interface lo yes # 3. drop multicast 3. drop multicast # 4. Allow services state new 4. syns out EXT LOG: OutputSynAccept # LOG: AcceptServicesIn 5. Accept Udp out (53 123) # 5. rest ->CHAIN: StatefulInputFilter 6. Udp out EXt LOG: OutputUdpAccept # 5.1 accept state established, related 7. Accept all # 5.2 accept 53 123 137 138 from lan # 5.3 rest from lan LOG:AcceptInLan # 5.4 accept rest state new from lan # 5.5 drop from Ext T 445,1433,135,4444,17300 # 5.6 drop from Ext U 137 1434 # 5.7 drop rest LOG: DropInputInternet # 5.8 DROP all # +-------+ +--------+ ############################################################################################### ######################################################################################## ###################################Chains and logging used, full version################ # +------------+ +---------+ +-------------+ #Packet -| PREROUTING |--- routing-----| FORWARD |-------+-------| POSTROUTING |- Packets # 1. (nat table) tcp-flags ALL All 1. T port 135,139,445,2049,1433,17300,6588 # --> chain: denylognat Log: DropTcpForward # 1.1 log: DropTcpFlags 2. drop ports point 1 1. All out of Ext --> # 1.2 Drop 3. Accept -dpt udp 53,123 chain: MASQUERADE # 2. (nat table) tcp-flags ALL NON 4. Accept -src udp 53,123 # --> chain: denylognat 5. UDP all Log:DropUdpForward # 2.1 log: DropTcpFlags 6. UDP all drop # 2.2 drop 7. Disabled: accept port 80 syns # 3. Disabled: 8. Tcp syns out of Ext Log: AcceptSynForward # syn --> chain: synflood 9. rest --> chain: StatefulForwardFilter # 3.1 limit 44/s burst 150: to 4 9.1 accept state established,related # 3.2 log: SynFloodDrop 9.2 accept state new from lan (not ext) # 3.3 drop 9.3 rest -> chain: denylog # 4. Disabled: redirect 9.3.1 log: WrongIcmpFilter # port 80 to 3280 (squid) 9.3.2 Drop # 5. default: accept #input +------------+ decision +-­-------+ | +-------------+ out # | | # +-------+ +--------+ # | INPUT |---- Local process -| OUTPUT | # 1. icmp->Chain icmpInOut 1. icmp -> chain: icmpInOut # 1.1 Accept ping 1.1 Accept ping # 1.2 Accept pong 1.2 Accept pong # 1.3 Accept port unreach 1.3 Accept port unreach # 1.4 Accept source quench 1.4 Accept source quench # 1.5 Accept time exceed 1.5 Accept time exceed # 1.6 Accept parameter problem 1.6 Accept parameter problem # 1.7.1 chain denylog 1.7.1 chain denylog # 1.7.2 log: WrongIcmpFilter 1.7.2 log: WrongIcmpFilter # 1.7.3 Drop 1.7.3 Drop # 2. Interface lo yes 2. Interface lo yes # 3. drop multicast 3. drop multicast # 4. Allow services state new 4. syns out EXT Log: OutputSynAccept # (80 25 53UT) # 4 Log: AcceptServicesIn 5. Accept Udp out (53 123) # 5. rest ->chain: StatefulInputFilter 6. Udp out EXt log: OutputUdpAccept # 5.1 accept state established, related 7. Accept all # 5.2 accept 53 123 137 138 from lan # 5.3 Log rest from lan as :AcceptInLan # 5.4 accept rest state new from lan # 5.5 drop from Ext T 445,1433,135,4444,17300 # 5.6 drop from Ext U 137 1434 # 5.7 drop rest Log: DropInputInternet # 5.8 DROP all # +-------+ +--------+ ############################################################################################### #The outside interface is eth1; the inside interface is eth0. #Outside ip address nor inside ip address is mentioned. echo -n "flushing all chains" /sbin/iptables -F -t filter /sbin/iptables -F -t nat /sbin/iptables -F -t mangle /sbin/iptables -X -t filter /sbin/iptables -X -t nat /sbin/iptables -X -t mangle /sbin/iptables --flush FORWARD /sbin/iptables --flush INPUT /sbin/iptables --flush OUTPUT /sbin/modprobe ip_nat_ftp /sbin/modprobe ip_conntrack_ftp #policies for the chains /sbin/iptables --policy FORWARD DROP /sbin/iptables --policy INPUT DROP /sbin/iptables --policy OUTPUT DROP #new chain denylog for use in the filter table. First logs, then drops /sbin/iptables --new-chain denylog /sbin/iptables --append denylog --jump LOG --log-prefix WrongIcmpFilter /sbin/iptables --append denylog --jump DROP #new chain denylog for use in the filter table. First logs, then drops /sbin/iptables --new-chain denylogstate /sbin/iptables --append denylogstate --jump LOG --log-prefix WrongStateFilter /sbin/iptables --append denylogstate --jump DROP #new chain denylog for use in the nat table (you can use the same named #for chains in the nat and filter table: they are different chains however!) /sbin/iptables -t nat --new-chain denylognat /sbin/iptables -t nat --append denylognat --jump LOG --log-prefix DropTcpFlags /sbin/iptables -t nat --append denylognat --jump DROP #new chain block if not new on eth1 or established /sbin/iptables --new-chain StatefulForwardFilter #new chain block if not new on eth1 or established /sbin/iptables --new-chain StatefulInputFilter #new chain icmp in /sbin/iptables --new-chain icmpInOut ###INPUT chain #first all icmp is sent to icmpInOut where only some are accepted. #then all on the local loop is accepted #then all multicast is dropped /sbin/iptables --append INPUT --protocol icmp --jump icmpInOut /sbin/iptables --append INPUT -i lo -j ACCEPT /sbin/iptables --append INPUT -s 224.0.0.0/4 -j DROP /sbin/iptables --append INPUT -d 224.0.0.0/4 -j DROP #now services into the server are logged and accepted as needed. Here http and smtp (webserver apache and smtp email). #first we log this ##logging is done by apache # /sbin/iptables --append INPUT -p tcp --dport 80 -m state --state NEW -j LOG --log-prefix AcceptServicesIn /sbin/iptables --append INPUT -p tcp --dport 25 -m state --state NEW -j LOG --log-prefix AcceptServicesIn /sbin/iptables --append INPUT -p udp --dport 53 -m state --state NEW -j LOG --log-prefix AcceptServicesIn /sbin/iptables --append INPUT -p tcp --dport 53 -m state --state NEW -j LOG --log-prefix AcceptServicesIn #now we actually let them in /sbin/iptables --append INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT /sbin/iptables --append INPUT -p tcp --dport 25 -m state --state NEW -j ACCEPT /sbin/iptables --append INPUT -p tcp --dport 53 -m state --state NEW -j ACCEPT /sbin/iptables --append INPUT -p udp --dport 53 -m state --state NEW -j ACCEPT #Everything else into the server is sent to the StatefulInputFilter chain. In that chain new conections are dropped, but connections related to established connections are accepted. /sbin/iptables --append INPUT -j StatefulInputFilter ####OUTPUT chain. Remember that only traffic from the server itsself passes here. #first icmp is screened into the icmpinout chain. #then local loop is accepted and multicast is blocked /sbin/iptables --append OUTPUT --protocol icmp --jump icmpInOut /sbin/iptables --append OUTPUT -o lo -j ACCEPT /sbin/iptables --append OUTPUT -s 224.0.0.0/4 -j DROP /sbin/iptables --append OUTPUT -d 224.0.0.0/4 -j DROP #Now all is accepted. Log all syns going out. A reason to screen here is to see what squid is doing. #log all outgoing tcp syns. /sbin/iptables --append OUTPUT --jump LOG --log-prefix OutputSynAccept -o eth1 -p tcp --syn #do not log dns and time protocol out, it drives you crazy /sbin/iptables --append OUTPUT --jump ACCEPT -p udp -m multiport --dport 53,123 #do log the rest of outgoing udp /sbin/iptables --append OUTPUT --jump LOG --log-prefix OutputUdpAccept -o eth1 -p udp #Finally we accept all outgoing traffic /sbin/iptables --append OUTPUT --jump ACCEPT #######FORWARD chain. Remember that this is the chain where traffic passes that goes through the server, so from the internal network to the internet and back. #We want to log traffic here to see trojans on the lan and to make a top 10 of popular urls for instance # There are two stances you can take. # 1. Allow anything and stop some specific ports. # 2. stop all and allow some. #We take the second stance, but not entirely. #We block most udp (only not 123,53). We block some tcp, but log all syns #Log and block known villan tcp ports /sbin/iptables --append FORWARD -j LOG --log-prefix DropTcpForward -p tcp -m multiport --destination-port 135,139,445,2049,1433,17300,6588 /sbin/iptables --append FORWARD -j DROP -p tcp -m multiport --destination-port 135,139,445,2049,1433,17300,6588 #accept some udp (you can block this if you want them to use your dns server only. That way you can use a split-brain dns solution) #/sbin/iptables --append FORWARD -j ACCEPT -p udp -m multiport --destination-port 53,123 /sbin/iptables --append FORWARD -j ACCEPT -p udp -m multiport --destination-port 123 #accept some ports in if this does not work well otherwise /sbin/iptables --append FORWARD -j ACCEPT -p udp --source-port 123 /sbin/iptables --append FORWARD -j ACCEPT -p udp --source-port 53 #now log and refuse all udp /sbin/iptables --append FORWARD -j LOG --log-prefix DropUdpForward -p udp /sbin/iptables --append FORWARD -j DROP -p udp #you can disable http logging from lan to internet. But a top-100 url list is impossible!! # /sbin/iptables --append FORWARD -j StatefulForwardFilter -p tcp -m multiport --destination-port 80 #log all syns from lan to internet /sbin/iptables --append FORWARD -j LOG --log-prefix AcceptSynForward -p tcp --syn -o eth1 #jump to statefull chain StatefulForwardFilter /sbin/iptables --append FORWARD -j StatefulForwardFilter # StatefulForwardFilter chain: accepts state established and related on all interfaces # but accepts state new only for the lan interface (not external) # Allow any already established or related connections on the forward chain /sbin/iptables --append StatefulForwardFilter -m state --state ESTABLISHED,RELATED -j ACCEPT /sbin/iptables --append StatefulForwardFilter -m state --state NEW -i ! eth1 -j ACCEPT /sbin/iptables --append StatefulForwardFilter --jump denylogstate #StatefulInputFilter chain for incoming syns to the firewall ip address on the internet and lan side. # Allow any already established or related connections from the input chain. /sbin/iptables --append StatefulInputFilter -m state --state ESTABLISHED,RELATED -j ACCEPT #Here we log what is accepted in on the lanside. #first we make sure we do not log dns and samba on the lanside.: we accept it without logging. /sbin/iptables --append StatefulInputFilter -i eth0 -p udp -m multiport --destination-port 53,123,137,138 -j ACCEPT #now we log all else accepted into the firewall from the lanside /sbin/iptables --append StatefulInputFilter -m state --state NEW -i ! eth1 -j LOG --log-prefix AcceptInLan #now we accept in all new connections from the lan into the firewall on eth0. /sbin/iptables --append StatefulInputFilter -m state --state NEW -i ! eth1 -j ACCEPT #this chain however not only is sed for traffic from the lan into the firewall, but also from the internet. We deal with this traffic here: #although we like to see what is going on we do not like to see hundreds of scans a day caused by microsoft products from the internet: we drop those right away without logging them. #drop and don't log some "known" tcp droppings and some udp droppings /sbin/iptables --append StatefulInputFilter -j DROP -i eth1 -p tcp -m multiport --destination-port 445,1433,135,4444,17300 /sbin/iptables --append StatefulInputFilter -j DROP -i eth1 -p udp -m multiport --destination-port 137,1434 #drop and log the rest /sbin/iptables --append StatefulInputFilter --jump LOG --log-prefix DropInputInternet /sbin/iptables --append StatefulInputFilter --jump DROP #chain icmpInOut This chain is used for icmp and lets only certain kinds in. /sbin/iptables --append icmpInOut --proto icmp --icmp-type echo-request --jump ACCEPT /sbin/iptables --append icmpInOut --proto icmp --icmp-type echo-reply --jump ACCEPT /sbin/iptables --append icmpInOut --proto icmp --icmp-type destination-unreachable --jump ACCEPT /sbin/iptables --append icmpInOut --proto icmp --icmp-type source-quench --jump ACCEPT /sbin/iptables --append icmpInOut --proto icmp --icmp-type time-exceeded --jump ACCEPT /sbin/iptables --append icmpInOut --proto icmp --icmp-type parameter-problem --jump ACCEPT /sbin/iptables --append icmpInOut --jump denylog #rules to drop bad packets right away. Prerouting is before all other chains. We drop packets that have impossible tcp-flags set. You can add all kinds of otherstuff here. /sbin/iptables -t nat --append PREROUTING -p tcp --tcp-flags ALL ALL --jump denylognat /sbin/iptables -t nat --append PREROUTING -p tcp --tcp-flags ALL NONE --jump denylognat #rules that can redirect incoming ports to others can go here. The example here reroutes port 80 on the internal interface to 3128 so that all webtraffic goes through squid. #/sbin/iptables -t nat --append PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3128 #rules to log all syns and stop dos atacks> Be carefull with this since you can #cause you own denial of service. I have made the rules available, but disable them all to use it in the nat table by default. This chain is in the prerouting chain which is before all other chains. /sbin/iptables -t nat -N synflood #further with the synflood protection /sbin/iptables -t nat --append synflood -m limit --limit 44/s --limit-burst 150 -j RETURN /sbin/iptables -t nat --append synflood -j LOG --log-prefix SynFloodDrop /sbin/iptables -t nat --append synflood -j DROP #now jump to that chain to synflood check Disabled by default #/sbin/iptables -t nat --append PREROUTING -i eth1 -d 10.0.0.111 -p tcp --syn --jump synflood #Here we log all syns (connection establishment in tcp) that go out the server. This includes packets from the server itsself as well as traffic from the intranet behind the server. #this is switched off here because we log all syns already in the output and forward chains. #masq rule /sbin/iptables -t nat --append POSTROUTING -o eth1 -j MASQUERADE #some /proc stuff #explictly disable ecn if [ -e /proc/sys/net/ipv4/tcp_en ] then echo 0 > /proc/sys/net/ipv4/tcp_en fi #disable spoofing on interfaces #you can enablethis on the outside interface if you want #echo 1 > /proc/sys/net/ipv4/conf/eth0/rp_filter #enableip forwarding for the internal lan echo 1 > /proc/sys/net/ipv4/ip_forward echo 1 > /proc/sys/net/ipv4/tcp_syncookies /usr/bin/logger Iptables script hcs implemented #/root/scripts/wshaper 2>&1 &