These are the scripts I use to set up firewalling on my system. First, in /etc/init.d/mine, I've put the following in and link it to /etc/rcS.d/S99mine: #!/bin/sh set -x /sbin/iptables -F /sbin/iptables -P INPUT DROP /sbin/iptables -P FORWARD ACCEPT /sbin/iptables -P OUTPUT DROP /sbin/iptables -t nat -F /sbin/iptables -A INPUT -i lo -j ACCEPT /sbin/iptables -A OUTPUT -o lo -j ACCEPT /sbin/iptables -A INPUT -i eth+ -j ACCEPT /sbin/iptables -A OUTPUT -o eth+ -j ACCEPT exit 0 I don't have start/stop targets for this, as these values should not change. Period. Okay, let's go over the script in "detail". Since this is executed at startup, I prefer to see the commands being executed instead of the traditional "Starting foo services..." type message. So I told /bin/sh via the set -x command to print out all the commands it runs. The -F option to iptables causes it to flush all rules it has. After that, I use the -P option to set the "default policy" on each chain. For any packets that are incoming, outgoing, or being forwarded on behalf of one of the systems in my LAN, the default policy is to silently drop the packets, ditto, and forward them. This configuration works for me, as I don't have to worry about the default ACCEPT policy on my internal systems due to the way they're configured. Your mileage may vary. The -t nat -F option tells iptables to flush the nat tables. NAT is an acronym for Network Address Translation. This includes things like masquerading, where all your internal hosts appear to be the NAT server, so you can have multiple systems on your LAN communicating with the outside work using one IP address. I also use the -A option to append rules to the chains. The rules are checked for every packet, and if none of them match, the default policy is used. I allow all connections over loopback, and all communication between my main system and the internal systems in my LAN. The -i option tells iptables which interface the rule applies to. In the above examples, I use lo for loopback, and eth+ to mean all ethernet interfaces. The + sign acts as a wildcard. The following is my /etc/network/interfaces file: auto lo iface lo inet loopback iface ppp0 inet ppp provider myisp.bg up sh -c 'echo 1 > /proc/sys/net/ipv4/ip_forward' down sh -c 'echo 0 > /proc/sys/net/ipv4/ip_forward' I limited this example to only my ppp interface. The only values you want to change in here are the provider and the up/down targets. The provider line tells ifup which chat script to use when establishing the ppp link. The files are located in /etc/ppp/peers. pppd looks for a file with the same name as the provider line, and that file in turn has options to pppd, including the location of the chat script, usually in /etc/chatscripts. Setting up all that manually is a FAQ in and of itself, so I'll just recommend you use wvdial. Nice program. :-) The echo statements you see there are to enable IP forwarding, so your internal systems can communicate out over the ppp link. If you only have one system on the link, you can rip those out. And here's my firewalling script! Well, some parts were removed for legal reasons. Don't ask. :-) #!/bin/sh # Do we have iptables support? iptables -nL > /dev/null 2>&1 if [ ! $? = 0 ] ; then exit 0 fi # Name servers we forward to. NAMESERVERS="ip.address.one ip.adress.two just.replace.these.with.your.own" # NTP servers we use. # grabbed off stratum 2 server list at: # http://www.eecis.udel.edu/~mills/ntp/clock2.htm NTPSERVERS="ntp1.cs.wisc.edu ntp3.cs.wisc.edu" # Internal network(s). LAN1=192.168.0.0/24 # Address on internal network SELF=192.168.0.3 # shorthand ME=$PPP_LOCAL # Allow stuff for existing connections through. iptables -A INPUT -i ppp+ -p tcp -d $ME -m state \ --state RELATED,ESTABLISHED -j ACCEPT # DNS. -- we use forwarders. since it's mostly UDP, we'll just have to # allow all traffic to the port from the name servers. But note, we # *can* get tcp packets if the reply won't fit in a UDP packet # (there's some really weird domains with lots of A records for one # entity.) # The TCP case is handled by the related/established state matching. # UDP Rules for i in $NAMESERVERS ; do iptables -A INPUT -i ppp+ -d $ME -p udp --dport 53 -s $i \ -j ACCEPT iptables -A OUTPUT -o ppp+ -s $ME -p udp --dport 53 -d $i \ -j ACCEPT done iptables -n -L sleep 5 # long story. don't ask. # NTP -- We need DNS set up, so we can use name resolution to get the # NTP server addresses for i in $NTPSERVERS ; do iptables -A INPUT -i ppp+ -p udp -s $i --sport 123 \ --dport 123 -d $ME -j ACCEPT iptables -A OUTPUT -o ppp+ -p udp -s $ME --sport 123 \ --dport 123 -d $i -j ACCEPT iptables -A OUTPUT -o ppp+ -p tcp -s $ME --dport 123 \ -d $i -j ACCEPT done # stuff elided # Okay, now we can enable new TCP connections. iptables -A OUTPUT -o ppp+ -p tcp -s $ME -m state \ --state RELATED,ESTABLISHED -j ACCEPT # ident. --irc. we need conntrack, but we'll just rely # on oidentd -r for info hiding due to laziness. iptables -A INPUT -i ppp+ -p tcp -d $ME --dport 113 -j ACCEPT # Forward for internal LAN echo 1 > /proc/sys/net/ipv4/ip_forward # Tweak ruleset as appropriate. iptables -t nat -A POSTROUTING -s $LAN1 -o ppp+ -j MASQUERADE iptables -A FORWARD -s $LAN1 -i eth+ -o ppp+ -j ACCEPT iptables -A FORWARD -i eth+ -s $LAN1 -o ppp+ -p tcp \ -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT iptables -A FORWARD -o eth+ -d $LAN1 -i ppp+ -p tcp \ -m state --state ESTABLISHED,RELATED -j ACCEPT Okay... that was a lot to digest in one chunk, wasn't it? Just change the NTPSERVERS and the NAMESERVERS line and you'll be fine. However, if you want to know how the script works, read on: The iptables -nL command just lists the rules throws the output away. If the command returns an exit code of 0, we have iptables support available. NAMESERVERS are the list of external DNS servers we send queries to. Usually, these will be your ISP's name servers. Since I use NTP, NTPSERVERS has the list of hostnames that provide NTP services to me. LAN is the CIDR-notation address of my internal network. For reference, here's a quick chart: Netmask CIDR 255.0.0.0 /8 255.240.0.0 /12 255.255.0.0 /16 255.255.255.0 /24 255.255.255.128 /25 255.255.255.192 /26 255.255.255.224 /27 255.255.255.240 /28 255.255.255.248 /29 255.255.255.252 /30 255.255.255.254 /31 255.255.255.255 /32 SELF is my address on the internal LAN, and ME is the PPP address. PPP_LOCAL is passed to the script by the script /etc/ppp/ip-up to the firewalling script. The outbound connections are firewalled, too. If you don't want this, set the output policy to ACCEPT. You should be careful what you run on your system all the time, but with the output rules set to be open, make sure you check via the netstat(1) command for outbound connections that you can't account for. Everything after that is explained pretty well in the comments. For the meaning behind the various command-line switches, please reference the man page for iptables. Copyright (c) 2000 - 2005 Daniel A. Nobuto