CCL Home Page
Up Directory CCL startfw.txt
#!/bin/bash
#
# Jan K Labanowski, jkl@ccl.net, Nov, 2001 Thu Aug 30 23:17:39 EDT 2001
# Last modified: Wed Dec 19 02:50:04 EST 2001
# Last modified: Tue May 28 18:42:55 EDT 2002
#
# 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.7 which came with RH7.2. The
#    iptables --version
# reports iptables v1.2.3
# 
# This assumes that you have a few static addresses (e.g., provided by
# your ISP with your DSL service) and you want to setup your own servers
# etc. This approach is suitable if you have A FEW addresses. It can be
# reworked to do ranges quite easily, but as it is now, it does not
# use ranges, subnetting, etc.  It also assimes that you run RedHat 7.2
# with latest kernel and iptables updates (it will not run without updates,
# since there is a bug in uptables 1.2.3 with log levels). The original
# 7.1 RH may run, but I did not try it. Next, you need to disable the
# iptables and ipchains startup scripts which came with the system (or
# when you installed firewall on your system. You do that:
#   cd /etc/rc.d
#   find . -name '[KS]*iptables' -print
#   find . -name '[KS]*ipchains' -print
# You get read of them as:
#   cd /etc/rc.d
#   find . -name '[KS]*iptables' -exec rm {} \;
#   find . -name '[KS]*ichains' -exec rm {} \;
#
# (of course, you can try:
#    chkconfig --del iptables
#    chkconfig --del ichains
# assuming that links were placed by chkconfig --add and scripts were not
# modified).
# 
#
# This setip  assumes that you have 3 ethernet cards.
# There are tons of confusing and often outdated notes on the Web about
# "Multiple Ethernet Cards". They often assume that you have the drivers
# compiled into the kernel. Read them, but remember that modern Linuces come
# with drivers as kernel modules, so all this stuff about lilo.conf and
# append is no longer valid. The way I do it is to have 3 cards which use
# different drivers (go to Hardware Compatibility List on RedHat site
# and see which cards use which drivers). In this case I was using
# the 3Com ISA 3c509 (module: 3c509), the 3Com PCI 3c900 Boomerang (module
# 3c59x), and Linksys NC100 (module tulip). After you install cards and
# reboot the machine, Linux kudzu will usually find them and ask you to
# configure the cards. Do it, but you will most likely have to correct the
# default settings. Also, you may need to add the parameters if the cards
# do not want to initialize with right interrupts numbers and IO addresses.
# You may also easily run out of iterrupts when you have other things
# installed on your system (like sound cards), or you have other things
# build into your motherboard. In this case, you may need to run BIOS Setup
# and disble serial ports or parallel port on your mother board, and play
# with PCI/PnP setting on your slots, until you get it right. Try also to
# change order in which modules are listed/loaded in /etc/modules.conf file.
# The relevant piece /etc/modules.conf file is:
#
#             alias eth2 3c59x
#             alias eth1 tulip
#             alias eth0 3c509 irq=5
#
# I had to put them in reverse order, and "suggest" interrupt 5 for the 
# Etherlink III card, since they were getting conflict initially. Before
# you give parameters, print the interrupts by:
#
#       cat /proc/interrupts
# 
# You can also list the IO port number which are taken by:
#
#       cat /proc/ioports
#
# and if your card allows setting the ports, choose something which is not
# already taken and specify it with io=xxxx parameter in /etc/modules.conf.
# Note that the slowest card in my case (ISA 3c509) is used to  talk to
# external Internet (eth0), since the DSL is far from saturating the bandwidth
# of the 10BT card. On the inside, I am using fast cards on my LAN and DMZ 
# side, since here I can use their speed for backup or copying files
# back and forth, printer support, etc. 
# 
# 
# My physical arrangement is similar to the following:
#
# [Internet/DSL]--eth0(3c509-ISA-10BT)::[Firewall/NAT]::eth1[Linksys/NC100]
# [5 static IPs]                            ..           [PCI-10/100BT]
#                                       eth2[3com900]         | 192.168.0.1
#                                        / 192.168.1.1        | 
#                                       /                     |
#                                      /                      |
#                                     /                       |
#                                    /                        |
#                                   /                         |
#                                  /                 LAN      |
#                                 /                         uplink
#                                /                        ------------
#                               /                         | EtherHub |   
#               DMZ          uplink                       |          |--HOST1
#                          ------------                   |          |
#                          | EtherHub |                   |          |--HOST2
#      DNS1-HOST(eth0)-----|          |                   .          .
#      192.168.1.2         |          |                   .          .
#                          |          |                   |          |--HOSTn  
#      DNS2-HOST(eth0)-----|          |                   ------------  
#      192.168.1.3         |          |
#                          /----------\
#                         /     |      \
#                       eth0    |    eth0  
#                 WEB-SERVER-1  |   WEB-SERVER-2
#                192.168.1.4    |    192.168.1.5
#                               |
#                              eth0 
#                           WEB-SERVER-3
#                           192.168.1.6 
# I have 5 static IP addresses and I want to do the following with them:
#   a) do IP masquerading to provide access to Internet for the local subnet
#      192.168.0.0 (LAN). Connection to the computers on the LAN cannot be
#      initiated from the outside, but can be initiated from the inside,
#      i.e., when the computer on the LAN subnet wants to connect to some
#      Web Server. The source address of the LAN computer in the packet
#      will be changed to the address of the Firewall and Firewall (based
#      on packet serial number) will direct the responses rom the outside
#      net back to the appropriate computer on the LAN. While you can
#      ssh from the LAN computer to some computer on the Internet, no computer
#      will be able to ssh directly to LAN computers. To do this, one needs to
#      first log into the Firewall or one of the DMZ computers if they allow
#      logging in. 
#   NOTE: by experiment I found that you cannot access the
#      DMZ computers from within DMZ using their "external" addresses.
#      In other words, you cannot use the same URL for the web page
#      as you would use outside. It may be a bug, or a feature, but the DNAT
#      and SNAT do not work for me together on the same interface (in my case
#      the eth2). Somehow, the netfilter gets confused. But you are perfectly
#      OK to access the DMZ computers from your LAN subnet with their
#      "external" IPs and ports. Do not ask me why... DNAT and SNAT should
#      work in principle on the same interface, but they do not work for me.
#      
# 
#   b) keep Web servers, DNSses, FTP servers, etc. in another local subnet 
#      192.168.1.0 (DMZ). Here I can keep servers for up to 5 domains
#      which represent 5 static IP addresses which I got assigned to my
#      DSL service. The services to be redirected to them will be
#      Port 20: ftp-data,  Port 21: ftp, Port 25: smpt (e-mail),
#      Port 53: domain (DNS server),  Port 80: http (Web Server),
#      Port 443: https (Secure Web Server). Nobody will be able to
#      log into them directly, only via Firewall, or from inside (LAN),
#
# Now, back to configuration. I did initially the default configuration
# for the default /etc/rc.d/init.d/network script of Red Hat Linux.
# I actually sugest you do it to, so you can test your network conncetivity.
# My speakeasy.net Gateway was: 
#     215.236.123.1
# My DNS addresses were: 216.254.95.2 and 216.231.41.2
# I named my DMZ domain as it would be named for the Web or mail, or whatever
# access on external Internet. Say, it was mymymy.com. You can name your
# LAN domain whatever you want. If you can make the host names different
# among ALL MACHINES (I mean, firewall, DMZ, and LAN), I would use the same
# domain as I use for external hosts. 
#
# On the firewall I assigned IP addresses to all interfaces (i.e., NIC cards)
# as follows. For the eth0 interface, I used the the out-of-order address
# which I was given by ISP (they usually give you a range of consecutive
# addresses and one odd address, but it varies, and is probably random).
# Say, I chose my address as: 215.236.123.210 for the eth0 facing the WORLD.
# 
# On each of my computers in DMZ and LAN (and firewall), I have an /etc/hosts
# file ( C:\WINNT\SYSTEM32\DRIVERS\ETC\HOSTS on Windoz2000 and C:\WINDOWS\HOSTS
# on Windoz9x ) which lists all computer names and domains with their real,
# actual, internal, IP addresses. I want them to talk to each other with their
# real IP addresses on internal wires. Note, these computers (especially the
# firewall and the computers in DMZ), will have different addresses in the
# DNS server -- there they have their external, "official", Internet addresses.
# Since the /etc/hosts file is by default searched first (you can make sure
# by having a file /etc/hosts.conf with lines
cat > /dev/null < /dev/null < /dev/null < /dev/null < /dev/null < /dev/null < /dev/null < /dev/null </dev/null <ToPort". All REALATED and
# ESTABLISHED packets initiated by the connection to these ports will be
# directed to the corresponding DMZ machines. 
# I am considering adding ranges syntax here, but I need to get it out fast.
# So no 20:25,30:50->2020-46 yet, maybe later.
#
# The popular ports are:
#    FTP         -- 20, 21
#    SSH         -- 22,
#    TELNET      -- 23
#    E-MAIL      -- 25
#    WHOIS       -- 43
#    DNS         -- 53
#    GOPHER      -- 70
#    FINGER      -- 79
#    HTTP        -- 80
#    KERBEROS    -- 88
#    POP3        -- 110
#    IDENT/AUTH  -- 113
#    NNTP        -- 119
#    NTP         -- 123 
#    IMAP        -- 143
#    WAIS        -- 210
#    HTTPS       -- 443
#    X-WINDOW    -- 6000:6063
# Also note that the above are "official" port numbers, but you can run stuff
# on other ports. I often saw people running SSHD on port 2222 (they had
# to change the sshd_config file). This actually allows you to do the trick.
# You can have the sshd running on DMZ machines on the different port than
# on the firewall, and when you use ssh without port number, you log in to
# firewall, and when you use it with a port number of sshd of the DMZ host
# (e.g., like: ssh -p 2222 ...) you can login directly to DMZ host from 
# outside (you better have a password which cracker will not crack, though).

