a MikroTik router (v7.12.1) having a GUA (e.g. 2001:db8::2/64) on its WAN and a ULA (e.g. fd01: 2345::1/80) on its LAN;
a local client having a ULA (e.g. fd01: 2345::2/80).
What I would like to achieve is NPTv6 for the LAN subnet, i.e. the packet forwarded to public addresses originating from the client should have a GUA (e.g. 2001:db8:0:0:fd::2) in its source address field, and the packet forwarded to the client originating from public addresses should have a ULA (e.g. fd01: 2345::2) in its destination address field.
These rules generally work, but there is a problem with IPv6 traceroute (both ICMP and UDP tested):
traceroute from the client to a public address: 1) fd01: 2345::1; 2) 2001:db8::1; 3) […]. Correct.
traceroute from a public address to the router (WAN): 1) […]; 2) 2001:db8::2. Correct.
traceroute from a public address to the router (LAN): 1) […]; 2) 2001:db8:0:0:fd::1. Correct.
traceroute from a public address to the client: 1) […]; 2) 2001:db8:0:0:fd::2; 3) 2001:db8:0:0:fd::2. Incorrect.
So the problem is that when tracing to the client’s netmapped address, I expect the router being an intermediary will reply from its WAN address (e.g. 2001:db8::2), but it puts the client’s netmapped address to the source address field of an outgoing packet. I don’t understand whether it is a bug, or a weird IPv6 traceroute behaviour.
If the client has a GUA, and no SNAT/DNAT rules are enabled, traceroute replies are correct in all the cases above.
Disclaimer: I certainly understand IPv6 is designed to work without NAT and it’s better when each client has its own GUA. Please, note it is out of scope of this particular question.
It’s the same with IPv4 NAT … TCP traceroute on NAT-ed port shows same IP address twice. And it’s completely correct as far as NAT works: dst-nat replaces DST address on “forward” packets and SRC address on “return” packets (and possibly same for port numbers if necessary). Regardless the L4 protocol.
From this perspective (hiding LAN IP addresses, doesn’t matter if they’re globally routable or not) the third case (traceroute from a public address to the router (LAN)) is actually incorrect … because it leaks LAN IPv6 address.
But IMO this is purely cosmetic issue if things work correctly.
Don’t have a bunch of public IPv4 addresses on one server to test, but thanks for confirming.
I’m not sure about that. I think it’s the packet processing order that matters. It the router receives a packet with 0 hop limit / TTL, it should respond that the destination host is unreachable / the TTL is exceeded, and it should use its own WAN address, not the one of the destination host.
I my example config, the third case should have 2001:db8::2 (if hop limit is processed before NAT) or 2001:db8:0:0:fd::1 (if hop limit is processed after NAT) at step 2.
I tend to agree with you, but each outgoing packet is composed with some logic. And here the logic seems to be broken.
@mkx, thank you for the link. You are right, DST-NAT is the last step in prerouting, TTL check is the first step in forward.
Thus, if a packet with 2001:db8:0:0:fd::2 as destination and TTL=1 (actually, hop limit) arrives, it is first changed to have fd01: 2345::2 as destination, then the router subtracts 1 from its TTL/hop limit. The router detects TTL/hop limit equals 0 and composes a new ICMP packet to the original packet source from itself to notify that TTL is exceeded/destination is unreachable. And my question is why the router puts the original packet destination address to the reply packet source address instead of its own WAN address.