code.gitea.io/gitea@v1.19.3/modules/proxyprotocol/conn.go (about) 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package proxyprotocol 5 6 import ( 7 "bufio" 8 "bytes" 9 "encoding/binary" 10 "io" 11 "net" 12 "strconv" 13 "strings" 14 "sync" 15 "time" 16 17 "code.gitea.io/gitea/modules/log" 18 ) 19 20 var ( 21 // v1Prefix is the string we look for at the start of a connection 22 // to check if this connection is using the proxy protocol 23 v1Prefix = []byte("PROXY ") 24 v1PrefixLen = len(v1Prefix) 25 v2Prefix = []byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A") 26 v2PrefixLen = len(v2Prefix) 27 ) 28 29 // Conn is used to wrap and underlying connection which is speaking the 30 // Proxy Protocol. RemoteAddr() will return the address of the client 31 // instead of the proxy address. 32 type Conn struct { 33 bufReader *bufio.Reader 34 conn net.Conn 35 localAddr net.Addr 36 remoteAddr net.Addr 37 once sync.Once 38 proxyHeaderTimeout time.Duration 39 acceptUnknown bool 40 } 41 42 // NewConn is used to wrap a net.Conn speaking the proxy protocol into 43 // a proxyprotocol.Conn 44 func NewConn(conn net.Conn, timeout time.Duration) *Conn { 45 pConn := &Conn{ 46 bufReader: bufio.NewReader(conn), 47 conn: conn, 48 proxyHeaderTimeout: timeout, 49 } 50 return pConn 51 } 52 53 // Read reads data from the connection. 54 // It will initially read the proxy protocol header. 55 // If there is an error parsing the header, it is returned and the socket is closed. 56 func (p *Conn) Read(b []byte) (int, error) { 57 if err := p.readProxyHeaderOnce(); err != nil { 58 return 0, err 59 } 60 return p.bufReader.Read(b) 61 } 62 63 // ReadFrom reads data from a provided reader and copies it to the connection. 64 func (p *Conn) ReadFrom(r io.Reader) (int64, error) { 65 if err := p.readProxyHeaderOnce(); err != nil { 66 return 0, err 67 } 68 if rf, ok := p.conn.(io.ReaderFrom); ok { 69 return rf.ReadFrom(r) 70 } 71 return io.Copy(p.conn, r) 72 } 73 74 // WriteTo reads data from the connection and writes it to the writer. 75 // It will initially read the proxy protocol header. 76 // If there is an error parsing the header, it is returned and the socket is closed. 77 func (p *Conn) WriteTo(w io.Writer) (int64, error) { 78 if err := p.readProxyHeaderOnce(); err != nil { 79 return 0, err 80 } 81 return p.bufReader.WriteTo(w) 82 } 83 84 // Write writes data to the connection. 85 // Write can be made to time out and return an error after a fixed 86 // time limit; see SetDeadline and SetWriteDeadline. 87 func (p *Conn) Write(b []byte) (int, error) { 88 if err := p.readProxyHeaderOnce(); err != nil { 89 return 0, err 90 } 91 return p.conn.Write(b) 92 } 93 94 // Close closes the connection. 95 // Any blocked Read or Write operations will be unblocked and return errors. 96 func (p *Conn) Close() error { 97 return p.conn.Close() 98 } 99 100 // LocalAddr returns the local network address. 101 func (p *Conn) LocalAddr() net.Addr { 102 _ = p.readProxyHeaderOnce() 103 if p.localAddr != nil { 104 return p.localAddr 105 } 106 return p.conn.LocalAddr() 107 } 108 109 // RemoteAddr returns the address of the client if the proxy 110 // protocol is being used, otherwise just returns the address of 111 // the socket peer. If there is an error parsing the header, the 112 // address of the client is not returned, and the socket is closed. 113 // One implication of this is that the call could block if the 114 // client is slow. Using a Deadline is recommended if this is called 115 // before Read() 116 func (p *Conn) RemoteAddr() net.Addr { 117 _ = p.readProxyHeaderOnce() 118 if p.remoteAddr != nil { 119 return p.remoteAddr 120 } 121 return p.conn.RemoteAddr() 122 } 123 124 // SetDeadline sets the read and write deadlines associated 125 // with the connection. It is equivalent to calling both 126 // SetReadDeadline and SetWriteDeadline. 127 // 128 // A deadline is an absolute time after which I/O operations 129 // fail instead of blocking. The deadline applies to all future 130 // and pending I/O, not just the immediately following call to 131 // Read or Write. After a deadline has been exceeded, the 132 // connection can be refreshed by setting a deadline in the future. 133 // 134 // If the deadline is exceeded a call to Read or Write or to other 135 // I/O methods will return an error that wraps os.ErrDeadlineExceeded. 136 // This can be tested using errors.Is(err, os.ErrDeadlineExceeded). 137 // The error's Timeout method will return true, but note that there 138 // are other possible errors for which the Timeout method will 139 // return true even if the deadline has not been exceeded. 140 // 141 // An idle timeout can be implemented by repeatedly extending 142 // the deadline after successful Read or Write calls. 143 // 144 // A zero value for t means I/O operations will not time out. 145 func (p *Conn) SetDeadline(t time.Time) error { 146 return p.conn.SetDeadline(t) 147 } 148 149 // SetReadDeadline sets the deadline for future Read calls 150 // and any currently-blocked Read call. 151 // A zero value for t means Read will not time out. 152 func (p *Conn) SetReadDeadline(t time.Time) error { 153 return p.conn.SetReadDeadline(t) 154 } 155 156 // SetWriteDeadline sets the deadline for future Write calls 157 // and any currently-blocked Write call. 158 // Even if write times out, it may return n > 0, indicating that 159 // some of the data was successfully written. 160 // A zero value for t means Write will not time out. 161 func (p *Conn) SetWriteDeadline(t time.Time) error { 162 return p.conn.SetWriteDeadline(t) 163 } 164 165 // readProxyHeaderOnce will ensure that the proxy header has been read 166 func (p *Conn) readProxyHeaderOnce() (err error) { 167 p.once.Do(func() { 168 if err = p.readProxyHeader(); err != nil && err != io.EOF { 169 log.Error("Failed to read proxy prefix: %v", err) 170 p.Close() 171 p.bufReader = bufio.NewReader(p.conn) 172 } 173 }) 174 return err 175 } 176 177 func (p *Conn) readProxyHeader() error { 178 if p.proxyHeaderTimeout != 0 { 179 readDeadLine := time.Now().Add(p.proxyHeaderTimeout) 180 _ = p.conn.SetReadDeadline(readDeadLine) 181 defer func() { 182 _ = p.conn.SetReadDeadline(time.Time{}) 183 }() 184 } 185 186 inp, err := p.bufReader.Peek(v1PrefixLen) 187 if err != nil { 188 return err 189 } 190 191 if bytes.Equal(inp, v1Prefix) { 192 return p.readV1ProxyHeader() 193 } 194 195 inp, err = p.bufReader.Peek(v2PrefixLen) 196 if err != nil { 197 return err 198 } 199 if bytes.Equal(inp, v2Prefix) { 200 return p.readV2ProxyHeader() 201 } 202 203 return &ErrBadHeader{inp} 204 } 205 206 func (p *Conn) readV2ProxyHeader() error { 207 // The binary header format starts with a constant 12 bytes block containing the 208 // protocol signature : 209 // 210 // \x0D \x0A \x0D \x0A \x00 \x0D \x0A \x51 \x55 \x49 \x54 \x0A 211 // 212 // Note that this block contains a null byte at the 5th position, so it must not 213 // be handled as a null-terminated string. 214 215 if _, err := p.bufReader.Discard(v2PrefixLen); err != nil { 216 // This shouldn't happen as we have already asserted that there should be enough in the buffer 217 return err 218 } 219 220 // The next byte (the 13th one) is the protocol version and command. 221 version, err := p.bufReader.ReadByte() 222 if err != nil { 223 return err 224 } 225 226 // The 14th byte contains the transport protocol and address family.otocol. 227 familyByte, err := p.bufReader.ReadByte() 228 if err != nil { 229 return err 230 } 231 232 // The 15th and 16th bytes is the address length in bytes in network endian order. 233 var addressLen uint16 234 if err := binary.Read(p.bufReader, binary.BigEndian, &addressLen); err != nil { 235 return err 236 } 237 238 // Now handle the version byte: (14th byte). 239 // The highest four bits contains the version. As of this specification, it must 240 // always be sent as \x2 and the receiver must only accept this value. 241 if version>>4 != 0x2 { 242 return &ErrBadHeader{append(v2Prefix, version, familyByte, uint8(addressLen>>8), uint8(addressLen&0xff))} 243 } 244 245 // The lowest four bits represents the command : 246 switch version & 0xf { 247 case 0x0: 248 // - \x0 : LOCAL : the connection was established on purpose by the proxy 249 // without being relayed. The connection endpoints are the sender and the 250 // receiver. Such connections exist when the proxy sends health-checks to the 251 // server. The receiver must accept this connection as valid and must use the 252 // real connection endpoints and discard the protocol block including the 253 // family which is ignored. 254 255 // We therefore ignore the 14th, 15th and 16th bytes 256 p.remoteAddr = p.conn.LocalAddr() 257 p.localAddr = p.conn.RemoteAddr() 258 return nil 259 case 0x1: 260 // - \x1 : PROXY : the connection was established on behalf of another node, 261 // and reflects the original connection endpoints. The receiver must then use 262 // the information provided in the protocol block to get original the address. 263 default: 264 // - other values are unassigned and must not be emitted by senders. Receivers 265 // must drop connections presenting unexpected values here. 266 return &ErrBadHeader{append(v2Prefix, version, familyByte, uint8(addressLen>>8), uint8(addressLen&0xff))} 267 } 268 269 // Now handle the familyByte byte: (15th byte). 270 // The highest 4 bits contain the address family, the lowest 4 bits contain the protocol 271 272 // The address family maps to the original socket family without necessarily 273 // matching the values internally used by the system. It may be one of : 274 // 275 // - 0x0 : AF_UNSPEC : the connection is forwarded for an unknown, unspecified 276 // or unsupported protocol. The sender should use this family when sending 277 // LOCAL commands or when dealing with unsupported protocol families. The 278 // receiver is free to accept the connection anyway and use the real endpoint 279 // addresses or to reject it. The receiver should ignore address information. 280 // 281 // - 0x1 : AF_INET : the forwarded connection uses the AF_INET address family 282 // (IPv4). The addresses are exactly 4 bytes each in network byte order, 283 // followed by transport protocol information (typically ports). 284 // 285 // - 0x2 : AF_INET6 : the forwarded connection uses the AF_INET6 address family 286 // (IPv6). The addresses are exactly 16 bytes each in network byte order, 287 // followed by transport protocol information (typically ports). 288 // 289 // - 0x3 : AF_UNIX : the forwarded connection uses the AF_UNIX address family 290 // (UNIX). The addresses are exactly 108 bytes each. 291 // 292 // - other values are unspecified and must not be emitted in version 2 of this 293 // protocol and must be rejected as invalid by receivers. 294 295 // The transport protocol is specified in the lowest 4 bits of the 14th byte : 296 // 297 // - 0x0 : UNSPEC : the connection is forwarded for an unknown, unspecified 298 // or unsupported protocol. The sender should use this family when sending 299 // LOCAL commands or when dealing with unsupported protocol families. The 300 // receiver is free to accept the connection anyway and use the real endpoint 301 // addresses or to reject it. The receiver should ignore address information. 302 // 303 // - 0x1 : STREAM : the forwarded connection uses a SOCK_STREAM protocol (eg: 304 // TCP or UNIX_STREAM). When used with AF_INET/AF_INET6 (TCP), the addresses 305 // are followed by the source and destination ports represented on 2 bytes 306 // each in network byte order. 307 // 308 // - 0x2 : DGRAM : the forwarded connection uses a SOCK_DGRAM protocol (eg: 309 // UDP or UNIX_DGRAM). When used with AF_INET/AF_INET6 (UDP), the addresses 310 // are followed by the source and destination ports represented on 2 bytes 311 // each in network byte order. 312 // 313 // - other values are unspecified and must not be emitted in version 2 of this 314 // protocol and must be rejected as invalid by receivers. 315 316 if familyByte>>4 == 0x0 || familyByte&0xf == 0x0 { 317 // - hi 0x0 : AF_UNSPEC : the connection is forwarded for an unknown address type 318 // or 319 // - lo 0x0 : UNSPEC : the connection is forwarded for an unspecified protocol 320 if !p.acceptUnknown { 321 p.conn.Close() 322 return &ErrBadHeader{append(v2Prefix, version, familyByte, uint8(addressLen>>8), uint8(addressLen&0xff))} 323 } 324 p.remoteAddr = p.conn.LocalAddr() 325 p.localAddr = p.conn.RemoteAddr() 326 _, err = p.bufReader.Discard(int(addressLen)) 327 return err 328 } 329 330 // other address or protocol 331 if (familyByte>>4) > 0x3 || (familyByte&0xf) > 0x2 { 332 return &ErrBadHeader{append(v2Prefix, version, familyByte, uint8(addressLen>>8), uint8(addressLen&0xff))} 333 } 334 335 // Handle AF_UNIX addresses 336 if familyByte>>4 == 0x3 { 337 // - \x31 : UNIX stream : the forwarded connection uses SOCK_STREAM over the 338 // AF_UNIX protocol family. Address length is 2*108 = 216 bytes. 339 // - \x32 : UNIX datagram : the forwarded connection uses SOCK_DGRAM over the 340 // AF_UNIX protocol family. Address length is 2*108 = 216 bytes. 341 if addressLen != 216 { 342 return &ErrBadHeader{append(v2Prefix, version, familyByte, uint8(addressLen>>8), uint8(addressLen&0xff))} 343 } 344 remoteName := make([]byte, 108) 345 localName := make([]byte, 108) 346 if _, err := p.bufReader.Read(remoteName); err != nil { 347 return err 348 } 349 if _, err := p.bufReader.Read(localName); err != nil { 350 return err 351 } 352 protocol := "unix" 353 if familyByte&0xf == 2 { 354 protocol = "unixgram" 355 } 356 357 p.remoteAddr = &net.UnixAddr{ 358 Name: string(remoteName), 359 Net: protocol, 360 } 361 p.localAddr = &net.UnixAddr{ 362 Name: string(localName), 363 Net: protocol, 364 } 365 return nil 366 } 367 368 var remoteIP []byte 369 var localIP []byte 370 var remotePort uint16 371 var localPort uint16 372 373 if familyByte>>4 == 0x1 { 374 // AF_INET 375 // - \x11 : TCP over IPv4 : the forwarded connection uses TCP over the AF_INET 376 // protocol family. Address length is 2*4 + 2*2 = 12 bytes. 377 // - \x12 : UDP over IPv4 : the forwarded connection uses UDP over the AF_INET 378 // protocol family. Address length is 2*4 + 2*2 = 12 bytes. 379 if addressLen != 12 { 380 return &ErrBadHeader{append(v2Prefix, version, familyByte, uint8(addressLen>>8), uint8(addressLen&0xff))} 381 } 382 383 remoteIP = make([]byte, 4) 384 localIP = make([]byte, 4) 385 } else { 386 // AF_INET6 387 // - \x21 : TCP over IPv6 : the forwarded connection uses TCP over the AF_INET6 388 // protocol family. Address length is 2*16 + 2*2 = 36 bytes. 389 // - \x22 : UDP over IPv6 : the forwarded connection uses UDP over the AF_INET6 390 // protocol family. Address length is 2*16 + 2*2 = 36 bytes. 391 if addressLen != 36 { 392 return &ErrBadHeader{append(v2Prefix, version, familyByte, uint8(addressLen>>8), uint8(addressLen&0xff))} 393 } 394 395 remoteIP = make([]byte, 16) 396 localIP = make([]byte, 16) 397 } 398 399 if _, err := p.bufReader.Read(remoteIP); err != nil { 400 return err 401 } 402 if _, err := p.bufReader.Read(localIP); err != nil { 403 return err 404 } 405 if err := binary.Read(p.bufReader, binary.BigEndian, &remotePort); err != nil { 406 return err 407 } 408 if err := binary.Read(p.bufReader, binary.BigEndian, &localPort); err != nil { 409 return err 410 } 411 412 if familyByte&0xf == 1 { 413 p.remoteAddr = &net.TCPAddr{ 414 IP: remoteIP, 415 Port: int(remotePort), 416 } 417 p.localAddr = &net.TCPAddr{ 418 IP: localIP, 419 Port: int(localPort), 420 } 421 } else { 422 p.remoteAddr = &net.UDPAddr{ 423 IP: remoteIP, 424 Port: int(remotePort), 425 } 426 p.localAddr = &net.UDPAddr{ 427 IP: localIP, 428 Port: int(localPort), 429 } 430 } 431 return nil 432 } 433 434 func (p *Conn) readV1ProxyHeader() error { 435 // Read until a newline 436 header, err := p.bufReader.ReadString('\n') 437 if err != nil { 438 p.conn.Close() 439 return err 440 } 441 442 if header[len(header)-2] != '\r' { 443 return &ErrBadHeader{[]byte(header)} 444 } 445 446 // Strip the carriage return and new line 447 header = header[:len(header)-2] 448 449 // Split on spaces, should be (PROXY <type> <remote addr> <local addr> <remote port> <local port>) 450 parts := strings.Split(header, " ") 451 if len(parts) < 2 { 452 p.conn.Close() 453 return &ErrBadHeader{[]byte(header)} 454 } 455 456 // Verify the type is known 457 switch parts[1] { 458 case "UNKNOWN": 459 if !p.acceptUnknown || len(parts) != 2 { 460 p.conn.Close() 461 return &ErrBadHeader{[]byte(header)} 462 } 463 p.remoteAddr = p.conn.LocalAddr() 464 p.localAddr = p.conn.RemoteAddr() 465 return nil 466 case "TCP4": 467 case "TCP6": 468 default: 469 p.conn.Close() 470 return &ErrBadAddressType{parts[1]} 471 } 472 473 if len(parts) != 6 { 474 p.conn.Close() 475 return &ErrBadHeader{[]byte(header)} 476 } 477 478 // Parse out the remote address 479 ip := net.ParseIP(parts[2]) 480 if ip == nil { 481 p.conn.Close() 482 return &ErrBadRemote{parts[2], parts[4]} 483 } 484 port, err := strconv.Atoi(parts[4]) 485 if err != nil { 486 p.conn.Close() 487 return &ErrBadRemote{parts[2], parts[4]} 488 } 489 p.remoteAddr = &net.TCPAddr{IP: ip, Port: port} 490 491 // Parse out the destination address 492 ip = net.ParseIP(parts[3]) 493 if ip == nil { 494 p.conn.Close() 495 return &ErrBadLocal{parts[3], parts[5]} 496 } 497 port, err = strconv.Atoi(parts[5]) 498 if err != nil { 499 p.conn.Close() 500 return &ErrBadLocal{parts[3], parts[5]} 501 } 502 p.localAddr = &net.TCPAddr{IP: ip, Port: port} 503 504 return nil 505 }