#faminor.edu (215.236.123.103)
INET_TO_DMZ[0]="215.236.123.103->192.168.1.129"  # Hx
DNAT_TCP_PORTS[0]="20->20 21->21 22->22 25->25 80->9083 9083->9083" 
DNAT_UDP_PORTS[0]=""

#basement.edu (215.236.123.104)
INET_TO_DMZ[1]="215.236.123.104->192.168.1.129"  # Hx
DNAT_TCP_PORTS[1]="20->20 21->21 22->22 25->25 80->9084 9084->9084" 
DNAT_UDP_PORTS[1]=""

#server1.cclun.edu (215.236.123.129)
INET_TO_DMZ[2]="215.236.123.129->192.168.1.129"  # D3
DNAT_TCP_PORTS[2]="20->20 21->21 22->22 25->25 53->53 80->9081 9081->9081 443->9443 9443->9443" 
DNAT_UDP_PORTS[2]="53->53"

#mail1.usdne.edu (215.236.123.130)
INET_TO_DMZ[3]="215.236.123.130->192.168.1.129"  # 03
DNAT_TCP_PORTS[3]="20->20 21->21 22->22 25->25 80->9080 9080->9080 8080->7080 7080->7080"
DNAT_UDP_PORTS[3]=""

#chumisty.edu (215.236.123.131)
INET_TO_DMZ[4]="215.236.123.131->192.168.1.129"  # 01
DNAT_TCP_PORTS[4]="20->20 21->21 22->22 25->25 53->53 80->9082 9082->9082"
DNAT_UDP_PORTS[4]="53->53"

