8000 implement RFC 8781 (Discovering PREF64 in Router Advertisements) · Issue #32 · toreanderson/clatd · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

implement RFC 8781 (Discovering PREF64 in Router Advertisements) #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ghost opened this issue Aug 6, 2023 · 12 comments
Closed

implement RFC 8781 (Discovering PREF64 in Router Advertisements) #32

ghost opened this issue Aug 6, 2023 · 12 comments

Comments

@ghost
Copy link
ghost commented Aug 6, 2023

Hi

RFC 8781 (https://www.rfc-editor.org/rfc/rfc8781.txt) is a nice way to get the plat-prefix direct by the router. So you don't need the dns64 server.

@toreanderson
Copy link
Owner

It is very unlikely that I would be able to implement this in clatd, because the receipt and parsing of ICMPv6 RAs are either done by the kernel or some user-space network management service like NetworkManager or systemd-networkd.

If they expose the prefix somewhere, like in sysfs or dbus, I guess it would be possible to look it up. I am not aware of any way to do it, though.

@ghost
Copy link
Author
ghost commented Aug 7, 2023

I'm currently writing a small C program to get the pref64 option. Would it be possible to include this with a plat-detector-script option (option name is just to have an example)?

@toreanderson
Copy link
Owner

Sure, I would be happy to include something like that!

@herbetom
Copy link

In systemd Version 255 a UsePREF64 option was added to networkd:

https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#UsePREF64=

Not sure if there are already tools taking advantage of it to have an implementation example.

To me it seems hoewer sensible to rely on the network configuration utilities to get that information.

@toreanderson
Copy link
Owner

In systemd Version 255 a UsePREF64 option was added to networkd:

Could someone using this send me output from networkctl --json=pretty status $plat_dev?

Alternatively, add script-up=networkctl --json=pretty status $plat_dev to /etc/clatd.conf and send me output from starting clatd.

@herbetom
Copy link
herbetom commented Feb 9, 2025

@toreanderson Here you go: https://gist.github.com/herbetom/e7a7eb380170d10b599ecc686689a2f1 :)

@toreanderson
Copy link
Owner

@herbetom I just realised that I can't do it like that, because the PLAT device isn't known at the time PLAT prefix discovery happens. I need to find the prefix first. Could you send me networkctl --json=pretty status (without specifying a device) instead?

@herbetom
Copy link

@toreanderson Sure, here is another example of a VM with two network interfaces. One has the PREF64 Option, the other not.

https://gist.github.com/herbetom/7065d329cf545552f706c67202fab33e

But i guess helpful would also be an example with at least two networks with PREF64 and maybe a third that doesn't have it so that it can be tested that the correct one for the default route is selected? But that's something to set up after lunch.

toreanderson added a commit that referenced this issue Feb 14, 2025
Makes clatd check if systemd-networkd is aware of any PLAT prefix (which
it may have learned from the PREF64 Router Advertisement option, cf. RFC
8781).

If a prefix is obtained from systemd-network, DNS64-based PLAT prefix
discovery is skipped, as mandated by
https://datatracker.ietf.org/doc/draft-ietf-v6ops-prefer8781/.

However, if the dns64-servers config option is set, clatd will use
DNS64-based PLAT prefix discovery towards the specified servers, and it
will not query systemd-networkd at all.

Closes #32
@toreanderson
Copy link
Owner

I have just pushed a feature branch that adds support for this now. Could you please try it out and see if it works (and ideally also see if it fails gracefully over to DNS64-based prefix discovery in the cases where systemd-networkd is not in use, is unaware of a PREF64, and so on)?

The feature branch is available here: https://github.com/toreanderson/clatd/tree/rfc8781

toreanderson added a commit that referenced this issue Feb 14, 2025
Makes clatd check if systemd-networkd is aware of any PLAT prefix (which
it may have learned from the PREF64 Router Advertisement option, cf. RFC
8781).

If a prefix is obtained from systemd-network, DNS64-based PLAT prefix
discovery is skipped, as mandated by
https://datatracker.ietf.org/doc/draft-ietf-v6ops-prefer8781/.

However, if the dns64-servers config option is set, clatd will use
DNS64-based PLAT prefix discovery towards the specified servers, and it
will not query systemd-networkd at all.

Closes #32
@herbetom
Copy link
herbetom commented Feb 21, 2025

Sorry, took me a while to get back to this. Tested it and discovery appears to be working.
But i didn't really test much in the form of corner cases. Only the single case shown below. Since i changed the used NAT64 Prefix (and DNS Server IP to one that doesn't provide DNS64) here is another paste of networkctl --json=pretty status: https://gist.github.com/herbetom/4bf57571b8d08cc7a064ae09ad0057aa

I've used NixOS (24.11) for testing with the following settings and adjustments if anyone else wants to give this a try (and also uses NixOS):

