@@ -3,19 +3,25 @@ package proxyproto
33import (
44 "bufio"
55 "bytes"
6+ "io"
7+ "net"
68 "strconv"
79 "strings"
810 "testing"
11+ "time"
912)
1013
1114var (
1215 IPv4AddressesAndPorts = strings .Join ([]string {IP4_ADDR , IP4_ADDR , strconv .Itoa (PORT ), strconv .Itoa (PORT )}, separator )
1316 IPv4AddressesAndInvalidPorts = strings .Join ([]string {IP4_ADDR , IP4_ADDR , strconv .Itoa (INVALID_PORT ), strconv .Itoa (INVALID_PORT )}, separator )
1417 IPv6AddressesAndPorts = strings .Join ([]string {IP6_ADDR , IP6_ADDR , strconv .Itoa (PORT ), strconv .Itoa (PORT )}, separator )
18+ IPv6LongAddressesAndPorts = strings .Join ([]string {IP6_LONG_ADDR , IP6_LONG_ADDR , strconv .Itoa (PORT ), strconv .Itoa (PORT )}, separator )
1519
1620 fixtureTCP4V1 = "PROXY TCP4 " + IPv4AddressesAndPorts + crlf + "GET /"
1721 fixtureTCP6V1 = "PROXY TCP6 " + IPv6AddressesAndPorts + crlf + "GET /"
1822
23+ fixtureTCP6V1Overflow = "PROXY TCP6 " + IPv6LongAddressesAndPorts
24+
1925 fixtureUnknown = "PROXY UNKNOWN" + crlf
2026 fixtureUnknownWithAddresses = "PROXY UNKNOWN " + IPv4AddressesAndInvalidPorts + crlf
2127)
@@ -58,7 +64,7 @@ var invalidParseV1Tests = []struct {
5864 {
5965 desc : "incomplete signature TCP4" ,
6066 reader : newBufioReader ([]byte ("PROXY TCP4 " + IPv4AddressesAndPorts )),
61- expectedError : ErrLineMustEndWithCrlf ,
67+ expectedError : ErrCantReadVersion1Header ,
6268 },
6369 {
6470 desc : "TCP6 with IPv4 addresses" ,
@@ -75,13 +81,18 @@ var invalidParseV1Tests = []struct {
7581 reader : newBufioReader ([]byte ("PROXY TCP4 " + IPv4AddressesAndInvalidPorts + crlf )),
7682 expectedError : ErrInvalidPortNumber ,
7783 },
84+ {
85+ desc : "header too long" ,
86+ reader : newBufioReader ([]byte ("PROXY UNKNOWN " + IPv6LongAddressesAndPorts + " " + crlf )),
87+ expectedError : ErrVersion1HeaderTooLong ,
88+ },
7889}
7990
8091func TestReadV1Invalid (t * testing.T ) {
8192 for _ , tt := range invalidParseV1Tests {
8293 t .Run (tt .desc , func (t * testing.T ) {
8394 if _ , err := Read (tt .reader ); err != tt .expectedError {
84- t .Fatalf ("expected %s, actual %s " , tt .expectedError , err . Error () )
95+ t .Fatalf ("expected %s, actual %v " , tt .expectedError , err )
8596 }
8697 })
8798 }
@@ -175,3 +186,150 @@ func TestWriteV1Valid(t *testing.T) {
175186 })
176187 }
177188}
189+
190+ // Tests for parseVersion1 overflow - issue #69.
191+
192+ type dataSource struct {
193+ NBytes int
194+ NRead int
195+ }
196+
197+ func (ds * dataSource ) Read (b []byte ) (int , error ) {
198+ if ds .NRead >= ds .NBytes {
199+ return 0 , io .EOF
200+ }
201+ avail := ds .NBytes - ds .NRead
202+ if len (b ) < avail {
203+ avail = len (b )
204+ }
205+ for i := 0 ; i < avail ; i ++ {
206+ b [i ] = 0x20
207+ }
208+ ds .NRead += avail
209+ return avail , nil
210+ }
211+
212+ func TestParseVersion1Overflow (t * testing.T ) {
213+ ds := & dataSource {}
214+ reader := bufio .NewReader (ds )
215+ bufSize := reader .Size ()
216+ ds .NBytes = bufSize * 16
217+ parseVersion1 (reader )
218+ if ds .NRead > bufSize {
219+ t .Fatalf ("read: expected max %d bytes, actual %d\n " , bufSize , ds .NRead )
220+ }
221+ }
222+
223+ func listen (t * testing.T ) * Listener {
224+ l , err := net .Listen ("tcp" , "127.0.0.1:0" )
225+ if err != nil {
226+ t .Fatalf ("listen: %v" , err )
227+ }
228+ return & Listener {Listener : l }
229+ }
230+
231+ func client (t * testing.T , addr , header string , length int , terminate bool , wait time.Duration , done chan struct {}) {
232+ c , err := net .Dial ("tcp" , addr )
233+ if err != nil {
234+ t .Fatalf ("dial: %v" , err )
235+ }
236+ defer c .Close ()
237+
238+ if terminate && length < 2 {
239+ length = 2
240+ }
241+
242+ buf := make ([]byte , len (header )+ length )
243+ copy (buf , []byte (header ))
244+ for i := 0 ; i < length - 2 ; i ++ {
245+ buf [i + len (header )] = 0x20
246+ }
247+ if terminate {
248+ copy (buf [len (header )+ length - 2 :], []byte (crlf ))
249+ }
250+
251+ n , err := c .Write (buf )
252+ if err != nil {
253+ t .Fatalf ("write: %v" , err )
254+ }
255+ if n != len (buf ) {
256+ t .Fatalf ("write; short write" )
257+ }
258+
259+ time .Sleep (wait )
260+ close (done )
261+ }
262+
263+ func TestVersion1Overflow (t * testing.T ) {
264+ done := make (chan struct {})
265+
266+ l := listen (t )
267+ go client (t , l .Addr ().String (), fixtureTCP6V1Overflow , 10240 , true , 10 * time .Second , done )
268+
269+ c , err := l .Accept ()
270+ if err != nil {
271+ t .Fatalf ("accept: %v" , err )
272+ }
273+
274+ b := []byte {}
275+ _ , err = c .Read (b )
276+ if err == nil {
277+ t .Fatalf ("net.Conn: no error reported for oversized header" )
278+ }
279+ }
280+
281+ func TestVersion1SlowLoris (t * testing.T ) {
282+ done := make (chan struct {})
283+ timeout := make (chan error )
284+
285+ l := listen (t )
286+ go client (t , l .Addr ().String (), fixtureTCP6V1Overflow , 0 , false , 10 * time .Second , done )
287+
288+ c , err := l .Accept ()
289+ if err != nil {
290+ t .Fatalf ("accept: %v" , err )
291+ }
292+
293+ go func () {
294+ b := []byte {}
295+ _ , err = c .Read (b )
296+ timeout <- err
297+ }()
298+
299+ select {
300+ case <- done :
301+ t .Fatalf ("net.Conn: reader still blocked after 10 seconds" )
302+ case err := <- timeout :
303+ if err == nil {
304+ t .Fatalf ("net.Conn: no error reported for incomplete header" )
305+ }
306+ }
307+ }
308+
309+ func TestVersion1SlowLorisOverflow (t * testing.T ) {
310+ done := make (chan struct {})
311+ timeout := make (chan error )
312+
313+ l := listen (t )
314+ go client (t , l .Addr ().String (), fixtureTCP6V1Overflow , 10240 , false , 10 * time .Second , done )
315+
316+ c , err := l .Accept ()
317+ if err != nil {
318+ t .Fatalf ("accept: %v" , err )
319+ }
320+
321+ go func () {
322+ b := []byte {}
323+ _ , err = c .Read (b )
324+ timeout <- err
325+ }()
326+
327+ select {
328+ case <- done :
329+ t .Fatalf ("net.Conn: reader still blocked after 10 seconds" )
330+ case err := <- timeout :
331+ if err == nil {
332+ t .Fatalf ("net.Conn: no error reported for incomplete and overflowed header" )
333+ }
334+ }
335+ }
0 commit comments