fosrl / fosrl/pangolin

Cannot connect when on an IPv6 ISP (mobile)

Open
#3,471 21 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
22.8k
Forks
783
Avg merge
1d 11h
Merged PRs (30d)
47

Description

### Describe the Bug

Hi!
I've been having an issue for a month or two (unfortunately I don't have a specific date it stopped working), I can't connect the Android client to my pangolin (self-hosted). From the debugging I've done, it seems that the client doesn't like when there is an IPv6 DNS server involved, it doesn't do the DNS resolution when trying to start the wireguard tunnel.

Here are some of the relevant debug lines of the Android client:
`
2026-07-20 18:00:04.743 [INFO] PangolinGo: Initializing with config
2026-07-20 18:00:04.744 [DEBUG] PangolinGo: Init config: {EnableAPI:true SocketPath:/data/user/0/net.pangolin.Pangolin/files/pangolin.sock LogLevel:debug Version:0.4.0 Agent:Pangolin Android LogFilePath:/data/user/0/net.pangolin.Pangolin/files/pangolin.log}
2026-07-20 18:00:04.745 [INFO] PangolinGo: File logging initialized: /data/user/0/net.pangolin.Pangolin/files/pangolin.log
2026-07-20 18:00:04.745 [DEBUG] PangolinGo: Checking permissions for native interface
2026-07-20 18:00:04.745 [INFO] PangolinGo: Init completed successfully
2026-07-20 18:00:04.746 [INFO] PangolinGo: Setting power mode to: normal
2026-07-20 18:00:04.746 [INFO] PangolinGo: Wake-up requested, starting 0s debounce timer
2026-07-20 18:00:04.746 [INFO] PangolinGo: Power mode set to: normal
2026-07-20 18:00:04.746 [INFO] PangolinGo: Debounce complete, switching to normal power mode
2026-07-20 18:00:04.746 [INFO] PangolinGo: Reconnecting websocket for normal power mode
2026-07-20 18:00:04.746 [INFO] PangolinGo: Switched to normal power mode
2026-07-20 18:00:04.747 [INFO] PangolinGo: SetSystemDNS called with: [[2605:b100:480:9::1]:53 [2605:b100:c80:9::1]:53]
2026-07-20 18:00:04.747 [DEBUG] PangolinGo: dnsMonitor not yet started, queued SetSystemDNS value
2026-07-20 18:00:04.749 [INFO] PangolinGo: SetSystemDNS called with: [[2605:b100:480:9::1]:53 [2605:b100:c80:9::1]:53]
2026-07-20 18:00:04.749 [DEBUG] PangolinGo: dnsMonitor not yet started, queued SetSystemDNS value
2026-07-20 18:00:04.755 [DEBUG] PangolinGo: Starting tunnel
2026-07-20 18:00:04.755 [DEBUG] PangolinGo: Tunnel config: {Endpoint:https://edgemgmt. ID: Secret: UserToken: MTU:1280 DNS: UpstreamDNS:[1.1.1.1:53] PublicDNS:[] InterfaceName: MatchDomains:[] Holepunch:true TlsClientCert: PingIntervalDuration:10s PingTimeoutDuration:30s OrgID: FileDescriptorTun:179 FileDescriptorUAPI:0 EnableUAPI:false OverrideDNS:true TunnelDNS:false InitialFingerprint:map[arch:aarch64 deviceModel:Pixel 6 hostname: kernelVersion: osVersion:17 platform:android platformFingerprint: serialNumber: username:] InitialPostures:map[autoUpdatesEnabled:false biometricsEnabled:true diskEncrypted:true firewallEnabled:false tpmAvailable:true] DisableRelay:false PreferLocalRoutes:false}
2026-07-20 18:00:04.756 [DEBUG] PangolinGo: Created Unix socket at /data/user/0/net.pangolin.Pangolin/files/pangolin.sock
2026-07-20 18:00:04.756 [INFO] PangolinGo: Starting HTTP server on socket /data/user/0/net.pangolin.Pangolin/files/pangolin.sock
2026-07-20 18:00:04.756 [INFO] PangolinGo: Starting OLM tunnel...
2026-07-20 18:00:04.756 [DEBUG] PangolinGo: Start tunnel completed successfully
2026-07-20 18:00:04.757 [DEBUG] PangolinGo: Starting tunnel with config: {Endpoint:https://edgemgmt. ID: Secret: UserToken: MTU:1280 DNS: UpstreamDNS:[1.1.1.1:53] PublicDNS:[] InterfaceName: MatchDomains:[] Holepunch:true TlsClientCert: PingIntervalDuration:10s PingTimeoutDuration:30s OrgID: FileDescriptorTun:179 FileDescriptorUAPI:0 EnableUAPI:false OverrideDNS:true TunnelDNS:false InitialFingerprint:map[arch:aarch64 deviceModel:Pixel 6 hostname: kernelVersion: osVersion:17 platform:android platformFingerprint: serialNumber: username:] InitialPostures:map[autoUpdatesEnabled:false biometricsEnabled:true diskEncrypted:true firewallEnabled:false tpmAvailable:true] DisableRelay:false PreferLocalRoutes:false}
2026-07-20 18:00:04.757 [INFO] PangolinGo: UpstreamDNS is statically configured ([1.1.1.1:53]); automatic system DNS detection will only update PublicDNS, DNS forwarding will keep using the configured value even if it becomes unreachable on a new network
2026-07-20 18:00:04.757 [DEBUG] PangolinGo: System DNS candidates changed, health-checking: [[2605:b100:480:9::1]:53 [2605:b100:c80:9::1]:53]
2026-07-20 18:00:04.762 [INFO] PangolinGo: Received metadata change request via API: {map[arch:aarch64 deviceModel:Pixel 6 hostname: kernelVersion: osVersion:17 platform:android platformFingerprint: serialNumber: username:] map[autoUpdatesEnabled:false biometricsEnabled:true diskEncrypted:true firewallEnabled:false tpmAvailable:true]}
2026-07-20 18:00:04.762 [INFO] PangolinGo: Received change metadata request via API
2026-07-20 18:00:04.786 [INFO] PangolinGo: System DNS changed: [[2605:b100:480:9::1]:53 [2605:b100:c80:9::1]:53]
2026-07-20 18:00:04.786 [INFO] PangolinGo: Applying system DNS: [[2605:b100:480:9::1]:53 [2605:b100:c80:9::1]:53]
2026-07-20 18:00:04.786 [DEBUG] PangolinGo: Not updating UpstreamDNS: statically configured to [1.1.1.1:53]
2026-07-20 18:00:04.787 [INFO] PangolinGo: Created shared UDP socket on port 50240 (refcount: 2)
2026-07-20 18:00:04.788 [DEBUG] PangolinGo: websocket: Requesting token from https://edgemgmt./api/v1/auth/olm/get-token with body: {"olmId":"","orgId":"","secret":"","userToken":""}
2026-07-20 18:00:04.976 [DEBUG] PangolinGo: websocket: Received token:
2026-07-20 18:00:04.976 [DEBUG] PangolinGo: Got exit nodes for hole punching: [{edgemgmt. 21820 [6]}]
2026-07-20 18:00:04.976 [DEBUG] PangolinGo: Updated hole punch exit nodes: [{edgemgmt. 21820 [6]}]
2026-07-20 18:00:04.976 [INFO] PangolinGo: Starting hole punch for 1 exit nodes
2026-07-20 18:00:04.976 [DEBUG] PangolinGo: Starting UDP hole punch to 1 exit nodes with shared bind
2026-07-20 18:00:04.979 [WARN] PangolinGo: Failed to resolve endpoint edgemgmt.: DNS lookup failed using all upstream servers: lookup edgemgmt. on [::1]:53: dial udp [2605:b100:c80:9::1]:53: connect: no route to host
2026-07-20 18:00:04.979 [INFO] PangolinGo: No exit nodes available yet, waiting for nodes to be added
2026-07-20 18:00:05.135 [INFO] PangolinGo: Websocket Connected
2026-07-20 18:00:05.636 [DEBUG] PangolinGo: Sending registration message to server with public key: and relay: false
2026-07-20 18:00:05.638 [DEBUG] PangolinGo: websocket: Sending message: olm/wg/register, data: map[chainId: fingerprint:map[arch:aarch64 deviceModel:Pixel 6 hostname: kernelVersion: osVersion:17 platform:android platformFingerprint: serialNumber: username:] olmAgent:Pangolin Android olmVersion:0.4.0 orgId: postures:map[autoUpdatesEnabled:false biometricsEnabled:true diskEncrypted:true firewallEnabled:false tpmAvailable:true] publicKey: relay:false userToken:]
... 14 similar logs
2026-07-20 18:00:34.775 [INFO] PangolinGo: Received metadata change request via API: {map[arch:aarch64 deviceModel:Pixel 6 hostname: kernelVersion: osVersion:17 platform:android platformFingerprint: serialNumber: username:] map[autoUpdatesEnabled:false biometricsEnabled:true diskEncrypted:true firewallEnabled:false tpmAvailable:true]}
2026-07-20 18:00:34.775 [INFO] PangolinGo: Received change metadata request via API
2026-07-20 18:00:35.640 [DEBUG] PangolinGo: websocket: Sending message: olm/wg/register, data: map[chainId: fingerprint:map[arch:aarch64 deviceModel:Pixel 6 hostname: kernelVersion: osVersion:17 platform:android platformFingerprint: serialNumber: username:] olmAgent:Pangolin Android olmVersion:0.4.0 orgId: postures:map[autoUpdatesEnabled:false biometricsEnabled:true diskEncrypted:true firewallEnabled:false tpmAvailable:true] publicKey: relay:false userToken:]
2026-07-20 18:00:37.639 [DEBUG] PangolinGo: websocket: Sending message: olm/wg/register, data: map[chainId: fingerprint:map[arch:aarch64 deviceModel:Pixel 6 hostname: kernelVersion: osVersion:17 platform:android platformFingerprint: serialNumber: username:] olmAgent:Pangolin Android olmVersion:0.4.0 orgId: postures:map[autoUpdatesEnabled:false biometricsEnabled:true diskEncrypted:true firewallEnabled:false tpmAvailable:true] publicKey: relay:false userToken:]
2026-07-20 18:00:39.639 [DEBUG] PangolinGo: websocket: Sending message: olm/wg/register, data: map[chainId: fingerprint:map[arch:aarch64 deviceModel:Pixel 6 hostname: kernelVersion: osVersion:17 platform:android platformFingerprint: serialNumber: username:] olmAgent:Pangolin Android olmVersion:0.4.0 orgId: postures:map[autoUpdatesEnabled:false biometricsEnabled:true diskEncrypted:true firewallEnabled:false tpmAvailable:true] publicKey: relay:false userToken:]
2026-07-20 18:00:39.745 [DEBUG] PangolinGo: websocket: setting config version to 0
2026-07-20 18:00:39.745 [DEBUG] PangolinGo: Received olm error message: map[code:HOLEPUNCH_MISSING message:Unable to coordinate client P2P connection. Please ensure your client can reach the server on UDP port 21820 and try registering again.]
2026-07-20 18:00:39.746 [ERROR] PangolinGo: Olm error (code: HOLEPUNCH_MISSING): Unable to coordinate client P2P connection. Please ensure your client can reach the server on UDP port 21820 and try registering again.
2026-07-20 18:00:40.998 [DEBUG] PangolinGo: Stopping tunnel
2026-07-20 18:00:40.998 [INFO] PangolinGo: Stopping tunnel process
2026-07-20 18:00:40.998 [DEBUG] PangolinGo: Cancelling tunnel context
2026-07-20 18:00:40.998 [DEBUG] PangolinGo: Waiting for tunnel goroutine to finish
2026-07-20 18:00:40.998 [INFO] PangolinGo: Tunnel process context cancelled, cleaning up
2026-07-20 18:00:40.999 [DEBUG] PangolinGo: websocket: connection closed during shutdown
2026-07-20 18:00:40.999 [INFO] PangolinGo: OLM tunnel stopped
2026-07-20 18:00:41.000 [DEBUG] PangolinGo: Tunnel goroutine finished
2026-07-20 18:00:41.000 [DEBUG] PangolinGo: Stopping registration interval
2026-07-20 18:00:41.000 [DEBUG] PangolinGo: websocket: Sending message: olm/disconnecting, data: map[]
2026-07-20 18:00:41.000 [INFO] PangolinGo: Hole punch manager stopped
2026-07-20 18:00:41.000 [DEBUG] PangolinGo: Closing unused TUN file descriptor 179
2026-07-20 18:00:41.000 [DEBUG] PangolinGo: Hole punch stopped by signal
2026-07-20 18:00:41.000 [INFO] PangolinGo: UDP hole punch goroutine ended for all exit nodes
2026-07-20 18:00:41.035 [INFO] PangolinGo: Closed unused TUN file descriptor
2026-07-20 18:00:41.035 [DEBUG] PangolinGo: Releasing shared bind (refcount before release: 2)
2026-07-20 18:00:41.035 [INFO] PangolinGo: Released shared UDP bind
2026-07-20 18:00:41.035 [INFO] PangolinGo: Olm service stopped
2026-07-20 18:00:41.035 [INFO] PangolinGo: Cleared all network settings
2026-07-20 18:00:41.035 [INFO] PangolinGo: Tunnel process stopped
2026-07-20 18:00:41.035 [INFO] PangolinGo: Stopping api server
2026-07-20 18:00:41.036 [DEBUG] PangolinGo: Removed Unix socket at /data/user/0/net.pangolin.Pangolin/files/pangolin.sock
2026-07-20 18:00:41.036 [DEBUG] PangolinGo: Tunnel stopped successfully
`

