Setting up an Ubuntu Router

I wanted to experiment with sniffing data on the network. Of course, my own network. This was not a creepy sniffing of my neighbours’ network. I was keen in converting my Ubuntu VM into a router VM. Then I can redirect all traffic from ‘client’ VM via the ‘router’ VM on which the sniffer is running. So, my requirements are simple, I need a VM with dual network adapter, one of which will be for the WAN side and other will be on the LAN side (exactly like a home router). What is required to convert a VM into router is a different topic and it will not be covered in this blog post.

Configure the Dual Network Adapter

The most important part of this is to understand that only one of the adapter is visible to your DHCP server and other is not. Why is this important? Because, only one of the adapter will get an IP from the DHCP and other will have to manually set. This DHCP-enabled adapter will be the WAN side adapter and the manual IP adapter will be the LAN side adapter. So, how do you configure dual interfaces on Ubuntu?

In Ubuntu, the networking system is configured via the ‘/etc/network/interfaces‘ file. Originally, there would have been only one interface as shown below:

$> ifconfig 
 eth0 Link encap:Ethernet HWaddr 08:00:27:d9:7a:ca 
 inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0
 inet6 addr: fe80::a00:27ff:fed9:7aca/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:600 errors:0 dropped:0 overruns:0 frame:0
 TX packets:852 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000 
 RX bytes:273084 (273.0 KB) TX bytes:141395 (141.3 KB)

lo Link encap:Local Loopback 
 inet addr:127.0.0.1 Mask:255.0.0.0
 inet6 addr: ::1/128 Scope:Host
 UP LOOPBACK RUNNING MTU:16436 Metric:1
 RX packets:479 errors:0 dropped:0 overruns:0 frame:0
 TX packets:479 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:0 
 RX bytes:147404 (147.4 KB) TX bytes:147404 (147.4 KB)

Now, let us configure the networking system to understand the 2nd interface, which we shall name as ‘eth1.’

So edit ‘/etc/network/interfaces‘ as show below:

# The loopback network interface
 auto lo
 iface lo inet loopback

# The primary network interface
 auto eth0
 iface eth0 inet dhcp

 auto eth1
 iface eth1 inet static
 address 192.168.50.1
 network 192.168.50.0
 netmask 255.255.255.0
 broadcast 192.168.50.255

What this means is that:

  • eth0 is DHCP-enabled and gets the IP from the DHCP server.
  • eth1 has static IP of 192.168.50.1

Restart the network (via ‘sudo /etc/init.d/networking restart’):

network-restart
Restart of network

Now, both the interfaces are up as shown below:

$> ifconfig 
 eth0 Link encap:Ethernet HWaddr 08:00:27:d9:7a:ca 
 inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0
 inet6 addr: fe80::a00:27ff:fed9:7aca/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:600 errors:0 dropped:0 overruns:0 frame:0
 TX packets:852 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000 
 RX bytes:273084 (273.0 KB) TX bytes:141395 (141.3 KB)

eth1 Link encap:Ethernet HWaddr 08:00:27:85:3a:24 
 inet addr:192.168.50.1 Bcast:192.168.50.255 Mask:255.255.255.0
 inet6 addr: fe80::a00:27ff:fe85:3a24/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:3043 errors:0 dropped:0 overruns:0 frame:0
 TX packets:34454004 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000 
 RX bytes:372333 (372.3 KB) TX bytes:3193181649 (3.1 GB)

lo Link encap:Local Loopback 
 inet addr:127.0.0.1 Mask:255.0.0.0
 inet6 addr: ::1/128 Scope:Host
 UP LOOPBACK RUNNING MTU:16436 Metric:1
 RX packets:479 errors:0 dropped:0 overruns:0 frame:0
 TX packets:479 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:0 
 RX bytes:147404 (147.4 KB) TX bytes:147404 (147.4 KB)

Now we have 2 interfaces:

  1. ‘eth0’ (DHCP-enabled) pointing to the WAN side
  2. ‘eth1’ (static IP) pointing to the LAN side

Configure NAT routing

Use the following script, which I had borrowed from somewhere (forgot!) and slightly modified to my taste (available on github):

#!/bin/sh


#
#--------------------------------- constants
fn_check_dependencies() {
	local __cmd=${1}
	local __path=$(which ${__cmd})

	if [ $? -ne 0 ]; then
		echo "****************** !! \${__cmd}\' IS NOT AVAILABLE !! ******************"
		echo
		exit 1
	fi

	echo ${__path}
}

