diff --git a/build.sh b/build.sh index 708e573..22ee733 100755 --- a/build.sh +++ b/build.sh @@ -1,6 +1,6 @@ #!/bin/sh -VERSION=0.5 +VERSION=0.5.1 DIR=$(cd $(dirname $0); pwd) cd $DIR diff --git a/cmd/transproxy/main.go b/cmd/transproxy/main.go index e5054a2..d1197ba 100644 --- a/cmd/transproxy/main.go +++ b/cmd/transproxy/main.go @@ -98,14 +98,29 @@ func main() { // seed the global random number generator, used in secureoperator rand.Seed(time.Now().UTC().UnixNano()) + // setup logger + colog.SetDefaultLevel(colog.LDebug) + colog.SetMinLevel(colog.LInfo) + level, err := colog.ParseLevel(*loglevel) + if err != nil { + log.Fatalf("alert: Invalid log level: %s", err.Error()) + } + colog.SetMinLevel(level) + colog.SetFormatter(&colog.StdFormatter{ + Colors: true, + Flag: log.Ldate | log.Ltime | log.Lmicroseconds, + }) + colog.ParseFields(true) + colog.Register() + if *explicitProxyOnly { - startExplicitProxyOnly() + startExplicitProxyOnly(level) } else { - startAllProxy() + startAllProxy(level) } } -func startExplicitProxyOnly() { +func startExplicitProxyOnly(level colog.Level) { startExplicitProxy() // serve until exit @@ -117,22 +132,7 @@ func startExplicitProxyOnly() { log.Printf("info: go-transproxy exited.") } -func startAllProxy() { - // setup logger - colog.SetDefaultLevel(colog.LDebug) - colog.SetMinLevel(colog.LInfo) - level, err := colog.ParseLevel(*loglevel) - if err != nil { - log.Fatalf("alert: Invalid log level: %s", err.Error()) - } - colog.SetMinLevel(level) - colog.SetFormatter(&colog.StdFormatter{ - Colors: true, - Flag: log.Ldate | log.Ltime | log.Lmicroseconds, - }) - colog.ParseFields(true) - colog.Register() - +func startAllProxy(level colog.Level) { // handling no_proxy environment noProxy := os.Getenv("no_proxy") if noProxy == "" { diff --git a/explicit.go b/explicit.go index 1b0c4ea..9610046 100644 --- a/explicit.go +++ b/explicit.go @@ -9,6 +9,7 @@ import ( "net/url" "os" "strings" + "time" ) type ExplicitProxy struct { @@ -39,11 +40,14 @@ func (s ExplicitProxy) Start() error { if err != nil { return err } - s.user = u.User.Username() if s.UseProxyAuthorization { s.category = "Explicit-Proxy(Auth)" + if u.User == nil { + log.Printf("info: Not Started because of no proxy user category='%s'", s.category) + return nil + } // For HTTPS s.proxyAuthorization = "Basic " + base64.StdEncoding.EncodeToString([]byte(u.User.String())) s.proxyHost = u.Host @@ -104,26 +108,44 @@ func (s ExplicitProxy) accessLog(r *http.Request) { } func (s ExplicitProxy) handleHttps(w http.ResponseWriter, r *http.Request) { - hj, _ := w.(http.Hijacker) - if proxyConn, err := net.Dial("tcp", s.proxyHost); err != nil { - log.Printf("error: %s", err) - } else if clientConn, _, err := hj.Hijack(); err != nil { - proxyConn.Close() - log.Printf("error: %s", err) - } else { - if s.UseProxyAuthorization { - r.Header.Set("Proxy-Authorization", s.proxyAuthorization) - } - r.Write(proxyConn) - go func() { - io.Copy(clientConn, proxyConn) - proxyConn.Close() - }() - go func() { - io.Copy(proxyConn, clientConn) - clientConn.Close() - }() + destConn, err := net.DialTimeout("tcp", s.proxyHost, 10*time.Second) + if err != nil { + log.Printf("error: %s category='%s'", err, s.category) + http.Error(w, err.Error(), http.StatusServiceUnavailable) + return } + + hj, ok := w.(http.Hijacker) + if !ok { + log.Printf("error: Hijacking not supported category='%s'", s.category) + http.Error(w, "Hijacking not supported", http.StatusInternalServerError) + destConn.Close() + return + } + clientConn, _, err := hj.Hijack() + if err != nil { + log.Printf("error: %s category='%s'", err, s.category) + http.Error(w, err.Error(), http.StatusServiceUnavailable) + destConn.Close() + return + } + + if s.UseProxyAuthorization { + r.Header.Set("Proxy-Authorization", s.proxyAuthorization) + } + + r.Write(destConn) + + go transfer(clientConn, destConn) + go transfer(destConn, clientConn) + + log.Printf("debug: End proxy category='%s'", s.category) +} + +func transfer(destination io.WriteCloser, source io.ReadCloser) { + defer destination.Close() + defer source.Close() + io.Copy(destination, source) } func (s ExplicitProxy) handleHttp(w http.ResponseWriter, r *http.Request) {