Skip to content

Instantly share code, notes, and snippets.

@aliicex
Last active February 4, 2025 07:47
Show Gist options
  • Save aliicex/3bd8413029b1f728c1f00bc1ac0e98b4 to your computer and use it in GitHub Desktop.
Save aliicex/3bd8413029b1f728c1f00bc1ac0e98b4 to your computer and use it in GitHub Desktop.
Faux-implementing IPv6 Policy-Based Routing on OpenWRT

Stangri's VPN Policy Routing package is a mainstay of my OpenWRT builds. It works great for IPv4, but I couldn't, for the life of me, get it working with IPv6. Instead, I had to faux-implement PBR as follows.

My VPN provider only gave me a single IP address with a /128 prefix, so I was forced to use NAT6. This left me with a stanza in my firewall config that looks like this; note the masq6 option

config zone
	option name 'wan_vpn'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	option mtu_fix '1'
	option network 'wg_vpn'
	option masq6 '1'
	option masq6_privacy '1'

With that in-place, I had to ignore my ISP's prefix delegation on those interfaces where I wanted IPv6 traffic to be directed over the VPN:

config interface 'lan'
	option type 'bridge'
	option proto 'static'
	option netmask '255.255.255.0'
	option ipaddr '192.168.1.1'
	option ifname 'eth1 eth2'
	option ip6assign '64'
	option ip6hint 'AA'
	list ip6class 'local'

Finally, I created a route:

config route6
	option target '::/0'
	option interface 'wg_vpn'

It's not pretty - there should be no need to use NAT with IPv6 - and I'm sure there's a better way; but it works. Perhaps one day my VPN provider will give me something like a /48; or at least a /60. In the meantime, if anybody knows how to get IPv6 PBR working with Stangri's package, please let me know!

@HomidWay
Copy link

HomidWay commented Nov 23, 2024

I don't think my case is representative but for me this worked as for now im getting only /64 prefix delegated from my ISP, but i made it work like this:

  1. Main subnet is on my lan interface with full /64 delegated
  2. ULA prefixes on every lan/wan/vpn interface
  3. VPN with /128 address delegated by VPN service
  4. IPv6 Masquarading enabled on VPN firewall zone
  5. Enable delegation of ULA for every interface which will be used in PBR configuration
  6. Lan interface in RA/DHCPv6 Server mode, RA on relay, wan all on relay disable everywhere else

Configs:
lan:

config interface 'lan'
	option device 'br-lan'
	option proto 'static'
	option gateway '***.***.***.***'
	list ipaddr '192.168.*.*/24'
	option ip6assign '64'
	option ip6hint '10'

wan_6:

config interface 'wan_6'
	option proto 'dhcpv6'
	option device '@wan'
	option reqaddress 'none'
	option reqprefix '64'
	option ip6ifaceid '::ffff'

wireguard interface config:

config interface 'wg_CF'
	option proto 'amneziawg'
	option private_key '*****'
	option delegate '0'
	option ip6assign '64'
	option ip6hint 'a'
	list addresses '172.16.0.2/32'
	list addresses '2000::ffff/128'
	list ip6class 'local'

firewall zone setup like this:

config zone
	option name 'wg'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	option mtu_fix '1'
	list network 'wg'
	option masq6 '1'

@christaikobo
Copy link

christaikobo commented Jan 12, 2025

Just curious, I'm a noob regarding IPv6, when routing through a VPN, we have to get IPv6 address from the VPN right? Can we just use ISP delegated IPv6 through the VPN tunnel?

My VPN has a /48, but I haven't got the time to test it with pbr.

EDIT: after some experimenting I now have the following understanding: (I'm not an expert so do take it with grain of salt)

  1. You can't use ISP delegated IPv6 through the VPN tunnel directly without NAT, because upstream router of VPN will simple discard the packet because it comes from an IP not under its delegation, so it's considered IP spoof.
  2. You can use it with NAT. Just use SNAT. No need to enable masq6, or disable GUA. You should SNAT twice, once at client openwrt wireguard interface to a ULA, second time at the server oif. Of course, don't forget to enable IPv6 in pbr.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment