h, ok := w.(http.Hijacker) if !ok { http.Error(w, "No hijack", 500) return } clientConn, _, err := h.Hijack() if err != nil { return } defer clientConn.Close()
clientConn.Write([]byte("HTTP/1.1 200 OK\r\n\r\n")) remote proxy for http injector
go func() { io.Copy(destConn, clientConn) }() io.Copy(clientConn, destConn) } h, ok := w
func main() { server := &http.Server{ Addr: ":8080", Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodConnect { handleTunnel(w, r) return } http.Error(w, "Only CONNECT method allowed", http.StatusMethodNotAllowed) }), } log.Fatal(server.ListenAndServe()) } 500) return } clientConn
// Bidirectional copy go func() { io.Copy(destConn, clientConn) }() io.Copy(clientConn, destConn) }
func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // Handle both CONNECT and normal HTTP requests with custom payload if r.Method == http.MethodConnect { handleInjectorTunnel(w, r) return } handleInjectorTunnel(w, r) // also handle GET/POST injector payloads })
type connPool struct { sync.Mutex conns map[string][]net.Conn } func (p *connPool) Get(addr string) net.Conn { p.Lock() defer p.Unlock() if pool, ok := p.conns[addr]; ok && len(pool) > 0 { conn := pool[len(pool)-1] p.conns[addr] = pool[:len(pool)-1] return conn } return nil }