#
#--------------------------------- constants
AWK=$(fn_check_dependencies awk)
ECHO=$(fn_check_dependencies echo)
DEPMOD=$(fn_check_dependencies depmod)
GREP=$(fn_check_dependencies grep)
IP=$(fn_check_dependencies ip)
IPTABLES=$(fn_check_dependencies iptables)
MODPROBE=$(fn_check_dependencies modprobe)
NETSTAT=$(fn_check_dependencies netstat)

#
#--------------------------------- functions
fn_get_wan_iface() {
	${ECHO} $(${IP} route show | ${GREP} default | ${AWK} '{print $5}')
}

fn_get_lan_iface() {
	local _wan_ip=$(fn_get_wan_iface)
	${ECHO} $(${NETSTAT} -i | ${GREP} -ve lo -ve Iface -ve Kernel -ve ${_wan_ip} | ${AWK} '{print $1}')
}

fn_load_mod() {
	local __mod_name=${1}
	${ECHO} " |->; ${__mod_name}"
	${MODPROBE} ${__mod_name}
	if [ $? -ne 0 ]; then
		${ECHO} "****************** !! FAILED TO LOAD ${__mod_name} !! ******************"
		${ECHO}
		exit 1
	fi
}

fn_load_modules() {
	${ECHO} " - Loading kernel modules: "
	${DEPMOD} -a
	fn_load_mod ip_tables
	fn_load_mod nf_conntrack
	fn_load_mod nf_conntrack_ftp
	fn_load_mod nf_conntrack_irc
	fn_load_mod iptable_nat
	fn_load_mod nf_nat_ftp
	${ECHO}
}

fn_enable_ipv4_forwarding() {
	${ECHO} " - Enabling forwarding.."
	${ECHO} "1" > /proc/sys/net/ipv4/ip_forward
}

fn_enable_ipv4_dynamic_addr() {
	${ECHO} " - Enabling DynamicAddr.."
	${ECHO} "1" > /proc/sys/net/ipv4/ip_dynaddr
}

fn_clear_previous_fw_rules() {
	${ECHO} " - Clearing existing firewall rules"
	${IPTABLES} -t nat -D POSTROUTING -o "$WANIF" -j MASQUERADE
	${IPTABLES} -t filter -D FORWARD -i "$WANIF" -o "$LANIF" -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 
	${IPTABLES} -t filter -D FORWARD -i "$LANIF" -o "$WANIF" -j ACCEPT
	${IPTABLES} -t filter -D FORWARD -j LOG
}

fn_create_fw_rules() {
	${ECHO} " - Enabling firewall rules"
	${IPTABLES} -t nat -A POSTROUTING -o "$WANIF" -j MASQUERADE
	${IPTABLES} -t filter -A FORWARD -i "$WANIF" -o "$LANIF" -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 
	${IPTABLES} -t filter -A FORWARD -i "$LANIF" -o "$WANIF" -j ACCEPT
	${IPTABLES} -t filter -A FORWARD -j LOG
}

#
#--------------------------------- Main
${ECHO}
${ECHO} "======================= Enabling NAT ======================="
${ECHO}

WANIF=$(fn_get_wan_iface)
LANIF=$(fn_get_lan_iface)

${ECHO} "WAN Interface: $WANIF"
${ECHO} "LAN Interface: $LANIF"
${ECHO}

if [ -z ${WANIF} ]; then
	${ECHO} "****************** !! WAN interface not found !! ******************"
	${ECHO}
	exit 1
fi

if [ -z ${LANIF} ]; then
	${ECHO} "****************** !! LAN interface not found !! ******************"
	${ECHO}
	exit 1
fi

if [ ${WAN} = ${LANIF} ]; then
	${ECHO} "****************** !! Only one interface found !! ******************"
	${ECHO}
	exit 1
fi

${ECHO} "Setting up network:"
fn_load_modules
fn_enable_ipv4_forwarding
fn_enable_ipv4_dynamic_addr
fn_clear_previous_fw_rules
fn_create_fw_rules
${ECHO}
${ECHO} "======================= Done ======================="
${ECHO}

The above script does the following:

  1. Ensures the required kernel modules are loaded.
  2. Enable IP forwarding
  3. Enable masquerading on the WAN side interface
  4. All connections via LAN interface should be transferred to WAN interface
  5. Finally, all ‘established’ or ‘related’ connections via WAN should be transferred to LAN.

Done. Now when a device connects to this Ubuntu box via ‘eth1’ it connect to the internet. In other words, this ubuntu box serves as a router for other connected devices.

No Comments

Post a Comment

%d bloggers like this: