add support for proxy protocol on HTTP listener (#1777)

* add support for proxy protocol on HTTP listener

* rename option, add doc
This commit is contained in:
Caleb Doxsey 2021-01-19 05:56:58 -07:00 committed by GitHub
parent 10912add67
commit 09747aa3ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 75 additions and 12 deletions

View file

@ -262,6 +262,9 @@ type Options struct {
// If unset, the GCP metadata server will be used to query for identity tokens.
GoogleCloudServerlessAuthenticationServiceAccount string `mapstructure:"google_cloud_serverless_authentication_service_account" yaml:"google_cloud_serverless_authentication_service_account,omitempty"` //nolint
// UseProxyProtocol configures the HTTP listener to require the HAProxy proxy protocol (either v1 or v2) on incoming requests.
UseProxyProtocol bool `mapstructure:"require_proxy_protocol" yaml:"require_proxy_protocol,omitempty" json:"require_proxy_protocol,omitempty"`
viper *viper.Viper
AutocertOptions `mapstructure:",squash" yaml:",inline"`

View file

@ -581,6 +581,15 @@ tracing_zipkin_endpoint | Url to the Zipkin HTTP endpoint. | ✅
![jaeger example trace](./img/jaeger.png)
### Use Proxy Protocol
- Environment Variable: `USE_PROXY_PROTOCOL`
- Config File Key: `use_proxy_protocol`
- Type: `bool`
- Optional
Setting `use_proxy_protocol` will configure Pomerium to require the [HAProxy proxy protocol](https://www.haproxy.org/download/1.9/doc/proxy-protocol.txt) on incoming connections. Versions 1 and 2 of the protocol are supported.
## Authenticate Service
### Authenticate Callback Path
@ -1227,7 +1236,7 @@ Remove Request Headers allows you to remove given request headers. This can be u
- Optional
- Example: `{ "host_redirect": "example.com" }`
`Redirect` is used to redirect incoming requests to a new URL. The `redirect` field is an object with several optional,
`Redirect` is used to redirect incoming requests to a new URL. The `redirect` field is an object with several possible
options:
- `https_redirect` (boolean): the incoming scheme will be swapped with "https".
@ -1236,7 +1245,6 @@ options:
- `port_redirect` (integer): the incoming port will be swapped with the given value.
- `path_redirect` (string): the incoming path portion of the URL will be swapped with the given value.
- `prefix_rewrite` (string): the incoming matched prefix will be swapped with the given value.
- `regex_rewrite_pattern`, `regex_rewrite_substitution` (string): the incoming matched regex will be swapped with this value.
- `response_code` (integer): the response code to use for the redirect. Defaults to 301.
- `strip_query` (boolean): indicates that during redirection, the query portion of the URL will be removed. Defaults to false.

View file

@ -661,6 +661,15 @@ settings:
#### Example
![jaeger example trace](./img/jaeger.png)
- name: "Use Proxy Protocol"
keys: ["use_proxy_protocol"]
attributes: |
- Environment Variable: `USE_PROXY_PROTOCOL`
- Config File Key: `use_proxy_protocol`
- Type: `bool`
- Optional
doc: |
Setting `use_proxy_protocol` will configure Pomerium to require the [HAProxy proxy protocol](https://www.haproxy.org/download/1.9/doc/proxy-protocol.txt) on incoming connections. Versions 1 and 2 of the protocol are supported.
- name: "Authenticate Service"
settings:
- name: "Authenticate Callback Path"

View file

@ -12,6 +12,7 @@ import (
envoy_config_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
envoy_extensions_filters_http_ext_authz_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3"
envoy_extensions_filters_http_lua_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/lua/v3"
envoy_extensions_filters_listener_proxy_protocol_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/proxy_protocol/v3"
envoy_http_connection_manager "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
envoy_extensions_transport_sockets_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
@ -52,6 +53,17 @@ func (srv *Server) buildListeners(options *config.Options) []*envoy_config_liste
}
func (srv *Server) buildMainListener(options *config.Options) *envoy_config_listener_v3.Listener {
listenerFilters := []*envoy_config_listener_v3.ListenerFilter{}
if options.UseProxyProtocol {
proxyCfg := marshalAny(&envoy_extensions_filters_listener_proxy_protocol_v3.ProxyProtocol{})
listenerFilters = append(listenerFilters, &envoy_config_listener_v3.ListenerFilter{
Name: "envoy.filters.listener.proxy_protocol",
ConfigType: &envoy_config_listener_v3.ListenerFilter_TypedConfig{
TypedConfig: proxyCfg,
},
})
}
if options.InsecureServer {
filter := buildMainHTTPConnectionManagerFilter(options,
getAllRouteableDomains(options, options.Addr))
@ -59,6 +71,7 @@ func (srv *Server) buildMainListener(options *config.Options) *envoy_config_list
return &envoy_config_listener_v3.Listener{
Name: "http-ingress",
Address: buildAddress(options.Addr, 80),
ListenerFilters: listenerFilters,
FilterChains: []*envoy_config_listener_v3.FilterChain{{
Filters: []*envoy_config_listener_v3.Filter{
filter,
@ -68,15 +81,17 @@ func (srv *Server) buildMainListener(options *config.Options) *envoy_config_list
}
tlsInspectorCfg := marshalAny(new(emptypb.Empty))
li := &envoy_config_listener_v3.Listener{
Name: "https-ingress",
Address: buildAddress(options.Addr, 443),
ListenerFilters: []*envoy_config_listener_v3.ListenerFilter{{
listenerFilters = append(listenerFilters, &envoy_config_listener_v3.ListenerFilter{
Name: "envoy.filters.listener.tls_inspector",
ConfigType: &envoy_config_listener_v3.ListenerFilter_TypedConfig{
TypedConfig: tlsInspectorCfg,
},
}},
})
li := &envoy_config_listener_v3.Listener{
Name: "https-ingress",
Address: buildAddress(options.Addr, 443),
ListenerFilters: listenerFilters,
FilterChains: buildFilterChains(options, options.Addr,
func(tlsDomain string, httpDomains []string) *envoy_config_listener_v3.FilterChain {
filter := buildMainHTTPConnectionManagerFilter(options, httpDomains)

View file

@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/pomerium/pomerium/config"
"github.com/pomerium/pomerium/internal/controlplane/filemgr"
"github.com/pomerium/pomerium/internal/testutil"
"github.com/pomerium/pomerium/pkg/cryptutil"
)
@ -500,3 +501,30 @@ func Test_buildRouteConfiguration(t *testing.T) {
assert.Equal(t, virtualHosts, routeConfig.GetVirtualHosts())
assert.False(t, routeConfig.GetValidateClusters().GetValue())
}
func Test_requireProxyProtocol(t *testing.T) {
srv := &Server{
filemgr: filemgr.NewManager(),
}
t.Run("required", func(t *testing.T) {
li := srv.buildMainListener(&config.Options{
UseProxyProtocol: true,
InsecureServer: true,
})
testutil.AssertProtoJSONEqual(t, `[
{
"name": "envoy.filters.listener.proxy_protocol",
"typedConfig": {
"@type": "type.googleapis.com/envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol"
}
}
]`, li.GetListenerFilters())
})
t.Run("not required", func(t *testing.T) {
li := srv.buildMainListener(&config.Options{
UseProxyProtocol: false,
InsecureServer: true,
})
assert.Len(t, li.GetListenerFilters(), 0)
})
}