Translate original post with Google Translate
You probably remember the article “Create a Linux router” I published long time ago. As this is now obsolete and I discovered new possibility, here is a page with updated information and more detailed tips. As a reminder, creating a Linux router using an old computer is a good way to secure your private network and to have a very good performance level for cheap. A very old computer is good enough to do this (for example a PIII 600 MHz with 256 MB of RAM and 2 GB hard drive).
1. What do you need ?
1.1. Hardware
In fact the computer have no reel importance, it just need to be able to run a very light Linux installation. The only thing it need is a network card for external connection (the one connected with the modem) and one or more other network card for your private network. You can have as much network card as you will want separate private network. For a private use, only one is required or two if you wish to have a separate WiFi network (as an example but you can have your WiFi network sharing the same zone as your wired network but this is less secure particularly if you wish to share your WiFi connection publicly). The other hardware you need is one (or more) Ethernet switch and, if you want WiFi, an access point. The hardware you use will need very good lifetime as the router is supposed to work 24/24 hours and 7/7
1.2. Software
Creating a Linux router requires very few requirements. You will need a Linux distribution with a very good stability and as light as possible. Debian is a good compromise between stability, performance on very little configuration and ease of use. There’s lighter distribution but they have less feedback in case of problems. Do not consider using something like Ubuntu, Mandriva, OpenSuse or any other big distributions as they are not created with stability in mind and (or, with their “professional” declination) they install too much things. Keep in mind that stability is very important as the router is not supposed to be stopped or restarted as you will loose internet connection if this happen. That’s why Debian is the best choice for me.
The website Distrowatch can help you compare hundreds of different distribution to help you making your choice. Here is a list of distributions that can be good for such a use and created to run on old computers starting from Pentium MMX with 64 MB or more of RAM:
- Debian GNU/Linux which can run on several different processor such as MIPS, SPARC, Alpha, etc. and have very good feedback
- Arch Linux a bit lighter than Debian and highly customizable
- Slackware which intended for advanced users (no dependency based package management)
- SLAX based on Slackware have very good hardware detection system which is good with some exotic hardware
- Crux which is something like a compromise between Debian and Arch
You may have an older computer starting from i386 with 4MB of RAM. In that case you will need something even smaller. Note that such distributions may includes older version of the needed packages so the given commands and configuration files in the next steps may require some changes. Another thing is, as far as I know, that those distributions will not includes the DHCP server and/or iptables. That means that you will have to compile yourself an old version (preferably the same as the given client) of these software. Here is a few list of such distributions, but I don’t know them enough to give you any additional information:
- Debian GNU/Liniux Etch version or older (i.e. version 3.0 or 3.1) – you can easily find CD images for version 3.0 and 3.1 but older ones seems to not be officially available.
- Damn Small Linux
- BasicLinux
- MuLinux
There’s also specialized distribution for routing. The advantage is simplicity, the availability of uPNP server (most of the time) and a web interface allowing you to configure the router just like any others you can buy to your preferred retailer. The problem of those systems is you will loose in flexibility and choice particularly with other external public servers. So I recommend those distributions if you do not have specific needs (unless you want fun
). Here is a list of such specialized Linux distributions:
- IPCop
- SmoothWall Express
- OpenWRT more designed to be used embedded, you will need to compile everything to use it on a computer.
Here is a list of the software you will need to be installed:
- dhcp-server will be the dhcp server that will give automatic address to the computers of your private network;
- iptables >= 1.0.0 that will act as both firewall and NAT routing system;
- A text editor such as vim or nano;
- dhcp-client may be needed to configure your external network particularly if you have a dynamic external address;
- A text web browser to test the connection such as w3m or links
- some server that may run on the router to give access to external service (i.e. accessible through the Internet).
- Debian Lenny or higher includes the package upnp-router-control needed if you want uPNP server on your router.
With Debian you should consider installing Leny or Squeeze or any newer version than Etch (elsewhere, the given command and parameters should not work). Anyway do not use Sid for Debian or any unstable version of the chosen system. On a Debian system you have to install all of this minimal requirement using command lines like those ones:
su #type your root password unless you already logged in as root apt-get install dhcp3-server dhcp3-client iptables nano w3m upnp-router-control apt-get install <needed server packages names>
You can use apt-cache search <your search> command if you don’t know the exact name of the additional server package you want.
As stability and security are the most important thing in such configuration, you should not install the X server and any graphical application or any unneeded software or servers. The best is to do a fresh Debian minimal installation (or the equivalent with the given distribution) and to type the commands given above once logged in.
Note that oppositely to the last tutorial I made, I do not recommend any more the use of iptables-persistant as a script will be created with this tutorial replacing its use with is much more efficient and can be loaded at boot time with an init script (in case of server reboot).
2. Configuring your connection
Now, lets suppose the following configuration of your future router:
- eth0 (first network card: external network) will be connected to your modem (or some set-top box)
- eth1 (second network card: private network) will be connected to an Ethernet hub or switch
- eth2 (third network card) will be connected to a WiFi access point for a public WiFi network
Of course the public WiFi access is optional and will be given as an example for such a use. For private WiFi access the best way is to connect it to the switch of the private network. You can also have several private separate network as well as several public WiFi. To do this you will just have to reproduce the lines given for that for each with the good parameters.
The base address that will be used is something like 192.168.x.y but you can use something else. Nevertheless, this base remains a good choice as you are sure it will not conflict with external address you may need to access. For example if you choose for one of your private network a base like 209.85.229.x, you may not be able to access the Google website, or part of it, wich is using it (209.85.229.147 is one of the address of www.google.com) as your private network will have the priority. The base address you can use are 192.168.x.y or (mainly if you have bigger needs) 10.x.y.z.
Note that this tutorial will consider that 192.168.1.y and 192.168.2.y will be considered as two different sub-network for more simplicity. This is enough most of the time as it’s rare to need to connect more than 250 computers. People doing this use more specialized systems providing much more complex routing systems (and so server systems) which is a bit out of this tutorial. Nevertheless, this is possible by attributing address on one sub-network with x and y are significant (e.g. a range of address from 192.168.0.1 to 192.168.3.254 for a first sub-network and 192.168.128.1 to 192.168.129.254 for a second one). To do this, the best is to calculate the network masks with precision. If you don’t know what is a network mask, you should forget to try that
…
Now, I will consider the following for the remainder of this tutorial:
- The internet zone will have the address given via DHCP. This address is either given by your ISP or by a router (like the integrated one in some advanced router or set-top box). If the address is something like 192.168.0.254, your private network can’t use the same sub-network (in that case 192.168.0.y).
- The private zone will have address dynamically attributed by the router you are about to build with a range of address from 192.168.0.1 to 192.168.0.250. The last address (192.168.0.251 to 192.168.0.254) will be reserved for statically attributed address that may be needed for other server. The router itself will have the static address 192.168.0.254.
- In the same way that the private zone, the public WiFi zone will have dynamic address from 192.168.1.1 to 192.168.1.5 (in order to limit the number of guest to five). The router will have the static address 192.168.1.254.
2.1 The /etc/network/interfaces file
This file is about configuring your network connections and is used by boot script to configure it correctly. Be careful, that configuration file is for Debian based based system and few others distributions using Debian scripts. You can have detailed information about this file here. According to the previous definitions it will look like that:
# Begin of /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
# The loopback network interface
auto lo,eth0,eth1,eth2
iface lo inet static
# Primary network interface: internet zone
auto eth0
iface eth0 inet dhcp
# Second network interface: private zone
iface eth1 inet static
address 192.168.0.254
network 192.168.0.0
netmask 255.255.255.0
broadcast 192.168.0.255
gateway 192.168.0.254
# Third network interface: wifi zone
iface eth2 inet static
address 192.168.1.127
network 192.168.1.0
netmask 255.255.255.128
broadcast 192.168.1.255
gateway 192.168.1.127
# End of /etc/network/interfaces
Now let’s explain that: we are defining four different interface. First we have the loopback network interface. This is a special and reserved zone with the default address 127.0.0.1. This is a zone where the computer is speaking to himself simulating a virtual network card. Every POSIX systems have such a feature allowing, for example, simulation. This is highly recommended to keep that as-is as some programs need it to work properly.
Then we have three real network interface. The first one is different because it is activated with DHCP. DHCP means Dynamic Host Configuration Protocol. This is commonly used when you boot up your computer to give him an IP address. In our case, we need that the modem give to the first interface a valid IP address particularly if your ISP is giving you a dynamic address that may change from time to time. It will be, so, our external address. The “auto” line, just before the configuration line for eth0 means that in case of service interruption (obviously from your ISP) or in case of external address change (most of the ISP change your address from time to time) the interface will be reconfigured automatically.
The two last network interfaces are configured manually. Habitually the router address ends up with 254. This is not an obligation, but more something like a tradition. We define the gateway as same as the IP address. This allows us to have the best security as IPTables will redirect everything to the good interface. In that way each zone is clearly separated from the others, IPTables making the link.
If you want more details about that file and much more advanced tweaks about it you should read the associated manual page with writing “man interface(5)” in a terminal.
2.2. Configuring DHCP server
The DHCP server’s job is to give IP address automatically to the computers that will be plugged on our network, as it’s difficult to ask anybody to configure manually its network connection. So we need that server to give us correct parameters for the following :
- IP address: it’s our address on the network;
- Mask: the mask is a way for the computers to know who is allowed to speak directly to them, everything that is not covered by this mask will be ignored;
- Gateway: it’s typically the router itself, so the computer that making the link between our private area and an external area;
- DNS (Domain Name Server): when you want to go on Google you type www.google.com and not an IP address: the DNS server(s) translate that name in IP address;
- Optionally the DHCP server can give more information such as PXE file, or an other DHCP server as master…
The file to edit to configure all of that stuff is /etc/dhcp/dhcpd.conf. If you are using Debian, the existing file contains many commented samples with explanation which could be a good help. Note that Debian version prior to Squeeze have /etc/dhcp3/dhcpd.conf file instead. Here is what that file look like:
# Begin /etc/dhcp/dhcpd.conf
# Use "interim" style name server updating procedures. This allow to update
# DNS server name in case of change via DHCP client. In that case the update
# is made in case of change (via a testing thread). The "ad-hoc" parametter is
# not testing and ask for DNS update periodically. It is considered as unsafe
# and deprecated. If your DNS is not supposed to change, change that
# parameter to "none".
ddns-update-style interim;
# Configure client's dns settings: replace 212.27.40.24x with your ISP DNS
# servers and optionally add your DNS server (192.168.1.254 here) if you have
# your own (here the router is also a DNS server).
option domain-name "jeff.levasseur.org";
option domain-name-servers 212.27.40.241, 212.27.40.240, 192.168.1.254;
# Configure lease time (in seconds) : here is the max values
default-lease-time 600000000;
max-lease-time 720000000;
# eth1 subnet configuration: this will give address from 192.168.1.10 to
# 192.168.1.250 and it's the only thing you may change. Note that you
# can have several range, and ranges with only one address.
subnet 192.168.0.0 netmask 255.255.255.0 {
range 192.168.0.10 192.168.0.250;
option routers 192.168.0.254;
option broadcast-address 192.168.0.255;
}
# eth2 subnet configuration: here you have an example of multiple range
# and a different mask
subnet 192.168.1.0 netmask 255.255.255.128 {
range 192.168.1.1 192.168.1.10;
range 192.168.1.30 192.168.1.40;
range 192.168.1.50
option routers 192.168.1.127;
option broadcast-address 192.168.1.255;
}
# End /etc/dhcp3/dhcpd.conf
To apply the changes, you need to restart the DHCP server with:
/etc/init.d/dhcp3-server restart
You should test the DHCP server by reconfiguring the network and pinging the server on one of the client machine. For example with Linux:
dhclient eth0 ifconfig ping 192.168.1.1
If dhclient is giving you a good IP address (shown with ifconfig) and ping returns no packet transmission error, you’re DHCP server is well configured. With Windows, you should use the “Control Panel” to configure the network settings of the client. If you use a WiFi hotspot you have to configure it before doing this test.
Note that at this point your local network should be fully functional but you will have no access to any external network and internet as there’s still no routing functionality activated. This is the next point subject.
2.3. Configuring IPTables
IPTables is a command line tool managing NetFilter. NetFilter is the firewall integrated in Linux kernel. But NetFilter is far more than a firewall, it is a redirecting utility working either on port or IP address, a NAT (Network Address Translation), it have Proxy capabilities, etc… Here we will need nearly all of those feature to make a very strong firewall and router. To be able to activate our rules at boot time we will create a script that will be called in the Init script of our distribution. Now that script is looking like that:
#!/bin/sh
# IPTABLES PROXY script for the Linux >= 2.4 kernel.
# This script is a derivative of the script presented in
# the IP Masquerade HOWTO page at (obsolete):
# www.tldp.org/HOWTO/IP-Masquerade-HOWTO/firewall-examples.html
# It was simplified to coincide with the configuration of
# the sample system presented in the Guides section of
# www.aboutdebian.com
#
# PLEASE SET THE USER VARIABLES
# IN SECTIONS A AND B OR C
echo "SETTING UP IPTABLES PROXY..."
# === SECTION A
# ----------- FOR EVERYONE
# SET THE INTERFACE DESIGNATION FOR THE NIC CONNECTED TO YOUR INTERNAL NETWORK
# The default value below is for "eth0". This value
# could also be "eth1" if you have TWO NICs in your system.
# You can use the ifconfig command to list the interfaces
# on your system. The internal interface will likely have
# have an address that is in one of the private IP address
# ranges.
# Note that this is an interface DESIGNATION - not
# the IP address of the interface.
# Enter the internal interface's designation for the
# INTIF variable:
INTIF="eth1"
# SET THE INTERFACE DESIGNATION FOR YOUR "EXTERNAL" (INTERNET) CONNECTION
# The default value below is "ppp0" which is appropriate
# for a MODEM connection.
# If you have two NICs in your system change this value
# to "eth0" or "eth1" (whichever is opposite of the value
# set for INTIF above). This would be the NIC connected
# to your cable or DSL modem (WITHOUT a cable/DSL router).
# Note that this is an interface DESIGNATION - not
# the IP address of the interface.
# Enter the external interface's designation for the
# EXTIF variable:
EXTIF="eth0"
# Enter the NETWORK address the Internal Interface is on
INTNET="192.168.0.0/24"
# Enter the IP address of the Internal Interface
INTIP="192.168.0.254/24"
# ! ! ! ! ! Use ONLY Section B *OR* Section C depending on
# ! ! ! ! the type of Internet connection you have.
# === SECTION B
# ----------- FOR THOSE WITH STATIC PUBLIC IP ADDRESSES
# SET YOUR EXTERNAL IP ADDRESS
# If you specified a NIC (i.e. "eth0" or "eth1" for
# the external interface (EXTIF) variable above,
# AND if that external NIC is configured with a
# static, public IP address (assigned by your ISP),
# UNCOMMENT the following EXTIP line and enter the
# IP address for the EXTIP variable:
EXTIP="82.x.y.z"
# === SECTION C
# ---------- DIAL-UP MODEM, AND RESIDENTIAL CABLE-MODEM/DSL (Dynamic IP) USERS
# SET YOUR EXTERNAL INTERFACE FOR DYNAMIC IP ADDRESSING
# If you get your IP address dynamically from SLIP, PPP,
# BOOTP, or DHCP, UNCOMMENT the command below.
# (No values have to be entered.)
# Note that if you are uncommenting these lines then
# the EXTIP line in Section B must be commented out.
#EXTIP="`/sbin/ifconfig eth1 | grep 'inet ' | awk '{print $2}' | sed -e 's/.*://'`"
# Define our universe (all the internet)
UNIVERSE="0.0.0.0/0"
# -------- No more variable setting beyond this point --------
echo " Loading required stateful/NAT kernel modules..."
# Updating module's dependencies
/sbin/depmod -a
# Force loading and activation of all the NAT and IPTables needed modules
/sbin/modprobe ip_tables
/sbin/modprobe ip_conntrack
/sbin/modprobe ip_conntrack_ftp
/sbin/modprobe ip_conntrack_irc
/sbin/modprobe iptable_nat
/sbin/modprobe ip_nat_ftp
/sbin/modprobe ip_nat_irc
echo " Enabling IP forwarding..."
echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/ip_dynaddr
echo " External interface: $EXTIF"
echo " External interface IP address is: $EXTIP"
echo " Loading proxy server rules..."
echo " Clearing existing rules..."
# 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
# 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 -s $UNIVERSE -d $UNIVERSE -j ACCEPT
# local interface, local machines, going anywhere is valid
iptables -A INPUT -i $INTIF -s $INTNET -d $UNIVERSE -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
# remote interface, any source, going to permanent PPP address is valid
iptables -A INPUT -i $EXTIF -s $UNIVERSE -d $EXTIP -j ACCEPT
# 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
# OPTIONAL: Uncomment the following two commands if plan on running
# an Apache Web site on the firewall server itself
#
#echo " Allowing EXTERNAL access to the WWW server"
#iptables -A INPUT -i $EXTIF -m state --state NEW,ESTABLISHED,RELATED -p tcp -s $UNIVERSE -d $EXTIP --dport 80 -j ACCEPT
echo " Allowing EXTERNAL access to the SSH server"
iptables -A INPUT -i $EXTIF -m state --state NEW,ESTABLISHED,RELATED -p tcp -s $UNIVERSE -d $EXTIP --dport 22 -j ACCEPT
# Catch all rule, all other incoming is denied and logged.
iptables -A INPUT -s $UNIVERSE -d $UNIVERSE -j drop-and-log-it
echo " 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 -s $UNIVERSE -d $UNIVERSE -j ACCEPT
# local interfaces, any source going to local net is valid
iptables -A OUTPUT -o $INTIF -s $EXTIP -d $INTNET -j ACCEPT
# local interface, any source going to local net is valid
iptables -A OUTPUT -o $INTIF -s $INTIP -d $INTNET -j ACCEPT
# outgoing to local net on remote interface, stuffed routing, deny
iptables -A OUTPUT -o $EXTIF -s $UNIVERSE -d $INTNET -j drop-and-log-it
# anything else outgoing on remote interface is valid
iptables -A OUTPUT -o $EXTIF -s $EXTIP -d $UNIVERSE -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 " Loading FORWARD rulesets"
#######################################################################
# FORWARD: Enable Forwarding and thus IPMASQ
# Allow all connections OUT and only existing/related 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 NAT (MASQUERADE) functionality on $EXTIF
iptables -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE
echo " Proxy server rule loading complete"
To be continued…
English