Updated on Dec 6, 2024
To turn a Raspberry Pi 5B into a router, I followed the excellent article: Setting up a Linux Server as a Router [1] . Also, helpful was Set Static IP Address [2] .
By default, Linux does not forward packets. That is, by default, if a computer (host) receives a packet that is not addressed to it, it simply ignores (drops) the packet.
Hence, the first step in using a computer as router, is to get it to forward packets to the next computer or router.
To enable packet forwarding, you have to modify the /etc/sysctl.conf file:
sudo vi /etc/sysctl.conf
Add the following line:
net.ipv4.ip_forward=1
and optionally:
net.ipv6.ip_forward=1
To check that packet forwarding is enabled:
cat /proc/sys/net/ipv4/ip_forward
References
For a computer to forward a packet, it has to have somewhere to forward it to. That is, the computer has to have a least a second network interface (Ethernet/Wireless).
One of the network interfaces will receive it's ip address from an upstream router. This address can be static or dynamic. The upstream router will also automaticlly assign a gateway and domain name server.
The ip addresses of the other network interfaces have to be manually set. How you do this, depends on the network manager, you are using. Debian has several network managers, and they can be running at the same time, as long as a particular network interface is only controlled by one network manager. In the referenced article, the author chooses, to assign ip addresses by modifying the /etc/network/interfaces files. This is probably the easiest and most straight forward way to do this.
The referenced article [1] assumes that the computer has 3 Ethernet interfaces, eth0, eth1, and eth2. It also assumes that eth0 has already been assigned an ip address from an upstream router or computer. The author assigns ip address 192.168.200.254 to eth1 and ip address 192.168.100.254 to eth2.
The computer that I wanted to turn into a router was a Raspberry Pi 5B. It only has one built-in Ethernet interface - eth0. For my second Ethernet interace, I used a Benfei USB 3.0 to Ethernet adapter - eth1. I did not implement the third Ethernet interface - eth2.
To assign the ip address, I added the following to /etc/network/interfaces:
sudo vi /etc/network/interfaces
I added the following:
auto eth1
iface eth1 inet static
address 192.168.200.254
netmask 255.255.255.0
This is old school. As of Raspberry Pi OS 12 (Bookworm), the NetworkManager is default package for managing network interfaces. To do this with the NetworkManager see references [5,6].
The referenced article assumes two client machines. The first is running Linux, and its Ethernet interface (eth0) is connected to Ethernet interface eth1 on the routing computer. The ip address on the Linux client is assigned 192.168.200.15. The ip address on the Windows client is 192.168.100.10. However, the author does not show how to set up either client, and this was my achilles' heel. On the Linux client, in addition to assigning an ip address, you must assign a gateway back to the routing computer.
My code for this was:
sudo vi /etc/network/interfaces
and, add the following:
auto eth0
iface eth0 inet static
address 192.168.200.15
netmask 255.255.255.0
gateway 192.168.200.254
Without setting the client's gateway, I could ping 192.168.200.15 from the routing computer, but I could not ping the routing computer from the client computer - ditto for SSHing and the Internet.
To see the gateways, run:
ip route
This is old school. As of Raspberry Pi OS 12 (Bookworm), the NetworkManager is default package for managing network interfaces. To do this with the NetworkManager see references [5,6].
Upstream Router Assigns IP address 192.168.50.45 and gateway | | | | ------------------------ | | | | | | --------------------------------- | | eth0 eth1 | | | 192.168.50.45 192.168.200.254 | | | | | | Enable Packet Forwarding: | | | sudo /etc/network/interfaces | | | net.ipv4.ip_forward=1 | | | net.ipv6.ip_forward=1 | | | | | | /etc/network/interfaces | | | auto eth1 | | | iface eth1 inet static | | | address 102.168.200.254 | | | netmask 255.255.255.0 | | --------------------------------- | | ---------------------------- | eth0 | | 192.168.200.15 | | | | /etc/network/interfaces | | auto eth0 | | iface eth0 inet static | | address 192.168.200.15 | | netmask 255.255.255.0 | | gateway 192.168.200.254 | ----------------------------
The easy part of this was the nft code for masquerading:
#!/usr/bin/nft -f
flush ruleset
table inet router {
chain prerouting {
type nat hook prerouting priority filter; policy accept;
}
chain input {
type filter hook input priority filter; policy accept;
}
chain forward {
type filter hook forward priority filter; policy accept;
}
chain output {
type filter hook output priority filter; policy accept;
}
chain postrouting {
type nat hook postrouting priority filter; policy accept;
masquerade
}
}
The primary advantage of a Linux Router is to do filtering with nftables, and this code does not do any filtering.
References
Internet / \ | | | ----------------------------------------------- | bond0 | | nic_inet | | | | Linx Router/Firewall | | | | nic_DMZ nic_LAN | | bond1 bond2 | ---------------------------------------------- | | | | ============ | =========== =========== | ============ || | || || | || || ---------- || || ---------- || || | Swtich | || || | Switch | || || ---------- || || ---------- || || | || || | || || -------------- || || -------------- || || | Server | || || | Workstation | || || | 10.0.1.2 | || || | 10.0.2.2 | || || -------------- || || -------------- || || || || || || 10.0.1.x DMZ Zone || || 10.0.2.x LAN || ========================== ==========================
There is only one Ethernet cable going from my desk into the floor. Hence, all of the hosts on my desk (HP EliteDesk and Raspberry Pi's) go through an Ethernet switch, and everything in my office goes to a second Ethernet Switch. Thus, traffic between any host on my desk and the Synology 220 (network attaches storage - nas) must pass through two Ethernet switches.
The diagram below depicts my test setup. The HP Elite Desk is running Windows 11. A Raspberry Pi 5B only has one native Ethernet port. For the second Ethernet Port, a Benfei USB 3.0 to Ethernet adapter was used ( Amazon #10 ).
Internet | | 192.168.50.xxx | /----------\ | Ethernet | | Switch | \----------/ | | | | ------- ------ | | | | /----------\ /----------\ | Synology | | Desk | | Network | | Ethernet | | Attached | | Switch | | Storage | \----------/ \----------/ | | 192.168.200.xxx NAS | ------- --------------------- | | | | | /--------------------\ | | | Ethernet USB 3.0 | | | | | /-----------------\ | | Linux Router | | USB 3.0 | | | Raspberry Pi 5B | | Benfie | | | NVMe Gen 3 x 1 | | USB to Ethernet | | \--------------------/ | Adapter | | | Ethernet | | \-----------------/ | | | | | /-------------------\ | | Ethernet USB 3.0 | /----------------\ | | | HP Elite Desk | | Raspberry Pi 5B | | Gen 6 | | NVMe Gen 2 x 1 | | NVME Gen 3 x 4 | | or SD Card | \----------------/ \-------------------/ Windows - Host Linux - Host
The table below is for transfer a single 7.5GB file, "Subject-Contactor-CT_Scan.zip" from and to the Synology NAT (network attached storage).
From | To | Seconds | Router |
---|---|---|---|
HP Elite Desk Gen 6 | Synology 220 | 69 | none |
Synology 220 | HP Elite Desk G6 | 69 | none |
RPi-5 with NVMe Gen 2 | Synology 220 | 74 | RPi-5 |
Synology 220 | RPi-5 with NVMe Gen 3 | 69 | RPi-5 |
RPi-5 with SD Card | Synology 220 | 84 | RPi-5 |
Synology 220 | RPi-5 with sd Card | 94 | Rpi-5 |
Thus, the Raspberry Pi 5B with a Benfie USB-to-Ethernet adapter is plenty fast enough for a 1 Gbps Ethernet network.
It looks like most Linux distros are using or switching to the "Network Manager" as their default network manager. The above code does not use the "Network Manager" to assign static IP address or the default gateway. I need to learn, how to do this with the "Network Manager".
Nordvpn has its own nftables. Unfortunately, Nordvpn will flush the nft rules in /etc/nftables.conf and install its own rules. This occurs even if Nordvpn is not connected.
However, after booting, you can install your own nft rules: with the command:
sudo nft -f /etc/nftables.conf
If you now execute:
sudo nft list ruleset
It will only list your ruleset and not Nordvpn's. However, Nordvpn is still working. In fact all host connected to this Linux router are going through Nordvpn.
If you want to have the list ruleset show both sets of rules, disconnect Nordvpn and then run your script or /etc/nftables.conf and afterwards reconnect to Nordvpn.
You can then disconnect and reconnect to Nordvpn, and both sets of rules will be active. Now all host connected to this Linux router, will go through Nordvpn. To the outside world, all host connected to this Linux router will all have the same IP address.
One way to accomplish this, is to not enable autoconnect on Nordvpn, and to use an on reboot cron job to load your nft ruleset and then connect to Nordvpn
References: