#!/bin/sh #version 1.1 september 2003 # description: Iptables script for masquerading an esmith 5.6 server as server-gateway. This script does not include PPTP!! #This script uses masquerading from an internal network to the internet using the outside ip address of the server. #These are the traffic flows: #I) for traffic in and out the firewall itsself, # 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. #This is not allowed by default: #Forwarded udp from the lan to the internet. (so point your dns traffic to the lan-NIC of the server). The reason is to stop many worms and viruses that try to connect to the internet and thereby compromise the network. #Specific tcp ports forwarded from the lan to the internet. (445,1433) These are logged. #pptp #This is allowed by default #Incoming tcp-port 80 and 25 syns (connection starts) to the server itself from internet. Since the server is webserver and mailserver. #All incoming traffic from the lan to the server itself. This is logged (syns and udp) except dns. #Outgoing traffic originating from the server ittself (output chain) to the internet and lan. This is logged, except port 53 and 123 udp #Outgoing forwarded traffic from the lan to internet, except all udp. All syns are logged. #All related traffic coming back in from the accepted outgoing traffic. #This script loggs about everyting by default #not logged is #Output dns/ntp from the server to internet. #And incoming scans on ports like 137,135,445,1433,1434 from the internet. #not logged is dns and samba traffic from the lan into the firewall. #also not logged is traffic as response to allowed syns. So such output from the server to internet and from the server to the lan. Also such traffic from the internet into the lan. #Logged is #Forwarded traffic to internet by logging all outgoing syns: that way you can see all visited www-sites. #All dropped packets are logged: syns and udp into the firewall from internet; illegal packets (with wrong tcp-flags) into iptables; udp from the lan to the internet; some ports tcp from the lan to internet. #Outgoing syns are logged in the output and forward chain. #logging uses prefixes: these are the prefixes used in this script: # WrongIcmpOrState in the filter denylog chain. Packets here get dropped are either icmp not-allowed packets, or packets that go into the forward chain that have no state: that would be odd. # DropTcpFlags in the nat denylognat chain. Here packets with tcpflags all/all and all/non are caught and dropped. # OutputSynAccept for output tcp-syns from the server itself to internet or the lan in the outputchain: here you can see what emails and so on were send from the server to internet (what connection the server itsself started). # OutputUdpAccept for output from the server itsself to the internet or to the lan in the output chain. # DropTcpFoward are tcp-syn drops form the lan to the internet on well-known villan ports in the forward chain: this should alarm you # DropUdpForward are udp packets from the lan to internet that are dropped in the forward chain. # AcceptSynForward are accepted syns from the lan to internet in the forward chain: you can use those to make a top100 www-site script # AcceptInLan are syns coming from the lan to the server itself. dns, time and netbios are not logged here: it would fill the disk too quickly. Port 135 is logged. # AcceptServicesIn logs port 80 and 25 in from the internet to the server itsself in the input chain: here you can see who send you mail and who visited the webserver. # DROP-INPUT logs all incoming packets into the server itself from the internet in the blocknostatein chain which is called frm the input chain. Well-known ports like 135,137 and so on are not logged. # SynFlood are packets in the pre-routing nat table: they catch incoming traffic from the internet when the rate is too high. This is off by default though. #This script has some things ready to uncheck (remove "#") to use: #Dnat rule to use transparant squid for browsing, and possibly accelerating for the webserver. #Limit rules to deny too many connections at the time. drops are logged. #ip-spoofing rules. #the outside interface is eth1; the inside interface is eth0. #The outside ip address is 10.0.0.111; the inside ip address is not mentioned. #This script was written by Hans-Cees Speel hanscees@hanscees.com. All improvements are welcome. 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 WrongIcmpOrState /sbin/iptables --append denylog --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 blocknostateforward #new chain block if not new on eth1 or established /sbin/iptables --new-chain blocknostatein #new chain icmp in /sbin/iptables --new-chain icmpInOut #input chain #first all icmp is sent to icmpInOut where onlysome 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 accepted as needed. Here http and smtp (webserver apache and smtp email). #first we log this /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 #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 #Everything else into the server is sent to the blocknostatein chain. In that chain new conections are dropped, but connections related to established connections are accepted. /sbin/iptables --append INPUT -j blocknostatein #output chain. Remember that only traffic from the server itsself passes here. # traffic from the network behind the server passes through the forwardchain.o #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 #after that all is accepted. Let us screen all syns going out for fun and profit. 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 log all outgoing udp , but first #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 #so now log all udp out. /sbin/iptables --append OUTPUT --jump LOG --log-prefix OutputUdpAccept -o eth1 -p udp #after logging we accept all /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. #This chain is problematic if we want to see well what is going out. We want to see that because trojans and viruses possibly on the internal network wil try to connect to the internet through here. (or through squid if you use it). # there are two instances you can take. First you can allow anything and stop some specific ports. #second you can stop all and allow some. #First an example to allow all and stop some. Trojans will probably get out fine here. #notice that we log with --prefix here so we can later find back better what happened. #####allow all and stop some. disabled here. #first we block outgoing trash. tcp and then udp # /sbin/iptables --append FORWARD -j denylog -p tcp -m multiport --destination-port 135,139,445,2049,1433,17300,6588 # /sbin/iptables --append FORWARD -j denylog -p udp -m multiport --destination-port 137,138,2049,1434 #then we accept all related (and new on non-outside nic) # /sbin/iptables --append FORWARD -j block #We take the second stance,but not entirely. We block all udp, but not all tcp. #We first block some tcp (like above) #but then we drop all udp except for some ports we know we want. #you might add 443 and 80 if you use squid #we first log 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 #then we block those ports /sbin/iptables --append FORWARD -j DROP -p tcp -m multiport --destination-port 135,139,445,2049,1433,17300,6588 #now we accept some udp time and dns (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 #accept some ports in if this does not work well otherwise /sbin/iptables --append FORWARD -j ACCEPT -p udp --source-port 123 #now we refuse all udp /sbin/iptables --append FORWARD -j LOG --log-prefix DropUdpForward -p udp /sbin/iptables --append FORWARD -j DROP -p udp #then we accept all related (and new on non-outside nic) #but first we log all outgoing syns #if all this logging of all tcp-syn traffic going out from the lan to the internet grows too much for you you can disable it here for some ports by dropping right away for some ports. But you cannot set up a top -100 url list anymore then!! # /sbin/iptables --append FORWARD -j DROP -p tcp -m multiport --destination-port 80 #we now log all syns going out from the lan to the internet /sbin/iptables --append FORWARD -j LOG --log-prefix AcceptSynForward -p tcp --syn -o eth1 #then we jump to the blocknostateforward chain where outgoing syns are allowed and its return traffic /sbin/iptables --append FORWARD -j blocknostateforward #dont know if weneed this #/sbin/iptables --masquerading --set 14400 60 600 #blocknostateforward chain which accepts if the state is established and #accepts new if the interface is not the outside interface # Allow any already established or related connections on the forward chain /sbin/iptables --append blocknostateforward -m state --state ESTABLISHED,RELATED -j ACCEPT /sbin/iptables --append blocknostateforward -m state --state NEW -i ! eth1 -j ACCEPT /sbin/iptables --append blocknostateforward --jump denylog #blocknostatein chain for incoming syns to the firewall ip address on the internet and lan side. Lan is eth0here: we accept new connections into eth0, not on eth1 (internet) in this chain. # Allow any already established or related connections form the input chain. /sbin/iptables --append blocknostatein -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 blocknostatein -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 blocknostatein -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 blocknostatein -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. #first tcp droppings /sbin/iptables --append blocknostatein -j DROP -i eth1 -p tcp -m multiport --destination-port 445,1433,135,4444,17300 #then udp droppings /sbin/iptables --append blocknostatein -j DROP -i eth1 -p udp -m multiport --destination-port 137,1434 #then we log the not-wel-known ports. /sbin/iptables --append blocknostatein --jump LOG --log-prefix DROP-INPUT #and finally we drop them. /sbin/iptables --append blocknostatein --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 wit 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