#search1.cclun.edu (215.236.123.132)
INET_TO_DMZ[5]="215.236.123.132->192.168.1.132"  # H1
DNAT_TCP_PORTS[5]="20->20 21->21 22->22 25->25 53->53 443->8443 8443->8443 7080->7080 8080->8080 9081->9081 9082->9082 9083->9083 9084->9084 9443->8443"
DNAT_UDP_PORTS[5]="53->53"

#bubulka.org (215.236.123.210)
INET_TO_DMZ[6]="215.236.123.210->192.168.1.210"  # D3
DNAT_TCP_PORTS[6]="22->22 25->25 53->53" 
DNAT_UDP_PORTS[6]="53->53"
 

LOOPBACK=127.0.0.0/8   # Idea taken from James C. Stephens
                       # http://www.cs.princeton.edu/~jns/security/iptables

IPTABLES=/sbin/iptables  # this is where I have my iptables

MY_IP_BCAST=""           # put here broadcast address for your subnet
                         # for example: MY_IP_BCAST="215.236.123.255"

# find my BROADCAST address (X.X.X.255) if the script was not updated above
if [ "${MY_IP_BCAST}x" = "x" ]; then
   MY_IP_BCAST=`echo $MY_IP_ADDRESS | /bin/sed  -e 's/\.[0-9]*$/.255/'`
fi

# 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 ACCEPT
$IPTABLES -t nat -P POSTROUTING ACCEPT
$IPTABLES -t filter -P INPUT DROP
$IPTABLES -t filter -P OUTPUT DROP
$IPTABLES -t filter -P FORWARD DROP