{ pkgs, lib, ... }:
{
  networking = {
    dhcpcd.enable = false;
    useDHCP = false;
    useHostResolvConf = false;
  };

  systemd.network = {
    enable = true;
    networks."50-enp5s0" = {
      matchConfig.Name = "enp5s0";
      networkConfig = {
        DHCP = "ipv4";
        IPv6AcceptRA = true;
      };
      linkConfig.RequiredForOnline = "routable";
      ipv6AcceptRAConfig.UsePREF64 = true;
    };
    networks."50-enp6s0" = {
      matchConfig.Name = "enp6s0";
      networkConfig = {
        DHCP = "ipv4";
        IPv6AcceptRA = true;
      };
      linkConfig.RequiredForOnline = "routable";
      ipv6AcceptRAConfig.UsePREF64 = true;
    };
  };

  networking.nftables.enable = true;
  networking.firewall.filterForward = true;
  networking.firewall.checkReversePath = false;

  services.clatd = {
    enable = true;
    package = pkgs.clatd.overrideAttrs (oldAttrs: {
      version = "2.0.0-rfc8781-1";
      src = pkgs.fetchFromGitHub {
        owner = "toreanderson";
        repo = "clatd";
        rev = "f564300918a5007fb3eda0af0a7f59b9c79cfdfb"; # https://github.com/toreanderson/clatd/commits/rfc8781/
        hash = "sha256-nDeB9GHzJFtlKmoocJVNDjVwALDN8mgBskli0O5izB4=";
      };
      buildInputs = with pkgs.perlPackages; [
        JSON
      ] ++ oldAttrs.buildInputs;

      postFixup = ''
        patchShebangs $out/bin/clatd
        wrapProgram $out/bin/clatd \
          --set PERL5LIB $PERL5LIB \
          --prefix PATH : ${
            lib.makeBinPath [
            pkgs.tayga
            pkgs.iproute2
            #pkgs.iptables
            pkgs.nftables
          ]
        }
      '';
    });
  };
  systemd.services.clatd.serviceConfig.RestrictAddressFamilies = [
    "AF_UNIX"
  ];
}

The Log output with this is the following:

Feb 21 15:19:10 test23 systemd[1]: Started 464XLAT CLAT daemon.
Feb 21 15:19:11 test23 clatd[10039]: Starting clatd v2.0.0 by Tore Anderson <tore@fud.no>
Feb 21 15:19:11 test23 clatd[10039]: Attempting to query systemd-networkd for PLAT prefix (cf. RFC 8781)
Feb 21 15:19:11 test23 clatd[10039]: Using PLAT (NAT64) prefix: 2001:67c:2960:6464::/96
Feb 21 15:19:21 test23 clatd[10039]: Device facing the PLAT: enp6s0
Feb 21 15:19:21 test23 clatd[10039]: Using CLAT IPv4 address: 192.0.0.1
Feb 21 15:19:21 test23 clatd[10039]: Using CLAT IPv6 address: 2a0e:b107:eb0:300:216:3eff:fe69:5d3e
Feb 21 15:19:21 test23 clatd[10039]: Checking if this system already has IPv4 connectivity in 10 sec(s)
Feb 21 15:19:21 test23 clatd[10039]: Enabling IPv6 forwarding
Feb 21 15:19:21 test23 clatd[10039]: Creating and configuring up CLAT device 'clat'
Feb 21 15:19:21 test23 clatd[10046]: Created persistent tun device clat
Feb 21 15:19:21 test23 clatd[10039]: Adding clatd nftable, using conntrack mark 49575
Feb 21 15:19:21 test23 clatd[10039]: Adding IPv4 default route via the CLAT
Feb 21 15:19:21 test23 clatd[10039]: Starting up TAYGA, using config file '/tmp/gh1oHHuP4S'
Feb 21 15:19:21 test23 tayga[10058]: starting TAYGA 0.9.2
Feb 21 15:19:21 test23 tayga[10058]: Using tun device clat with MTU 1500
Feb 21 15:19:21 test23 tayga[10058]: TAYGA's IPv4 address: 192.0.0.2
Feb 21 15:19:21 test23 tayga[10058]: TAYGA's IPv6 address: 2001:67c:2960:6464::c000:2
Feb 21 15:19:21 test23 tayga[10058]: NAT64 prefix: 
8000
2001:67c:2960:6464::/96

It seems like the wrong "CLAT IPv6 address" is beeing used. That address belongs to a different Interface then the one where the PREF64 Option is received. It's still working but if this wouldn't be a Public NAT64 Prefix i'm not sure it would.

@DanielG
Copy link
Contributor
DanielG commented Feb 21, 2025

As discussed with Tore on IRC I have a design and (partial) implementation for facilitating access to RA options like PREF64 without systemd-networkd or NetworkManager. Currently only the [DESIGN] doc is public https://gist.github.com/DanielG/4d1cba309c9ed541038e2c2f7a346109 will work on getting the program published and uploaded to Debian also. Help welcome.

--Daniel

@toreanderson
Copy link
Owner

@herbetom What clatd does, is to perform a route lookup towards the NAT64 prefix in order to find the outgoing interface. In your case that would be ip route get 2001:67c:2960:6464::.

If I understand you correctly you are receiving a NAT64 prefix on interface X, but the outgoing route to that prefix is using interface Y. Therefore clatd picks an address from interface Y.

It's not necessarily the case that it would be any better to pick an address from interface X, because the Linux kernel would still route the packets towards the NAT64 out interface Y, but ISP Y might drop those packets as being spoofed (using a source address belonging to ISP X). Or, in the case of a non-public prefix (e.g., 64:ff9b::/96), ISP Y might not be able to reach the NAT64 instance at all.

In any case, this is no different from the DNS64 method of prefix discovery. Your system might have learned DNS servers both from ISPs X and Y, and the local resolver might give an answer for ipv4only.arpa that came from ISP X's DNS server, but you still might have the outgoing route to that prefix via ISP Y, so you end up in the same situation.

I don't really see how clatd could behave any different here.

toreanderson added a commit that referenced this issue Mar 21, 2025
New feature:

* Support for RFC 8781 PLAT prefix discovery through the PREF64 Router
  Advertisement option. Relies on systemd-networkd's support for the
  same being enabled. (See issue #32.)

Bugfixes:

* Create any missing leading directories in the Makefile's install
  target. (See pull request #47, thanks @DanielG!)
* Apply metadata mark earlier in the nftables pipeline. This makes clatd
  interoperate with the IPv6 reverse path filtering as implemented by
  NixOS. (See pull request #49, thanks @jmbaur!)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants
0