@@ -11,8 +11,10 @@ import (
1111 "testing"
1212 "time"
1313
14+ "github.com/hashicorp/go-sockaddr"
1415 "github.com/hashicorp/vault/internalshared/configutil"
1516 "github.com/mitchellh/cli"
17+ "github.com/pires/go-proxyproto"
1618)
1719
1820func TestTCPListener (t * testing.T ) {
@@ -28,7 +30,7 @@ func TestTCPListener(t *testing.T) {
2830 return net .Dial ("tcp" , ln .Addr ().String ())
2931 }
3032
31- testListenerImpl (t , ln , connFn , "" , 0 )
33+ testListenerImpl (t , ln , connFn , "" , 0 , "127.0.0.1" , false )
3234}
3335
3436// TestTCPListener_tls tests TLS generally
@@ -85,7 +87,7 @@ func TestTCPListener_tls(t *testing.T) {
8587 }
8688 }
8789
88- testListenerImpl (t , ln , connFn (true ), "foo.example.com" , 0 )
90+ testListenerImpl (t , ln , connFn (true ), "foo.example.com" , 0 , "127.0.0.1" , false )
8991
9092 ln , _ , _ , err = tcpListenerFactory (& configutil.Listener {
9193 Address : "127.0.0.1:0" ,
@@ -110,7 +112,7 @@ func TestTCPListener_tls(t *testing.T) {
110112 t .Fatalf ("err: %s" , err )
111113 }
112114
113- testListenerImpl (t , ln , connFn (false ), "foo.example.com" , 0 )
115+ testListenerImpl (t , ln , connFn (false ), "foo.example.com" , 0 , "127.0.0.1" , false )
114116}
115117
116118func TestTCPListener_tls13 (t * testing.T ) {
@@ -167,7 +169,7 @@ func TestTCPListener_tls13(t *testing.T) {
167169 }
168170 }
169171
170- testListenerImpl (t , ln , connFn (true ), "foo.example.com" , tls .VersionTLS13 )
172+ testListenerImpl (t , ln , connFn (true ), "foo.example.com" , tls .VersionTLS13 , "127.0.0.1" , false )
171173
172174 ln , _ , _ , err = tcpListenerFactory (& configutil.Listener {
173175 Address : "127.0.0.1:0" ,
@@ -194,7 +196,7 @@ func TestTCPListener_tls13(t *testing.T) {
194196 t .Fatalf ("err: %s" , err )
195197 }
196198
197- testListenerImpl (t , ln , connFn (false ), "foo.example.com" , tls .VersionTLS13 )
199+ testListenerImpl (t , ln , connFn (false ), "foo.example.com" , tls .VersionTLS13 , "127.0.0.1" , false )
198200
199201 ln , _ , _ , err = tcpListenerFactory (& configutil.Listener {
200202 Address : "127.0.0.1:0" ,
@@ -208,5 +210,254 @@ func TestTCPListener_tls13(t *testing.T) {
208210 t .Fatalf ("err: %s" , err )
209211 }
210212
211- testListenerImpl (t , ln , connFn (false ), "foo.example.com" , tls .VersionTLS12 )
213+ testListenerImpl (t , ln , connFn (false ), "foo.example.com" , tls .VersionTLS12 , "127.0.0.1" , false )
214+ }
215+
216+ func TestTCPListener_proxyProtocol (t * testing.T ) {
217+ for name , tc := range map [string ]struct {
218+ Behavior string
219+ Header * proxyproto.Header
220+ AuthorizedAddr string
221+ ExpectedAddr string
222+ ExpectError bool
223+ }{
224+ "none-no-header" : {
225+ Behavior : "" ,
226+ ExpectedAddr : "127.0.0.1" ,
227+ Header : nil ,
228+ },
229+ "none-v1" : {
230+ Behavior : "" ,
231+ ExpectedAddr : "127.0.0.1" ,
232+ ExpectError : true ,
233+ Header : & proxyproto.Header {
234+ Version : 1 ,
235+ Command : proxyproto .PROXY ,
236+ TransportProtocol : proxyproto .TCPv4 ,
237+ SourceAddr : & net.TCPAddr {
238+ IP : net .ParseIP ("10.1.1.1" ),
239+ Port : 1000 ,
240+ },
241+ DestinationAddr : & net.TCPAddr {
242+ IP : net .ParseIP ("20.2.2.2" ),
243+ Port : 2000 ,
244+ },
245+ },
246+ },
247+ "none-v2" : {
248+ Behavior : "" ,
249+ ExpectedAddr : "127.0.0.1" ,
250+ ExpectError : true ,
251+ Header : & proxyproto.Header {
252+ Version : 2 ,
253+ Command : proxyproto .PROXY ,
254+ TransportProtocol : proxyproto .TCPv4 ,
255+ SourceAddr : & net.TCPAddr {
256+ IP : net .ParseIP ("10.1.1.1" ),
257+ Port : 1000 ,
258+ },
259+ DestinationAddr : & net.TCPAddr {
260+ IP : net .ParseIP ("20.2.2.2" ),
261+ Port : 2000 ,
262+ },
263+ },
264+ },
265+
266+ // use_always makes it possible to send the PROXY header but does not
267+ // require it
268+ "use_always-no-header" : {
269+ Behavior : "use_always" ,
270+ ExpectedAddr : "127.0.0.1" ,
271+ Header : nil ,
272+ },
273+
274+ "use_always-header-v1" : {
275+ Behavior : "use_always" ,
276+ ExpectedAddr : "10.1.1.1" ,
277+ Header : & proxyproto.Header {
278+ Version : 1 ,
279+ Command : proxyproto .PROXY ,
280+ TransportProtocol : proxyproto .TCPv4 ,
281+ SourceAddr : & net.TCPAddr {
282+ IP : net .ParseIP ("10.1.1.1" ),
283+ Port : 1000 ,
284+ },
285+ DestinationAddr : & net.TCPAddr {
286+ IP : net .ParseIP ("20.2.2.2" ),
287+ Port : 2000 ,
288+ },
289+ },
290+ },
291+ "use_always-header-v1-unknown" : {
292+ Behavior : "use_always" ,
293+ ExpectedAddr : "127.0.0.1" ,
294+ Header : & proxyproto.Header {
295+ Version : 1 ,
296+ Command : proxyproto .PROXY ,
297+ TransportProtocol : proxyproto .UNSPEC ,
298+ },
299+ },
300+ "use_always-header-v2" : {
301+ Behavior : "use_always" ,
302+ ExpectedAddr : "10.1.1.1" ,
303+ Header : & proxyproto.Header {
304+ Version : 2 ,
305+ Command : proxyproto .PROXY ,
306+ TransportProtocol : proxyproto .TCPv4 ,
307+ SourceAddr : & net.TCPAddr {
308+ IP : net .ParseIP ("10.1.1.1" ),
309+ Port : 1000 ,
310+ },
311+ DestinationAddr : & net.TCPAddr {
312+ IP : net .ParseIP ("20.2.2.2" ),
313+ Port : 2000 ,
314+ },
315+ },
316+ },
317+ "use_always-header-v2-unknown" : {
318+ Behavior : "use_always" ,
319+ ExpectedAddr : "127.0.0.1" ,
320+ Header : & proxyproto.Header {
321+ Version : 2 ,
322+ Command : proxyproto .LOCAL ,
323+ TransportProtocol : proxyproto .UNSPEC ,
324+ },
325+ },
326+ "allow_authorized-no-header-in" : {
327+ Behavior : "allow_authorized" ,
328+ AuthorizedAddr : "127.0.0.1/32" ,
329+ ExpectedAddr : "127.0.0.1" ,
330+ },
331+ "allow_authorized-no-header-not-in" : {
332+ Behavior : "allow_authorized" ,
333+ AuthorizedAddr : "10.0.0.1/32" ,
334+ ExpectedAddr : "127.0.0.1" ,
335+ },
336+ "allow_authorized-v1-in" : {
337+ Behavior : "allow_authorized" ,
338+ AuthorizedAddr : "127.0.0.1/32" ,
339+ ExpectedAddr : "10.1.1.1" ,
340+ Header : & proxyproto.Header {
341+ Version : 1 ,
342+ Command : proxyproto .PROXY ,
343+ TransportProtocol : proxyproto .TCPv4 ,
344+ SourceAddr : & net.TCPAddr {
345+ IP : net .ParseIP ("10.1.1.1" ),
346+ Port : 1000 ,
347+ },
348+ DestinationAddr : & net.TCPAddr {
349+ IP : net .ParseIP ("20.2.2.2" ),
350+ Port : 2000 ,
351+ },
352+ },
353+ },
354+
355+ // allow_authorized still accepts the PROXY header when not in the
356+ // authorized addresses but discards it silently
357+ "allow_authorized-v1-not-in" : {
358+ Behavior : "allow_authorized" ,
359+ AuthorizedAddr : "10.0.0.1/32" ,
360+ ExpectedAddr : "127.0.0.1" ,
361+ Header : & proxyproto.Header {
362+ Version : 1 ,
363+ Command : proxyproto .PROXY ,
364+ TransportProtocol : proxyproto .TCPv4 ,
365+ SourceAddr : & net.TCPAddr {
366+ IP : net .ParseIP ("10.1.1.1" ),
367+ Port : 1000 ,
368+ },
369+ DestinationAddr : & net.TCPAddr {
370+ IP : net .ParseIP ("20.2.2.2" ),
371+ Port : 2000 ,
372+ },
373+ },
374+ },
375+
376+ "deny_unauthorized-no-header-in" : {
377+ Behavior : "deny_unauthorized" ,
378+ AuthorizedAddr : "127.0.0.1/32" ,
379+ ExpectedAddr : "127.0.0.1" ,
380+ },
381+ "deny_unauthorized-no-header-not-in" : {
382+ Behavior : "deny_unauthorized" ,
383+ AuthorizedAddr : "10.0.0.1/32" ,
384+ ExpectedAddr : "127.0.0.1" ,
385+ ExpectError : true ,
386+ },
387+ "deny_unauthorized-v1-in" : {
388+ Behavior : "deny_unauthorized" ,
389+ AuthorizedAddr : "127.0.0.1/32" ,
390+ ExpectedAddr : "10.1.1.1" ,
391+ Header : & proxyproto.Header {
392+ Version : 1 ,
393+ Command : proxyproto .PROXY ,
394+ TransportProtocol : proxyproto .TCPv4 ,
395+ SourceAddr : & net.TCPAddr {
396+ IP : net .ParseIP ("10.1.1.1" ),
397+ Port : 1000 ,
398+ },
399+ DestinationAddr : & net.TCPAddr {
400+ IP : net .ParseIP ("20.2.2.2" ),
401+ Port : 2000 ,
402+ },
403+ },
404+ },
405+ "deny_unauthorized-v1-not-in" : {
406+ Behavior : "deny_unauthorized" ,
407+ AuthorizedAddr : "10.0.0.1/32" ,
408+ ExpectedAddr : "127.0.0.1" ,
409+ ExpectError : true ,
410+ Header : & proxyproto.Header {
411+ Version : 1 ,
412+ Command : proxyproto .PROXY ,
413+ TransportProtocol : proxyproto .TCPv4 ,
414+ SourceAddr : & net.TCPAddr {
415+ IP : net .ParseIP ("10.1.1.1" ),
416+ Port : 1000 ,
417+ },
418+ DestinationAddr : & net.TCPAddr {
419+ IP : net .ParseIP ("20.2.2.2" ),
420+ Port : 2000 ,
421+ },
422+ },
423+ },
424+ } {
425+ t .Run (name , func (t * testing.T ) {
426+ proxyProtocolAuthorizedAddrs := []* sockaddr.SockAddrMarshaler {}
427+ if tc .AuthorizedAddr != "" {
428+ sockAddr , err := sockaddr .NewSockAddr (tc .AuthorizedAddr )
429+ if err != nil {
430+ t .Fatal (err )
431+ }
432+ proxyProtocolAuthorizedAddrs = append (
433+ proxyProtocolAuthorizedAddrs ,
434+ & sockaddr.SockAddrMarshaler {SockAddr : sockAddr },
435+ )
436+ }
437+
438+ ln , _ , _ , err := tcpListenerFactory (& configutil.Listener {
439+ Address : "127.0.0.1:0" ,
440+ TLSDisable : true ,
441+ ProxyProtocolBehavior : tc .Behavior ,
442+ ProxyProtocolAuthorizedAddrs : proxyProtocolAuthorizedAddrs ,
443+ }, nil , cli .NewMockUi ())
444+ if err != nil {
445+ t .Fatalf ("err: %s" , err )
446+ }
447+
448+ connFn := func (lnReal net.Listener ) (net.Conn , error ) {
449+ conn , err := net .Dial ("tcp" , ln .Addr ().String ())
450+ if err != nil {
451+ return nil , err
452+ }
453+
454+ if tc .Header != nil {
455+ _ , err = tc .Header .WriteTo (conn )
456+ }
457+ return conn , err
458+ }
459+
460+ testListenerImpl (t , ln , connFn , "" , 0 , tc .ExpectedAddr , tc .ExpectError )
461+ })
462+ }
212463}
0 commit comments