# Let us define some "routines" which we will "call" in other chains
# Some of those is to drop stuff, while at the same time I set my polices
# to drop, so it is redundant. In theory you could have only -j ACCEPT
# as your actions, but it is easier to DROP junk as soon as possible, so
# you can assume when you do ACCEPT stuff that the bad things are already
# in the trash...
#
# [[======= DropSpoof user defined chain  ====]]
#
# DropSpoof  -- drops nonroutable source addresses and our addresses
#               if they came on $INET_IFACE. We will call them in INPUT
#               and FORWARD chain
# 

$IPTABLES -N DropSpoof
 
# $IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -s 192.168.0.0/16 -j LOG \
#   --log-level notice --log-prefix "192.168.x.x on eth0: "
$IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -s 192.168.0.0/16 -j DROP

# $IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -s 10.0.0.0/8 -j LOG \
#   --log-level notice --log-prefix "10.x.x.x on eth0: "
$IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -s 10.0.0.0/8 -j DROP

# $IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -s 172.16.0.0/12 -j LOG \
#   --log-level notice --log-prefix "10.x.x.x on eth0: "
$IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -s 172.16.0.0/12 -j DROP

# $IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -s 224.0.0.0/4 -j LOG \
#   --log-level notice --log-prefix "224.0.0.0 on eth0: "
$IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -s 224.0.0.0/4 -j DROP

# $IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -s 240.0.0.0/5 -j LOG \
#   --log-level notice --log-prefix "240.0.0.0 on eth0: "
$IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -s 240.0.0.0/5 -j DROP

# changed on Tue May 28 18:42:55 EDT 2002 on advice from
# Pedro Rodrigues  -- Thanks Pedro...
# $IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -s $LOOPBACK -j LOG \
#   --log-level notice --log-prefix "loopback eth0: "

#replaced $IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -d $LOOPBACK -j DROP
$IPTABLES -t filter -A DropSpoof  -i $INET_IFACE -s $LOOPBACK -j DROP

# do not allow spoofing packets with your source address on the INET_IFACE
# The packets can only have our address as destination address but not source

