github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/transport/internet/headers/http/http.go (about) 1 package http 2 3 //go:generate go run v2ray.com/core/common/errors/errorgen 4 5 import ( 6 "bufio" 7 "bytes" 8 "context" 9 "io" 10 "net" 11 "net/http" 12 "strings" 13 "time" 14 15 "v2ray.com/core/common" 16 "v2ray.com/core/common/buf" 17 ) 18 19 const ( 20 // CRLF is the line ending in HTTP header 21 CRLF = "\r\n" 22 23 // ENDING is the double line ending between HTTP header and body. 24 ENDING = CRLF + CRLF 25 26 // max length of HTTP header. Safety precaution for DDoS attack. 27 maxHeaderLength = 8192 28 ) 29 30 var ( 31 ErrHeaderToLong = newError("Header too long.") 32 33 ErrHeaderMisMatch = newError("Header Mismatch.") 34 ) 35 36 type Reader interface { 37 Read(io.Reader) (*buf.Buffer, error) 38 } 39 40 type Writer interface { 41 Write(io.Writer) error 42 } 43 44 type NoOpReader struct{} 45 46 func (NoOpReader) Read(io.Reader) (*buf.Buffer, error) { 47 return nil, nil 48 } 49 50 type NoOpWriter struct{} 51 52 func (NoOpWriter) Write(io.Writer) error { 53 return nil 54 } 55 56 type HeaderReader struct { 57 req *http.Request 58 expectedHeader *RequestConfig 59 } 60 61 func (h *HeaderReader) ExpectThisRequest(expectedHeader *RequestConfig) *HeaderReader { 62 h.expectedHeader = expectedHeader 63 return h 64 } 65 66 func (h *HeaderReader) Read(reader io.Reader) (*buf.Buffer, error) { 67 buffer := buf.New() 68 totalBytes := int32(0) 69 endingDetected := false 70 71 var headerBuf bytes.Buffer 72 73 for totalBytes < maxHeaderLength { 74 _, err := buffer.ReadFrom(reader) 75 if err != nil { 76 buffer.Release() 77 return nil, err 78 } 79 if n := bytes.Index(buffer.Bytes(), []byte(ENDING)); n != -1 { 80 headerBuf.Write(buffer.BytesRange(0, int32(n+len(ENDING)))) 81 buffer.Advance(int32(n + len(ENDING))) 82 endingDetected = true 83 break 84 } 85 lenEnding := int32(len(ENDING)) 86 if buffer.Len() >= lenEnding { 87 totalBytes += buffer.Len() - lenEnding 88 headerBuf.Write(buffer.BytesRange(0, buffer.Len()-lenEnding)) 89 leftover := buffer.BytesFrom(-lenEnding) 90 buffer.Clear() 91 copy(buffer.Extend(lenEnding), leftover) 92 93 if _, err := readRequest(bufio.NewReader(bytes.NewReader(headerBuf.Bytes())), false); err != io.ErrUnexpectedEOF { 94 return nil, err 95 } 96 } 97 } 98 99 if !endingDetected { 100 buffer.Release() 101 return nil, ErrHeaderToLong 102 } 103 104 if h.expectedHeader == nil { 105 if buffer.IsEmpty() { 106 buffer.Release() 107 return nil, nil 108 } 109 return buffer, nil 110 } 111 112 //Parse the request 113 114 if req, err := readRequest(bufio.NewReader(bytes.NewReader(headerBuf.Bytes())), false); err != nil { 115 return nil, err 116 } else { 117 h.req = req 118 } 119 120 //Check req 121 path := h.req.URL.Path 122 hasThisUri := false 123 for _, u := range h.expectedHeader.Uri { 124 if u == path { 125 hasThisUri = true 126 } 127 } 128 129 if !hasThisUri { 130 return nil, ErrHeaderMisMatch 131 } 132 133 if buffer.IsEmpty() { 134 buffer.Release() 135 return nil, nil 136 } 137 138 return buffer, nil 139 } 140 141 type HeaderWriter struct { 142 header *buf.Buffer 143 } 144 145 func NewHeaderWriter(header *buf.Buffer) *HeaderWriter { 146 return &HeaderWriter{ 147 header: header, 148 } 149 } 150 151 func (w *HeaderWriter) Write(writer io.Writer) error { 152 if w.header == nil { 153 return nil 154 } 155 err := buf.WriteAllBytes(writer, w.header.Bytes()) 156 w.header.Release() 157 w.header = nil 158 return err 159 } 160 161 type HttpConn struct { 162 net.Conn 163 164 readBuffer *buf.Buffer 165 oneTimeReader Reader 166 oneTimeWriter Writer 167 errorWriter Writer 168 errorMismatchWriter Writer 169 errorTooLongWriter Writer 170 171 errReason error 172 } 173 174 func NewHttpConn(conn net.Conn, reader Reader, writer Writer, errorWriter Writer, errorMismatchWriter Writer, errorTooLongWriter Writer) *HttpConn { 175 return &HttpConn{ 176 Conn: conn, 177 oneTimeReader: reader, 178 oneTimeWriter: writer, 179 errorWriter: errorWriter, 180 errorMismatchWriter: errorMismatchWriter, 181 errorTooLongWriter: errorTooLongWriter, 182 } 183 } 184 185 func (c *HttpConn) Read(b []byte) (int, error) { 186 if c.oneTimeReader != nil { 187 buffer, err := c.oneTimeReader.Read(c.Conn) 188 if err != nil { 189 c.errReason = err 190 return 0, err 191 } 192 c.readBuffer = buffer 193 c.oneTimeReader = nil 194 } 195 196 if !c.readBuffer.IsEmpty() { 197 nBytes, _ := c.readBuffer.Read(b) 198 if c.readBuffer.IsEmpty() { 199 c.readBuffer.Release() 200 c.readBuffer = nil 201 } 202 return nBytes, nil 203 } 204 205 return c.Conn.Read(b) 206 } 207 208 // Write implements io.Writer. 209 func (c *HttpConn) Write(b []byte) (int, error) { 210 if c.oneTimeWriter != nil { 211 err := c.oneTimeWriter.Write(c.Conn) 212 c.oneTimeWriter = nil 213 if err != nil { 214 return 0, err 215 } 216 } 217 218 return c.Conn.Write(b) 219 } 220 221 // Close implements net.Conn.Close(). 222 func (c *HttpConn) Close() error { 223 if c.oneTimeWriter != nil && c.errorWriter != nil { 224 // Connection is being closed but header wasn't sent. This means the client request 225 // is probably not valid. Sending back a server error header in this case. 226 227 //Write response based on error reason 228 229 if c.errReason == ErrHeaderMisMatch { 230 c.errorMismatchWriter.Write(c.Conn) 231 } else if c.errReason == ErrHeaderToLong { 232 c.errorTooLongWriter.Write(c.Conn) 233 } else { 234 c.errorWriter.Write(c.Conn) 235 } 236 } 237 238 return c.Conn.Close() 239 } 240 241 func formResponseHeader(config *ResponseConfig) *HeaderWriter { 242 header := buf.New() 243 common.Must2(header.WriteString(strings.Join([]string{config.GetFullVersion(), config.GetStatusValue().Code, config.GetStatusValue().Reason}, " "))) 244 common.Must2(header.WriteString(CRLF)) 245 246 headers := config.PickHeaders() 247 for _, h := range headers { 248 common.Must2(header.WriteString(h)) 249 common.Must2(header.WriteString(CRLF)) 250 } 251 if !config.HasHeader("Date") { 252 common.Must2(header.WriteString("Date: ")) 253 common.Must2(header.WriteString(time.Now().Format(http.TimeFormat))) 254 common.Must2(header.WriteString(CRLF)) 255 } 256 common.Must2(header.WriteString(CRLF)) 257 return &HeaderWriter{ 258 header: header, 259 } 260 } 261 262 type HttpAuthenticator struct { 263 config *Config 264 } 265 266 func (a HttpAuthenticator) GetClientWriter() *HeaderWriter { 267 header := buf.New() 268 config := a.config.Request 269 common.Must2(header.WriteString(strings.Join([]string{config.GetMethodValue(), config.PickUri(), config.GetFullVersion()}, " "))) 270 common.Must2(header.WriteString(CRLF)) 271 272 headers := config.PickHeaders() 273 for _, h := range headers { 274 common.Must2(header.WriteString(h)) 275 common.Must2(header.WriteString(CRLF)) 276 } 277 common.Must2(header.WriteString(CRLF)) 278 return &HeaderWriter{ 279 header: header, 280 } 281 } 282 283 func (a HttpAuthenticator) GetServerWriter() *HeaderWriter { 284 return formResponseHeader(a.config.Response) 285 } 286 287 func (a HttpAuthenticator) Client(conn net.Conn) net.Conn { 288 if a.config.Request == nil && a.config.Response == nil { 289 return conn 290 } 291 var reader Reader = NoOpReader{} 292 if a.config.Request != nil { 293 reader = new(HeaderReader) 294 } 295 296 var writer Writer = NoOpWriter{} 297 if a.config.Response != nil { 298 writer = a.GetClientWriter() 299 } 300 return NewHttpConn(conn, reader, writer, NoOpWriter{}, NoOpWriter{}, NoOpWriter{}) 301 } 302 303 func (a HttpAuthenticator) Server(conn net.Conn) net.Conn { 304 if a.config.Request == nil && a.config.Response == nil { 305 return conn 306 } 307 return NewHttpConn(conn, new(HeaderReader).ExpectThisRequest(a.config.Request), a.GetServerWriter(), 308 formResponseHeader(resp400), 309 formResponseHeader(resp404), 310 formResponseHeader(resp400)) 311 } 312 313 func NewHttpAuthenticator(ctx context.Context, config *Config) (HttpAuthenticator, error) { 314 return HttpAuthenticator{ 315 config: config, 316 }, nil 317 } 318 319 func init() { 320 common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { 321 return NewHttpAuthenticator(ctx, config.(*Config)) 322 })) 323 }