Creating a Linux Gateway

A few years ago I had an old computer laying around and decided to give it some use by putting Linux on it and having it serve, among other services, as a gateway to the other computers at home.

I decided to write this quick and dirty wiki article for my presentation in my CSCI 345 course (Computer Architecture III).

Contents

Requirements

Hardware required

Nothing really fancy. To create a gateway you would at the very least need:

  • Old PC - Mostly any computer lying around would do.
  • Atleast two ethernet ports - Two ethernet cards or a dual port ethernet card is fine. Setting up mine however, I used one dual port ethernet card and the built-in ethernet port. I will explain why I did this later.
  • Switch - Though you could use a hub but switches are safer. This would be use the gateway as the uplink and connect to other computers.

The bottleneck would most likely to be your outside connection. For example, in my configuration I currently have a DSL connection of 3.0Mbit although all my internal ethernet connections are Fast Ethernet which has a limit of 100Mbit. I recommend using Fast Ethernet, maybe even Gigabit, supporting hardware if you plan to have heavy traffic internally.

Software

  • Linux - Although I use Fedora in my setup, I know that Red Hat and CentOS are not much different---I'm assuming that other distros might just have a different name for packages and configuration file locations.
  • IPTables package - Firewall software (yum package: iptables).
  • DHCP daemon package - To serve IPs to your computers (yum package: dhcp) .

Configuration

Please be aware, this configuration is for an internet connection with static IP. There will be slight differences for a dynamic IP.

Also, I use 3 ethernet ports:

  • eth0 - for my wired internet and it's connected to the switch 's uplink port.
  • eth1 - for my wireless internet and it's connected to a Wifi Access Point.
  • eth3 - my internet connection.

The reason I separated my internal network into two subnets is because I wanted to have the flexibility of handling wireless and wired connections differently as far as firewall rules and DHCP.

sysctl.conf

First thing we need to do is enable IP forwarding in Linux. On Fedora, you just need to enable (set to 1) the net.ipv4.ip_forward option in /etc/sysctl.conf:

/etc/sysctl.conf

net.ipv4.ip_forward = 1

Hardware configuration

Now, we will have to configure the ethernet connections. In my setup, I have three of them: The configuration files are in the /etc/sysconfig/network-scripts/ directory. Here are the contents for each ethernet card's configuration file (with some comments to explain the options):

/etc/sysconfig/network-scripts/ifcfg-eth0:

# General stuff
DEVICE=eth0
HWADDR=00:11:AA:BB:CC:DD
ONBOOT=yes
TYPE=Ethernet

# Giving this ethernet card a static IP 
# in the 192.168.3. subnet (wired subnet)
BOOTPROTO=none
IPADDR=192.168.3.1
NETMASK=255.255.255.0
NETWORK=192.168.3.0
BROADCAST=192.168.3.255

The configuration for eth1 will be pretty much the same other than the fact that we are changing the subnet to 192.168.4. for the wireless portion of the network.

/etc/sysconfig/network-scripts/ifcfg-eth1

DEVICE=eth1
BOOTPROTO=none
HWADDR=00:00:11:AA:BB:CC
ONBOOT=yes
TYPE=Ethernet
IPADDR=192.168.4.1
NETMASK=255.255.255.0
NETWORK=192.168.4.0
BROADCAST=192.168.4.255

And finally, the configuration for eth2 device that will be the connection to the internet. If you have a dynamic IP, the configuration might be a bit different---the BOOTPROT, IPADDR and all the other IP related options would be different.

/etc/sysconfig/network-scripts/ifcfg-eth2

DEVICE=eth2
HWADDR=00:00:00:AA:BB:CC
TYPE=Ethernet
ONBOOT=yes
HOSTNAME=home.iambelmin.com
IPADDR=68.161.230.103
NETMASK=255.255.255.0
GATEWAY=68.161.230.1

Configuring DHCP

So now that the hardware is configured, we need to setup DHCP so that machines that connect to the internal ethernet cards are assigned IP addresses. Below is the DHCP daemon's configuration file along with comments explaining what the important options.

/etc/dhcpd.conf

ddns-update-style none;
ignore client-updates;

authoritative;

allow unknown-clients;
option domain-name-servers 151.202.0.85;
one-lease-per-client on; 

# Wired subnet
subnet 192.168.3.0 netmask 255.255.255.0 {
  option routers 192.168.3.1;
  option subnet-mask 255.255.255.0;
  option broadcast-address 192.168.3.255;
  range 192.168.3.50 192.168.3.100;
  default-lease-time 86400;     # 24 hours
  max-lease-time 172800;        # 48 hours
}

