Skip to content

CLI: UDP port forwarding does not work with IPv6 #14529

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

Closed
RobinKa opened this issue Sep 2, 2024 · 3 comments
Closed

CLI: UDP port forwarding does not work with IPv6 #14529

RobinKa opened this issue Sep 2, 2024 · 3 comments
Assignees
Labels
customer-reported Bugs reported by enterprise customers. Only humans may set this. networking Area: networking

Comments

@RobinKa
Copy link

RobinKa commented Sep 2, 2024

UDP port forwarding doesn't seem to work with IPv6. I verified it does work with IPv4.

Reproduction steps (e.g. with https://gist.github.com/tuxmartin/e64d2132061ffef7e031 and modified to work with Python3 by changing the prints and MESSAGE to have b prefix)

  1. UDP port forward with coder cli: coder port-forward <workspace> --udp 5005
  2. Run server inside the coder workspace
  3. Run client locally with AF_INET6 and UDP_IP=::1 or localhost: doesn't work (with Wireshark I can see it's using IPv6)
  4. Run client locally with AF_INET and UDP_IP=127.0.0.1 or localhost: works (with Wireshark I can see it's using IPv4)
@coder-labeler coder-labeler bot added bug networking Area: networking labels Sep 2, 2024
@matifali matifali added the customer-reported Bugs reported by enterprise customers. Only humans may set this. label Sep 2, 2024
@deansheather
Copy link
Member

This is intentionally not supported for UDP due to technical reasons. For TCP this is supported as the process is straightforward: we dial 127.0.0.1 in the agent, and if that fails, we try ::1 for the same port.

However, for UDP, there is no concept of a connection, so we cannot determine whether the IPv4 attempt failed. When implementing the TCP fallback, I considered several potential solutions for UDP but decided against all of them:

  1. Send the packet to both IPv4 and IPv6: This would cause servers that listen on all interfaces on the same port to receive the same packet twice from two different sockets, which is unexpected.
  2. Allow specifying ::1 or an --ipv6 flag in the coder port-forward command: Since the protocol is IP encapsulated in WireGuard, there's no way to attach this information to the packet; the IP address in the IP header will always be the agent's IPv6 address in the tailnet.
  3. Configure UDP loopback at the agent level via an environment variable, like CODER_AGENT_UDP_LOOPBACK: This approach restricts the loopback to either IPv4 or IPv6, but not both. Given that this would require specific configuration anyway, users could simply change their apps to listen on IPv4.
  4. Scan the system for listening ports to determine which address to use whenever a UDP packet is received: This solution is janky and not cross-platform.

Instead, I recommend changing your app to listen on the IPv4 loopback or using a UDP proxy, such as socat, to forward packets from the IPv4 loopback to the IPv6 loopback for the required ports. Is there anything preventing you from doing either of these things?

@spikecurtis
Copy link
Contributor

spikecurtis commented Nov 18, 2024

@RobinKa when port forwarding, there are two different listeners. There is a local listener, opened as part of the coder port-forward process, and then there is the remote listener, which belongs to the service you are forwarding packets to.

As @deansheather mentioned, our Agent, running in the remote workspace, only forwards UDP packets to IPv4 on the local loopback. There isn't much we can really do without a bunch of extra config. So, we don't plan on changing that behavior in the near term at least. Hopefully you can configure the remote listening app to listen on IPv4.

For the local listener, coder port-forward listens on 127.0.0.1:5005 if use use --udp 5005, that is, IPv4 only. I've noticed that we don't support setting IPv6 addresses explicitly, e.g. --udp [::1]:5005:5005 fails. I've raised #15561 to track. As a workaround, to get an IPv6 local listener, you could listen on --udp 0.0.0.0:5005:5005, which listens on all interfaces and both IPv4 and IPv6.

@spikecurtis
Copy link
Contributor

I'm going to close out this issue as we have merged fixes for IPv6 listening on the local side. On the workspace side, we recommend socat if your application cannot listen on IPv4 for some reason.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
customer-reported Bugs reported by enterprise customers. Only humans may set this. networking Area: networking
Projects
None yet
Development

No branches or pull requests

4 participants