Raspberry Pi
Route network traffic using a Pi
careful issuing iptables commands, especially if you’re accessing the Pi over a network SSH connection. A wrong command can lock out your session until you can physically access the Pi and remove the errant rule.
When a network connection tries to establish itself on the Pi interface, iptables looks for a chain rule in its list that matches the request. If iptables doesn’t find a rule, it resorts to the default action defined for the chain. For security reasons the default should be REJECT, because there’s no rule to govern the condition.
In addition to iptables providing filtering rules, it can also provide network address translation (NAT). The NAT rule defined in iptables enables all IP addresses from the PDUs on the one network to be replaced with the single IP address used in the other network.
In this project all the host’s PDUs that have DHCP assigned IP addresses will be translated into the one IP addresses that’s been assigned to the Wi-Fi interface in the second network. The iptables service will maintain a state table to translate the returning PDUs back to the correct DHCP IP address for their destination.
Configuring the Pi
For this project we’re using a Pi 3B+ with Raspbian Buster Lite, Version: February 2020. The Pi’s wired connector is connected to an Ethernet network using a CAT5 cable. We’re assuming that you have sufficient knowledge to establish an operating system on the Pi and can configure the Pi to support an SSH connection from an external host. Before starting the configuration, ensure all software updates to the Raspbian operating system have been completed.
Let’s get the network interfaces active. The first step is to establish a static IP address on the Pi Ethernet interface. Using your usual text editor amend the /etc/ dhcpcd.conf file to reflect the following: interface eth0 static ip_ address=192.168.200.1/24 static routers=192.168.200.0 The file will have information similar to what’s shown above, but will be commented out with an octothorp, another term for the hash sign (#). The file can be changed to support our configuration by adding the lines to the end of the file or by removing the octothorp in front of the existing lines and correcting the text to reflect what’s shown. The entries are assigning an IP address to the interface named eth0, defining the network bits by providing the subnet mask of /24.
Creating the file /etc/wpa_ supplicant.conf with the Wi-Fi network configuration parameters will establish a Wi-Fi connection. One way to accomplish this is from the command line using a text editor. An easier approach would be to use the Raspbian configuration tool raspi-config to establish a Wi-Fi network. You’ll need to know the Wi-Fi connection credentials, SSID and password to complete this task.
In our example the SSID for the Wi-Fi was ‘Guest-Network’ with a password of ‘Pi 3B+wifi’.
A reboot should restore the Pi with interfaces configured with the IP address. Confirm this from the command line using the ip a command. The eth0 interface will have the IP address and the Wi-Fi should be connected, providing the IP address from that network.
The next step is to establish DHCP services. This version of Raspbian utilises the dnsmasq package to support DHCP. The package provides both a DHCP server and a local DNS server. Remember that DHCP is looking after the IP assignments to hosts and DNS is carrying out URL address translation. The dnsmasq package replaces two packages, isc-dhcp-server and bind9, that were previously used to provide the services.
From the Pi CLI, issue the commands to install the dnsmasq package. In addition we’re going to move the default configuration file for this service to preserve its contents before we customise it for our needs. sudo apt install dnsmasq sudo mv /etc/dnsmasq.conf / etc/dnsmasq.conf.orig
Use your usual text editor create the file /etc/dnsmasq.conf containing the following lines:
interface=eth0 # Use interface eth0
listen-address=192.168.200.1 # Specify the address to listen on
bind-interfaces # Bind to the interface
server=8.8.8.8 # Use Google
DNS
domain-needed # Don’t forward short names
bogus-priv # Drop the non-routed address spaces.
dhcp-range=192.168.200.50,19 2.168.200.150,12h # IP range and lease time
The original file ownership and permissions for the configuration file need to be applied when the new file is established. Let’s take a quick look at the contents of the file. The listening interface line is the static IP address we assigned earlier. Looks like we are using Google DNS from the server IP. The range parameter defines what IP addresses’ range to use when giving out IP addresses to hosts that make DHCP requests. A reboot of the Pi will bring the Pi DHCP server online.
The original dnsmasq file that was preserved in /etc/dnsmasq. conf.orig is well documented. It’s an ideal reference for finding out more information about the parameters available in the configuration file.
This device has the potential of creating problems in a network, if the Pi Ethernet interface is connected to a production network. The Pi DHCP server will answer DHCP requests. If the network already has a DHCP server, the Pi’s server may cause confusion in the network. For testing, it’s recommended that the Pi Ethernet interface be connected to an isolated network switch similar to the configuration shown in the block diagram at the start of the article.
We can confirm the dnsmasq service is operational and run a test of the configuration file by executing the following commands from the command line on the Pi: journalctl -u dnsmasq.service dnsmasq --test
The commands confirm the service is active and does a check of the configuration file to confirm it has correct syntax.
The Pi DHCP server can be operationally tested by connecting a PC that’s configured to request an IP address from DHCP to the network switch connected to the Pi. The Pi DHCP server keeps track of host assignments in the file /var/lib/misc/dnsmasq. leases. A cat of the file during testing produced the line:
1581347125 68:5b:35:83:c0:f6 192.168.200.54 sconwayMacBookPro 01:68:5b:35:83:c0:f6
An IP address 192.168.200.54 was assigned to hostname sconway-MacBookPro with a MAC address 01:68:5b:35:83:c0:f6.
The next change enables the Pi to route between the wired ethernet interface and the Wi-Fi interface. Using a text editor modify the file /etc/sysctl.conf by removing the # from the line net. ipv4.ip_forward=1 . B y d efault, forwarding between interfaces is turned off. Removing the # enables forwarding.
The iptables service is running by default on the Raspbian OS. The three rule tables or chains for iptables can be examined by issuing the following command from the Pi CLI: sudo iptables -L
Notice the three (policy ACCEPT) listings, one for each chain. This indicates iptables is accepting all network traffic into, out of or between the interfaces on the Pi. No rules are in place to manage traffic.
The syntax for the configuration file for iptables is exacting. If we had the time we could use a text editor to produce a rules file containing the options to configure iptables. A much easier method is to just send the needed rules to iptables and have iptables generate its own configuration file containing the rules.
From the Pi CLI issue the following commands to establish the iptables rules and then save the configuration to a rules file that can be restored later. Recall the purpose of using iptables is to establish NAT (network address translation) so PDUs can move from the wired side of the Pi and assume the Wi-Fi IP address on the network. Notice the rules reference the two Pi network interfaces:
sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
sudo iptables -A FORWARD -i wlan0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT
sudo sh -c “iptables-save > / etc/ iptables.ipv4.nat”
As rules are entered they take effect immediately. Using the iptables -L command will show some of the changes to the chains that have taken place.
The generated iptables rules file needs to be loaded when the Pi starts up. This can be done by adding a command call to the / etc/rc.local file. Using your text editor add the text shown in the line, above the line in the file containing exit 0 that’s at the bottom of the file:
# restore iptables configuration to establishing nat
sudo iptables-restore < /etc/ iptables.ipv4.nat
Here ends a whole lot of networking theory along with a Pi configuration that enables hosts from an Ethernet network to route their PDUs to a Wi-Fi network. The topic is complex, but we tried to consistently apply terminology to avoid confusion.