OpenWrt: route different computers via different upstreams based on their IP
Let's say you have two IPv4 upstreams: 10.1.0.1
and 10.2.0.1
.
10.1.0.1
is used as the default route, but you want some computers to be routed via 10.2.0.1
, based on their LAN IP address.
Let's imagine for an example that you have two DHCP clients connected:
# cat /tmp/dhcp.leases
1629000000 01:02:03:aa:bb:cc 192.168.1.200 MacBook-Pro 01:01:02:03:aa:bb:cc
1629000000 01:02:03:dd:ee:ff 192.168.1.210 MacBook-Air 01:01:02:03:dd:ee:ff
and you want to route MacBook-Air
(192.168.1.210
) via the second upstream 10.2.0.1
.
Your main routing table looks like this:
# ip r
default via 10.1.0.1 dev eth2 src 10.1.0.100
192.168.1.0/24 dev br-lan scope link src 192.168.1.1
10.1.0.0/24 dev eth2 scope link src 10.1.0.100
10.2.0.0/24 dev eth3 scope link src 10.2.0.100
Add new routing table:
# echo "100 mytable" >> /etc/iproute2/rt_tables
Define new IP set:
# ipset create myset hash:net
Fill it with LAN IPs of computers you want to route via the second upstream:
# ipset add myset 192.168.1.210
Add iptables rules to mark packets coming from those IPs. Add it to /etc/firewall.user
, then restart firewall.
iptables -t mangle -A PREROUTING -m set --match-set myset src -j MARK --set-mark 0x64
Add routing rule matching the fwmark:
# ip rule add fwmark 0x64 table mytable
Set default route in table mytable
:
# ip route add default via 10.2.0.1 table mytable
You may also want to add route for LAN:
# ip route add 192.168.1.0/24 via 192.168.1.1 table mytable
Basically that's it, now packets coming from 192.168.1.210
will be routed through 10.2.0.1
.
To make these changes persistent, use /etc/rc.local
script (executed at boot) and /etc/hotplug.d
hooks.