Setting up Linux as a router and firewall is an excellent exercise to get some hands-on experience with system administration on Linux and gain some insight in routing and networking. It's also rather easy.
In today's world of broadband internet connections, the word "router" is usually associated with a device that connects you to the internet and allows you to connect multiple computers on a simple ISP account (possibly a 'one computer' account). Those devices combine functionality of several devices : an ADSL modem or cable modem, a router, network address translation, some firewall functionality, and a switch. We will limit ourselves to the router with NAT, and a firewall. A switch v-can be connected separately, as it only servers to physically connect multiple PC's. It is possible to build in an ADSL board in a PC, but it's probably easier to just use a dedicated ADSL or Cable modem.
What I'll explain here is how to turn a basic Linux system into a router, and add firewall functionality with iptables (netfilter).
setting up routing is explained here
As we are routing between private networks and the public internet, the private IP addresses will need to be translated in to a public address. As we're connecting multiple hosts through this gateway, we'll need translation from multiple private addresses to the 1 public address assigned to eth0 by our internet provider. We need NAT : Network Address Translation. On Linux, this kind of NAT is called MASQUERADING.
setting up masquerading is also explained here
# delete old configuration, if any #Flush all the rules in filter and nat tables iptables --flush iptables --table nat --flush # delete all chains that are not in default filter and nat table iptables --delete-chain iptables --table nat --delete-chain # Set up IP FORWARDing and Masquerading (NAT) iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE iptables --append FORWARD --in-interface eth1 -j ACCEPT iptables --append FORWARD --in-interface eth2 -j ACCEPT #enable forwarding echo 1 > /proc/sys/net/ipv4/ip_forward
Don't forget this script has to be executable : chmod 700 <script>. You may want to make this a startup script so that it is re-enabled after a system reboot. Startup scripts are kept in /etc/init.d, with symbolic links in the /etc/rcX.d for the corresponding runlevels. You can use the update-rc.d command to create them, or create them by hand with ln.
Details :
The network address translation protects your local networks against any connection from outside, because the addresses on the LAN can not be routed without translation, and because in the outside world, only the public address of eth0 is visible.
The make it a real firewall, you may want to add rules about what kind of connections / traffic / communication will be allowed, be it between the LANs and the internet, or between the LANs themselves. These could be rather arbitrary, such as 'no web browsing allowed', or 'only web browsing allowed', but they also have security impact : while incoming connections will be stopped by the NAT, nothing prevents a program on the LAN to set up a connection to an external system. So if that program is a trojan, a backdoor, a virus, a key logger, ... that somehow found its way on to one of your computers (email ? a malicious web site ? downloaded during a chat session or peer-to-peer file sharing ?) and at that external system somebody is patiently waiting until the door is opened, you're still in trouble.
Also : your LAN is invisible to the outside world, but your router is not. So you will need additional rules that govern the circumstances under which a connection to and from this machine will be allowed.
iptables has 3 'chains' : INPUT and OUTPUT govern traffic to and from your router (the machine running iptables), FORWARD governs traffic going through the router (eg from your private network to the internet, or the other way around.) Chains have a default policy, which you can set to ACCEPT or DROP (or DENY). The best practice for firewall configuration is to set a default policy of DENY (or DROP if you prefer stealth), then set rules to allow certain traffic. You allow or deny traffic to by appending (-A) rules to the appropriate chain. A classic example is a rule that allows all trafic towards the internet and accept established/related traffic coming back (eg the reply from a web server) :
#assuming eth0 = WAN, eth1 = LAN iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT
Packets that are routed through the router are governed by rules in the FORWARD chain. Connections from and to the router itself are managed by the INPUT and OUTPUT chains. Rules should be written as if no NAT occurs, using the 'real' addresses.
The router itself should at least be allowed to request and accept DHCP, if it needs a DHCP-assigned IP address from your ISP. If it acts as a DNS server / forwarder, DNS packets should be allowed as well. For remote administration, ssh from that LAN can be allowed. The router should only respond to connections, not initiate them. With the 'state' options of iptables (-m state --state ESTABLISHED), this can easily be implemented without too many extra rules. For DNS and DHCP, see also dealing with DNS and DHCP.
We add the following rules to the firewall script to deal with those:
#router : default = DROP iptables -P INPUT DROP iptables -P OUTPUT DROP #allow DHCP from and to the router on its external interface iptables -A OUTPUT -s 0/0 -i eth0 -p udp --sport 67:68 --dport 67:68 -j ACCEPT iptables -A INPUT -s 0/0 -i eth0 -p udp --sport 67:68 --dport 67:68 -j ACCEPT #allow ssh remote access from LAN, and allow router to respond iptables -A INPUT -s 192.168.10.0/24 -i eth1 -p tcp --sport 22 -j ACCEPT iptables -A OUTPUT -d 192.168.10.0/24 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT #allow troubleshouting etc if done from LAN iptables -A INPUT -s 192.168.10.0/24 -p icmp -j ACCEPT iptables -A OUTPUT -d 192.168.10.0/24 -p icmp -j ACCEPT
Note how you can use either an interface name (eg eth0), an ip address or a network to indicate source and destinations of the traffic.
In addition, you can add some kernel options that protect your router against common exploits and attacks.
With this setup, you're have a basic firewall, that protects the internal LAN by Network Address Translation and some minimal iptables rules. You can further limit or manage access by adding additional rules to the firewall. Here are some sample firewall rules for home networks. This paper explains what your firewall should allow, and why. All of this is already quite good security for a home network. You can check for holes in the firewall with a scanner such as nmap. You may also want to read about Armoring Linux, although the IPCHAINS mentioned there have now been replaced by IPTABLES.
Since a NAT router blocks all incoming connections to the private LAN, it is not possible to run publicly accessible services on the private network : clients outside the private network can only connect to the public IP address, which belongs to the router, not the server behind it. The workaround is to set up "port forwarding" for the service port of the service that you want to be publicly accessible. This is a form of Destination NAT (Destination Address and Port Translation, actually) ; eg redirecting traffic (public address: )port 8888 -> 192.168.1.1 port 80/tcp
iptables -t nat -A PREROUTING -p tcp -i eth0 1 --dport 8888-j DNAT --to 192.168.1.1:80 iptables -A FORWARD -p tcp -i eth0 -d 192.168.1.1 --dport 80 -j ACCEPT