Skip to content

Commit 63f0e4f

Browse files
Buffer only proxy header data
Reverts and re-implements incorrect #116 which passed all connection data through the buffered reader.
1 parent 3b89f41 commit 63f0e4f

File tree

4 files changed

+29
-11
lines changed

4 files changed

+29
-11
lines changed

header.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type Header struct {
4242
SourceAddr net.Addr
4343
DestinationAddr net.Addr
4444
rawTLVs []byte
45+
length int
4546
}
4647

4748
// HeaderProxyFromAddrs creates a new PROXY header from a source and a

protocol.go

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package proxyproto
22

33
import (
44
"bufio"
5+
"bytes"
56
"errors"
67
"fmt"
78
"io"
@@ -51,7 +52,8 @@ type Conn struct {
5152
once sync.Once
5253
readErr error
5354
conn net.Conn
54-
bufReader *bufio.Reader
55+
reader io.Reader
56+
headerBuf *bytes.Buffer
5557
header *Header
5658
ProxyHeaderPolicy Policy
5759
Validate Validator
@@ -150,14 +152,8 @@ func (p *Listener) Addr() net.Addr {
150152
// NewConn is used to wrap a net.Conn that may be speaking
151153
// the proxy protocol into a proxyproto.Conn
152154
func NewConn(conn net.Conn, opts ...func(*Conn)) *Conn {
153-
// For v1 the header length is at most 108 bytes.
154-
// For v2 the header length is at most 52 bytes plus the length of the TLVs.
155-
// We use 256 bytes to be safe.
156-
const bufSize = 256
157-
158155
pConn := &Conn{
159-
bufReader: bufio.NewReaderSize(conn, bufSize),
160-
conn: conn,
156+
conn: conn,
161157
}
162158

163159
for _, opt := range opts {
@@ -178,7 +174,7 @@ func (p *Conn) Read(b []byte) (int, error) {
178174
return 0, p.readErr
179175
}
180176

181-
return p.bufReader.Read(b)
177+
return p.reader.Read(b)
182178
}
183179

184180
// Write wraps original conn.Write
@@ -294,7 +290,22 @@ func (p *Conn) readHeader() error {
294290
}
295291
}
296292

297-
header, err := Read(p.bufReader)
293+
// For v1 the header length is at most 108 bytes.
294+
// For v2 the header length is at most 52 bytes plus the length of the TLVs.
295+
// We use 256 bytes to be safe.
296+
const bufSize = 256
297+
298+
bb := bytes.NewBuffer(make([]byte, 0, bufSize))
299+
tr := io.TeeReader(p.conn, bb)
300+
br := bufio.NewReaderSize(tr, bufSize)
301+
302+
header, err := Read(br)
303+
304+
if err == nil {
305+
io.CopyN(io.Discard, bb, int64(header.length))
306+
}
307+
p.headerBuf = bb
308+
p.reader = io.MultiReader(bb, p.conn)
298309

299310
// If the connection's readHeaderTimeout is more than 0, undo the change to the
300311
// deadline that we made above. Because we retain the readDeadline as part of our
@@ -360,5 +371,9 @@ func (p *Conn) WriteTo(w io.Writer) (int64, error) {
360371
if p.readErr != nil {
361372
return 0, p.readErr
362373
}
363-
return p.bufReader.WriteTo(w)
374+
375+
if n, err := p.headerBuf.WriteTo(w); err != nil {
376+
return n, err
377+
}
378+
return io.Copy(w, p.conn)
364379
}

v1.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ func parseVersion1(reader *bufio.Reader) (*Header, error) {
125125
// Command doesn't exist in v1 but set it for other parts of this library
126126
// to rely on it for determining connection details.
127127
header := initVersion1()
128+
header.length = len(buf)
128129

129130
// Transport protocol has been processed already.
130131
header.TransportProtocol = transportProtocol

v2.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ func parseVersion2(reader *bufio.Reader) (header *Header, err error) {
100100
if !header.validateLength(length) {
101101
return nil, ErrInvalidLength
102102
}
103+
header.length = 16 + int(length)
103104

104105
// Return early if the length is zero, which means that
105106
// there's no address information and TLVs present for UNSPEC.

0 commit comments

Comments
 (0)