So I use just ULA addresses for my WG (you already have that fd00:9::0/64) then use selective NAT66 for that subnet.
Then you need to take care of routing of the ULA WG subnet out of the WAN, I found out the hard way that there is no general default route for IPv6 as the source is normally taken into account.
If you disable source routing you will get a general default route which also routes the ULA WG subnet.
This assumes IPv6 is otherwise already working on your server and the server has a GUA which serves as the endpoint.
But I am not the expert so wait for the more knowledgeable users to chime in
The allowed_ips on the server should be of the form:
Client #1 allowed IP subnet: 2001:db8:0:1::/64
Client #2 allowed IP subnet: 2001:db8:0:2::/64
etc.
Then the client IP can be anything within its /64, though it would be simplest to just use 1:
Client #1 client IP: 2001:db8:0:1::1/64
Client #2 client IP: 2001:db8:0:2::1/64
On the server the wireguard interface has a /48 which includes all of these /64s.
Server wg interface IPv6: 2001:db8:0::/48
In all of these the 0 after db8 can be replaced with any 16 bit number (1-4 hex digits)-- of course use the same number on all these psuedo-GUA IPs associated with the wireguard interface. This may help in case any clients try to get smart and treat 2001:db8 as not a real IP.
You don't have to redact 2001:db8 IPs as those are a reserved block that can exist only inside your network. They will never be reachable from the Internet.
Now that the addressing is in place make sure that wg0 forwards to wan6 and that IPv6 NAT is active. The simplest way to do that is to set masqv6 on the wan zone, but that will have the side effect that your LAN will also be NATd. It is a place to start for testing though. I'm not sure how to make it selective. Also srcfilter 0 must be set on the wg zone so that unexpected sources can be routed.
Thanks a lot, @mk24 and @egc. Setting up the right addresses for the interface, configuring Selective NAT and Disabling the source filter seem to do the trick and now I can get my public IPv6 working as normal. Can't thank enough everyone here who've helped me through this.
Just a small doubt regarding this
Is there any reason to have 1 at the very end? I assumed you would just increment that for example 2001:db8::1, 2001:db8::2 and so on... Is there a much shortened version of the IPv6 addressing to make things a bit easier to manage?
Each client has a different 64 bit prefix, so the last 64 bits can be the same.
The double colon notation is a short version to specify IPv6 addresses. The complete address would be
2001:db8:0:1::1 = 2001:db8:0:1:0:0:0:1 or even 2001:0db8:0000:0001:0000:0000:0000:0001