{"record":{"id":"689cede441e9b955","repo":"snail007/goproxy","slug":"connection-err-s","errorCode":null,"errorMessage":"connection err: %s","messagePattern":"connection err: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"services/tunnel_client.go","lineNumber":83,"sourceCode":"\t\t\t\tlog.Printf(\"read connection signal err: %s\", err)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tlog.Printf(\"signal revecived:%s\", signal)\n\t\t\tif *s.cfg.IsUDP {\n\t\t\t\tgo s.ServeUDP()\n\t\t\t} else {\n\t\t\t\tgo s.ServeConn()\n\t\t\t}\n\t\t}\n\t}\n}\nfunc (s *TunnelClient) Clean() {\n\ts.StopService()\n}\nfunc (s *TunnelClient) GetInConn(typ uint8) (outConn net.Conn, err error) {\n\toutConn, err = s.GetConn()\n\tif err != nil {\n\t\terr = fmt.Errorf(\"connection err: %s\", err)\n\t\treturn\n\t}\n\tkeyBytes := []byte(*s.cfg.Key)\n\tkeyLength := uint16(len(keyBytes))\n\tpkg := new(bytes.Buffer)\n\tbinary.Write(pkg, binary.LittleEndian, typ)\n\tbinary.Write(pkg, binary.LittleEndian, keyLength)\n\tbinary.Write(pkg, binary.LittleEndian, keyBytes)\n\t_, err = outConn.Write(pkg.Bytes())\n\tif err != nil {\n\t\terr = fmt.Errorf(\"write connection data err: %s ,retrying...\", err)\n\t\tutils.CloseConn(&outConn)\n\t\treturn\n\t}\n\treturn\n}\nfunc (s *TunnelClient) GetConn() (conn net.Conn, err error) {\n\tvar _conn tls.Conn","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/snail007/goproxy/blob/e6d6a821db80e7f47ee6e981a144984e1d4ddb3d/services/tunnel_client.go#L65-L101","documentation":"GetInConn obtains an outbound tunnel connection by calling s.GetConn() and wraps any failure as \"connection err: %s\". It means the tunnel client could not establish a connection to the tunnel server (or its parent) before writing the handshake packet.","triggerScenarios":"GetConn fails because the tunnel server is unreachable, refusing connections, TLS handshake fails, or the connection pool is exhausted; GetInConn wraps that underlying error and returns it to callers Start, ServeUDP, or ServeConn.","commonSituations":"Server down or wrong server_ip/server_port in client config; firewall/security group blocking the port; TLS cert mismatch on the tunnel port; server at max connections so the pool cannot hand out a conn.","solutions":["Read the wrapped inner error: fix the root cause (connection refused -> server down/wrong port; timeout -> firewall/routing)","Verify the client's server address/port and key configuration match the running server","Confirm the tunnel server process is up and listening (ss/netstat on the server) and the port is open in firewalls","If pool exhaustion is the cause, increase connection limits or reduce client concurrency"],"exampleFix":"// before (wrong port in client config -> GetConn fails)\n// server_addr=1.2.3.4:9999\n// after\n// server_addr=1.2.3.4:8024","handlingStrategy":"retry","validationCode":"addr := net.JoinHostPort(cfg.ServerIP, cfg.ServerPort)\nif conn, err := net.DialTimeout(\"tcp\", addr, 5*time.Second); err != nil {\n    return fmt.Errorf(\"tunnel server %s unreachable before start: %v\", addr, err)\n} else { conn.Close() }","typeGuard":null,"tryCatchPattern":"conn, err := client.GetInConn(typ)\nif err != nil {\n    if strings.Contains(err.Error(), \"connection err:\") {\n        // inspect wrapped cause; retry with backoff\n        time.Sleep(time.Second)\n        conn, err = client.GetInConn(typ)\n    }\n}","preventionTips":["Pre-flight check server reachability (dial the port) in your startup script","Keep a health check/reconnect loop in long-running clients","Align server_ip/server_port and TLS settings between client and server configs","Open the tunnel port in firewalls/security groups before rollout"],"tags":["network","tunnel","connection","client"],"backgroundTag":"connection-refused","analyzedSha":"e6d6a821db80e7f47ee6e981a144984e1d4ddb3d","analyzedAt":"2026-09-03T15:32:42.750Z","contentChangedAt":"2026-09-03T15:32:42.750Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}