#!/bin/bash # # Jan K Labanowski, jkl@ccl.net, August, 2001 Thu Aug 30 23:17:39 EDT 2001 # # Please help me to maintain the script. If you see something wrong, bad # or stupid, just tell me to fix it. Firewalls are not my specialty, what # the true gurus can see. Reward me for my humility... . # # This "yet another firewal script" (YAFS) makes the assumption which I have # at home. It uses kernel 2.4.9 specially compiled for the occession and the # iptables-1.2.2 release. The compilation and installation of kernel # and iptables is described elsewhere: # http://www.ccl.net/cca/software/unix/iptables # # My arrangement at home is very simple: # # DHCP # Internet---CableModem--[Ethernet Hub]--eth0(3C509)[Firewall/NAT Host] # (Tulip) # eth1 [192.168.0.1] # | # |Cross over cable # | # eth0 [192.168.0.5] # (PCMCIA Ether Card) # My Laptop (Dell) # # # # or actually there are a bunch of PCs running Windoz attached. # # Internet---CableModem--[Ethernet Hub]--eth0(3C509)[Firewall/NAT Host] # (Tulip) # eth1 [192.168.0.1] # | # | # | # | # -------- | # | Ether | uplink | # | Hub |----------------- # | | # | |---------------------- # | | | # | |----------- | # | | | | # | |----- | | # | | | | | # | | | | | # | | | | | # | | | | | # -------- | | | # | | | # | | | # -------------- | ------ # | | | # | | | # 192.168.0.5 192.168.0.3 192.168.0.4 # Static IP address Static IP address Static IP add. # Linux Laptop Windows 98 Windows 98 # eth0 eth0 eth0 # # # # # Few principles behind the script: # I USUALLY LOG what I DROP/REJECT, at least during debuging stage. # Later on, it is probably sensible just to comment out most if not all of the # lines which have -j LOG in them, so they do not clutter your console # and /var/log/messages file. # My logging is done via "notice" level which I enabled in /etc/syslog.conf # file. I added the following line # *.notice /var/log/messages.notice # to /etc/syslog.conf # and then I ran: # /etc/rc.d/init.d/syslog restart # # I use log-level "notice" in -j LOG to write log entry in # /var/log/messages.notice # While I am logging most DROPs during debugging it is probably not a good idea # in the production setting, since hackers will fill up your disk in no time. # But for my home network, the worst I will have is to do is log in as: # LILO: linux single # and remove/truncate my /var/log/messages.notice file I should probably # link it to some separate partition, so system does not die when I fill # up the partition with /var/log/messages.notice # # Hint for debugging... # I have all policies set to DROP on all chains. But sometimes things # do not work. So, before the end of the script, I have a number of # commented out lines, which let everything in, but log this stuff which # was let in with the unique prefix. When I am desperate, and I cannot # do what I need to do, I am uncommenting these lines, and let everything # through. But then, by looking at the log (/var/log/messages.notice), # I know which rules I need to add/change, to make things work. # # I only allow the following ports to be accessible (+ ftp going outside ports) # 22(ssh), 53(DNS), 80(HTTP), 443(HTTPS) # If you run more stuff on the firewall (like sendmail, gopher, whatever) you # need to look fir lins with "22,53" and add it there. You also may need special # modules to classify packets as RELATED if sockets are opened in two # directions (review the ftp case which is supported here as example). # # I am sure there are many errors and logical mistakes in this script. # If you find them, could you please tell me? # # The basic organization of the script is this: # 1) Get some information to put into environmental variables, and load modules # 2) Load iptables modules and set few flags # 3) Set policies on chains which I am using to DROP # 4) Start Masquerading # 5) Junk some obviously sick packets in the PREROUTING stage # 6) foreach built-in chain in (PREROUTING, POSTROUTING, INPUT, OUTPUT, FORWARD) # foreach protocol in (ucp, tcp, icmp) # accept or reject the packets # 7) foreach built-in chain in (PREROUTING, POSTROUTING, INPUT, OUTPUT, FORWARD) # for ALL protocols, do some final clean up. # 8) Debug logs for missed packets (usually commented out). # 9) Turn on forwarding flag # # I tried to do it like this that the rules on the top of chain/protocol # combination are the most specific, so I do not inadvertently do not drop # the good packet, or accept the wrong packet. Then when the specific cleaning # is done, I do some generic DROP or ACCEPT actions, since most of the # packets should already been taken care of with specific rules. Very few # packets should get to the end of chain, and most of it should be something # which you do not really care much. So you want to do accept what you can # accept, and the chain policy will kill the rest anyhow. # Of course, there are as many filtering rule-sets as there are people. # I am sure I erred, and again, if you see bad things tell me. # Another stuff... I do allow some NEW packets comming to my firewall, # and I do not care much whats get out (OUTPUT chain and POSTROUTING). # This is my home network, and I am more weary that they mess up my computer # than they see my secrets, since I only have a few of them {:-)}. # For example, I allow ports 6000-10 (X-window) which they can come an see # my screen. I do not care, really... # # set -x # Uncomment for Debugging DATE=`date` # todays time stamp INET_IFACE=eth0 # Internet side interface (it can be ppp0 too) LAN_IFACE=eth1 # LAN side interface LOCALHOST_IP=127.0.0.1 # localhost LAN_IP=192.168.0.0/24 # IP addresses on the LAN side LOOPBACK=127.0.0.0/8 # Idea taken from James C. Stephens # http://www.cs.princeton.edu/~jns/security/iptables STATIC_IP_ADDRESS="" # if you have a static IP address, put someting here IPTABLES=/usr/bin/iptables # this is where I have my iptables # Note... in the grep below the string 'inet addr:' is looked for. # This is for English Linuces... I was told that in French linuces, the # string is: 'inet adr:' and in other languages may be different. # run ifconfig manually and see what it is # I need to get my current IP address MY_IP_ADDRESS=`/sbin/pump --status | /bin/grep IP: | /bin/sed -e 's/.*IP: //'` if [ ${MY_IP_ADDRESS}x = "x" ]; then MY_IP_ADDRESS=`/sbin/ifconfig $INET_IFACE | grep 'inet addr:' | \ awk '{print $2}' | sed -e 's/addr://'` fi # find my BROADCAST address (X.X.X.255). MY_IP_BCAST=`echo $MY_IP_ADDRESS | /bin/sed -e 's/\.[0-9]*$/.255/'` # echo $MY_IP_ADDRESS # echo $MY_IP_BCAST # find RPC UDP ports RPC_UDP_PORTS=`/usr/sbin/rpcinfo -p localhost | grep udp | awk '{print $4}'` # find RPC TCP ports RPC_TCP_PORTS=`/usr/sbin/rpcinfo -p localhost | grep tcp | awk '{print $4}'` # Mark in the /var/log/messages/notice that we are starting the firewall /usr/bin/logger -p kern.notice -t NETFILTER \ "====== Netfilter Start: $DATE =========" # check if needed iptables modules are loaded /sbin/modprobe ip_tables /sbin/modprobe ip_queue /sbin/modprobe iptable_filter /sbin/modprobe iptable_mangle /sbin/modprobe iptable_nat /sbin/modprobe ipt_limit /sbin/modprobe ipt_LOG /sbin/modprobe ipt_MASQUERADE /sbin/modprobe ipt_MIRROR /sbin/modprobe ipt_multiport /sbin/modprobe ipt_REDIRECT /sbin/modprobe ipt_REJECT /sbin/modprobe ipt_state /sbin/modprobe ipt_unclean /sbin/modprobe ip_nat_ftp /sbin/modprobe ip_conntrack /sbin/modprobe ip_conntrack_ftp # do not accept source routed packets /bin/echo "0" > /proc/sys/net/ipv4/conf/all/accept_source_route # do not accept ICMP redirects /bin/echo "0" > /proc/sys/net/ipv4/conf/all/accept_redirects $IPTABLES -t nat -P PREROUTING DROP $IPTABLES -t nat -P POSTROUTING DROP $IPTABLES -t filter -P INPUT DROP $IPTABLES -t filter -P OUTPUT DROP $IPTABLES -t filter -P FORWARD DROP # *** set MASQUERADING *** if [ ${STATIC_IP_ADDRESS}x = "x" ]; then # if you are running DHCP $IPTABLES -t nat -A POSTROUTING -o $INET_IFACE -j MASQUERADE else $IPTABLES -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to $MY_IP_ADDRESS fi # do not allow forbiden addresses on eth0 # $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 192.168.0.0/16 -j LOG \ # --log-level NOTICE --log-prefix "PRE 192.168.x.x on eth0: " $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 192.168.0.0/16 -j DROP # $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 10.0.0.0/8 -j LOG \ # --log-level NOTICE --log-prefix "PRE 10.x.x.x on eth0: " $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 10.0.0.0/8 -j DROP # $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 172.16.0.0/12 -j LOG \ # --log-level NOTICE --log-prefix "PRE 10.x.x.x on eth0: " $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 172.16.0.0/12 -j DROP # $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 224.0.0.0/4 -j LOG \ # --log-level NOTICE --log-prefix "PRE 224.0.0.0 on eth0: " $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 224.0.0.0/4 -j DROP # $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 240.0.0.0/5 -j LOG \ # --log-level NOTICE --log-prefix "PRE 240.0.0.0 on eth0: " $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -s 240.0.0.0/5 -j DROP # $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -d $LOOPBACK -j LOG \ # --log-level NOTICE --log-prefix "PRE loopback eth0: " $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -d $LOOPBACK -j DROP # $IPTABLES -t nat -A PREROUTING -p ! icmp -i $INET_IFACE -s $MY_IP_ADDRESS \ # -j LOG --log-level NOTICE --log-prefix "PRE MY_IP on eth0: " $IPTABLES -t nat -A PREROUTING -p ! icmp -i $INET_IFACE -s $MY_IP_ADDRESS \ -j DROP # kill INVALID or UNCLEAN packets... I am not really sure what it does # so some rules which I give later for TCP or ICMP may be redundant # I am no logging them, since there fill up my logs too much # $IPTABLES -t mangle -A PREROUTING -m state --state INVALID -j LOG \ # --log-level NOTICE --log-prefix "PRE INV: " #IPTABLES -t mangle -A PREROUTING -m state --state INVALID -j DROP # $IPTABLES -t mangle -A PREROUTING -i $INET_IFACE -m unclean \ # -j LOG --log-level NOTICE --log-prefix "PRE UNCLEAN: " # $IPTABLES -t mangle -A PREROUTING -i $INET_IFACE -m unclean -j DROP # $IPTABLES -t mangle -A PREROUTING -m unclean -j DROP # [[======= Rules for UDP protocol in PREROUTING chain ====]] $IPTABLES -t nat -N PRE_UDP $IPTABLES -t nat -A PREROUTING -p udp -j PRE_UDP # block all NetBios (Samba) stuff coming and going to INET_IFACE # block access to ports: 512, 514, 515, # I am not logging this stuff, since it fills logs fast # $IPTABLES -t nat -A PRE_UDP -p udp -i $INET_IFACE -m multiport \ # --dport 137,138,139,512,514,515 \ # -j LOG --log-level NOTICE --log-prefix "PRE UDP low to eth0: " # $IPTABLES -t nat -A PRE_UDP -p udp -i $INET_IFACE -m multiport \ # --dport 137,138,139,512,514,515 -j DROP # block RPC ports from INET_IFACE for UDP_PORT in $RPC_UDP_PORTS; do $IPTABLES -t nat -A PRE_UDP -p udp -i $INET_IFACE --dport $UDP_PORT -j DROP done # maybe I should not, but I am openning all UDP ports above 1023 $IPTABLES -t nat -A PRE_UDP -p udp --dport 1024: -j ACCEPT #================================================================= # [[======= Rules for TCP protocol in PREROUTING chain ====]] $IPTABLES -t nat -N PRE_TCP $IPTABLES -t nat -A PREROUTING -p tcp -j PRE_TCP # block all NetBios (Samba) stuff coming and going to INET_IFACE # block access to ports: 512, 514, 515, # block the logging here since there is a lot of NetBios stuff on the NET # and it fills my logs with garbage. # $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE -m multiport \ # --dport 137,138,139,512,514,515 \ # -j LOG --log-level NOTICE --log-prefix "PRE TCP low to eth0: " $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE -m multiport \ --dport 137,138,139,512,514,515 -j DROP # accept AUTH/IDENT requests, they will be REJECTED in INPUT and FORWARD # I have positively no idea why I cannot do -j REJECT here, but iptables bark... # $IPTABLES -t nat -A PRE_TCP -p tcp --dport 113 \ # -j LOG --log-level NOTICE --log-prefix "PRE IDENT1 ACPT : " $IPTABLES -t nat -A PRE_TCP -p tcp --dport 113 -j ACCEPT # reject port scans coming from $INET_IFACE # $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE --tcp-flags ALL FIN,URG,PSH \ # -j LOG --log-level NOTICE --log-prefix "PRE FUP to eth0: " $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE --tcp-flags ALL FIN,URG,PSH \ -j DROP # # $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE --tcp-flags ALL FIN \ # -j LOG --log-level NOTICE --log-prefix "PRE F to eth0: " $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE --tcp-flags ALL FIN \ -j DROP # $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE --tcp-flags ALL NONE \ # -j LOG --log-level NOTICE --log-prefix "PRE NONE to eth0: " $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE --tcp-flags ALL NONE \ -j DROP # # $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE --tcp-flags SYN,FIN SYN,FIN \ # -j LOG --log-level NOTICE --log-prefix "PRE SF to eth0: " $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE --tcp-flags SYN,FIN SYN,FIN \ -j DROP # # $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE --tcp-flags SYN,RST SYN,RST \ # -j LOG --log-level NOTICE --log-prefix "PRE SR to eth0: " $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE --tcp-flags SYN,RST SYN,RST \ -j DROP # block RPC ports from INET_IFACE for TCP_PORT in $RPC_TCP_PORTS; do $IPTABLES -t nat -A PRE_TCP -p tcp -i $INET_IFACE --dport $TCP_PORT -j DROP done $IPTABLES -t nat -A PRE_TCP -p tcp -m multiport \ --dport 22,53,80,443 -j ACCEPT $IPTABLES -t nat -A PRE_TCP -p tcp --dport 6000:6010 -j ACCEPT # allow ftp access from my box to internet $IPTABLES -t nat -A PRE_TCP -i $INET_IFACE -p tcp --sport 21 --dport 1024:\ -m state --state ESTABLISHED,RELATED \ -j LOG --log-level NOTICE --log-prefix "PRE sport21: " $IPTABLES -t nat -A PRE_TCP -i $INET_IFACE -p tcp --sport 21 --dport 1024: \ -m state --state ESTABLISHED,RELATED \ -j ACCEPT # allow ftp $IPTABLES -t nat -A PRE_TCP -i $INET_IFACE -p tcp --sport 20 --dport 1024:\ -m state --state ESTABLISHED,RELATED \ -j LOG --log-level NOTICE --log-prefix "PRE sport20: " $IPTABLES -t nat -A PRE_TCP -i $INET_IFACE -p tcp --sport 20 --dport 1024: \ -m state --state ESTABLISHED,RELATED \ -j ACCEPT $IPTABLES -t nat -A PRE_TCP -p tcp -m state --state ESTABLISHED,RELATED \ -j ACCEPT $IPTABLES -t nat -A PRE_TCP -p tcp -i $LAN_IFACE -m state --state NEW \ -j ACCEPT #================================================================= # [[======= Rules for ICMP protocol in PREROUTING chain ====]] $IPTABLES -t nat -N PRE_ICMP $IPTABLES -t nat -A PREROUTING -p icmp -j PRE_ICMP $IPTABLES -t nat -A PREROUTING -p icmp -i $LAN_IFACE -s $MY_IP_ADDRESS \ -j ACCEPT # The -m limit option slows things down. Once I put something more robust # for a firewall, I am commenting the ACCEPT/limit stuff # You may comment the ACCEPT ones with -m limit, if your firewall is slow $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type echo-reply -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type destination-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type network-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type host-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type protocol-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type port-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type fragmentation-needed -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type source-route-failed -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type network-unknown -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type host-unknown -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type network-prohibited -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type host-prohibited -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type TOS-network-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type TOS-host-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type communication-prohibited -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type host-precedence-violation -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type precedence-cutoff -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type source-quench -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type redirect -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type network-redirect -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type host-redirect -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type TOS-network-redirect -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type TOS-host-redirect -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type echo-request -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type router-advertisement -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type router-solicitation -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type time-exceeded -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type ttl-zero-during-transit -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type ttl-zero-during-reassembly -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type parameter-problem -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type ip-header-bad -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type required-option-missing -m limit --limit 1/s -j ACCEPT $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type timestamp-request -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type timestamp-reply -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type address-mask-request -j DROP $IPTABLES -t nat -A PRE_ICMP -i $INET_IFACE -p icmp \ --icmp-type address-mask-reply -j DROP # accept the others (though if you uncommented the limit lines, there are none) $IPTABLES -t nat -A PRE_ICMP -p icmp -j ACCEPT #================================================================= # [[======= Rules for UDP protocol in POSTROUTING chain ====]] $IPTABLES -t nat -N POST_UDP $IPTABLES -t nat -A POSTROUTING -p udp -j POST_UDP # block all NetBios (Samba) stuff coming and going to INET_IFACE # $IPTABLES -t nat -A POST_UDP -p udp -o $INET_IFACE --sport 137:139 \ # -j LOG --log-level NOTICE --log-prefix "PRE SMB packet to eth0: " $IPTABLES -t nat -A POST_UDP -p udp -o $INET_IFACE --sport 137:139 -j DROP # protect NFS through the firewall # $IPTABLES -t nat -A POST_UDP -p udp -o $INET_IFACE --sport 635 \ # -j LOG --log-level NOTICE --log-prefix "POST UDP 635 to eth0: " $IPTABLES -t nat -A POST_UDP -p udp -o $INET_IFACE --sport 635 -j DROP # $IPTABLES -t nat -A POST_UDP -p udp -o $INET_IFACE --sport 2049 \ # -j LOG --log-level NOTICE --log-prefix "POST UDP 2049 to eth0: " $IPTABLES -t nat -A POST_UDP -p udp -o $INET_IFACE --sport 2049 -j DROP # $IPTABLES -t nat -A POST_UDP -p udp -o $INET_IFACE --sport 111 \ # -j LOG --log-level NOTICE --log-prefix "POST UDP 111 to eth0: " $IPTABLES -t nat -A POST_UDP -p udp -o $INET_IFACE --sport 111 -j DROP #================================================================= # [[======= Rules for TCP protocol in POSTROUTING chain ====]] $IPTABLES -t nat -N POST_TCP $IPTABLES -t nat -A POSTROUTING -p tcp -j POST_TCP # block all NetBios (Samba) stuff coming and going to INET_IFACE # $IPTABLES -t nat -A POST_TCP -p tcp -o $INET_IFACE --sport 137:139 \ # -j LOG --log-level NOTICE --log-prefix "PRE SMB packet to eth0: " $IPTABLES -t nat -A POST_TCP -p tcp -o $INET_IFACE --sport 137:139 -j DROP # protect NFS through the firewall # $IPTABLES -t nat -A POST_TCP -p tcp -o $INET_IFACE --sport 635 \ # -j LOG --log-level NOTICE --log-prefix "POST_TCP 635 to eth0: " $IPTABLES -t nat -A POST_TCP -p tcp -o $INET_IFACE --sport 635 -j DROP # $IPTABLES -t nat -A POST_TCP -p tcp -o $INET_IFACE --sport 2049 \ # -j LOG --log-level NOTICE --log-prefix "POST_TCP 2049 to eth0: " $IPTABLES -t nat -A POST_TCP -p tcp -o $INET_IFACE --sport 2049 -j DROP # $IPTABLES -t nat -A POST_TCP -p tcp -o $INET_IFACE --sport 111 \ # -j LOG --log-level NOTICE --log-prefix "POST_TCP 111 to eth0: " $IPTABLES -t nat -A POST_TCP -p tcp -o $INET_IFACE --sport 111 -j DROP #================================================================= # [[======= Rules for ICMP protocol in POSTROUTING chain ====]] $IPTABLES -t nat -N POST_ICMP $IPTABLES -t nat -A POSTROUTING -p icmp -j POST_ICMP $IPTABLES -t nat -A POSTROUTING -p icmp -j ACCEPT #================================================================= # [[======= Rules for UDP protocol in INPUT chain ====]] $IPTABLES -t filter -N INP_UDP $IPTABLES -t filter -A INPUT -p udp -j INP_UDP # allow ESTABLISHED connections to firewall $IPTABLES -t filter -A INP_UDP -p udp -m state --state ESTABLISHED,RELATED \ -j ACCEPT # allow NEW connections to firewall but not from INET side $IPTABLES -t filter -A INP_UDP -p udp -i ! $INET_IFACE -j ACCEPT # allow DNS queries to firewall (we may want to do DNAT on this one day) $IPTABLES -t filter -A INP_UDP -p udp --dport 53 -j ACCEPT #================================================================= # [[======= Rules for TCP protocol in INPUT chain ====]] $IPTABLES -t filter -N INP_TCP $IPTABLES -t filter -A INPUT -p tcp -j INP_TCP # kill invalid packets # This is done on the PREROUTING stage, I hope # $IPTABLES -t filter -A INP_TCP -p tcp -m state --state INVALID -j LOG \ # --log-level NOTICE --log-prefix "INP-ICP-INV: " # $IPTABLES -t filter -A INP_TCP -p tcp -m state --state INVALID -j DROP # # # kill packets which are not --syn but are new # $IPTABLES -t filter -A INP_TCP -p tcp ! --syn -m state --state NEW -j LOG \ # --log-level NOTICE --log-prefix "INP-ICP-NEWNotSYN: " # $IPTABLES -t filter -A INP_TCP -p tcp ! --syn -m state --state NEW -j DROP # reject ident probes with tcp reset so you can sent mail to outside # $IPTABLES -t filter -A INP_TCP -p tcp -i $INET_IFACE --dport 113 \ # -j LOG --log-level NOTICE --log-prefix "INP IDENT: " $IPTABLES -t filter -A INP_TCP -p tcp -i $INET_IFACE --dport 113 \ -j REJECT # allow ftp out # $IPTABLES -t filter -A INP_TCP -p tcp -i $INET_IFACE --sport 21 \ # -m state --state ESTABLISHED,RELATED \ # -j LOG --log-level NOTICE --log-prefix "INP ftp21: " $IPTABLES -t filter -A INP_TCP -p tcp -i $INET_IFACE --sport 21 \ -m state --state ESTABLISHED,RELATED \ -j ACCEPT # allow new packets from internal LAN network $IPTABLES -t filter -A INP_TCP -p tcp -i $LAN_IFACE -m state --state NEW \ -j ACCEPT # allow all ESTABLISHED and related packets (from both LAN and INET) $IPTABLES -t filter -A INP_TCP -p tcp -m state --state ESTABLISHED,RELATED \ -j ACCEPT # OPEN port 22,53,80,443 (ssh, dns, http, https) but with syn-flood protect # $IPTABLES -t filter -A INP_TCP -p tcp -m multiport \ # --dport 22,53,80,443 -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_TCP -p tcp -m multiport \ --dport 22,53,80,443 -j ACCEPT $IPTABLES -t filter -A INP_TCP -p tcp --dport 6000:6010 -j ACCEPT # DROP all packets which are NEW here and come from INET_IFACE # If you want to add servers on firewall, do it ABOVE this line # $IPTABLES -t filter -A INP_TCP -p tcp -i $INET_IFACE -m state --state NEW \ # -j LOG --log-level NOTICE --log-prefix "INP TCP New" $IPTABLES -t filter -A INP_TCP -p tcp -i $INET_IFACE -m state --state NEW \ -j DROP #================================================================= # [[======= Rules for ICMP protocol in INPUT chain ====]] $IPTABLES -t filter -N INP_ICMP $IPTABLES -t filter -A INPUT -p icmp -j INP_ICMP # I am allowing ESTABLISHED, and RELATED ICMP packets, but you may reconsider $IPTABLES -t filter -A INP_ICMP -p icmp -m state --state ESTABLISHED,RELATED -j ACCEPT # I am allowing NEW ICMP packets but not from the INET side $IPTABLES -t filter -A INP_ICMP -p icmp -i ! $INET_IFACE \ -m state --state ESTABLISHED,RELATED -j ACCEPT # I do not allow broadcasts to my address coming from $INET_IFACE ] # $IPTABLES -t filter -A INP_ICMP -p icmp -i $INET_IFACE -d $MY_IP_BCAST \ # -j LOG --log-level NOTICE --log-prefix "INP-ICMP-BCAST: " $IPTABLES -t filter -A INP_ICMP -p icmp -i $INET_IFACE -d $MY_IP_BCAST -j DROP # The -m limit option slows things down. if you have a slow computer as FW. # Comment the ACCEPT/limit stuff if you are slow $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type echo-reply -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type destination-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type network-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type host-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type protocol-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type port-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type fragmentation-needed -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type source-route-failed -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type network-unknown -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type host-unknown -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type network-prohibited -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type host-prohibited -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type TOS-network-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type TOS-host-unreachable -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type communication-prohibited -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type host-precedence-violation -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type precedence-cutoff -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type source-quench -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type redirect -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type network-redirect -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type host-redirect -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type TOS-network-redirect -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type TOS-host-redirect -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type echo-request -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type router-advertisement -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type router-solicitation -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type time-exceeded -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type ttl-zero-during-transit -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type ttl-zero-during-reassembly -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type parameter-problem -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type ip-header-bad -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type required-option-missing -m limit --limit 1/s -j ACCEPT $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type timestamp-request -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type timestamp-reply -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type address-mask-request -j DROP $IPTABLES -t filter -A INP_ICMP -i $INET_IFACE -p icmp \ --icmp-type address-mask-reply -j DROP # accept the others $IPTABLES -t filter -A INP_ICMP -p icmp -j ACCEPT #================================================================= # [[======= Rules for UDP protocol in OUTPUT chain ====]] $IPTABLES -t filter -N OUT_UDP $IPTABLES -t filter -A OUTPUT -p udp -j OUT_UDP # block all NetBios (Samba) stuff coming and going to INET_IFACE # $IPTABLES -t filter -A OUT_UDP -p udp -o $INET_IFACE --sport 137:139 \ # -j LOG --log-level NOTICE --log-prefix "OUT UDP SMB to eth0: " $IPTABLES -t filter -A OUT_UDP -p udp -o $INET_IFACE --sport 137:139 -j DROP # let all other stuff out $IPTABLES -t filter -A OUT_UDP -p udp -j ACCEPT #================================================================= # [[======= Rules for TCP protocol in OUTPUT chain ====]] $IPTABLES -t filter -N OUT_TCP $IPTABLES -t filter -A OUTPUT -p tcp -j OUT_TCP # block all NetBios (Samba) stuff coming and going to INET_IFACE # $IPTABLES -t filter -A OUT_TCP -p tcp -o $INET_IFACE --sport 137:139 \ # -j LOG --log-level NOTICE --log-prefix "OUT TCP SMB to eth0: " $IPTABLES -t filter -A OUT_TCP -p tcp -o $INET_IFACE --sport 137:139 -j DROP # Needed for ftp from firewall to outside # $IPTABLES -t filter -A OUT_TCP -p tcp --dport 21 -m state \ # --state NEW \ # -j LOG --log-level NOTICE --log-prefix "OUT TCP NEWdport21: " # $IPTABLES -t filter -A OUT_TCP -p tcp --dport 21 -m state \ # --state ESTABLISHED,RELATED \ # -j LOG --log-level NOTICE --log-prefix "OUT TCP dport21: " $IPTABLES -t filter -A OUT_TCP -p tcp --dport 21 -m state \ --state ESTABLISHED,RELATED -j ACCEPT # $IPTABLES -t filter -A OUT_TCP -p tcp --dport 20 -m state \ # --state ESTABLISHED \ # -j LOG --log-level NOTICE --log-prefix "OUT TCP dport20: " $IPTABLES -t filter -A OUT_TCP -p tcp --dport 20 -m state \ --state ESTABLISHED -j ACCEPT # allow ftp # $IPTABLES -t filter -A OUT_TCP -o $INET_IFACE -p tcp --sport 20 --dport 1024:\ # -m state --state ESTABLISHED,RELATED \ # -j LOG --log-level NOTICE --log-prefix "INP sport20: " $IPTABLES -t filter -A OUT_TCP -o $INET_IFACE -p tcp --sport 20 --dport 1024: \ -m state --state ESTABLISHED,RELATED \ -j ACCEPT # $IPTABLES -t filter -A OUT_TCP -p tcp --sport 1024: --dport 1024: -m state \ # --state ESTABLISHED,RELATED \ # -j LOG --log-level NOTICE --log-prefix "OUT TCP dport1024: " $IPTABLES -t filter -A OUT_TCP -p tcp --sport 1024: --dport 1024: -m state \ --state ESTABLISHED,RELATED -j ACCEPT # allow everything from OUTPUT $IPTABLES -t filter -A OUT_TCP -p tcp -j ACCEPT #================================================================= # [[======= Rules for ICMP protocol in OUTPUT chain ====]] # $IPTABLES -t filter -N OUT_ICMP # $IPTABLES -t filter -A OUTPUT -p icmp -j OUT_ICMP # I am allowing NEW, ESTABLISHED, and RELATED ICMP packets, # $IPTABLES -t filter -A OUT_ICMP -m state --state NEW,ESTABLISHED,RELATED \ # -j ACCEPT # I am allowing all ICMP packets out $IPTABLES -t filter -A OUTPUT -p icmp -j ACCEPT #================================================================= # [[======= Rules for UDP protocol in FORWARD chain ====]] $IPTABLES -t filter -N FORW_UDP $IPTABLES -t filter -A FORWARD -p udp -j FORW_UDP # block all NetBios (Samba) stuff coming and going to INET_IFACE # $IPTABLES -t filter -A FORW_UDP -p udp -o $INET_IFACE --sport 137:139 \ # -j LOG --log-level NOTICE --log-prefix "FORW UDP SMB to eth0: " $IPTABLES -t filter -A FORW_UDP -p udp -o $INET_IFACE --sport 137:139 -j DROP # I am allowing ESTABLISHED, and RELATED packets, $IPTABLES -t filter -A FORW_UDP -p udp -m state --state ESTABLISHED,RELATED \ -j ACCEPT # I am allowing NEW from LAN side, $IPTABLES -t filter -A FORW_UDP -p udp -i $LAN_IFACE \ -m state --state NEW -j ACCEPT #================================================================= # [[======= Rules for TCP protocol in FORWARD chain ====]] $IPTABLES -t filter -N FORW_TCP $IPTABLES -t filter -A FORWARD -p tcp -j FORW_TCP # kill invalid packets # $IPTABLES -t filter -A FORW_TCP -p tcp -m state --state INVALID -j LOG \ # --log-level NOTICE --log-prefix "FORW-ICMP-INV: " $IPTABLES -t filter -A FORW_TCP -p tcp -m state --state INVALID -j DROP # Port scanner slowdown $IPTABLES -t filter -A FORW_TCP -p tcp --tcp-flags SYN,ACK,FIN,RST RST \ -m limit --limit 1/s -j ACCEPT # reject ident probes with tcp reset so you can sent mail to outside # $IPTABLES -t filter -A FORW_TCP -p tcp -i $INET_IFACE --dport 113 \ # -j LOG --log-level NOTICE --log-prefix "FORW IDENT: " $IPTABLES -t filter -A FORW_TCP -p tcp -i $INET_IFACE --dport 113 \ -j REJECT # block all NetBios (Samba) stuff coming and going to INET_IFACE # $IPTABLES -t filter -A FORW_TCP -p tcp -o $INET_IFACE --sport 137:139 \ # -j LOG --log-level NOTICE --log-prefix "FORW TCP SMB to eth0: " $IPTABLES -t filter -A FORW_TCP -p tcp -o $INET_IFACE --sport 137:139 -j DROP $IPTABLES -t filter -A FORW_TCP -p tcp -m multiport \ --dport 22,53,80,443 -j ACCEPT $IPTABLES -t filter -A FORW_TCP -p tcp --dport 6000:6010 -j ACCEPT # allow ftp access from my firewall to internet # $IPTABLES -t filter -A FORW_TCP -i $INET_IFACE -p tcp --dport 20 -m state # --state ESTABLISHED -j LOG --log-level NOTICE --log-prefix "FORW dport20: " $IPTABLES -t filter -A FORW_TCP -i $INET_IFACE -p tcp --dport 20 -m state \ --state ESTABLISHED -j ACCEPT # $IPTABLES -t filter -A FORW_TCP -i $INET_IFACE -p tcp --sport 21 -m state # --state ESTABLISHED -j LOG --log-level NOTICE --log-prefix "FORW sport21: " $IPTABLES -t filter -A FORW_TCP -i $INET_IFACE -p tcp --sport 21 -m state \ --state ESTABLISHED -j ACCEPT # $IPTABLES -t filter -A FORW_TCP -i $INET_IFACE -p tcp --sport 1024: \ # --dport 1024: -m state --state ESTABLISHED -j LOG --log-level NOTICE \ # --log-prefix "FORW sdport1024: " $IPTABLES -t filter -A FORW_TCP -i $INET_IFACE -p tcp --sport 1024: \ --dport 1024: -m state --state ESTABLISHED -j ACCEPT # $IPTABLES -t filter -A FORW_TCP -o $INET_IFACE -p tcp --dport 21 -m state \ # --state NEW -j LOG --log-level NOTICE --log-prefix "FORW TCP NEWdport21: " # $IPTABLES -t filter -A FORW_TCP -o $INET_IFACE -p tcp --dport 21 -m state \ # --state ESTABLISHED,RELATED \ # -j LOG --log-level NOTICE --log-prefix "FORW TCP dport21: " $IPTABLES -t filter -A FORW_TCP -o $INET_IFACE -p tcp --dport 21 -m state \ --state ESTABLISHED,RELATED -j ACCEPT # $IPTABLES -t filter -A FORW_TCP -o $INET_IFACE -p tcp --sport 1024: \ # --dport 1024: -m state --state ESTABLISHED,RELATED \ # -j LOG --log-level NOTICE --log-prefix "FORW TCP dport1024: " $IPTABLES -t filter -A FORW_TCP -o $INET_IFACE -p tcp --sport 1024: \ --dport 1024: -m state --state ESTABLISHED,RELATED -j ACCEPT # allow all ESTABLISHED and related packets (from both LAN and INET) $IPTABLES -t filter -A FORW_TCP -p tcp -m state --state ESTABLISHED,RELATED \ -j ACCEPT # allow NEW packets from LAN side $IPTABLES -t filter -A FORW_TCP -p tcp -i $LAN_IFACE -m state --state NEW \ -j ACCEPT #================================================================= # [[======= Rules for ICMP protocol in FORWARD chain ====]] # $IPTABLES -t filter -N FORW_ICMP # $IPTABLES -t filter -A FORWARD -p icmp -j FORW_ICMP # I am accepting everything $IPTABLES -t filter -A FORWARD -p icmp -j ACCEPT #================================================================= # [[======= Rules for ALL protocols in PREROUTING chain ====]] $IPTABLES -t nat -N PRE_ALL $IPTABLES -t nat -A PREROUTING -j PRE_ALL # allow anything to come out of LAN interface $IPTABLES -t nat -A PRE_ALL -p ALL -i $LAN_IFACE -j ACCEPT #================================================================= # [[======= Rules for ALL protocols in POSTROUTING ====]] $IPTABLES -t nat -N POST_ALL $IPTABLES -t nat -A POSTROUTING -j POST_ALL # allow anything to enter from my own (i.e., the firewall) IP address $IPTABLES -t nat -A POST_ALL -p ALL -s $MY_IP_ADDRESS -j ACCEPT # allow anything to enter from the "localhost" $IPTABLES -t nat -A POST_ALL -p ALL -s localhost -j ACCEPT #================================================================= # [[======= Rules for ALL protocols in INPUT chain ====]] # $IPTABLES -t filter -N INP_ALL # $IPTABLES -t filter -A INPUT -p ALL -j INP_ALL #================================================================= # [[======= Rules for ALL protocols in OUTPUT chain ====]] # $IPTABLES -t filter -N OUT_ALL # $IPTABLES -t filter -A OUTPUT -p ALL -j OUT_ALL #================================================================= # [[======= Rules for ALL protocols in FORWARD chain ====]] # $IPTABLES -t filter -N FORW_ALL # $IPTABLES -t filter -A FORWARD -p ALL -j FORW_ALL #================================================================= # These are commented out. You use them for debugging. # These LOG entries list all packets which were missed by previous rules # Not, all policies are set to DROP # You have a choice: # Uncomment only -j LOG rules (packets will be logged but dropped nevertheless # Use it occassionally to see what kind of garbage hits your firewall # Uncomment all lines, so packets are ACCEPTed and LOGged # Use this, when you want to provide rules for a new protocol or service # and you want to ALLOW everything, and then look up in messages.notice # which rules are need to make it through the firewall. # In production setting, these rules SHOULD BE ALWAYS commented out. # # $IPTABLES -t nat -A POSTROUTING -j LOG \ # --log-level NOTICE --log-prefix "POST DEBUG: " # $IPTABLES -t nat -A POSTROUTING -j ACCEPT # # $IPTABLES -t nat -A PREROUTING -j LOG \ # --log-level NOTICE --log-prefix "PRE DEBUG: " # $IPTABLES -t nat -A PREROUTING -j ACCEPT \ # # $IPTABLES -t filter -A INPUT -j LOG \ # --log-level NOTICE --log-prefix "INPUT DEBUG: " # $IPTABLES -t filter -A INPUT -j ACCEPT # # $IPTABLES -t filter -A OUTPUT -j LOG \ # --log-level NOTICE --log-prefix "OUTPUT DEBUG: " # $IPTABLES -t filter -A OUTPUT -j ACCEPT # # $IPTABLES -t filter -A FORWARD -j LOG \ # --log-level NOTICE --log-prefix "FORWARD DEBUG: " # $IPTABLES -t filter -A FORWARD -j ACCEPT # $IPTABLES -t nat -A POSTROUTING -j LOG \ # --log-level NOTICE --log-prefix "POST DEBUG: " # $IPTABLES -t nat -A POSTROUTING -j ACCEPT # Turn on the IP Forwarding /bin/echo 1 > /proc/sys/net/ipv4/ip_forward /bin/echo 1 > /proc/sys/net/ipv4/ip_dynaddr