Sunday, September 30, 2018

Network Routing Between Two Private Subnets with Raspberry Pi

Again probably of limited interest to most people, but here's how to use Raspberry Pi to route traffic between two private network segments.

Search online and you'll find plenty of guides for turning a Raspberry Pi into a DHCP server and default gateway —
but I wanted to leave DHCP and the default gateway to normal WiFi routers and only route between private segments. I couldn't find that anywhere.

The Goal

As shown in the diagram, there are two WiFi routers creating two networks: LAN1 (192.168.1.0/24) and LAN2 (192.168.2.0/24).
LAN1 has a NAS and the main Mac. LAN2 has a Windows machine for the kids.
Both sides can reach the internet through their respective routers, but the Windows machine on LAN2 also needs to reach the NAS on LAN1 — so I used Raspberry Pi as a gateway between them.
DHCP stays with each WiFi router, and the default gateway for each subnet remains its WiFi router.

The "normal" solution would be to configure the second WiFi router as a converter/repeater,
but I happened to have a spare router, so this is where things went.

Also, the house has a multimedia outlet built into the wall — plugging a LAN cable into it puts you on the global network,
which was part of the mess. Ideally, the ceiling hub would be replaced with a router and the wall wiring would become private — but that's a separate project.

Enabling Routing on Raspberry Pi

Even with Raspberry Pi connected to both wired and wireless networks, it won't route by default.
Enabling IP forwarding and configuring iptables is all it takes.

First, uncomment the line "#net.ipv4.ip_forward=1" in /etc/sysctl.conf.
Then write "1" to /proc/sys/net/ipv4/ip_forward and reboot:
root@raspberrypi:~ # echo -n 1 > /proc/sys/net/ipv4/ip_forward
root@raspberrypi:~ # reboot
Next, add iptables rules to allow forwarding.
Passing traffic straight through probably doesn't strictly need NAT rules, but I'm not certain enough about the fine details:
root@raspberrypi:~ # iptables -F
root@raspberrypi:~ # iptables -X
root@raspberrypi:~ # iptables -t nat -F
root@raspberrypi:~ # iptables -t nat -X
root@raspberrypi:~ # iptables -t mangle -F
root@raspberrypi:~ # iptables -t mangle -X
root@raspberrypi:~ # iptables -P INPUT ACCEPT
root@raspberrypi:~ # iptables -P FORWARD ACCEPT
root@raspberrypi:~ # iptables -P OUTPUT ACCEPT
root@raspberrypi:~ # iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
root@raspberrypi:~ # iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
If "iptables -L" shows output like this, the rules are in place:
root@raspberrypi:~ # iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
At this point Raspberry Pi should be routing — but pinging 192.168.1.x from Windows still won't get a reply.
That's unrelated to the Pi; it's dealt with later.

Making iptables Rules Persist Across Reboots

Raspbian has iptables installed by default, but rules aren't restored on reboot.
The "iptables-persistent" package handles this.

Install it with: sudo apt-get install iptables-persistent
During installation it asks whether to save the current iptables rules — answer YES.
Reboot, and the rules will be restored.

Allowing Windows to Reach the NAS on the Other Subnet

Routing is configured, but Windows still can't ping the NAS.
The reason: Windows' default gateway is WiFi router 2, which doesn't know about 192.168.1.0/24 and forwards the traffic to the internet.

If WiFi router 2 supports adding a static route for 192.168.1.0/24 pointing to Raspberry Pi, configure it there.
Most consumer routers don't support that level of routing, so this is done on the Windows side instead.

The normal Windows Control Panel doesn't expose this. Open a Command Prompt as Administrator and run:
route -p add 192.168.1.0/24 192.168.2.10
"192.168.2.10" is Raspberry Pi's address on LAN2.
The "-p" flag makes the route persistent across reboots.
Omit "-p" to test first — the route will disappear after a reboot if it causes problems.

Now test from Windows:
ping 192.168.2.10
PING 192.168.2.10 (192.168.2.10): 56 data bytes
64 bytes from 192.168.2.10: icmp_seq=0 ttl=64 time=2.546 ms
  :
ping 192.168.1.10
PING 192.168.1.10 (192.168.1.10): 56 data bytes
64 bytes from 192.168.1.10: icmp_seq=0 ttl=64 time=2.546 ms
  :
ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
... hm.
Raspberry Pi's LAN1 address responds, so routing is working.
But the NAS on LAN1 doesn't respond.

The ping reaches the NAS — but the NAS's default gateway is WiFi router 1, so the reply goes back through router 1 instead of through the Pi. Again.

Since the NAS rarely needs direct internet access,
the fix is to set Raspberry Pi (192.168.1.10) as the NAS's default gateway.
Alternatively, add only a specific route for 192.168.2.0/24 — but most consumer NAS devices don't support per-route configuration, so changing the default gateway is simpler.

Editing the Windows Hosts File

At this point, Windows on LAN2 can reach the NAS on LAN1.
But without name resolution, everything requires an IP address.

Running DNS on Raspberry Pi would work but seems like overkill, so I added entries directly to the Windows hosts file.
Open Notepad as Administrator and add lines to the end of the file at C:\Windows\System32\drivers\etc\hosts:
192.168.1.10  NAS
The file server is now accessible by hostname.

Done.

No comments:

Post a Comment