How to set route rule for ipv6 nat?

1. goal

  1. clients all allocated with private ipv6 address with a specified ULA prefix, not public ipv6 address
  2. clients' can visit public ipv6 internet, but cannot be visited from public ipv6 internet

2. network toplogic

  1. a main router support ipv6, and ISP assigned a public ipv6 address, ipv6 and ipv4 both works well
  2. a secondary router run openwrt behind main router, ipv6 and ipv4 both works well
  3. clients behind openwrt router, allocated with private ipv6 address from openwrt. now ipv4 works well, but visit outer ipv6 network failed, can visit openwrt via private ipv6 address

3. network config info

/etc/config/network

# cat /etc/config/network

config interface 'loopback'
        option device 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fdce:afd0:3d18::/48'

config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'eth1'

config device
        option name 'eth1'
        option macaddr '06:91:62:b4:31:27'

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option netmask '255.255.255.0'
        option ip6assign '60'
        option ipaddr '192.168.1.1'

config device
        option name 'eth0'
        option macaddr '04:91:62:b4:31:27'

config interface 'wan'
        option device 'eth0'
        option proto 'dhcp'
        option peerdns '0'
        list dns '192.168.3.1'

config interface 'wan6'
        option device 'eth0'
        option proto 'dhcpv6'
        option reqaddress 'try'
        option reqprefix 'auto'
        option peerdns '0'
        list dns '::1'

ifconfig

# ifconfig
br-lan    Link encap:Ethernet  HWaddr 06:91:62:B4:31:27
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::491:62ff:feb4:3127/64 Scope:Link
          inet6 addr: fdce:afd0:3d18::1/60 Scope:Global
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:36357 errors:0 dropped:0 overruns:0 frame:0
          TX packets:55427 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:6282092 (5.9 MiB)  TX bytes:43703229 (41.6 MiB)

eth0      Link encap:Ethernet  HWaddr 04:91:62:B4:31:27
          inet addr:192.168.3.73  Bcast:192.168.3.255  Mask:255.255.255.0
          inet6 addr: xx:xx:xx:AA:3471:46c2:828f:e/128 Scope:Global
          inet6 addr: xx:xx:xx:BB:691:62ff:feb4:3127/64 Scope:Global
          inet6 addr: fe80::691:62ff:feb4:3127/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:143465 errors:0 dropped:0 overruns:0 frame:0
          TX packets:116999 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:59751679 (56.9 MiB)  TX bytes:17795802 (16.9 MiB)
          Interrupt:35

eth1      Link encap:Ethernet  HWaddr 06:91:62:B4:31:27
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:37172 errors:0 dropped:8 overruns:0 frame:0
          TX packets:55424 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:6835148 (6.5 MiB)  TX bytes:43702859 (41.6 MiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:65889 errors:0 dropped:0 overruns:0 frame:0
          TX packets:65889 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:24728072 (23.5 MiB)  TX bytes:24728072 (23.5 MiB)

route table

ip -6 route list table main
default from 240e:381:3831:9100:3471:46c2:828f:e via fe80::1 dev eth0 proto static metric 384 pref medium
default from 240e:381:3831:9183::/64 via fe80::1 dev eth0 proto static metric 384 pref medium
240e:381:3831:9183::/64 dev eth0 proto static metric 256 pref medium
unreachable 240e:381:3831:9183::/64 dev lo proto static metric 2147483647 pref medium
fdce:afd0:3d18::/64 dev br-lan proto static metric 1024 pref medium
unreachable fdce:afd0:3d18::/48 dev lo proto static metric 2147483647 pref medium
fe80::/64 dev br-lan proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium

4.problem

after google a lot, I knew that I have to two thing to meet my goal:

  1. add a ipv6 route rule let private ipv6 trafic send to gateway
  2. use below command to translate private trafic
    ip6tables -t nat -I POSTROUTING -s uci get network.globals.ula_prefix-j MASQUERADE

now I have problem about add a ipv6 route rule. I followed ipv4 add default gateway route, but it not working.how to add such a route rule? I think many people have such a problem, not everyone accept expose inner net to public

I'm not quiet sure if I understand your requirements, and if your only issue is, that clients should not be reachable from WAN, what the firewall does on default settings anyway...
But I think you want, not ip rule but ip route:

ip -6 route add default from ULA-PREFIX 
# you may need to add "dev WAN-IF", not sure. Like:
# ip -6 route add default from ULA-PREFIX dev pppoe-wan
# and then the MASQUERADE
ip6tables -t nat -A POSTROUTING -s ULA-PREFIX -o pppoe-wan -j MASQUERADE

(I use this for wireguard clients, which have only ULA, but need to reach the WAN.)

ISP assigned a /64 cidr, if not allocate private ipv6 address, clients can only get ipv6 address via relay mode, firewall on openwrt will not effect on clients(I guess), beside this, I still want clients allocated private ipv6 address just like ipv4

NAT was long a crutch that people thought provided security. It never was a firewall. It arguably caused more security problems than it resolved.

I'd assign your hosts "real" (routable) addresses and set up proper firewall rules for your hosts.

It is a lot easier when you've got end-to-end address consistency. No more dual sets and crazy dynamic rules and hoping that conntrack keeps the original and NAT-ed addresses all straight.

I have no experience with relay mode as I have a /64 for the WAN interface and a /56 routed. Sorry I can not help on this part.
But on the default firewall ruleset, the forwarding from WAN to LAN is rejected, only established connections and some ICMP is allowed.

However, did the ip route command with the from flag helped? (I dont know how to put this into the UCI config or /etc/config/network, I assign these route with a hotplug script.

For firewall4:

config nat
  option family ipv6
  option proto all
  option src wan
  option src_ip fc00::/7
  option target MASQUERADE 
2 Likes

put config nat into /etc/config/firewall?, if put into /etc/config/firewall, it said Section @nat[0] specifies unknown option 'dest'

Ah right, just option src, and set it to wan. I modified my post accordingly.

config nat seemed same with https://openwrt.org/docs/guide-user/network/ipv6/ipv6.nat6 Enable the new masq6 option in your firewall on your upstream zone.

Except that masq6 would masquerady any IPv6 traffic (undesirable) while the config nat rule above restricts masquerading to private ULA space.

get, after apply this config, clients still cannot visit public ipv6 web, need I add a route rule? if need, how to set such a rule?

Yeah, the router likely needs an IPv6 default route policy for the fc00::/7 range. By default only source addresses within the public prefixes are routed.

Try adding the following route to /etc/config/network:

config route6
	option interface 'wan6'
	option target '::/0'
	option source 'fc00::/7'

Then run ifup wan6. Afterwards you should see a route similar to this:

# ip -6 route
...
default from fc00::/7 dev 6in4-wan6 proto static metric 1024 pref medium
...
1 Like

route setting problem?

That guess is incorrect. This is what firewall does in IPv6, you don't need NAT. So you only need to set up NAT if it's you're preference. NAT was never designed [originally] to be a security technology.