I've created this thread to have a dedicated place to discuss some trouble I've been having using the pbr package as well as be a dedicated resource for future users hoping to do what is described in the title. I'm sure the folks at Policy-Based-Routing (pbr) package discussion will appreciate me keeping this discussion and my questions elsewhere.
My goal is to route traffic coming in on a VPN interface to a specific LAN host based on port number. Similarly my goal is to route any egress traffic from said LAN host back through the VPN before it is transmitted to the destination address. It is my understanding this can be achieved using pbr but due to my limited understanding of firewall zones/iptables etc. I find myself needing a little bit of help.
Thus far, I have been able to use 3 simple iptables rules on my VPS (running the vpn server) to redirect incoming traffic on a specified port/proto to the vpn client:
Now I'd like to do something similar in openwrt to route the traffic from the VPN to a specific LAN host but am running into some trouble in that I don't know which tables to assign a similar rule set to, and I'm unsure of how to use nf_tables/pbr package to do this. Any help is appreciated and I'm more than happy to provide cfg or screenshots if needed. Thanks
One option is to avoid the double DNAT. The VPS can redirect straight to the lan host. This means that the VPS must have a route for the 192.168.2.0/24
Second option is to use the luci to create the redirect, because it seems that you are using nftables.
I understand why avoiding double NAT could be easier but I, unfortunately have some reasons as to why that won't work with my setup. Funnily enough my setup is pretty easy in terms of reserving specific ports and simply chaning the destination addr and source addr at a couple points in the routing process.
I'd really like to be able to replicate the example on openwrt's own wiki. I find it odd I can't create a rule where I change the destination addr in prerouting.
As for creating the redirect using luci I believe i have tried that to no avail. Here's a section of my /etc/config/firewall:
config forwarding
option src 'lan'
option dest 'vpn'
config redirect
option dest 'lan'
option target 'DNAT'
option name 'test'
list proto 'tcp'
option src 'vpn'
option src_dport '34'
option dest_port '34'
option reflection '0'
option src_port '34'
option dest_ip '192.168.2.218'
Also is there any way to dump the list of rules that are actively in effect from the CLI, I'd like to verify what this rule is and if it is actually being applied.
It's not duplicate. One is src_port the other is src_ d port. You need the src_dport to match the destination port of the source packet. The src_port is rarely matched, at the source port is usually random.
Please run the following commands (copy-paste the whole block) and paste the output here, using the "Preformatted text </> " button:
Remember to redact passwords, MAC addresses and any public IP addresses you may have
ubus call system board; \
uci export network; uci export firewall; \
head -n -0 /etc/firewall.user; \
iptables-save -c; nft list ruleset
meta nfproto ipv4 tcp dport 34 counter packets 5 bytes 300 dnat ip to 192.168.2.218:34 comment "!fw4: test"
You have already some hits, so the packets are coming fine and are forwarded. Are you saying that you don't see the packets getting to the host 192.168.2.218?
I played around with some other cfg and I'm now seeing traffic on the LAN host. Great!
Now for the fun part, I'd like to force any egress traffic on LAN with a specific port through the VPN interface.
I understand DNAT cannot be used as it modifies the dest address of the packet which would remove the intended recipient. I was hoping to "forward?" it, sort of like forcing OpenWRT to believe the next hop is the VPN server so the packet is sent over the interface and the VPN can handle the final SNAT and sending it out over its WAN.
a set of rules/routes for each internet connection.
Unfortunately the uci implementation of ip rules does not support ports, so you can either do it by matching something else, or by using the native ip rule add ... which supports ports, but it is not so much integrated to OpenWrt.
Not sure how familiar you are with the pbr package. But I'm struggling to understand which chain the rule should belong to and which fields should be populated with which address.
I'd assume I should choose the VPN interface as the interface on pbr? With local IP being the LAN IP and Destination IP being the VPN gateway?
Do I only populate the source port, thus filtering only by traffic originating from said IP:port?
Can I track what pbr rules have been created by checking some file, nft -a list chain inet fw4 pbr_x, or conntrack?
uci add pbr policy
uci set pbr.@policy[-1].enabled='1'
uci set pbr.@policy[-1].name='test'
uci set pbr.@policy[-1].src_addr='192.168.2.218'
uci set pbr.@policy[-1].src_port='34'
uci set pbr.@policy[-1].interface='vpn'
uci commit pbr
service pbr restart
Does this cover you? Rename the interface name, obviously.
I must say I'm a bit surprised I hit so many nuances. Perhaps I was a little too reliant on the luci-app or was too specific when setting the rules?
Regardless I'll definitely want to play around with this some more but it appears to be working, so for that I thank you.
I'm happy enough with pbr assuming for simple forwarding such as this doesn't result in high CPU usage.
I must admit I'm a little curious about the mwan approach if it doesn't require extensive explanation (just pointing me to a thread or man page would help). I also may be wanting to dive into that package soon as I'll have a fallback WAN connection in my new setup.