# Wireless subnet
subnet 192.168.4.0 netmask 255.255.255.0 {
  option routers 192.168.4.1;
  option subnet-mask 255.255.255.0;
  option broadcast-address 192.168.4.255;
  range 192.168.4.50 192.168.4.100;
  default-lease-time 43200;     # 12 hours
  max-lease-time 86400;         # 24 hours
}

# Wireless static
host bel-laptopwifi {
 hardware ethernet 00:11:22:33:AA:BB;
 fixed-address 192.168.4.10;
}

host bel-wii {
 client-hostname wii;
 fixed-address 192.168.4.15;
}

# Wired static
host bel-laptop {
  hardware ethernet 00:AA:BB:CC:11:22;
  fixed-address 192.168.3.10;
}

Configuring IPTables

Finally, probably the most important part of the configuration is the firewall (iptables). We use IPTables to perform the function of a NAT router.

Script's content

#!/bin/sh

# DEFINE VARIABLES
ethExt="eth2"
ethInt1="eth0"
ethInt2="eth1"
lanMask="192.168.0.0/16"

# ONLY WHEN EXT INTERFACE LOADS
if [ "${1}" != "ifcfg-${ethExt}" ]; then
  exit 0
fi

# CLEAN UP TABLES/CHAINS
/usr/bin/logger -t iptables Cleaning up...
/sbin/iptables -F
/sbin/iptables -F INPUT
/sbin/iptables -F OUTPUT
/sbin/iptables -F FORWARD
/sbin/iptables -F -t mangle
/sbin/iptables -F -t nat
/sbin/iptables -X
/sbin/iptables -Z

# CREATE DUMP TABLE
/sbin/iptables -N DUMP
/sbin/iptables -F DUMP 

# SETTING UP STATES CHAIN
/usr/bin/logger -t iptables Creating STATES...
/sbin/iptables -N STATES
/sbin/iptables -I STATES -m state --state ESTABLISHED,RELATED \
-j ACCEPT
/sbin/iptables -A STATES -m state --state NEW -i ! ${ethExt} \
-j ACCEPT
/sbin/iptables -A STATES -j DUMP

# SETTING UP SERVER SERVICES
/usr/bin/logger -t iptables Server services...
## SSH
/sbin/iptables -A INPUT -p tcp -i ${ethExt} --dport 22 \
-j ACCEPT
## Web
/sbin/iptables -A INPUT -p tcp -i ${ethExt} --dport 80 \
-j ACCEPT

# NAT ROUTING
/usr/bin/logger -t iptables Turning On NAT
## Masquerade IP when going out
/sbin/iptables -A POSTROUTING -t nat -s ${lanMask} -o ${ethExt} \
-j MASQUERADE
/sbin/iptables -A FORWARD -i ${ethExt} -o ${ethInt1} \
-j ACCEPT
/sbin/iptables -A FORWARD -i ${ethExt} -o ${ethInt2} \
-j ACCEPT

# PORT FORWARDING
/usr/bin/logger -t iptables Port forwarding...
## Torrents
/sbin/iptables -A PREROUTING -t nat -p tcp -i ${ethExt} \
--dport 51149  -j DNAT --to 192.168.3.10
/sbin/iptables -A FORWARD -s 192.168.3.10 -p tcp \
--dport 51149 -j ACCEPT
## Pidgin
/sbin/iptables -A PREROUTING -t nat -p tcp -i ${ethExt} \
--dport 3071:3327  -j DNAT --to 192.168.3.10
/sbin/iptables -A FORWARD -s 192.168.3.10 -p tcp \
--dport 3071:3327 -j ACCEPT

# PUSH TO STATES
/usr/bin/logger -t iptables Default to states
/sbin/iptables -A INPUT -j STATES
/sbin/iptables -A FORWARD -j STATES
/sbin/iptables -A OUTPUT -j STATES

# DONE
/usr/bin/logger -t iptables Rules loaded.

(Here is a link to whole script without the escaped linebreaks)

Script's location

Now that we created the script we have to have it execute when the external interface is loaded up (this could be different for dynamic IPs).

Linux executes the /sbin/ifup-pre-local script everytime an interface goes up that is why we had the following section in the script:

# ONLY WHEN EXT INTERFACE LOADS
if [ "${1}" != "ifcfg-${ethExt}" ]; then
  exit 0
fi

Other IPTables considerations

The script above only handles routing. It'll probably be a good idea to investigate implementing security related rules.

Possible additions

  • File server - Using something like SAMBA or an FTP daemon to have the gateway also be an in-house file server.
  • Web server - Installing Apache, PHP and such to use as a sandbox for web development.
  • SSH server - Open it up to SSH to have shell access from the outside.
  • Etc, etc, etc

More information links