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
AsyncIO V4MAPPED addresses with V6ONLY. #80389
Comments
I'm working with aiocoap, which uses the AI_V4MAPPED flag to use IPv4-mapped addresses for dual-stack support. When trying to run on Windows, creating a connection fails, because the socket option IPV6_V6ONLY is set to true per default on Windows, whereas the value is configurable on Linux. I've attached a file that should reproduce the error. A possible fix would be calling socket.setsockopt(socket.IPPROTO_IPV6, If you require any more information, feel free to contact me! |
See also bpo-35934. |
I'm not sure I understand the issue, but setting IPV6_V6ONLY to 0 by default is not an option because asyncio wants to serve IPv4 and IPv6 with 2 distinct sockets on purpose. The reason for that is because when an IPv4 connection occurs we want getpeername/getsockname to return '127.0.0.1' instead of '::ffff:127.0.0.1'. Also, IPV6_V6ONLY = 1 is set by default on all platforms. It is not set on Windows because IPPROTO_IPV6 constant is missing due to bpo-29515, but that doesn't matter because IPV6_V6ONLY = 1 is already the default on Windows. As for Linux, /proc/sys/net/ipv6/bindv6only shouldn't matter because setting the option in Python is supposed to overwrite what /proc/sys/net/ipv6/bindv6only dictates. With that said, what's your use case exactly? Why does your test script uses AF_INET6 and an IPv4 address? |
The intention for V4MAPPED is to allow "single-stack" usage of V4 and V6 addresses (or am I misunderstanding the purpose of the V4MAPPED socket option here?). The application only handles V6 addresses, and the system transparently converts from mapped addresses to "proper" IPv4 addresses. Unfortunately, when V6ONLY is set on a socket, this does not work.
If IPV6_V6ONLY is always set, the V4MAPPED socket option is nonsensical, as the socket can't send IPv4 packages. This is what the test_bad script is trying to simulate (badly☺): The lookup for neverssl.com returns only an IPv4 address (since the running system doesn't have IPv6 connectivity). If V6ONLY was 0, this would work, and we would get a mapped V4 address (something like '::ffff:52.222.163.80'). With V6ONLY=1, we cannot connect to this mapped address. A better test script would have this main method (I've attached the new version as well): async def main():
on_con_lost = asyncio.Future()
transport, protocol = await asyncio.get_event_loop().create_connection(
lambda: TestProtocol(on_con_lost),
family=socket.AF_INET6,
flags=socket.AI_V4MAPPED,
host='neverssl.com',
port=80)
On my system, the lookup returns a V4 address. Since I've enabled AI_V4MAPPED, I get a mapped V6 address that I would be able to connect to if V6ONLY is disabled. However, with V6ONLY enabled, the address is not connectable. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: