(wr http.ResponseWriter, req *http.Request, username string)
| 79 | } |
| 80 | |
| 81 | func (s *ProxyHandler) HandleTunnel(wr http.ResponseWriter, req *http.Request, username string) { |
| 82 | conn, err := s.dialer.DialContext(req.Context(), "tcp", req.RequestURI) |
| 83 | if err != nil { |
| 84 | var accessErr derrors.ErrAccessDenied |
| 85 | if errors.As(err, &accessErr) { |
| 86 | s.logger.Warning("Access denied: %v", err) |
| 87 | s.rejectAccess(wr, req) |
| 88 | return |
| 89 | } |
| 90 | s.logger.Error("Can't satisfy CONNECT request: %v", err) |
| 91 | http.Error(wr, "Can't satisfy CONNECT request", http.StatusBadGateway) |
| 92 | return |
| 93 | } |
| 94 | |
| 95 | localAddr := conn.LocalAddr().String() |
| 96 | s.outboundMux.Lock() |
| 97 | s.outbound[localAddr] = req.RemoteAddr |
| 98 | s.outboundMux.Unlock() |
| 99 | defer func() { |
| 100 | conn.Close() |
| 101 | s.outboundMux.Lock() |
| 102 | delete(s.outbound, localAddr) |
| 103 | s.outboundMux.Unlock() |
| 104 | }() |
| 105 | |
| 106 | if req.ProtoMajor == 0 || req.ProtoMajor == 1 { |
| 107 | // Upgrade client connection |
| 108 | localconn, rw, err := hijack(wr) |
| 109 | if err != nil { |
| 110 | s.logger.Error("Can't hijack client connection: %v", err) |
| 111 | http.Error(wr, "Can't hijack client connection", http.StatusInternalServerError) |
| 112 | return |
| 113 | } |
| 114 | defer localconn.Close() |
| 115 | |
| 116 | if buffered := rw.Reader.Buffered(); buffered > 0 { |
| 117 | s.logger.Debug("saving %d bytes buffered in bufio.ReadWriter", buffered) |
| 118 | s.forward( |
| 119 | req.Context(), |
| 120 | username, |
| 121 | wrapH1ReqBody(io.NopCloser(io.LimitReader(rw.Reader, int64(buffered)))), |
| 122 | wrapH1RespWriter(conn), |
| 123 | "tcp", |
| 124 | req.RequestURI, |
| 125 | ) |
| 126 | s.forward( |
| 127 | req.Context(), |
| 128 | username, |
| 129 | wrapPendingWrite( |
| 130 | fmt.Appendf(nil, "HTTP/%d.%d 200 OK\r\n\r\n", req.ProtoMajor, req.ProtoMinor), |
| 131 | localconn, |
| 132 | ), |
| 133 | conn, |
| 134 | "tcp", |
| 135 | req.RequestURI, |
| 136 | ) |
| 137 | } else { |
| 138 | s.logger.Debug("not rescuing remaining data in bufio.ReadWriter") |
no test coverage detected