erlang/otp

inet6 to inet fallback in networks without ipv6 support

ruslandoga opened this issue ยท 1 comments

๐Ÿ‘‹

Is your feature request related to a problem? Please describe.

Not sure yet. First I'd like double check if gen_tcp:connect and ssl:connect with inet6 option are supposed to fallback to inet when IPv6 connection is not successful. And if it's not supposed to work this way, I'd like to request this feature!

Right now I'm not able to make this sort of fallback work. Here're some examples from Fly.io dual-stack machine and from an IPv4-only container running on AWS EC2. I'm using IPv4-only and IPv6-only hosts from http://dual.tlund.se

From Fly.io Machine
1> inet:getifaddrs().
{ok,[{lo,[{flags,[up,loopback,running]},
             {addr,{127,0,0,1}},
             {netmask,{255,0,0,0}},
             {addr,{0,0,0,0,0,0,0,1}},
             {netmask,{65535,65535,65535,65535,65535,65535,65535,65535}},
             {hwaddr,[0,0,0,0,0,0]}]},
     {dummy0,[{flags,[broadcast]},
                {hwaddr,[150,232,97,230,238,118]}]},
     {eth0,[{flags,[up,broadcast,running,multicast]},
              {addr,{172,19,136,2}},
              {netmask,{255,255,255,248}},
              {broadaddr,{172,19,136,7}},
              {addr,{172,19,136,3}},
              {netmask,{255,255,255,248}},
              {broadaddr,{172,19,136,7}},
              {addr,{9733,19520,344,51602,0,62017,27426,1}},
              {netmask,{65535,65535,65535,65535,65535,65535,65535,65534}},
              {addr,{64938,0,24663,2683,129,62017,27426,2}},
              {netmask,{65535,65535,65535,65535,65535,65535,65535,0}},
              {addr,{65152,0,0,0,56493,55039,65078,12685}},
              {netmask,{65535,65535,65535,65535,0,0,0,0}},
              {hwaddr,[222,173,214,54,49,141]}]},
     {teql0,[{flags,[]}]}
    ]}.

Connecting to IPv4-Only Host works with default inet option

2> {ok, Socket} = gen_tcp:connect("ipv4.tlund.se", 80, [{active, false}]).
3> inet:peername(Socket).
{ok,{{193,15,228,195},80}}.

But fails when inet6 option is provided

4> gen_tcp:connect("ipv4.tlund.se", 80, [inet6, active, false]).
{error,nxdomain}.

ipv6_v6only doesn't Help

5> gen_tcp:connect("ipv4.tlund.se", 80, [inet6, {ipv6_v6only, false}, active, false]).
{error,nxdomain}.

Default options (inet) don't work with IPv6-only host

6> gen_tcp:connect("ipv6.tlund.se", 80, [active, false]).
{error,nxdomain}.

inet6 works with IPv6-only host

7> {ok, Socket} = gen_tcp:connect("ipv6.tlund.se", 80, [inet6, {active, false}]).
8> inet:peername(Socket).
{ok,{{10752,2049,15,0,0,0,0,405},80}}.
From IPv4-only container on AWS EC2
1> inet:getifaddrs().
{ok,[{lo,[{flags,[up,loopback,running]},
             {addr,{127,0,0,1}},
             {netmask,{255,0,0,0}},
             {hwaddr,[0,0,0,0,0,0]}]},
     {eth0,[{flags,[up,broadcast,running,multicast]},
              {addr,{172,24,0,3}},
              {netmask,{255,255,0,0}},
              {broadaddr,{172,24,255,255}},
              {hwaddr,[2,66,172,24,0,3]}]}
    ]}.

No fallback to inet

2> gen_tcp:connect("ipv6.tlund.se", 80, [inet6, {active, false}]).
{error,eaddrnotavail}.

Describe the solution you'd like

inet6 would fallback to inet automatically when needed so that providing inet6 option would always increase the chance of a successful connection.

Describe alternatives you've considered

Some Elixir libraries perform a manual fallback from inet6 to inet like Mint and some other libraries like Postgrex allow a list of endpoints to be provided for connection attempts.

Additional context

Relevant discussion (where this question originated): phoenixframework/phoenix#4289 (comment)

In place of a "ping": I would also happily work on implementing happy eyeballs into Erlang!

Related issues / discussions / projects: