robbertkl / docker-ipv6nat

Extend Docker with IPv6 NAT, similar to IPv4
MIT License
662 stars 48 forks source link

Prefer ipv6 over ipv4 #78

Open guysoft opened 2 years ago

guysoft commented 2 years ago

Hey, Is there a way to set that Ipv6 would be preferred to ipv4?

If I bring up a container I get that unless spefied (or ipv6-only site) ipv4 is used:

ping www.google.com
PING www.google.com (142.250.184.196): 56 data bytes
64 bytes from 142.250.184.196: seq=0 ttl=110 time=69.688 ms

Only if I force ipv6 it uses it:

/ # ping -6 www.google.com
PING www.google.com (2a00:1450:4001:80f::2004): 56 data bytes
64 bytes from 2a00:1450:4001:80f::2004: seq=0 ttl=116 time=59.688 ms

Its like this for every container I tried. docker-compose:

  ipv6:
    image: robbertkl/ipv6nat
    container_name: ipv6nat
    restart: always
    network_mode: "host"
    privileged: true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /lib/modules:/lib/modules:ro
networks:
  default:
    enable_ipv6: true
    driver: bridge
    driver_opts:
      com.docker.network.enable_ipv6: "true"
    ipam:
      driver: default
      config:
       - subnet: fd00:0000:0000:1::/64

/etc/docker/daemon.json:

 {
          "ipv6": true,
          "fixed-cidr-v6": "fd00::/80"
}
$ sudo docker version
Client: Docker Engine - Community
 Version:           20.10.10
 API version:       1.41
 Go version:        go1.16.9
 Git commit:        b485636
 Built:             Mon Oct 25 07:42:19 2021
 OS/Arch:           linux/arm
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.10
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.9
  Git commit:       e2f740d
  Built:            Mon Oct 25 07:40:35 2021
  OS/Arch:          linux/arm
  Experimental:     false
 containerd:
  Version:          1.4.11
  GitCommit:        5b46e404f6b9f661a205e28d59c982d3634148f8
 runc:
  Version:          1.0.2
  GitCommit:        v1.0.2-0-g52b36a2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Thanks

7cio commented 2 years ago

You can use the subnet 2001:db8::/64 The containers will prefer IPv6 over IPv4

guysoft commented 2 years ago

@vNa3006 That subnet type changes the preference?

From what I understand that is an address block (2001:db8::/64) used for documentation examples: https://en.wikipedia.org/wiki/IPv6_address#Special_addresses

7cio commented 2 years ago

Yes, I don't know why it works that way, but when you use 2001:db8::/64, the containers will prefer ipv6

guysoft commented 2 years ago

I probably want though a subset not used for documentation :) Any other blocks or explanation why?

7cio commented 2 years ago

I haven't tried anything else yet. I'm OK with that subnet for now.

guysoft commented 2 years ago

From #ipv6 on librechat I was updated that what sets the priority is /etc/gai.conf (getaddrinfo). I am not sure how to use it though

7cio commented 2 years ago

You can backup the gai.conf file, then replace the content of the file to

label ::1/128 0 label ::/0 1 label 2002::/16 2 label ::/96 3 label ::ffff:0:0/96 4 label fec0::/10 5 label fc00::/7 6

label 2001:0::/32 7

It should work also

guysoft commented 2 years ago

@vNa3006 Does this go in the container? host? or the docker-ipv6nat container? Does not seem to work in the container.

7cio commented 2 years ago

I've just tested with a clean ubuntu container, it works right after editing the gai.conf file without restarting the container.

jsravn commented 1 year ago

For posterity sake, this is a quirk of glibc: https://codebrowser.dev/glibc/glibc/sysdeps/posix/getaddrinfo.c.html#1234.

It explicitly ignores ipv6 standards and returns ipv4 addresses first when using ULA addresses. The assumption is "ipv6 will never be NAT'd" :). This ignoring the RFC has caused many headaches.

That's why 2001 works. But ipv6nat only NATs ULA addresses, so I'm not sure how you're using the container.

guysoft commented 1 year ago

@jsravn Thanks for digging in and finding the root cause.

Its not that they don't expect ipv6 to be nated. More the logic is "if we have a ipv6 local address then we expect that we have only ipv6 locally and not globally". So they will only route IPv6 if if there is a global address to the device. Because the situarion of a local ipv6 and no global ipv6 is more common.

And the workaround we are doing is assigning a global address to make glibc think it has a global address and route correctly.

Sounds like a reason to file a bug on glibc: https://sourceware.org/bugzilla/

jsravn commented 1 year ago

I doubt they would change it at this point. I also noticed RFC 6724 updates the source selection logic to follow what glibc does - so it seems it will become the standard soon. As a result, seems like the "use example range" hack is going to be codified into ipv6 for all of time :).