From 8b9ceadcd688f425818d1a99dfb4bde6451cfd87 Mon Sep 17 00:00:00 2001 From: Wendel Hime <6754291+WendelHime@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:25:32 -0300 Subject: [PATCH] adding provider ID to op and verify error before failing the op (#46) * chore: adding provider ID to op and verify error before failing the op * fix: add comment explaining about both err handling approaches --- fronted.go | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/fronted.go b/fronted.go index 9ec9ca9..37299f7 100644 --- a/fronted.go +++ b/fronted.go @@ -14,6 +14,7 @@ import ( "strings" "sync" "sync/atomic" + "syscall" "time" tls "github.com/refraction-networking/utls" @@ -371,10 +372,13 @@ func (f *fronted) doDial(m MasqueradeInterface) (conn net.Conn, retriable bool, defer op.End() op.Set("masquerade_domain", m.getDomain()) op.Set("masquerade_ip", m.getIpAddress()) + op.Set("masquerade_provider", m.getProviderID()) conn, err = m.dial(f.certPool, f.clientHelloID) if err != nil { - op.FailIf(err) + if !isNetworkUnreachable(err) { + op.FailIf(err) + } log.Debugf("Could not dial to %v, %v", m.getIpAddress(), err) // Don't re-add this candidate if it's any certificate error, as that // will just keep failing and will waste connections. We can't access the underlying @@ -386,12 +390,32 @@ func (f *fronted) doDial(m MasqueradeInterface) (conn net.Conn, retriable bool, log.Debugf("Unexpected error dialing, keeping masquerade: %v", err) retriable = true } - } else { - log.Debugf("Got successful connection to: %v", m) + return } + log.Debugf("Got successful connection to: %+v", m) return } +func isNetworkUnreachable(err error) bool { + var opErr *net.OpError + if errors.As(err, &opErr) { + // The following error verifications look for errors that generally happen at Linux/Unix devices + if errors.Is(opErr.Err, syscall.ENETUNREACH) || errors.Is(opErr.Err, syscall.EHOSTUNREACH) { + return true + } + + // The string verification errors use a broader approach with errors from windows and also linux/unix devices + errMsg := opErr.Err.Error() + if strings.Contains(errMsg, "network is unreachable") || + strings.Contains(errMsg, "no route to host") || + strings.Contains(errMsg, "unreachable network") || + strings.Contains(errMsg, "unreachable host") { + return true + } + } + return false +} + func verifyPeerCertificate(rawCerts [][]byte, roots *x509.CertPool, domain string) error { if len(rawCerts) == 0 { return fmt.Errorf("no certificates presented")