Skip to content

fix(client): force AF_INET socket when resolvePreference is IPv4 - #1606

Open
HaizakiKu wants to merge 1 commit into
apernet:masterfrom
HaizakiKu:fix/quic-ipv4-only-socket
Open

fix(client): force AF_INET socket when resolvePreference is IPv4#1606
HaizakiKu wants to merge 1 commit into
apernet:masterfrom
HaizakiKu:fix/quic-ipv4-only-socket

Conversation

@HaizakiKu

Copy link
Copy Markdown
Contributor

Fixes #1599.

Problem

On Linux systems with IPv4-only virtual interfaces like ip.gre GRE tunnels,
the Hysteria client fails with:

FATAL failed to initialize client {"error": "connect error: timeout: no recent network activity"}

The root cause: Go's net package defaults to dual-stack AF_INET6 sockets when
the network type is "udp". Linux GRE tunnels are strictly IPv4 structures and
silently drop outbound UDP packets arriving from an AF_INET6 socket, causing the
QUIC handshake to time out.

strace confirms the issue -- even when the server address is a plain IPv4 address,
the outbound QUIC socket was created as AF_INET6 and bound to :::

socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET6, ... inet_pton(AF_INET6, "::", ...) ...}, 28) = 0

Fix

After fillServerAddr resolves the server address, fillConnFactory now inspects
the resolved IP and selects the appropriate UDP network type before opening the
socket:

  • IPv4 server → "udp4"AF_INET socket
  • IPv6 server → "udp6"AF_INET6 socket

This applies to both the regular UDP path and the port-hopping path.

Changes

  • fillConnFactory: pass resolved network type to so.ListenUDPAddrNetwork
    instead of the implicit dual-stack so.ListenUDP
  • add udpNetworkFromAddr helper

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.

client: Connection timeout on Linux IPv4-only GRE tunnels due to AF_INET6 socket usage

1 participant