From what I can understand, the agent isn't able to communicate with the upstream DNS server 2605:b100:c80:9::1.

I do not have IPv6 setup on the VPS with Pangolin.

Here is the debugging I've done so far:
* I have configured a static DNS server: fail to connect
* I have tried without a static DNS server: fail to connect
* I have tried on my home network (no IPv6): I can connect
* I have tried on a different endpoint over an IPv4 network (not home): I can connect
* The Pangolin dashboard is still accessible from a browser and from the client, only the wireguard VPN seems to have that issue

Let me know if you need more information.

Thanks a lot for your time!

### Environment

- OS Type & Version: Ubuntu 24.04.4
- Pangolin Version: 1.20.0
- Edition (Community or Enterprise): Enterprise
- Gerbil Version: 1.4.3
- Traefik Version: 3.6.23
- Newt Version: 1.15.0
- Client Version: 0.4.0

### To Reproduce

To reproduce, connect an Android client on an IPv6 network and try to connect the VPN. The wireguard connection fail saying that it can't connect to the port 21820.

On an IPv4-only network, it connects without issues.

### Expected Behavior

The client should connect regardless it is on an IPv4 or IPv6 network to an IPv4-only Pangolin.

Contributor guide

Open the contributing guide

Research direction

Start with the Android client's tunnel startup and DNS resolution path, using the provided logs around system DNS candidates, endpoint resolution, and UDP hole punching. Reproduce on an IPv6 ISP and compare with an IPv4 network; done means the WireGuard tunnel connects successfully when IPv6 DNS is present.

Written by the indexing model from the issue text.

Assessment

Tech stack
android
Domain
mobile-dev, networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.