I recently had the pleasure of trying to figure out how to set up a router with a firewall (aka Network Address Translation (NAT) aka IP Masquerading) for a small network. Figuring all of this stuff out took me a whole day, and I have no wish to repeat it (since it's actually not hard - but I've had huge pitfalls with the DNS stuff - e.g. resolving names on my local network).
Note that for determining services that are listening on your computer at any given time, the command "netstat -luntp" can be very useful. You can also do a portscan (from a remote host) with "nmap -sV [remotehost]" to see how your firewall is REALLY looking to an outsider.
Note: these firewall scripts only keep traffic where it belongs. It does NOT limit bandwidth (e.g. won't protect you from a Denial of Service DoS flood attack). For that you should look at combining "iptables" with the iproute2 software (Debian package "iproute"). Just as iptables replaced the older ipchains firewall, the iproute2 commands "tc" and "ip" replace the older "route" and "ifconfig" commands (which are now, for backward compatibility, just scripts that call iproute2). Consult the Linux Advanced Routing and Traffic Control Howto for the ultimate guide. This will tell you how to "shape" (limit and prioritize outgoing traffic) and "police" (limit and prioritize incoming traffic). The package "wondershaper" does a few of these things automatically.
The package "fail2ban" (useful for SSH Security and (with some configuration) avoiding webserver and email server attacks) will kill many types of unwanted traffic by scanning the logs and banning unwanted IPs. Also have a look at (D)DoS-Deflate for preventing those DoS attacks.
Before we begin, I should point out that if you merely have a regular computer with one interface and you just want some simple firewalling rules then you might want to use a graphical firewall frontend like "guarddog+guidedog" or "firestarter". Under the hood they all use IPTABLES. In my experience if you are going to be doing ANYTHING more than the simplest standalone firewalling then you should just learn IPTABLES - at least you'll then know what the machine is doing. Here is a script that brings up some firewalling rules on a machine with only one network interface.
THIS SCRIPT IS FOR A STANDALONE COMPUTER (i.e. not a router for other computers) WITH ONLY 1 NETWORK INTERFACE. PLEASE SKIP BELOW IF YOU WANT TO KNOW ABOUT THE FIREWALLED ROUTER. I USE THIS FIREWALL SCRIPT FOR SOME SERVERS THAT SIT BEHIND DSL/CABLE ROUTERS, BUT IT WORKS EVEN FOR WORKSTATION (NOT SERVER) COMPUTERS.
#!/bin/sh # SAMPLE IPTABLES FIREWALL script # I'm assuming that the interface is "up" # YOU CAN SPECIFY THE INTERFACE AS AN ARGUMENT ON THE COMMANDLINE # i.e. "firewall.sh ath0" echo -e "\n\nSETTING UP IPTABLES FIREWALL..." # SET THE INTERFACE DESIGNATION AND ADDRESS AND NETWORK ADDRESS # FOR THE NIC CONNECTED TO EXTERNAL NETWORK # The default value below is for "eth0". This value # You can use the ifconfig command to list the interfaces # on your system. EXTIF="eth0" #check for a commandline argument if [ "$1" != "" ] then EXTIF="$1" fi EXTIP="`/sbin/ifconfig $EXTIF | grep 'inet addr' \ | awk '{print $2}' | sed -e 's/.*://'`" UNIVERSE="0.0.0.0/0" # Clear any existing rules and setting default policy to DROP iptables -P INPUT DROP iptables -F INPUT iptables -P OUTPUT DROP iptables -F OUTPUT iptables -P FORWARD DROP iptables -F FORWARD iptables -F -t nat # Flush the user chain.. if it exists if [ "`iptables -L | grep drop-and-log-it`" ]; then iptables -F drop-and-log-it fi # Delete all User-specified chains iptables -X # Reset all IPTABLES counters iptables -Z # Creating a DROP chain iptables -N drop-and-log-it iptables -A drop-and-log-it -j LOG --log-level info iptables -A drop-and-log-it -j REJECT echo -e " - Loading INPUT rulesets" ####################################################################### # INPUT: Incoming traffic from various interfaces. All rulesets are # already flushed and set to a default policy of DROP. # # loopback interfaces are valid. iptables -A INPUT -i lo -j ACCEPT # THIS WOULD ALLOW EVERYTHING TO GET IN - FOR TESTING ONLY #iptables -A INPUT -i $EXTIF -s $UNIVERSE -d $EXTIP -j ACCEPT # This is necessary for basic network functionality iptables -A INPUT -i $EXTIF -p icmp -s $UNIVERSE -d $EXTIP -j ACCEPT # THIS ALLOWS ALREADY-ESTABLISHED TRAFFIC IN # Allow any related traffic coming back to the MASQ server in iptables -A INPUT -i $EXTIF -s $UNIVERSE -d $EXTIP \ -m state --state ESTABLISHED,RELATED -j ACCEPT ######################################################################## # HERE ARE THE INCOMING SERVICES THAT ARE ALLOWED. YOU MAY ADD # MORE IF YOU NEED TO OPEN UP A PORT FOR A SPECIFIC REASON, # BUT YOU SHOULD REALIZE THAT ANY SERVICE LISTED HERE ALLOWS # SOMEBODY TO GET INTO YOUR MACHINE!!! ####################################################################### # ping/echo iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ --dport 7 -j ACCEPT iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ --dport 7 -j ACCEPT # GOOD IF YOU ARE RUNNING A WEB SERVER #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 80 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ # --dport 80 -j ACCEPT # GOOD IF YOU ARE RUNNING AN FTP SERVER #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 20:21 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ # --dport 21 -j ACCEPT # NFS (Network File System) server # YOU NEED RPC PORTMAPPER (portmap), rpc.statd???, nlockmgr???, # rpc.mountd??? (these last 3 have changing port numbers!!!) # NFS is a COMPLETE MESS!!! Firewall+NFS = oil+water #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 2049 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ # --dport 2049 -j ACCEPT # RPC Portmapper (portmap) #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 111 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ # --dport 111 -j ACCEPT # NETBIOS (SMB=samba Windows networking) #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 137:139 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ # --dport 137:139 -j ACCEPT #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 445 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ # --dport 445 -j ACCEPT # GOOD IF YOU ARE RUNNING AN SSL WEB SERVER #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 443 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ # --dport 443 -j ACCEPT # rsync #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 873 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ # --dport 873 -j ACCEPT # ident/auth (YOU PROBABLY DON'T NEED THIS # YOU NEED BOTH INCOMING AND OUTGOING #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 113 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ # --dport 113 -j ACCEPT # incoming ssh connections iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ --dport 22 -j ACCEPT # incoming SSH connections (with restrictions) ### restricts to 3 "burst", then once per minute #iptables -A INPUT -m tcp -p tcp --dport 22 -m state --state \ # ESTABLISHED,RELATED -j ACCEPT ### uncomment the next line to put no restrictions on IP range 10.1.0.0/24 # iptables -A INPUT -m tcp -p tcp -s 10.1.0.0/24 --dport 22 -j ACCEPT #iptables -A INPUT -m tcp -p tcp --dport 22 -m state --state NEW -m limit \ # --limit 1/min --limit-burst 3 -j ACCEPT #iptables -A INPUT -m tcp -p tcp --dport 22 -j DROP # ntp (NETWORK TIME PROTOCOL) #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 123 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ # --dport 123 -j ACCEPT # eDonkey2000 # NEED BOTH INCOMING AND OUTGOING #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 4661:4662 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ # --dport 4665:4666 -j ACCEPT # OverNET # NEED BOTH INCOMING AND OUTGOING #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 4953 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE -d $EXTIP \ # --dport 4953 -j ACCEPT # BitTorrent # NEED BOTH INCOMING AND OUTGOING #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 6881:6889 -j ACCEPT #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 6969 -j ACCEPT # Windows Media Player # NEED BOTH INCOMING AND OUTGOING #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 1755 -j ACCEPT #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 1755 -j ACCEPT # RealPlayer Audio # NEED BOTH INCOMING AND OUTGOING #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 554 -j ACCEPT #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 7070 -j ACCEPT #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE -d $EXTIP \ # --dport 6970:7170 -j ACCEPT # ADD MORE INCOMING SERVICES HERE # Catch all rule, all other incoming is denied and logged. iptables -A INPUT -s $UNIVERSE -d $UNIVERSE -j drop-and-log-it echo -e " - Loading OUTPUT rulesets" ####################################################################### # OUTPUT: Outgoing traffic from various interfaces. All rulesets are # already flushed and set to a default policy of DROP. # # loopback interface is valid. iptables -A OUTPUT -o lo -j ACCEPT # THIS ALLOWS ANYTHING OUT # IF YOU ARE PARANOID THEN YOU CAN COMMENT THIS OUT # AND MANUALLY SELECT FROM THE LIST BELOW iptables -A OUTPUT -o $EXTIF -s $EXTIP -d $UNIVERSE -j ACCEPT # This is necessary for basic network functionality iptables -A OUTPUT -o $EXTIF -p icmp -s $EXTIP -d $UNIVERSE -j ACCEPT ######################################################################## # HERE ARE THE OUTGOING SERVICES THAT ARE ALLOWED. YOU MAY ADD # MORE IF YOU NEED TO OPEN UP A PORT FOR A SPECIFIC REASON ####################################################################### # ALLOW ALREADY ESTABLISHED CONNECTIONS OUT iptables -A OUTPUT -o $EXTIF -s $EXTIP -d $UNIVERSE \ -m state --state ESTABLISHED,RELATED -j ACCEPT # IN CASE YOU WANT TO REDIRECT WEB TRAFFIC TO A PROXY # Here the Squid server operates as user "proxy" on port 3128 # and the Dansguardian server operates as user "dansguardian" on port 8080 #### OPEN UP DANSGUARDIAN PORT #iptables -A OUTPUT -p tcp --dport 8080 -j ACCEPT #### ALLOW SQUID TO SEND TRAFFIC TO THE INTERNET #iptables -t nat -A OUTPUT -p tcp \ # --dport 80 -m owner --uid-owner proxy -j ACCEPT #### LET DANSGUARDIAN TALK TO SQUID #iptables -t nat -A OUTPUT -p tcp \ # --dport 3128 -m owner --uid-owner dansguardian -j ACCEPT #### CHANGE "EXEMPT_USER" TO MATCH ANY EXEMPT USERS (E.G. PARENT) #iptables -t nat -A OUTPUT -p tcp \ # --dport 80 -m owner --uid-owner EXEMPT_USER -j ACCEPT #### REDIRECT PORT 80 TO DANSGUARDIAN #iptables -t nat -A OUTPUT -p tcp \ # --dport 80 -j REDIRECT --to-ports 8080 #### DON'T LET ANYBODY ELSE BYPASS DANSGUARDIAN AND TALK DIRECTLY TO SQUID #iptables -t nat -A OUTPUT -p tcp \ # --dport 3128 -j REDIRECT --to-ports 8080 # ALLOW ARBITRARY OUTGOING CONNECTIONS TO "HIGH" PORT NUMBERS iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ --dport 1024:65535 -j ACCEPT # DNS requests iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ --dport 53 -j ACCEPT iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ --dport 53 -j ACCEPT # ping/echo iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ --dport 7 -j ACCEPT iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ --dport 7 -j ACCEPT # http iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ --dport 80 -j ACCEPT iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ --dport 80 -j ACCEPT # https iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ --dport 443 -j ACCEPT iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ --dport 443 -j ACCEPT # ftp iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ --dport 20:21 -j ACCEPT iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ --dport 21 -j ACCEPT # NFS (Network File System) # You need RPC Portmapper (portmap) and the services # rpc.statd???, nlockmgr???, rpc.mountd??? (the last 3 # have changing port numbers!!!). NFS is a COMPLETE mess! # NFS+Firewall = hell #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 2049 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ # --dport 2049 -j ACCEPT # RPC Portmapper (portmap) #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 111 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ # --dport 111 -j ACCEPT # NETBIOS ports (SMB=samba Windows networking) #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 137:139 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ # --dport 137:139 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 445 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ # --dport 445 -j ACCEPT # outgoing ssh iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ --dport 22 -j ACCEPT # ident/auth (you probably need this) # YOU WILL NEED INCOMING udp as well (see above) iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ --dport 113 -j ACCEPT iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ --dport 113 -j ACCEPT # ntp (Network Time Protocol) # YOU WILL NEED THE INCOMING udp 123 at LEAST as well (see above) #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 123 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ # --dport 123 -j ACCEPT # rsync #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 873 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ # --dport 873 -j ACCEPT # AOL instant messenger #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 5190:5193 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ # --dport 5190:5193 -j ACCEPT # eDonkey2000 # UDP protocol NEEDS BOTH INCOMING AND OUTGOING #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 4661:4662 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ # --dport 4665:4666 -j ACCEPT # OverNET # UDP NEEDS BOTH INCOMING AND OUTGOING #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 4953 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p udp -s $EXTIP -d $UNIVERSE \ # --dport 4953 -j ACCEPT # BitTorrent #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 6881:6889 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 6969 -j ACCEPT # Windows Media Player # UDP NEEDS BOTH INCOMING AND OUTGOING #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 1755 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 1755 -j ACCEPT # RealPlayer Audio # NEED BOTH INCOMING AND OUTGOING #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 554 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 7070 -j ACCEPT #iptables -A OUTPUT -o $EXTIF -p tcp -s $EXTIP -d $UNIVERSE \ # --dport 6970:7170 -j ACCEPT # ADD MORE OUTGOING SERVICES HERE # Catch all rule, all other outgoing is denied and logged. iptables -A OUTPUT -s $UNIVERSE -d $UNIVERSE -j drop-and-log-it
Router and Firewall
The rest of this document will deal with a machine with TWO INTERFACES meant to glue together separate networks. Please note that I only used the firewall for a day, so I cannot comment on its reliability or speed (DNSMASQ seemed pretty slow in name resolution, actually).
Here is the setup: I have a Debian box that has two network cards - one an "external" card linking to the outside world, and another an "internal" card linking to my LAN. I wanted to set this box to be a DHCP server (automatically assign IP addresses to computers added on the LAN), and I wanted this machine to act as a simple DNS - e.g. manage names on the LAN and forward name lookups to the internet if not found on the LAN. Finally, I wanted to (obviously) forward traffic between the two cards so that the LAN can see the internet.
The "industrial-grade" way of handling this is to use the "dhcpd" server and the big DNS utility "bind". I didn't want to go this route since it seems like overkill, although it would've been a good learning experience (I have other things to learn right now). The alternative is to use a neat little utility called "dnsmasq" - this simple little utility does *almost* everything that I want, so that's the choice (I'm still unhappy with the name resolution for computers on the LAN, but I can live with it).
Getting the kernel to use multiple ethernet cards
It was already difficult enough to figure out that the kernel doesn't
automatically sense every ethernet card in the box. You need to TELL
the kernel to use all of the cards explicitly. In my case, when running
"lspci" I found the lines
Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8169 Gigabit
Ethernet (rev 10)
Ethernet controller: VIA Technologies, Inc. VT6102 [Rhine-II] (rev 74)
After poking around in /lib/modules I found that the appropriate drivers
were "r8169" and "via_rhine" - so I put both of those entries in
/etc/modules (this file just forces the kernel to load these modules
explicitly). I have no idea how to control which becomes eth0 and which
becomes eth1 (I tried adding aliases - that didn't work). Anyway, I
found that my via_rhine became eth1 and my r8169 became eth0 (and it
was consistent reboot after reboot after reboot) so I just learned to
live with it (if anybody can tell me how to force the eth0/eth1 naming
then I'd be much obliged). If the drivers are compiled in the kernel then you
need to pass a kernel argument when booting from grub or lilo such as
"ether=0,0,eth0 ether=0,0,eth1". I'm using modules so I can't speak
from experience.
Now my eth0 will be my INTERNAL card and my eth1 will be my EXTERNAL
card. How you connect your EXTERNAL card to the internet will vary
widely - many will probably use ADSL with PPPoE or something similar.
In my case I actually can push out to my ISP a DHCP request - so my
firewall becomes a DHCP *client* on the EXTERNAL interface (like the
way your computer normally gets on a network). This has nothing to do
with the fact that I am trying to set up a DHCP *server* on my INTERNAL
network. To get both interfaces up I have the following lines in
/etc/network/interfaces (yours will probably be similar)
auto lo eth0 eth1 iface lo inet loopback mapping eth1 script grep map eth1 allow-hotplug eth1 iface eth1 inet dhcp
iface eth0 inet static address 192.168.0.254 netmask 255.255.255.0
If you want to play around and check thinks out manually then use "ifconfig". For example just typing "ifconfig" will list all interfaces that are UP - useful for debugging. You can manually assign eth0 to 192.168.0.254 by typing "ifconfig eth0 192.168.0.254 up", for example.
Setting up DNSMASQ as a DHCP and DNS service
Now you can install "dnsmasq" through apt-get if you like Debian. The
relevant configuration file is located in "/etc/dnsmasq.conf". It's
pretty self-explanatory, but I'll mention the relevant entries here (I
assume that my domain is called "localdomain" - bad idea, I know).
# set up the local domain local=/localdomain/ domain=localdomain # limit DHCP requests to this INTERNAL interface interface=eth1 # nice so that you don't have to use fully qualified names - tacks # on that localdomain for you expand-hosts # set the DHCP ranges to assign dhcp-range=192.168.0.50,192.168.0.150,12h # MANUALLY set hostnames on the network using the hardware MAC address # for each host # if you don't care about referring to a computer by name then this isn't # necessary dhcp-host=00:20:E0:6B:C4:EA,charlene,192.168.0.50 dhcp-host=00:40:E7:6B:C4:EA,greasyspoon,192.168.0.51
192.168.0.50 charlene 192.168.0.51 greasyspoon
Gluing the two interfaces together
Now it's time to actually forward TCP/IP traffic (you already forwarded DNS
name resolution, but no actual traffic can get through yet).
This is done using an IPTABLES set of rules. To learn about the "iptables"
command you should consult
this website... it's
quite instructive.
Here's a script that just acts as a pass-through - you should only use it for testing purposes since there are NO firewalling rules whatsoever here.
#!/bin/sh # Just a straight-through gluing script - for testing ONLY # Here I'll assume the the interfaces are already "up" # this merely adds FORWARDING rules echo -e "\n\nSETTING UP IPTABLES FORWARDER..." # SET THE INTERFACE DESIGNATION FOR THE NIC CONNECTED TO YOUR INTERNAL NETWORK INTIF="eth0" # SET THE INTERFACE DESIGNATION FOR YOUR "EXTERNAL" (INTERNET) CONNECTION EXTIF="eth1" echo 1 > /proc/sys/net/ipv4/ip_forward # Clearing any existing rules and setting default policy iptables -P INPUT ACCEPT iptables -F INPUT iptables -P OUTPUT ACCEPT iptables -F OUTPUT iptables -P FORWARD DROP iptables -F FORWARD iptables -t nat -F # FWD: Allow all connections OUT and only existing and related ones IN iptables -A FORWARD -i $EXTIF -o $INTIF -m state \ --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT # Enabling SNAT (MASQUERADE) functionality on $EXTIF iptables -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE echo -e " Proxy server rule loading complete\n\n"
Really you will need to add some IPTABLES firewall rules to keep the bad guys out. For something a little more sturdy you could start with this: Note the built-in support for transparent web proxying and web filtering! Give it a try - you'll love it.
#!/bin/sh # SAMPLE IPTABLES FIREWALL script # Again, I'm assuming that both interfaces are "up" echo -e "\n\nSETTING UP IPTABLES FIREWALL..." # SET THE INTERFACE DESIGNATION AND ADDRESS AND NETWORK ADDRESS # FOR THE NIC CONNECTED TO YOUR _INTERNAL_ NETWORK # Enter the designation for the Internal Interface's INTIF="eth1" # Enter the NETWORK address the Internal Interface is on INTNET="192.168.200.0/24" # Enter the IP address of the Internal Interface INTIP="192.168.200.254" # SET THE INTERFACE DESIGNATION FOR YOUR "EXTERNAL" (INTERNET) CONNECTION EXTIF="eth0" EXTIP="`/sbin/ifconfig $EXTIF | grep 'inet addr' \ | awk '{print $2}' | sed -e 's/.*://'`" UNIVERSE="0.0.0.0/0" echo 1 > /proc/sys/net/ipv4/ip_forward # Clear any existing rules and setting default policy to DROP iptables -P INPUT DROP iptables -F INPUT iptables -P OUTPUT DROP iptables -F OUTPUT iptables -P FORWARD DROP iptables -F FORWARD iptables -F -t nat # Flush the user chain.. if it exists if [ "`iptables -L | grep drop-and-log-it`" ]; then iptables -F drop-and-log-it fi # Delete all User-specified chains iptables -X # Reset all IPTABLES counters iptables -Z # Creating a DROP chain iptables -N drop-and-log-it iptables -A drop-and-log-it -j LOG --log-level info iptables -A drop-and-log-it -j REJECT echo -e " - Loading INPUT rulesets" ####################################################################### # INPUT: Incoming traffic from various interfaces. All rulesets are # already flushed and set to a default policy of DROP. # # TRUST ANYTHING COMING IN ON LOOPBACK iptables -A INPUT -i lo -j ACCEPT # remote interface, claiming to be local machines, IP spoofing, get lost iptables -A INPUT -i $EXTIF -s $INTNET -d $UNIVERSE -j drop-and-log-it # these are necessary for basic networking functionality iptables -A INPUT -i $INTIF -p icmp -s $INTNET -d $UNIVERSE -j ACCEPT iptables -A INPUT -i $EXTIF -p icmp -s $UNIVERSE -d $EXTIP -j ACCEPT # THIS ALLOWS ANY TRAFFIC TO COME IN ON THE INTERNAL # CARD - THIS IS PROBABLY TOO LENIENT. THE RULES BELOW # ARE MORE SELECTIVE #iptables -A INPUT -i $INTIF -s $INTNET -d $UNIVERSE -j ACCEPT ############################################################# # HERE ARE RULES FOR WHICH TRAFFIC ORIGINATING ON THE LOCAL # NETWORK IS ALLOWED TO ACCESS THE FIREWALL ITSELF - # THIS HAS NOTHING TO DO WITH WHAT IS FORWARDED THROUGH!!! ############################################################# # Allow any related traffic coming back to the MASQ server in iptables -A INPUT -i $INTIF -s $INTNET -d $INTIP -m state \ --state ESTABLISHED,RELATED -j ACCEPT # ping/echo iptables -A INPUT -i $INTIF -p tcp -s $INTNET -d $UNIVERSE --dport 7 -j ACCEPT iptables -A INPUT -i $INTIF -p udp -s $INTNET -d $UNIVERSE --dport 7 -j ACCEPT # DNS requests iptables -A INPUT -i $INTIF -p tcp -s $INTNET -d $UNIVERSE --dport 53 -j ACCEPT iptables -A INPUT -i $INTIF -p udp -s $INTNET -d $UNIVERSE --dport 53 -j ACCEPT # ident/auth #iptables -A INPUT -i $INTIF -p tcp -s $INTNET -d $UNIVERSE \ # --dport 113 -j ACCEPT #iptables -A INPUT -i $INTIF -p udp -s $INTNET -d $UNIVERSE \ # --dport 113 -j ACCEPT # ssh #iptables -A INPUT -i $INTIF -p tcp -s $INTNET -d $UNIVERSE \ # --dport 22 -j ACCEPT # UNCOMMENT THIS STANZA FOR WEB CACHE/PROXY SUPPORT # USING A DANSGUARDIAN/SQUID SETUP #iptables -A INPUT -i $INTIF -p tcp --dport 8080 -j ACCEPT # Redirect port 80 to Dansguardian (port 8080) #iptables -t nat -A PREROUTING -i $INTIF -p tcp \ # --dport 80 -j REDIRECT --to-ports 8080 # THIS ALLOWS ANYTHING TO COME IN ON THE EXTERNAL INTERFACE. # THIS IS OBVIOUSLY UNACCEPTABLE. UNCOMMENT ONLY FOR TESTING # PURPOSES #iptables -A INPUT -i $EXTIF -s $UNIVERSE -d $EXTIP -j ACCEPT ############################################################# # HERE ARE RULES FOR WHICH *INBOUND* TRAFFIC IS ALLOWED # ON THE EXTERNAL INTERFACE - THIS IS THE CRITICAL PART!!! # ANY SERVICE SPECIFIED HERE MUST BE EITHER PROVIDED BY # THE FIREWALL ITSELF, OR THE PORT MUST BE FORWARDED TO # SOME SPECIFIC MACHINE ON THE INTERNAL LAN # SEE BOTTOM OF SCRIPT FOR PORT FORWARDING EXAMPLE ############################################################# # Allow any related traffic coming back to the MASQ server in iptables -A INPUT -i $EXTIF -s $UNIVERSE -d $EXTIP -m state \ --state ESTABLISHED,RELATED -j ACCEPT # ping/echo iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE \ -d $EXTIP --dport 7 -j ACCEPT iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE \ -d $EXTIP --dport 7 -j ACCEPT # ident/auth #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE \ # -d $EXTIP --dport 113 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE \ # -d $EXTIP --dport 113 -j ACCEPT # ssh (no restrictions) iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE \ -d $EXTIP --dport 22 -j ACCEPT # SSH (restricted) to 3 burst attempts, then once per minute #iptables -A INPUT -i $EXTIF -m tcp -p tcp --dport 22 -m state --state \ # ESTABLISHED,RELATED -j ACCEPT #iptables -A INPUT -i $EXTIF -m tcp -p tcp --dport 22 -m state --state \ # NEW -m limit --limit 1/min --limit-burst 3 -j ACCEPT #iptables -A INPUT -i $EXTIF -m tcp -p tcp --dport 22 -j DROP # http #iptables -A INPUT -i $EXTIF -p tcp -s $UNIVERSE \ # -d $EXTIP --dport 80 -j ACCEPT #iptables -A INPUT -i $EXTIF -p udp -s $UNIVERSE \ # -d $EXTIP --dport 80 -j ACCEPT #################################################### # SEE SCRIPT AT BEGINNING OF THIS WEBPAGE TO # LOCATE MORE SERVICES THAT YOU MIGHT WANT # ADD YOUR OWN RULES ##################################################### # Catch all rule, all other incoming is denied and logged. iptables -A INPUT -s $UNIVERSE -d $UNIVERSE -j drop-and-log-it echo -e " - Loading OUTPUT rulesets" ####################################################################### # OUTPUT: Outgoing traffic from various interfaces. All rulesets are # already flushed and set to a default policy of DROP. # # YOU WILL PROBABLY NOT NEED TO MODIFY THE OUTGOING RULES # UNLESS YOU REALLY WANT A BOMBPROOF FIREWALL # outgoing to local net on remote interface, stuffed routing, deny iptables -A OUTPUT -o $EXTIF -s $UNIVERSE -d $INTNET -j drop-and-log-it # loopback is valid iptables -A OUTPUT -o lo -j ACCEPT # local interface, any source going to local net is valid iptables -A OUTPUT -o $INTIF -d $INTNET -j ACCEPT # anything else outgoing on remote interface is valid iptables -A OUTPUT -o $EXTIF -j ACCEPT # Catch all rule, all other outgoing is denied and logged. iptables -A OUTPUT -s $UNIVERSE -d $UNIVERSE -j drop-and-log-it echo -e " - Loading FORWARD rulesets" ####################################################################### # FORWARD: Enable Forwarding and thus IPMASQ ################################################################ # ADD PORT FORWARDING RULES HERE # ANY ENTRY HERE MUST HAVE A CORRESPONDING ENTRY IN THE # "INPUT ON THE EXTERNAL INTERFACE" SECTION - SEE ABOVE ################################################################ # EXAMPLE FORWARD PORT 80 TO COMPUTER ON LAN WITH IP 192.168.200.5 # THIS comes in two sections. Forward what comes in on the outside, # and make a special exception to forward whatever originated # on INTERNAL network BACK inside #iptables -t nat -A PREROUTING -i $EXTIF -p tcp --dport 80 \ # -j DNAT --to-destination 192.168.200.5 #iptables -A FORWARD -i $EXTIF -p tcp --dport 80 -j ACCEPT #iptables -t nat -A PREROUTING -i $INTIF -p tcp -d $EXTIP --dport 80 \ # -j DNAT --to-destination 192.168.200.5 #iptables -A FORWARD -i $INTIF -p tcp -d $EXTIP --dport 80 -j ACCEPT ######################################################### # ADD YOUR RULES HERE FOR TRAFFIC THAT WILL BE # FORWARDED FROM THE INTERNAL INTERFACE TO THE # EXTERNAL INTERFACE - this is not as critical as # the INCOMING filter above, but still worthwhile ######################################################### # Enable (MASQUERADE) functionality on $EXTIF iptables -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE iptables -t nat -A POSTROUTING -o $INTIF -j MASQUERADE # this allows everything from inside to outside # MAYBE too lenient, but maybe not. If you are # PARANOID THEN COMMENT THIS OUT and consider # the rules below!!! iptables -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT # allow any previously established traffic through iptables -A FORWARD -i $EXTIF -o $INTIF -m state \ --state ESTABLISHED,RELATED -j ACCEPT # ICMP protocol necessary for ping, etc iptables -A FORWARD -i $INTIF -p icmp -j ACCEPT # high port numbers allowed out iptables -A FORWARD -i $INTIF -p tcp --dport 1024:65535 -j ACCEPT iptables -A FORWARD -i $INTIF -p udp --dport 1024:65535 -j ACCEPT # ping/echo iptables -A FORWARD -i $INTIF -p tcp --dport 7 -j ACCEPT iptables -A FORWARD -i $INTIF -p udp --dport 7 -j ACCEPT # DNS iptables -A FORWARD -i $INTIF -p tcp --dport 53 -j ACCEPT iptables -A FORWARD -i $INTIF -p udp --dport 53 -j ACCEPT # ident/auth iptables -A FORWARD -i $INTIF -p tcp --dport 113 -j ACCEPT iptables -A FORWARD -i $INTIF -p udp --dport 113 -j ACCEPT # ssh iptables -A FORWARD -i $INTIF -p tcp --dport 22 -j ACCEPT iptables -A FORWARD -i $INTIF -p udp --dport 22 -j ACCEPT # http iptables -A FORWARD -i $INTIF -p tcp --dport 80 -j ACCEPT iptables -A FORWARD -i $INTIF -p udp --dport 80 -j ACCEPT # https iptables -A FORWARD -i $INTIF -p tcp --dport 443 -j ACCEPT iptables -A FORWARD -i $INTIF -p udp --dport 443 -j ACCEPT # ftp iptables -A FORWARD -i $INTIF -p tcp --dport 20:21 -j ACCEPT iptables -A FORWARD -i $INTIF -p udp --dport 21 -j ACCEPT # Catch all rule, all other forwarding is denied and logged. iptables -A FORWARD -j drop-and-log-it echo -e " Firewall server rule loading complete\n\n"
I think that it is interesting to talk about Web proxies like Squid. A "proxy" can allow you to cache Web data (speeds up the internet) and, more importantly, control Web access on your LAN. For example, by using a Squid add-on such as SquidGuard or Dansguardian (recommended) you can even FILTER WEB CONTENT. Please see my Dansguardian/Squid HOWTO for more information.
This page has been visited times since December 25, 2005