to='*->';
from='->*';
let count=0
while (( $count < ${#INET_TO_DMZ[*]} ))
   do
     addresses=${INET_TO_DMZ[count]};

     inet_address=${addresses%$from};    # extract the stuff before ->

# changed on Tue May 28 18:42:55 EDT 2002
     # $IPTABLES -t filter -A DropSpoof -p ! icmp -i $INET_IFACE -s \
     #   ${inet_address} -j LOG --log-level notice
     #   --log-prefix "MY_IP on ${INET_IFACE}: "

       $IPTABLES -t filter -A DropSpoof -p ! icmp -s ${inet_address} \
         -j LOG --log-level notice  \
         --log-prefix "MY_IP in source"

#changed on Tue May 28 18:42:55 EDT 2002
      $IPTABLES -t filter -A DropSpoof -p ! icmp -s ${inet_address} -j DROP
#     $IPTABLES -t filter -A DropSpoof -p ! icmp -i $INET_IFACE \
#         -s ${inet_address} -j DROP
     let count="count + 1"
   done
 
 
# =============== End of DropSpoof ======================
 
# Kill PortScans (the badly formatted packets
# [[======= KillPortScans user defined chain  ====]]

$IPTABLES -N KillPortScans

# REJECT ident requests...
# $IPTABLES -t filter -A KillPortScans -p tcp --dport 113 \
#   -j LOG --log-level notice --log-prefix "IDENT1 ACPT : "
$IPTABLES -t filter -A KillPortScans -p tcp --dport 113 \
    -j REJECT --reject-with tcp-reset 

  # reject port scans coming from $INET_IFACE
# $IPTABLES -t filter -A KillPortScans -p tcp -i $INET_IFACE \ 
#   --tcp-flags ALL FIN,URG,PSH \
#   -j LOG --log-level notice --log-prefix "FUP to eth0: "
$IPTABLES -t filter -A KillPortScans -p tcp -i $INET_IFACE \
   --tcp-flags ALL FIN,URG,PSH -j DROP
# 
# $IPTABLES -t filter -A KillPortScans -p tcp -i $INET_IFACE \
#   --tcp-flags ALL FIN -j LOG --log-level notice --log-prefix "F to eth0: "
$IPTABLES -t filter -A KillPortScans -p tcp -i $INET_IFACE \
   --tcp-flags ALL FIN -j DROP
 
# $IPTABLES -t filter -A KillPortScans -p tcp -i $INET_IFACE \
#   --tcp-flags ALL NONE \
#    -j LOG --log-level notice --log-prefix "NONE to eth0: "
$IPTABLES -t filter -A KillPortScans -p tcp -i $INET_IFACE \
    --tcp-flags ALL NONE -j DROP
# 
# $IPTABLES -t filter -A KillPortScans -p tcp -i $INET_IFACE \
#    --tcp-flags SYN,FIN SYN,FIN \
#    -j LOG --log-level notice --log-prefix "SF to eth0: "
$IPTABLES -t filter -A KillPortScans -p tcp -i $INET_IFACE \
   --tcp-flags SYN,FIN SYN,FIN -j DROP
# 
# $IPTABLES -t filter -A KillPortScans -p tcp -i $INET_IFACE \
#    --tcp-flags SYN,RST SYN,RST \
#    -j LOG --log-level notice --log-prefix "SR to eth0: "
$IPTABLES -t filter -A KillPortScans -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 filter -A KillPortScans -p tcp -i $INET_IFACE \
     --dport $TCP_PORT -j DROP
done


# block RPC ports from INET_IFACE
for UDP_PORT in $RPC_UDP_PORTS; do
  $IPTABLES -t filter -A KillPortScans -p udp -i $INET_IFACE \
     --dport $UDP_PORT -j DROP
done

# ========================= End of KillPortScans =================


# These rules will be called in INPUT and FORWARD chain
# [[======= FilterICMP user defined chain  ====]]

$IPTABLES -N FilterICMP

$IPTABLES -t filter -A FilterICMP -p icmp -i $LAN_IFACE -s $MY_IP_ADDRESS \
    -j ACCEPT
$IPTABLES -t filter -A FilterICMP -p icmp -i $DMZ_IFACE -s $MY_IP_ADDRESS \
    -j ACCEPT

# $IPTABLES -t filter -A FilterICMP -p icmp -i $DMZ_IFACE -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 filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type echo-reply   -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type destination-unreachable  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    network-unreachable  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    host-unreachable  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    protocol-unreachable  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    port-unreachable  -m limit --limit 1/s -j ACCEPT

$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    fragmentation-needed  -j DROP

$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    source-route-failed  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    network-unknown  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    host-unknown  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    network-prohibited  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    host-prohibited  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    TOS-network-unreachable  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    TOS-host-unreachable  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    communication-prohibited  -m limit --limit 1/s -j ACCEPT

$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    host-precedence-violation  -j DROP

$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    precedence-cutoff  -j DROP

$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type source-quench  -j DROP

$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type redirect  -j DROP

$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    network-redirect  -j DROP

$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    host-redirect  -j DROP
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    TOS-network-redirect  -j DROP
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    TOS-host-redirect  -j DROP

$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type echo-request  -m limit --limit 1/s -j ACCEPT

$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type router-advertisement  -j DROP
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type router-solicitation  -j DROP

$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type time-exceeded  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    ttl-zero-during-transit  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    ttl-zero-during-reassembly  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type parameter-problem  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    ip-header-bad  -m limit --limit 1/s -j ACCEPT
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type    required-option-missing  -m limit --limit 1/s -j ACCEPT

$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type timestamp-request  -j DROP
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type timestamp-reply  -j DROP
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type address-mask-request  -j DROP
$IPTABLES -t filter -A FilterICMP -i $INET_IFACE -p icmp \
   --icmp-type address-mask-reply  -j DROP

# accept the others (though there should be no left, I hope...)
$IPTABLES -t filter -A FilterICMP -p icmp -j ACCEPT

#  ===============  End of FilterICMP =========================

# [[======= BlockPortFromOutside user defined chain  ====]]
$IPTABLES -N BlockPortFromOutside

# block syslog, lpr, rsh, rexec
$IPTABLES -t filter -A BlockPortFromOutside -i $INET_IFACE -p udp \
  --dport 514 -j DROP
$IPTABLES -t filter -A BlockPortFromOutside -i $INET_IFACE -p tcp \
  --dport 514 -j DROP
$IPTABLES -t filter -A BlockPortFromOutside -i $INET_IFACE -p tcp \
  --dport 515 -j DROP
$IPTABLES -t filter -A BlockPortFromOutside -i $INET_IFACE -p tcp \
  --dport 512 -j DROP
# =============== End BlockPortFromOutside =================


# These rules will be called in OUTPUT and FORWARD chain
# [[======= DoNotSendOutside user defined chain  ====]]
  
$IPTABLES -N DoNotSendOutside

# block all NetBios (Samba) stuff coming and going to INET_IFACE
# $IPTABLES -t filter -A DoNotSendOutside -p udp -o $INET_IFACE \
#    --sport 137:139 -j LOG --log-level notice --log-prefix "SMB to eth0: "
$IPTABLES -t filter -A DoNotSendOutside -p udp -o $INET_IFACE \
   --sport 137:139 -j DROP
  # protect NFS through the firewall
# $IPTABLES -t filter -A DoNotSendOutside -p udp -o $INET_IFACE --sport 635 \
#    -j LOG --log-level notice --log-prefix "UDP 635 to eth0: "
$IPTABLES -t filter -A DoNotSendOutside -p udp -o $INET_IFACE \
   --sport 635 -j DROP

# $IPTABLES -t filter -A DoNotSendOutside -p udp -o $INET_IFACE --sport 2049 \
#     -j LOG --log-level notice --log-prefix "UDP 2049 to eth0: "
$IPTABLES -t filter -A DoNotSendOutside -p udp -o $INET_IFACE \
   --sport 2049 -j DROP

# $IPTABLES -t filter -A DoNotSendOutside -p udp -o $INET_IFACE --sport 111 \
#    -j LOG --log-level notice --log-prefix "UDP 111 to eth0: "
$IPTABLES -t filter -A DoNotSendOutside -p udp -o $INET_IFACE \
   --sport 111 -j DROP

# block all NetBios (Samba) stuff coming and going to INET_IFACE
# $IPTABLES -t filter -A DoNotSendOutside -p tcp -o $INET_IFACE \
#   --sport 137:139 -j LOG --log-level notice --log-prefix "SMB to eth0: "
$IPTABLES -t filter -A DoNotSendOutside -p tcp -o $INET_IFACE \
   --sport 137:139 -j DROP

  # protect NFS through the firewall
# $IPTABLES -t filter -A DoNotSendOutside -p tcp -o $INET_IFACE --sport 635 \
#     -j LOG --log-level notice --log-prefix "635 to eth0: "
$IPTABLES -t filter -A DoNotSendOutside -p tcp -o $INET_IFACE \
   --sport 635 -j DROP

# $IPTABLES -t filter -A DoNotSendOutside -p tcp -o $INET_IFACE --sport 2049 \
#     -j LOG --log-level notice --log-prefix "2049 to eth0: "
$IPTABLES -t filter -A DoNotSendOutside -p tcp -o $INET_IFACE \
  --sport 2049 -j DROP

# $IPTABLES -t filter -A DoNotSendOutside -p tcp -o $INET_IFACE --sport 111 \
#     -j LOG --log-level notice --log-prefix "111 to eth0: "
$IPTABLES -t filter -A DoNotSendOutside -p tcp -o $INET_IFACE \
   --sport 111 -j DROP

# =============== End DoNotSendOutside =================


#==================================================================
#[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
#==================================================================
#
#   This is where we start filtering (the stuff above is "subroutines"...
# While it is irrelevant which chain I start to shake first, I will try to
# follow the "abstract" route of a packed in netfilter
#


#[][][][][][][][][] PREROUTING [][][][][][][][][][][][][][][][][][]
#
# []*** PREROUTING ***[]
# Packet just entered the interface (ANY INTERFACE, i.e., eth0, eth1, or eth2)
#
#
# [[======= Rules for UDP protocol in PREROUTING chain ====]]

# perform DNAT for UDP addresses/ports

to='*->';
from='->*';
let count=0
while (( $count < ${#INET_TO_DMZ[*]} ))
  do
    addresses=${INET_TO_DMZ[count]};

    inet_address=${addresses%$from};
    dmz_address=${addresses#$to};

    for ports in ${DNAT_UDP_PORTS[count]}
      do
        inet_port=${ports%$from};
        dmz_port=${ports#$to};

#        $IPTABLES -t nat -A PREROUTING -p udp -i $INET_IFACE \
#           -d  ${inet_address} --dport ${inet_port} -j DNAT \
#           --to ${dmz_address}:${dmz_port}

        $IPTABLES -t nat -A PREROUTING -p udp \
           -d  ${inet_address} --dport ${inet_port} -j DNAT \
           --to ${dmz_address}:${dmz_port}
      done
    let count="count + 1"
  done


# [[======= Rules for TCP protocol in PREROUTING chain ====]]

# perform DNAT on TCP addresses/ports
to='*->';
from='->*';
let count=0
while (( $count < ${#INET_TO_DMZ[*]} ))
  do
    addresses=${INET_TO_DMZ[count]};

    inet_address=${addresses%$from};
    dmz_address=${addresses#$to};

    for ports in ${DNAT_TCP_PORTS[count]}
      do
        inet_port=${ports%$from};
        dmz_port=${ports#$to};

        # $IPTABLES -t nat -A PREROUTING -p tcp -i $INET_IFACE  \
        #   -d $inet_address  --dport ${inet_port}
        #   --log-level notice --log-prefix "PRE port ${INET_IFACE}:${dmz_port}: "
#        $IPTABLES -t nat -A PREROUTING -p tcp -i $INET_IFACE \
#           -d  ${inet_address} --dport ${inet_port} -j DNAT \
#           --to ${dmz_address}:${dmz_port}

        $IPTABLES -t nat -A PREROUTING -p tcp \
           -d  ${inet_address} --dport ${inet_port} -j DNAT \
           --to ${dmz_address}:${dmz_port}
      done
    let count="count + 1"
  done

#[][][][][][][][][] INPUT [][][][][][][][][][][][][][][][][][]
#
# []*** INPUT ***[]  
# Packet is destined FOR THE FIREWALL ITSELF.

#
# Reject spoof
$IPTABLES -t filter -A INPUT -j DropSpoof
# Kill port scans
$IPTABLES -t filter -A INPUT -j KillPortScans
# Filter ICMP
$IPTABLES -t filter -A INPUT -j FilterICMP
# Block certain ports from outside
$IPTABLES -t filter -A INPUT -j BlockPortFromOutside

# Allow SSH to Firewall
# This strange looking port is the SSHD port which I will be using
# on the firewall rather than the 22 port. I changed port 22 to 2222 in
# /etc/ssh/sshd_config and restarted sshd. Note that Port 22 will be
# forwarded to the DMZ zone (so I can log in directly to my DMZ machines).
# There is one problem though if you are logging with ssh to FW and to the DMZ
# machine which has matching address. Since on your local machine the file
# $HOME/.ssh/known_hosts and/or known_hosts2 are created the ssh will not
# allow you to connect to the "same" machine with different fingerprint
# (for ssh it is the same machine, since it does not mark entries known_hosts
# with the port number). You can cheat in a number of ways:
#   1) by deleting (or moving it to some file temporarily) known_hosts
#      in $HOME/.ssh/known_host* before using ssh to FW
#   2) By using different ssh protocol (so in one case, the known_hosts
#      is used, and in the other case, the known_hosts2 is used). For example
#         ssh -2 -l root -p 22 my.machine.com
#         ssh -1 -l root -p 2222 my.machine.com
#   3) You can change the /etc/ssh/ss_config file for ssh on your machine
#       and set: StrictHostKeyChecking no
#   4) You can use:
#         ssh -2 -l root -p 22 -o 'StrictHostKeyChecking no' 215.236.123.129 
# One of them may work for you.
#       
#
$IPTABLES -t filter -A INPUT -p tcp --syn  --dport 2222 -m state \
    --state NEW -j LOG --log-prefix "New SSH on FW:"
$IPTABLES -t filter -A INPUT -p tcp --syn  --dport 2222 -m state \
    --state NEW -j ACCEPT

# Allow NEW connections to anything on LAN and DMZ
# This assumes that you TRUST your LAN and DMZ. If you do not, you need
# to modify this... But then, you may not be able to log into your FW
# beside on its own keyboard...
# I probably should be paranoid, and think "What if someone breaks to my
# firewall? But then, if they break into, they will correct this table
# the way they want, so why bother...
#
$IPTABLES -t filter -A INPUT -i $LAN_IFACE -m state --state NEW \
   -j ACCEPT
$IPTABLES -t filter -A INPUT -i $DMZ_IFACE -m state --state NEW \
   -j ACCEPT
$IPTABLES -t filter -A INPUT -m state --state ESTABLISHED,RELATED \
   -j ACCEPT


#[][][][][][][][][] FORWARD [][][][][][][][][][][][][][][][][][]
#
# []*** FORWARD ***[]  
# Packets that are going LAN/DMZ <=> INET, and LAN <=> DMZ. These
# packets do not originate or end on the FW itself.
# 
#
# Reject spoof
$IPTABLES -t filter -A FORWARD -j DropSpoof
# Kill port scans
$IPTABLES -t filter -A FORWARD -j KillPortScans
# Filter ICMP
$IPTABLES -t filter -A FORWARD -j FilterICMP
# Block certain ports from outside
$IPTABLES -t filter -A FORWARD -j BlockPortFromOutside

# log each SSH connection to DMZ
$IPTABLES -t filter -A FORWARD -p tcp -o $DMZ_IFACE --syn  --dport 22 \
   -m state --state NEW -j LOG --log-prefix "New SSH to DMZ"

# Allow the DNAT packets in the FORWARD chain
let count=0
while (( $count < ${#INET_TO_DMZ[*]} ))
  do
    addresses=${INET_TO_DMZ[count]};

    inet_address=${addresses%$from};
    dmz_address=${addresses#$to};

    for ports in ${DNAT_UDP_PORTS[count]}
      do
        inet_port=${ports%$from};
        dmz_port=${ports#$to};

        # $IPTABLES -t filter -A FORWARD -p udp -i $INET_IFACE  \
        #   -d ${dmz_address}  --dport ${dmz_port} \
        #   -m state --state NEW \
        #   --log-level notice --log-prefix "FORW ${INET_IFACE}:${inet_port}: "

#        $IPTABLES -t filter -A FORWARD -p udp -i $INET_IFACE \
#           -m state --state NEW \
#           -d ${dmz_address} --dport ${dmz_port} -j ACCEPT

        $IPTABLES -t filter -A FORWARD -p udp  \
           -m state --state NEW \
           -d ${dmz_address} --dport ${dmz_port} -j ACCEPT

      done
    let count="count + 1"
  done

let count=0
while (( $count < ${#INET_TO_DMZ[*]} ))
  do
    addresses=${INET_TO_DMZ[count]};

    inet_address=${addresses%$from};
    dmz_address=${addresses#$to};

    for ports in ${DNAT_TCP_PORTS[count]}
      do
        inet_port=${ports%$from};
        dmz_port=${ports#$to};

        # $IPTABLES -t filter -A FORWARD -p tcp -i $INET_IFACE  \
        #   -d ${dmz_address}  --dport ${dmz_port} \
        #   -m state --state NEW \
        #   --log-level notice --log-prefix "FORW ${INET_IFACE}:${inet_port}: "

#        $IPTABLES -t filter -A FORWARD -p tcp -i $INET_IFACE \
#           -m state --state NEW \
#           -d ${dmz_address} --dport ${dmz_port} -j ACCEPT

        $IPTABLES -t filter -A FORWARD -p tcp  \
           -m state --state NEW \
           -d ${dmz_address} --dport ${dmz_port} -j ACCEPT
      done
    let count="count + 1"
  done

# Allow NEW connections to anywhere and anything from LAN and DMZ
# This assumes that you TRUST your LAN and DMZ.
#

$IPTABLES -t filter -A FORWARD -i $LAN_IFACE -m state --state NEW \
   -j ACCEPT
$IPTABLES -t filter -A FORWARD -i $DMZ_IFACE -m state --state NEW \
   -j ACCEPT
$IPTABLES -t filter -A FORWARD -m state --state ESTABLISHED,RELATED \
   -j ACCEPT


#[][][][][][][][][] OUTPUT [][][][][][][][][][][][][][][][][][]
#
# []*** OUTPUT ***[]  
# Packets that were created by FW itself and go outside:
# FW => INET, FW => LAN, FW => DMZ
# Again... I trust that all connections initiated from FW are OK
#

$IPTABLES -t filter -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED \
   -j ACCEPT


#[][][][][][][][][] POSTROUTING [][][][][][][][][][][][][][][][][][]
#
# []*** POSTROUTING ***[]  
  #  *** set SNAT/MASQUARADING on the MY_IP_ADDRESS on the list ***

$IPTABLES -t nat -A POSTROUTING -o $INET_IFACE -s ${LAN_IP} -j SNAT \
  --to $MY_IP_ADDRESS
$IPTABLES -t nat -A POSTROUTING -o $INET_IFACE -s ${DMZ_IP} -j SNAT \
  --to $MY_IP_ADDRESS

# =================================================================
  

# 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


# $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



 #  Turn on the IP Forwarding
/bin/echo 1 > /proc/sys/net/ipv4/ip_forward
Modified: Tue May 28 23:57:08 2002 GMT
Page accessed 9473 times since Fri Jan 31 06:41:35 2003 GMT