Accepting IPv4 connections as IPv6 Server

Started by
3 comments, last by evillive2 5 years ago

I am trying to accept IPv4 connections on my server that is listening on an IPv6 TCP socket.

 

I was currently working on porting a blocking socket example i'm using for some tutorials i've been making, and i've noticed behavior that I did not expect.

Current github dev branch: https://github.com/Pindrought/PNet/tree/TCP_Blocking_Winsock_Tutorial_17Dev

My client is connecting using an IPv4 socket.

My server is accepting connections on an ipv6 socket, and i've disabled the IPV6_V6ONLY socket option to allow both ipv4 and ipv6 incoming connections.

 

The connections are accepted just fine - the confusion for me arises in the fact that the accepted connection appears to be an IPv6 connection according to the address family in the sockaddr struct.

https://github.com/Pindrought/PNet/blob/TCP_Blocking_Winsock_Tutorial_17Dev/PNet/PNet/Socket.cpp#L128-L145

 

I was under the impression that the ipv4 connection would have an address family of AF_INET6.

Is this expected behavior? I just want to make sure that i'm not doing anything wrong here. If this is expected behavior, is there any way I can determine from the server side if the connecting client did so using IPv4 or IPv6?

 

Thanks!

Edited to add:

This is the output my server has

Quote

Winsock api successfully initialized.
Socket successfully created.
Socket successfully listening on port 4790.
New IPv6 connection accepted!
IP Version: IPv6
Hostname: ::ffff:127.0.0.1
IP: ::ffff:127.0.0.1
Port: 59191
IP bytes...
0
0
0
0
0
0
0
0
0
0
255
255
127
0
0
1
New connection accepted.

 

 

Advertisement

For a dual-stack socket, the only differentiation between IPv6 and IPv4 traffic is the "format" of the IPv6 IP address.  Everything is handled on (your) code side as IPv6 (AF_INET6).  The only thing that is different is that IPv4 traffic will have a special "mapped" IPv6 IP address (the ::ffff:x.x.x.x format you see above).  To send IPv4 traffic you need to translate to that mapped address (in your case just use the same address that connected), and if you care you can check to see if the received connection/traffic is IPv4 by checking to see if the upper 12 bytes of the address match 0000:0000:0000:0000:0000:ffff.  The lower 4 bytes of the IPv6 address will be the IPv4 IP address.

This page lays it out clearly (and references a few handy Microsoft/windows-specific macros for checking for and translating between IPv6 mapped addresses and IPv4, presuming you are doing a win32 project):

https://docs.microsoft.com/en-us/windows/desktop/winsock/dual-stack-sockets

 

 

7 minutes ago, SBD said:

For a dual-stack socket, the only differentiation between IPv6 and IPv4 traffic is the "format" of the IPv6 IP address.  Everything is handled on (your) code side as IPv6 (AF_INET6).  The only thing that is different is that IPv4 traffic will have a special "mapped" IPv6 IP address (the ::ffff:x.x.x.x format you see above).  To send IPv4 traffic you need to translate to that mapped address (in your case just use the same address that connected), and if you care you can check to see if the received connection/traffic is IPv4 by checking to see if the upper 12 bytes of the address match 0000:0000:0000:0000:0000:ffff.  The lower 4 bytes of the IPv6 address will be the IPv4 IP address.

This page lays it out clearly (and references a few handy Microsoft/windows-specific macros for checking for and translating between IPv6 mapped addresses and IPv4, presuming you are doing a win32 project):

https://docs.microsoft.com/en-us/windows/desktop/winsock/dual-stack-sockets

 

Great reply! This makes perfect sense. Thanks so much for the detailed explanation.

A quick suggestion is to allow a layer 4 proxy like haproxy to handle the dual stack side for you. There are a ton of possible benefits to this as an abstraction layer - managing ports, ipv4/ipv6, security, logging and monitoring etc. Most importantly is it lets you get back to completing the game.

Evillive2

This topic is closed to new replies.

Advertisement