Skip to content
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

Add IPv6 support #8

Merged
merged 1 commit into from
Apr 6, 2020
Merged

Add IPv6 support #8

merged 1 commit into from
Apr 6, 2020

Conversation

ac000
Copy link
Contributor

@ac000 ac000 commented Apr 6, 2020

Hi,

This adds support for IPv6 in the server. This allows the server to accept IPv6 connections and also to make IPv6 requests.

See the commit message for details.

Cheers,
Andrew

This adds support for IPv6 in the server.

This allows the server to accept IPv6 connections and also to make IPv6
requests.

I.e, for IPv4 we get (pertinent messages only)

    $ build/server -vvv --ip-address 0.0.0.0 --port 1234
    [2020-04-05 20:07:14] INFO Starting UDP proxy on 0.0.0.0:1234
    [2020-04-05 20:07:14] DEBUG Received packet of 34 bytes from 127.0.0.1
    [2020-04-05 20:07:14] DEBUG Performing DNS lookup of google.com
    [2020-04-05 20:07:15] DEBUG Resolved host google.com to ip address 216.58.205.46

with IPv6 we get

    $ build/server -vvv --ip-address :: --port 1234
    [2020-04-05 20:08:41] INFO Starting UDP proxy on [::]:1234
    [2020-04-05 20:08:47] DEBUG Received packet of 34 bytes from ::1
    [2020-04-05 20:08:47] DEBUG Performing DNS lookup of google.com
    [2020-04-05 20:08:47] DEBUG Resolved host google.com to ip address 2a00:1450:4009:808::200e

As you can see, with these changes the server can listen on IPv6
addresses and make IPv6 requests, in the second case we got the IPv6
address for google.com.

If the requested host doesn't have a AAAA record then it will use IPv4,
e.g

    $ build/server -vvv --ip-address :: --port 1234
    [2020-04-05 20:08:11] INFO Starting UDP proxy on [::]:1234
    [2020-04-05 20:08:17] DEBUG Received packet of 35 bytes from ::1
    [2020-04-05 20:08:17] DEBUG Performing DNS lookup of amazon.com
    [2020-04-05 20:08:17] DEBUG Resolved host amazon.com to ip address 176.32.98.166

There is one more case this handles, when listening on an IPv6 address,
you can connect to the server over IPv4, e.g

    $ build/server -vvv --ip-address :: --port 1234
    [2020-04-06 00:12:44] INFO Starting UDP proxy on [::]:1234
    [2020-04-06 00:12:56] DEBUG Received packet of 35 bytes from ::ffff:127.0.0.1
    [2020-04-06 00:12:56] DEBUG Performing DNS lookup of google.com
    [2020-04-06 00:12:56] DEBUG Resolved host google.com to ip address 2a00:1450:4009:811::200e

Here the server was set to listen on :: (the IPv6 equivalent of
INADDR_ANY) yet we connected to it over IPv4 from 127.0.0.1, the
::ffff:127.0.0.1 is called an IPv4-mapped IPv6 address[0].

On Linux (at least) this is the default behaviour of IPv6 sockets. This
behaviour can however be disabled by setting the IPV6_V6ONLY socket
option. There is a new --ipv6-v6only argument to ff-proxy for setting
this option. e.g

    $ build/server -vvv --ip-address :: --port 1234 --ipv6-v6only
    [2020-04-06 01:01:24] INFO Starting UDP proxy on [::]:1234
    [2020-04-06 01:01:24] DEBUG Setting IPV6_V6ONLY socket option

and from the client side

    $ echo -e "GET / HTTP/1.1\nHost: google.com \n\n" | nc -u 127.0.0.1 1234
    Ncat: Connection refused.

The main way IPv6 support was added was to replace the calls to
gethostbyname(3) with calls to getaddrinfo(3).

gethostbyname(3) is obsolete, from the gethostbyname(3) Linux man page

    "POSIX.1-2001 specifies gethostbyname(), gethostbyaddr(),
     sethostent(), endhostent(), gethostent(), and h_errno;
     gethostbyname(), gethostbyaddr(), and h_errno are marked
     obsolescent in that standard. POSIX.1-2008 removes the
     specifications of gethostbyname(), gethostbyaddr(), and h_errno,
     recommending the use of getaddrinfo(3) and getnameinfo(3) instead."

One of the advantages of getaddrinfo(3) is that it is address family
agnostic.

In struct ff_config we just store the port number and listen IP address
as const char *'s as that is what you pass into getaddrinfo(3).

We also get rid of various bits of manually filling out various network
structures which is essentially replaced by getaddrinfo(3).

We also fix up various tests to take into account that the port number
and IP address are now just strings.

[0]: https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses
@TimeToogo TimeToogo merged commit 0dafcd7 into TimeToogo:master Apr 6, 2020
@TimeToogo
Copy link
Owner

Merged, thanks for your contribution :)

@ac000 ac000 deleted the ipv6 branch April 7, 2020 15:23
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

Successfully merging this pull request may close these issues.

2 participants