Photo by Compare Fibre on Unsplash
Convert a Linux machine into a Router
Ever wanted to build a router? Ever wondered how router works internally? If any of the question is "YES", then this blog is for you (🫵).
Introduction
I've used VMware workstation for virtualization. You can use Virtual Box and follow this steps. Just interface name will be different.
Also, ubuntu server 22.04
iso is used for creating 3 virtual machines - client, router, server.
Create Network
vmnet8: NAT -
192.168.22.0/24
- DHCP (for internet connection)vmnet2: Host-only -
10.10.1.0/24
vmnet3: Host-only -
10.10.2.0/24
Building Router
Create a VM using ubuntu server 22.04
iso image.
It will use the following configurations:
RAM: 2048 MB
Processors: 1
Network Adapter 1 → vmnet8
Network Adapter 2 → vmnet2
Network Adapter 3 → vmnet3
Setup the configuration of these 3 interface in /etc/netplan/*.yaml
file.
network:
ethernets:
ens33:
dhcp4: true
ens36:
addresses: [10.10.1.1/24]
ens37:
addresses: [10.10.2.1/24]
version: 2
The above configuration:
Enables the DHCP protocol on
ens33
interface. IP and gateway address will be set dynamically.Sets IP address of
ens36
interface.Sets IP address of
ens37
interface.
Change permission: sudo chmod 600 *.yaml
Apply the change: sudo netplan apply
Stop and remove UFW firewall.
sudo systemctl stop ufw
sudo apt purge ufw
Building Client
Clone the router VM. Go to settings and delete adapter 1, 3.
Configure the interface using netplan. in /etc/netplan/*.yaml
file.
network:
ethernets:
ens36:
addresses: [10.10.1.10/24]
routes:
- to: default
via: 10.10.1.1
nameservers:
addresses:
- 8.8.8.8
- 8.8.4.4
version: 2
The above configuration:
Sets device IP address (
10.10.1.10
) and Netmask (/24
).Sets any destination IP address route except this network will go to specific gateway (
10.10.1.1
).
Apply the change: sudo netplan apply
Building Server
Clone the router VM. Go to settings and delete adapter 1, 2.
Configure the interface in /etc/netplan/*.yaml
file.
network:
ethernets:
ens37:
addresses: [10.10.2.20/24]
routes:
- to: default
via: 10.10.2.1
nameservers:
addresses:
- 8.8.8.8
- 8.8.4.4
version: 2
Apply the change: sudo netplan apply
Now both client and server can communicate with the router.
Client (or Server) VM can't ping the Router VM?
Ping client (or server) from the router.
This will invoke the ARP request to get the MAC address of client (or server).
Enable packet forwarding
Router need to forward packet from one interface to another. Thant's why we need to enable packet forwarding.
sudo echo 1 > /proc/sys/net/ipv4/ip_forward
Source NAT for local network
From the configured infrastructure, we know that two host-only network is in 10.10.1.0/24
& 10.10.2.0/24
range. Devices connected in these network is configured with 10.10.1.1
& 10.10.2.1
IP address respectively as Gateway IP.
(we don't need to configure MAC address manually. All interface will get the MAC address through ARP broadcast, if they don't have it in cache.)
The router has three network interfaces; ens36
& ens37
for two different host-only network and ens33
for internet-facing connection.
Now your packet from client (or server) can go to routers appropriate interface. If the packet goes from one network to another, the gateway would not recognize the source IP. It will send ARP request to the network to get MAC address of the source IP. If it doesn't get response, it will drop it.
So, to send the packet of different network, we are going to change the source IP address with interfaces own IP address.
We will run the following two rules in router VM to do IP Masquerading when the packet is coming form 10.10.1.0/24
and 10.10.2.0/24
network.
sudo iptables -t nat -s 10.10.1.0/24 -A POSTROUTING -j MASQUERADE
sudo iptables -t nat -s 10.10.2.0/24 -A POSTROUTING -j MASQUERADE
Now, say a device in local network with IP address 10.10.1.10 wants to access a website on the internet. When the device sends a packet to the gateway, the iptables rule kicks in.
The source IP address (10.10.1.10) of the outgoing packet is dynamically replaced with the routers private IP address of the ens33
interface.
This is called IP Masquerading. In this process, nothing is changed except the source IP.
Tracing IP on different interface
I have used tcpdump to check the source and destination IP address of a packet in every interface.
The following table shows when a packet is going form client machine to server machine:
Client Interface | Router Interface | Server Interface |
ens36: 10.10.1.10 > 10.10.2.20 | ens36: 10.10.1.10 > 10.10.2.20 ens33: - ens37: 10.10.2.1 > 10.10.2.20 | ens37: 10.10.2.1 > 10.10.2.20 |
The following table shows when a packet is going from server machine to internet:
Server Interface | Router Interface | Client Interface |
ens37: 10.10.2.20 > 1.1.1.1 | ens36: - ens33: 192.168.22.132 > 1.1.1.1 ens37: 10.10.2.20 > 1.1.1.1 | ens36: - |
How packet is moving from one interface to other
When a packet comes, linux kernel checks the routing table to determine the appropriate interface for the packet.
If the packet was destined for the internet, the routing table directs the packet to the ens33
interface. After going to that interface, in POSTROUTING chain, the source IP is changed to current interface's IP.
If the packet was destined for the server VM, the routing table would direct the packet to ens37
interface. Similar to above, the source IP would change.