@@ -2,10 +2,13 @@ package main
22
33import (
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