mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 02:28:09 +00:00 
			
		
		
		
	Add support for PROXY protocol v2 in TCP listener (#13540)
* Add support for PROXY protocol v2 in TCP listener I did not find tests for this so I added one trying to cover different configurations to make sure I did not break something. As far as I know, the behavior should be exactly the same as before except for one thing when proxy_protocol_behavior is set to "deny_unauthorized", unauthorized requests were previously silently reject because of https://github.com/armon/go-proxyproto/blob/7e956b284f0a/protocol.go#L81-L84 but it will now be logged. Also fixes https://github.com/hashicorp/vault/issues/9462 by adding support for `PROXY UNKNOWN` for PROXY protocol v1. Closes https://github.com/hashicorp/vault/issues/3807 * Add changelog
This commit is contained in:
		
							
								
								
									
										4
									
								
								changelog/13540.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								changelog/13540.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | ```release-note:improvement | ||||||
|  | core: Vault now supports the PROXY protocol v2. Support for UNKNOWN connections | ||||||
|  | has also been added to the PROXY protocol v1. | ||||||
|  | ``` | ||||||
| @@ -11,8 +11,10 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/hashicorp/go-sockaddr" | ||||||
| 	"github.com/hashicorp/vault/internalshared/configutil" | 	"github.com/hashicorp/vault/internalshared/configutil" | ||||||
| 	"github.com/mitchellh/cli" | 	"github.com/mitchellh/cli" | ||||||
|  | 	"github.com/pires/go-proxyproto" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func TestTCPListener(t *testing.T) { | func TestTCPListener(t *testing.T) { | ||||||
| @@ -28,7 +30,7 @@ func TestTCPListener(t *testing.T) { | |||||||
| 		return net.Dial("tcp", ln.Addr().String()) | 		return net.Dial("tcp", ln.Addr().String()) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	testListenerImpl(t, ln, connFn, "", 0) | 	testListenerImpl(t, ln, connFn, "", 0, "127.0.0.1", false) | ||||||
| } | } | ||||||
|  |  | ||||||
| // TestTCPListener_tls tests TLS generally | // TestTCPListener_tls tests TLS generally | ||||||
| @@ -85,7 +87,7 @@ func TestTCPListener_tls(t *testing.T) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	testListenerImpl(t, ln, connFn(true), "foo.example.com", 0) | 	testListenerImpl(t, ln, connFn(true), "foo.example.com", 0, "127.0.0.1", false) | ||||||
|  |  | ||||||
| 	ln, _, _, err = tcpListenerFactory(&configutil.Listener{ | 	ln, _, _, err = tcpListenerFactory(&configutil.Listener{ | ||||||
| 		Address:                       "127.0.0.1:0", | 		Address:                       "127.0.0.1:0", | ||||||
| @@ -110,7 +112,7 @@ func TestTCPListener_tls(t *testing.T) { | |||||||
| 		t.Fatalf("err: %s", err) | 		t.Fatalf("err: %s", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	testListenerImpl(t, ln, connFn(false), "foo.example.com", 0) | 	testListenerImpl(t, ln, connFn(false), "foo.example.com", 0, "127.0.0.1", false) | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestTCPListener_tls13(t *testing.T) { | func TestTCPListener_tls13(t *testing.T) { | ||||||
| @@ -167,7 +169,7 @@ func TestTCPListener_tls13(t *testing.T) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	testListenerImpl(t, ln, connFn(true), "foo.example.com", tls.VersionTLS13) | 	testListenerImpl(t, ln, connFn(true), "foo.example.com", tls.VersionTLS13, "127.0.0.1", false) | ||||||
|  |  | ||||||
| 	ln, _, _, err = tcpListenerFactory(&configutil.Listener{ | 	ln, _, _, err = tcpListenerFactory(&configutil.Listener{ | ||||||
| 		Address:                       "127.0.0.1:0", | 		Address:                       "127.0.0.1:0", | ||||||
| @@ -194,7 +196,7 @@ func TestTCPListener_tls13(t *testing.T) { | |||||||
| 		t.Fatalf("err: %s", err) | 		t.Fatalf("err: %s", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	testListenerImpl(t, ln, connFn(false), "foo.example.com", tls.VersionTLS13) | 	testListenerImpl(t, ln, connFn(false), "foo.example.com", tls.VersionTLS13, "127.0.0.1", false) | ||||||
|  |  | ||||||
| 	ln, _, _, err = tcpListenerFactory(&configutil.Listener{ | 	ln, _, _, err = tcpListenerFactory(&configutil.Listener{ | ||||||
| 		Address:               "127.0.0.1:0", | 		Address:               "127.0.0.1:0", | ||||||
| @@ -208,5 +210,254 @@ func TestTCPListener_tls13(t *testing.T) { | |||||||
| 		t.Fatalf("err: %s", err) | 		t.Fatalf("err: %s", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	testListenerImpl(t, ln, connFn(false), "foo.example.com", tls.VersionTLS12) | 	testListenerImpl(t, ln, connFn(false), "foo.example.com", tls.VersionTLS12, "127.0.0.1", false) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestTCPListener_proxyProtocol(t *testing.T) { | ||||||
|  | 	for name, tc := range map[string]struct { | ||||||
|  | 		Behavior       string | ||||||
|  | 		Header         *proxyproto.Header | ||||||
|  | 		AuthorizedAddr string | ||||||
|  | 		ExpectedAddr   string | ||||||
|  | 		ExpectError    bool | ||||||
|  | 	}{ | ||||||
|  | 		"none-no-header": { | ||||||
|  | 			Behavior:     "", | ||||||
|  | 			ExpectedAddr: "127.0.0.1", | ||||||
|  | 			Header:       nil, | ||||||
|  | 		}, | ||||||
|  | 		"none-v1": { | ||||||
|  | 			Behavior:     "", | ||||||
|  | 			ExpectedAddr: "127.0.0.1", | ||||||
|  | 			ExpectError:  true, | ||||||
|  | 			Header: &proxyproto.Header{ | ||||||
|  | 				Version:           1, | ||||||
|  | 				Command:           proxyproto.PROXY, | ||||||
|  | 				TransportProtocol: proxyproto.TCPv4, | ||||||
|  | 				SourceAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("10.1.1.1"), | ||||||
|  | 					Port: 1000, | ||||||
|  | 				}, | ||||||
|  | 				DestinationAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("20.2.2.2"), | ||||||
|  | 					Port: 2000, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		"none-v2": { | ||||||
|  | 			Behavior:     "", | ||||||
|  | 			ExpectedAddr: "127.0.0.1", | ||||||
|  | 			ExpectError:  true, | ||||||
|  | 			Header: &proxyproto.Header{ | ||||||
|  | 				Version:           2, | ||||||
|  | 				Command:           proxyproto.PROXY, | ||||||
|  | 				TransportProtocol: proxyproto.TCPv4, | ||||||
|  | 				SourceAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("10.1.1.1"), | ||||||
|  | 					Port: 1000, | ||||||
|  | 				}, | ||||||
|  | 				DestinationAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("20.2.2.2"), | ||||||
|  | 					Port: 2000, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		// use_always makes it possible to send the PROXY header but does not | ||||||
|  | 		// require it | ||||||
|  | 		"use_always-no-header": { | ||||||
|  | 			Behavior:     "use_always", | ||||||
|  | 			ExpectedAddr: "127.0.0.1", | ||||||
|  | 			Header:       nil, | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		"use_always-header-v1": { | ||||||
|  | 			Behavior:     "use_always", | ||||||
|  | 			ExpectedAddr: "10.1.1.1", | ||||||
|  | 			Header: &proxyproto.Header{ | ||||||
|  | 				Version:           1, | ||||||
|  | 				Command:           proxyproto.PROXY, | ||||||
|  | 				TransportProtocol: proxyproto.TCPv4, | ||||||
|  | 				SourceAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("10.1.1.1"), | ||||||
|  | 					Port: 1000, | ||||||
|  | 				}, | ||||||
|  | 				DestinationAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("20.2.2.2"), | ||||||
|  | 					Port: 2000, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		"use_always-header-v1-unknown": { | ||||||
|  | 			Behavior:     "use_always", | ||||||
|  | 			ExpectedAddr: "127.0.0.1", | ||||||
|  | 			Header: &proxyproto.Header{ | ||||||
|  | 				Version:           1, | ||||||
|  | 				Command:           proxyproto.PROXY, | ||||||
|  | 				TransportProtocol: proxyproto.UNSPEC, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		"use_always-header-v2": { | ||||||
|  | 			Behavior:     "use_always", | ||||||
|  | 			ExpectedAddr: "10.1.1.1", | ||||||
|  | 			Header: &proxyproto.Header{ | ||||||
|  | 				Version:           2, | ||||||
|  | 				Command:           proxyproto.PROXY, | ||||||
|  | 				TransportProtocol: proxyproto.TCPv4, | ||||||
|  | 				SourceAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("10.1.1.1"), | ||||||
|  | 					Port: 1000, | ||||||
|  | 				}, | ||||||
|  | 				DestinationAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("20.2.2.2"), | ||||||
|  | 					Port: 2000, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		"use_always-header-v2-unknown": { | ||||||
|  | 			Behavior:     "use_always", | ||||||
|  | 			ExpectedAddr: "127.0.0.1", | ||||||
|  | 			Header: &proxyproto.Header{ | ||||||
|  | 				Version:           2, | ||||||
|  | 				Command:           proxyproto.LOCAL, | ||||||
|  | 				TransportProtocol: proxyproto.UNSPEC, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		"allow_authorized-no-header-in": { | ||||||
|  | 			Behavior:       "allow_authorized", | ||||||
|  | 			AuthorizedAddr: "127.0.0.1/32", | ||||||
|  | 			ExpectedAddr:   "127.0.0.1", | ||||||
|  | 		}, | ||||||
|  | 		"allow_authorized-no-header-not-in": { | ||||||
|  | 			Behavior:       "allow_authorized", | ||||||
|  | 			AuthorizedAddr: "10.0.0.1/32", | ||||||
|  | 			ExpectedAddr:   "127.0.0.1", | ||||||
|  | 		}, | ||||||
|  | 		"allow_authorized-v1-in": { | ||||||
|  | 			Behavior:       "allow_authorized", | ||||||
|  | 			AuthorizedAddr: "127.0.0.1/32", | ||||||
|  | 			ExpectedAddr:   "10.1.1.1", | ||||||
|  | 			Header: &proxyproto.Header{ | ||||||
|  | 				Version:           1, | ||||||
|  | 				Command:           proxyproto.PROXY, | ||||||
|  | 				TransportProtocol: proxyproto.TCPv4, | ||||||
|  | 				SourceAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("10.1.1.1"), | ||||||
|  | 					Port: 1000, | ||||||
|  | 				}, | ||||||
|  | 				DestinationAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("20.2.2.2"), | ||||||
|  | 					Port: 2000, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		// allow_authorized still accepts the PROXY header when not in the | ||||||
|  | 		// authorized addresses but discards it silently | ||||||
|  | 		"allow_authorized-v1-not-in": { | ||||||
|  | 			Behavior:       "allow_authorized", | ||||||
|  | 			AuthorizedAddr: "10.0.0.1/32", | ||||||
|  | 			ExpectedAddr:   "127.0.0.1", | ||||||
|  | 			Header: &proxyproto.Header{ | ||||||
|  | 				Version:           1, | ||||||
|  | 				Command:           proxyproto.PROXY, | ||||||
|  | 				TransportProtocol: proxyproto.TCPv4, | ||||||
|  | 				SourceAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("10.1.1.1"), | ||||||
|  | 					Port: 1000, | ||||||
|  | 				}, | ||||||
|  | 				DestinationAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("20.2.2.2"), | ||||||
|  | 					Port: 2000, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		"deny_unauthorized-no-header-in": { | ||||||
|  | 			Behavior:       "deny_unauthorized", | ||||||
|  | 			AuthorizedAddr: "127.0.0.1/32", | ||||||
|  | 			ExpectedAddr:   "127.0.0.1", | ||||||
|  | 		}, | ||||||
|  | 		"deny_unauthorized-no-header-not-in": { | ||||||
|  | 			Behavior:       "deny_unauthorized", | ||||||
|  | 			AuthorizedAddr: "10.0.0.1/32", | ||||||
|  | 			ExpectedAddr:   "127.0.0.1", | ||||||
|  | 			ExpectError:    true, | ||||||
|  | 		}, | ||||||
|  | 		"deny_unauthorized-v1-in": { | ||||||
|  | 			Behavior:       "deny_unauthorized", | ||||||
|  | 			AuthorizedAddr: "127.0.0.1/32", | ||||||
|  | 			ExpectedAddr:   "10.1.1.1", | ||||||
|  | 			Header: &proxyproto.Header{ | ||||||
|  | 				Version:           1, | ||||||
|  | 				Command:           proxyproto.PROXY, | ||||||
|  | 				TransportProtocol: proxyproto.TCPv4, | ||||||
|  | 				SourceAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("10.1.1.1"), | ||||||
|  | 					Port: 1000, | ||||||
|  | 				}, | ||||||
|  | 				DestinationAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("20.2.2.2"), | ||||||
|  | 					Port: 2000, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		"deny_unauthorized-v1-not-in": { | ||||||
|  | 			Behavior:       "deny_unauthorized", | ||||||
|  | 			AuthorizedAddr: "10.0.0.1/32", | ||||||
|  | 			ExpectedAddr:   "127.0.0.1", | ||||||
|  | 			ExpectError:    true, | ||||||
|  | 			Header: &proxyproto.Header{ | ||||||
|  | 				Version:           1, | ||||||
|  | 				Command:           proxyproto.PROXY, | ||||||
|  | 				TransportProtocol: proxyproto.TCPv4, | ||||||
|  | 				SourceAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("10.1.1.1"), | ||||||
|  | 					Port: 1000, | ||||||
|  | 				}, | ||||||
|  | 				DestinationAddr: &net.TCPAddr{ | ||||||
|  | 					IP:   net.ParseIP("20.2.2.2"), | ||||||
|  | 					Port: 2000, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} { | ||||||
|  | 		t.Run(name, func(t *testing.T) { | ||||||
|  | 			proxyProtocolAuthorizedAddrs := []*sockaddr.SockAddrMarshaler{} | ||||||
|  | 			if tc.AuthorizedAddr != "" { | ||||||
|  | 				sockAddr, err := sockaddr.NewSockAddr(tc.AuthorizedAddr) | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Fatal(err) | ||||||
|  | 				} | ||||||
|  | 				proxyProtocolAuthorizedAddrs = append( | ||||||
|  | 					proxyProtocolAuthorizedAddrs, | ||||||
|  | 					&sockaddr.SockAddrMarshaler{SockAddr: sockAddr}, | ||||||
|  | 				) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			ln, _, _, err := tcpListenerFactory(&configutil.Listener{ | ||||||
|  | 				Address:                      "127.0.0.1:0", | ||||||
|  | 				TLSDisable:                   true, | ||||||
|  | 				ProxyProtocolBehavior:        tc.Behavior, | ||||||
|  | 				ProxyProtocolAuthorizedAddrs: proxyProtocolAuthorizedAddrs, | ||||||
|  | 			}, nil, cli.NewMockUi()) | ||||||
|  | 			if err != nil { | ||||||
|  | 				t.Fatalf("err: %s", err) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			connFn := func(lnReal net.Listener) (net.Conn, error) { | ||||||
|  | 				conn, err := net.Dial("tcp", ln.Addr().String()) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return nil, err | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if tc.Header != nil { | ||||||
|  | 					_, err = tc.Header.WriteTo(conn) | ||||||
|  | 				} | ||||||
|  | 				return conn, err | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			testListenerImpl(t, ln, connFn, "", 0, tc.ExpectedAddr, tc.ExpectError) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -10,12 +10,15 @@ import ( | |||||||
|  |  | ||||||
| type testListenerConnFn func(net.Listener) (net.Conn, error) | type testListenerConnFn func(net.Listener) (net.Conn, error) | ||||||
|  |  | ||||||
| func testListenerImpl(t *testing.T, ln net.Listener, connFn testListenerConnFn, certName string, expectedVersion uint16) { | func testListenerImpl(t *testing.T, ln net.Listener, connFn testListenerConnFn, certName string, expectedVersion uint16, expectedAddr string, expectError bool) { | ||||||
| 	serverCh := make(chan net.Conn, 1) | 	serverCh := make(chan net.Conn, 1) | ||||||
| 	go func() { | 	go func() { | ||||||
| 		server, err := ln.Accept() | 		server, err := ln.Accept() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
|  | 			if !expectError { | ||||||
| 				t.Errorf("err: %s", err) | 				t.Errorf("err: %s", err) | ||||||
|  | 			} | ||||||
|  | 			close(serverCh) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		if certName != "" { | 		if certName != "" { | ||||||
| @@ -23,6 +26,13 @@ func testListenerImpl(t *testing.T, ln net.Listener, connFn testListenerConnFn, | |||||||
| 			tlsConn.Handshake() | 			tlsConn.Handshake() | ||||||
| 		} | 		} | ||||||
| 		serverCh <- server | 		serverCh <- server | ||||||
|  | 		addr, _, err := net.SplitHostPort(server.RemoteAddr().String()) | ||||||
|  | 		if err != nil { | ||||||
|  | 			t.Error(err) | ||||||
|  | 		} | ||||||
|  | 		if addr != expectedAddr { | ||||||
|  | 			t.Errorf("expected: %s, got: %s", expectedAddr, addr) | ||||||
|  | 		} | ||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
| 	client, err := connFn(ln) | 	client, err := connFn(ln) | ||||||
| @@ -45,6 +55,15 @@ func testListenerImpl(t *testing.T, ln net.Listener, connFn testListenerConnFn, | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	server := <-serverCh | 	server := <-serverCh | ||||||
|  |  | ||||||
|  | 	if server == nil { | ||||||
|  | 		if !expectError { | ||||||
|  | 			// Something failed already so we abort the test early | ||||||
|  | 			t.Fatal("aborting test because the server did not accept the connection") | ||||||
|  | 		} | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	defer client.Close() | 	defer client.Close() | ||||||
| 	defer server.Close() | 	defer server.Close() | ||||||
|  |  | ||||||
| @@ -62,8 +81,8 @@ func testListenerImpl(t *testing.T, ln net.Listener, connFn testListenerConnFn, | |||||||
| 	client.Close() | 	client.Close() | ||||||
|  |  | ||||||
| 	<-copyCh | 	<-copyCh | ||||||
| 	if buf.String() != "foo" { | 	if (buf.String() != "foo" && !expectError) || (buf.String() == "foo" && expectError) { | ||||||
| 		t.Fatalf("bad: %v", buf.String()) | 		t.Fatalf("bad: %q, expectError: %t", buf.String(), expectError) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							| @@ -27,7 +27,6 @@ require ( | |||||||
| 	github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5 | 	github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5 | ||||||
| 	github.com/apple/foundationdb/bindings/go v0.0.0-20190411004307-cd5c9d91fad2 | 	github.com/apple/foundationdb/bindings/go v0.0.0-20190411004307-cd5c9d91fad2 | ||||||
| 	github.com/armon/go-metrics v0.3.10 | 	github.com/armon/go-metrics v0.3.10 | ||||||
| 	github.com/armon/go-proxyproto v0.0.0-20210323213023-7e956b284f0a |  | ||||||
| 	github.com/armon/go-radix v1.0.0 | 	github.com/armon/go-radix v1.0.0 | ||||||
| 	github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a | 	github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a | ||||||
| 	github.com/aws/aws-sdk-go v1.37.19 | 	github.com/aws/aws-sdk-go v1.37.19 | ||||||
| @@ -151,6 +150,7 @@ require ( | |||||||
| 	github.com/ory/dockertest v3.3.5+incompatible | 	github.com/ory/dockertest v3.3.5+incompatible | ||||||
| 	github.com/ory/dockertest/v3 v3.8.0 | 	github.com/ory/dockertest/v3 v3.8.0 | ||||||
| 	github.com/patrickmn/go-cache v2.1.0+incompatible | 	github.com/patrickmn/go-cache v2.1.0+incompatible | ||||||
|  | 	github.com/pires/go-proxyproto v0.6.1 | ||||||
| 	github.com/pkg/errors v0.9.1 | 	github.com/pkg/errors v0.9.1 | ||||||
| 	github.com/posener/complete v1.2.3 | 	github.com/posener/complete v1.2.3 | ||||||
| 	github.com/pquerna/otp v1.2.1-0.20191009055518-468c2dd2b58d | 	github.com/pquerna/otp v1.2.1-0.20191009055518-468c2dd2b58d | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
								
							| @@ -205,8 +205,6 @@ github.com/armon/go-metrics v0.3.4/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4 | |||||||
| github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= | github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= | ||||||
| github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo= | github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo= | ||||||
| github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= | github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= | ||||||
| github.com/armon/go-proxyproto v0.0.0-20210323213023-7e956b284f0a h1:AP/vsCIvJZ129pdm9Ek7bH7yutN3hByqsMoNrWAxRQc= |  | ||||||
| github.com/armon/go-proxyproto v0.0.0-20210323213023-7e956b284f0a/go.mod h1:QmP9hvJ91BbJmGVGSbutW19IC0Q9phDCLGaomwTJbgU= |  | ||||||
| github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= | ||||||
| github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= | github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= | ||||||
| github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= | github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= | ||||||
| @@ -1350,6 +1348,8 @@ github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9F | |||||||
| github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= | github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= | ||||||
| github.com/pierrec/lz4/v4 v4.1.8 h1:ieHkV+i2BRzngO4Wd/3HGowuZStgq6QkPsD1eolNAO4= | github.com/pierrec/lz4/v4 v4.1.8 h1:ieHkV+i2BRzngO4Wd/3HGowuZStgq6QkPsD1eolNAO4= | ||||||
| github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= | github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= | ||||||
|  | github.com/pires/go-proxyproto v0.6.1 h1:EBupykFmo22SDjv4fQVQd2J9NOoLPmyZA/15ldOGkPw= | ||||||
|  | github.com/pires/go-proxyproto v0.6.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY= | ||||||
| github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= | github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= | ||||||
| github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= | github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= | ||||||
| github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= | github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= | ||||||
|   | |||||||
| @@ -1,14 +1,15 @@ | |||||||
| package proxyutil | package proxyutil | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net" | 	"net" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	proxyproto "github.com/armon/go-proxyproto" |  | ||||||
| 	"github.com/hashicorp/go-secure-stdlib/parseutil" | 	"github.com/hashicorp/go-secure-stdlib/parseutil" | ||||||
| 	sockaddr "github.com/hashicorp/go-sockaddr" | 	sockaddr "github.com/hashicorp/go-sockaddr" | ||||||
|  | 	proxyproto "github.com/pires/go-proxyproto" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // ProxyProtoConfig contains configuration for the PROXY protocol | // ProxyProtoConfig contains configuration for the PROXY protocol | ||||||
| @@ -42,33 +43,33 @@ func WrapInProxyProto(listener net.Listener, config *ProxyProtoConfig) (net.List | |||||||
| 	case "use_always": | 	case "use_always": | ||||||
| 		newLn = &proxyproto.Listener{ | 		newLn = &proxyproto.Listener{ | ||||||
| 			Listener:           listener, | 			Listener:           listener, | ||||||
| 			ProxyHeaderTimeout: 10 * time.Second, | 			ReadHeaderTimeout: 10 * time.Second, | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 	case "allow_authorized", "deny_unauthorized": | 	case "allow_authorized", "deny_unauthorized": | ||||||
| 		newLn = &proxyproto.Listener{ | 		newLn = &proxyproto.Listener{ | ||||||
| 			Listener:           listener, | 			Listener:           listener, | ||||||
| 			ProxyHeaderTimeout: 10 * time.Second, | 			ReadHeaderTimeout: 10 * time.Second, | ||||||
| 			SourceCheck: func(addr net.Addr) (bool, error) { | 			Policy: func(addr net.Addr) (proxyproto.Policy, error) { | ||||||
| 				config.RLock() | 				config.RLock() | ||||||
| 				defer config.RUnlock() | 				defer config.RUnlock() | ||||||
|  |  | ||||||
| 				sa, err := sockaddr.NewSockAddr(addr.String()) | 				sa, err := sockaddr.NewSockAddr(addr.String()) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					return false, fmt.Errorf("error parsing remote address: %w", err) | 					return proxyproto.REJECT, fmt.Errorf("error parsing remote address: %w", err) | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				for _, authorizedAddr := range config.AuthorizedAddrs { | 				for _, authorizedAddr := range config.AuthorizedAddrs { | ||||||
| 					if authorizedAddr.Contains(sa) { | 					if authorizedAddr.Contains(sa) { | ||||||
| 						return true, nil | 						return proxyproto.USE, nil | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				if config.Behavior == "allow_authorized" { | 				if config.Behavior == "allow_authorized" { | ||||||
| 					return false, nil | 					return proxyproto.IGNORE, nil | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				return false, proxyproto.ErrInvalidUpstream | 				return proxyproto.REJECT, errors.New(`upstream connection not trusted proxy_protocol_behavior is "deny_unauthorized"`) | ||||||
| 			}, | 			}, | ||||||
| 		} | 		} | ||||||
| 	default: | 	default: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Rémi Lapeyre
					Rémi Lapeyre