// Handles a new http connection from the public internet func httpHandler(tcpConn net.Conn, proto string) { // wrap up the connection for logging conn := conn.NewHttp(tcpConn, "pub") defer conn.Close() defer func() { // recover from failures if r := recover(); r != nil { conn.Warn("httpHandler failed with error %v", r) } }() // Make sure we detect dead connections while we decide how to multiplex conn.SetDeadline(time.Now().Add(connReadTimeout)) // read out the http request req, err := conn.ReadRequest() if err != nil { conn.Warn("Failed to read valid %s request: %v", proto, err) conn.Write([]byte(BadRequest)) return } // read out the Host header from the request host := strings.ToLower(req.Host) conn.Debug("Found hostname %s in request", host) // multiplex to find the right backend host tunnel := tunnelRegistry.Get(fmt.Sprintf("%s://%s", proto, host)) if tunnel == nil { conn.Info("No tunnel found for hostname %s", host) conn.Write([]byte(fmt.Sprintf(NotFound, len(host)+18, host))) return } // If the client specified http auth and it doesn't match this request's auth // then fail the request with 401 Not Authorized and request the client reissue the // request with basic authdeny the request if tunnel.req.HttpAuth != "" && req.Header.Get("Authorization") != tunnel.req.HttpAuth { conn.Info("Authentication failed: %s", req.Header.Get("Authorization")) conn.Write([]byte(NotAuthorized)) return } // dead connections will now be handled by tunnel heartbeating and the client conn.SetDeadline(time.Time{}) // let the tunnel handle the connection now tunnel.HandlePublicConnection(conn) }
/** * Handles a new http connection from the public internet */ func httpHandler(tcpConn net.Conn) { // wrap up the connection for logging conn := conn.NewHttp(tcpConn, "pub") defer conn.Close() defer func() { // recover from failures if r := recover(); r != nil { conn.Warn("httpHandler failed with error %v", r) } }() // read out the http request req, err := conn.ReadRequest() if err != nil { conn.Warn("Failed to read valid http request: %v", err) conn.Write([]byte(BadRequest)) return } // read out the Host header from the request host := strings.ToLower(req.Host) conn.Debug("Found hostname %s in request", host) // multiplex to find the right backend host tunnel := tunnels.Get("http://" + host) if tunnel == nil { conn.Info("No tunnel found for hostname %s", host) conn.Write([]byte(fmt.Sprintf(NotFound, len(host)+18, host))) return } // If the client specified http auth and it doesn't match this request's auth // then fail the request with 401 Not Authorized and request the client reissue the // request with basic authdeny the request if tunnel.regMsg.HttpAuth != "" && req.Header.Get("Authorization") != tunnel.regMsg.HttpAuth { conn.Info("Authentication failed: %s", req.Header.Get("Authorization")) conn.Write([]byte(NotAuthorized)) return } tunnel.HandlePublicConnection(conn) }
/** * Handles a new http connection from the public internet */ func httpHandler(tcpConn net.Conn) { // wrap up the connection for logging conn := conn.NewHttp(tcpConn, "pub") defer conn.Close() defer func() { // recover from failures if r := recover(); r != nil { conn.Warn("httpHandler failed with error %v", r) } }() // read out the http request req, err := conn.ReadRequest() if err != nil { conn.Warn("Failed to read valid http request: %v", err) conn.Write([]byte(BadRequest)) return } // multiplex to find the right backend host conn.Debug("Found hostname %s in request", req.Host) tunnel := tunnels.Get("http://" + req.Host) if tunnel == nil { conn.Info("No tunnel found for hostname %s", req.Host) conn.Write([]byte(fmt.Sprintf(NotFound, len(req.Host)+18, req.Host))) return } // satisfy auth, if necessary conn.Debug("From client: %s", req.Header.Get("Authorization")) conn.Debug("To match: %s", tunnel.regMsg.HttpAuth) if req.Header.Get("Authorization") != tunnel.regMsg.HttpAuth { conn.Info("Authentication failed") conn.Write([]byte(NotAuthorized)) return } tunnel.HandlePublicConnection(conn) }
/** * Listens for new proxy connections from tunnel clients */ func proxyListener(addr *net.TCPAddr, domain string) { listener, err := conn.Listen(addr, "pxy", tls.Config) if err != nil { panic(err) } // set global proxy addr variable proxyAddr = fmt.Sprintf("%s:%d", domain, listener.Port) log.Info("Listening for proxy connection on %d", listener.Port) for proxyConn := range listener.Conns { go func(conn conn.Conn) { // fail gracefully if the proxy connection dies defer func() { if r := recover(); r != nil { conn.Warn("Failed with error: %v", r) conn.Close() } }() // read the proxy register message var regPxy msg.RegProxyMsg if err = msg.ReadMsgInto(conn, ®Pxy); err != nil { panic(err) } // look up the tunnel for this proxy conn.Info("Registering new proxy for %s", regPxy.Url) tunnel := tunnels.Get(regPxy.Url) if tunnel == nil { panic("No tunnel found for: " + regPxy.Url) } // register the proxy connection with the tunnel tunnel.RegisterProxy(conn) }(proxyConn) } }