Skip to content

Commit 856bb35

Browse files
committed
fix: add DNS fallback using 8.8.8.8 for Android/Termux
Android/Termux /etc/resolv.conf often points to [::1]:53 (localhost) with no DNS server running, causing Go's internal resolver to fail. Added dialWS() which tries system DNS first, then falls back to a custom resolver using 8.8.8.8:53 directly.
1 parent f7c8270 commit 856bb35

1 file changed

Lines changed: 66 additions & 1 deletion

File tree

bridge/main.go

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ package main
22

33
import (
44
"bytes"
5+
"context"
56
"encoding/json"
67
"fmt"
78
"io"
9+
"net"
810
"net/http"
11+
"net/url"
912
"os"
1013
"os/exec"
1114
"os/signal"
@@ -322,9 +325,71 @@ func readCommands(wsc *wsConn, dot string) bool {
322325
}
323326
}
324327

325-
func dialAndRun(wsURL, code, connectURL string, quit <-chan struct{}) (string, bool) {
328+
// dialWS connects to a WebSocket URL, falling back to 8.8.8.8 for DNS
329+
// if the system resolver fails (common on Android/Termux where /etc/resolv.conf
330+
// points to a non-existent localhost DNS server).
331+
func dialWS(wsURL string) (*websocket.Conn, *http.Response, error) {
332+
u, err := url.Parse(wsURL)
333+
if err != nil {
334+
return nil, nil, err
335+
}
336+
326337
dialer := websocket.Dialer{HandshakeTimeout: 15 * time.Second}
327338
conn, resp, err := dialer.Dial(wsURL, http.Header{})
339+
if err == nil {
340+
return conn, resp, nil
341+
}
342+
343+
// Check if it's a DNS error by trying to resolve with a fallback DNS
344+
hostname := u.Hostname()
345+
port := u.Port()
346+
if port == "" {
347+
if u.Scheme == "wss" {
348+
port = "443"
349+
} else {
350+
port = "80"
351+
}
352+
}
353+
354+
// Try to resolve using the system DNS first (may have failed)
355+
ips, lookupErr := net.DefaultResolver.LookupHost(context.Background(), hostname)
356+
if lookupErr != nil {
357+
// System DNS failed — try Google DNS (8.8.8.8) directly
358+
altResolver := &net.Resolver{
359+
PreferGo: true,
360+
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
361+
d := net.Dialer{Timeout: 5 * time.Second}
362+
return d.DialContext(ctx, "udp", "8.8.8.8:53")
363+
},
364+
}
365+
ips, lookupErr = altResolver.LookupHost(context.Background(), hostname)
366+
if lookupErr != nil || len(ips) == 0 {
367+
return conn, resp, fmt.Errorf("%w (DNS: also tried 8.8.8.8: %v)", err, lookupErr)
368+
}
369+
}
370+
371+
// Try each resolved IP with the WebSocket dialer
372+
for _, ip := range ips {
373+
directURL := wsURL
374+
if strings.HasPrefix(wsURL, "ws://") {
375+
directURL = fmt.Sprintf("ws://%s:%s", ip, port)
376+
} else if strings.HasPrefix(wsURL, "wss://") {
377+
directURL = fmt.Sprintf("wss://%s:%s", ip, port)
378+
}
379+
380+
headers := http.Header{}
381+
headers.Set("Host", hostname)
382+
conn, resp, err = dialer.Dial(directURL, headers)
383+
if err == nil {
384+
return conn, resp, nil
385+
}
386+
}
387+
388+
return conn, resp, err
389+
}
390+
391+
func dialAndRun(wsURL, code, connectURL string, quit <-chan struct{}) (string, bool) {
392+
conn, resp, err := dialWS(wsURL)
328393
if err != nil {
329394
if resp != nil {
330395
_, _ = io.Copy(io.Discard, resp.Body)

0 commit comments

Comments
 (0)