Skip to content

Commit 317a238

Browse files
authored
Support PROXY Protocol listener filter (1.7) (#5119)
* PROXY protocol listener filter * fix invalid test helper * Merge refs/heads/v1.7.x into backport/v1.7.x/proxy-protocol-listener-filter
1 parent c0570e3 commit 317a238

File tree

8 files changed

+518
-17
lines changed

8 files changed

+518
-17
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
changelog:
2+
- type: FIX
3+
issueLink: https://github.com/solo-io/gloo/issues/5116
4+
resolvesIssue: false
5+
description: >
6+
Add PROXY protocol as listener filter, instead of relying on the deprecated
7+
use_proxy_proto flag that Envoy exposes. We ensure the filter occurs before
8+
the TLS inspector filter, to ensure that PROXY protocol and SNI can be used
9+
together.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package proxyprotocol
2+
3+
import (
4+
envoy_config_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
5+
envoy_listener_proxy_protocol "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/proxy_protocol/v3"
6+
"github.com/envoyproxy/go-control-plane/pkg/wellknown"
7+
v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1"
8+
"github.com/solo-io/gloo/projects/gloo/pkg/plugins"
9+
"github.com/solo-io/gloo/projects/gloo/pkg/utils"
10+
)
11+
12+
func NewPlugin() *plugin {
13+
return &plugin{}
14+
}
15+
16+
// Compile-time assertion
17+
var (
18+
_ plugins.Plugin = new(plugin)
19+
_ plugins.ListenerPlugin = new(plugin)
20+
)
21+
22+
type plugin struct{}
23+
24+
func (p *plugin) Init(params plugins.InitParams) error {
25+
return nil
26+
}
27+
28+
func (p *plugin) ProcessListener(params plugins.Params, in *v1.Listener, out *envoy_config_listener_v3.Listener) error {
29+
if !in.GetUseProxyProto().GetValue() {
30+
// If UseProxyProto is not defined on the listener or it is false, do not append the filter
31+
return nil
32+
}
33+
34+
envoyProxyProtocol := &envoy_listener_proxy_protocol.ProxyProtocol{}
35+
msg, err := utils.MessageToAny(envoyProxyProtocol)
36+
if err != nil {
37+
return err
38+
}
39+
40+
listenerFilter := &envoy_config_listener_v3.ListenerFilter{
41+
Name: wellknown.ProxyProtocol,
42+
ConfigType: &envoy_config_listener_v3.ListenerFilter_TypedConfig{
43+
TypedConfig: msg,
44+
},
45+
}
46+
47+
out.ListenerFilters = append(out.ListenerFilters, listenerFilter)
48+
return nil
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package proxyprotocol
2+
3+
import (
4+
envoy_config_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
5+
"github.com/envoyproxy/go-control-plane/pkg/wellknown"
6+
"github.com/golang/protobuf/ptypes/wrappers"
7+
. "github.com/onsi/ginkgo"
8+
. "github.com/onsi/gomega"
9+
v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1"
10+
"github.com/solo-io/gloo/projects/gloo/pkg/plugins"
11+
)
12+
13+
var _ = Describe("Plugin", func() {
14+
15+
var (
16+
p *plugin
17+
params plugins.Params
18+
19+
in *v1.Listener
20+
out *envoy_config_listener_v3.Listener
21+
)
22+
23+
BeforeEach(func() {
24+
p = NewPlugin()
25+
26+
err := p.Init(plugins.InitParams{})
27+
Expect(err).NotTo(HaveOccurred())
28+
29+
in = &v1.Listener{}
30+
out = &envoy_config_listener_v3.Listener{}
31+
})
32+
33+
When("UseProxyProto=true is defined on the listener", func() {
34+
35+
BeforeEach(func() {
36+
in.UseProxyProto = &wrappers.BoolValue{Value: true}
37+
})
38+
39+
It("appends ProxyProtocol listener filter", func() {
40+
err := p.ProcessListener(params, in, out)
41+
Expect(err).NotTo(HaveOccurred())
42+
43+
Expect(out.ListenerFilters).To(HaveLen(1))
44+
Expect(out.ListenerFilters).To(HaveLen(1))
45+
Expect(out.ListenerFilters[0].GetName()).To(Equal(wellknown.ProxyProtocol))
46+
})
47+
48+
})
49+
50+
When("UseProxyProto=false is defined on the listener", func() {
51+
52+
BeforeEach(func() {
53+
in.UseProxyProto = &wrappers.BoolValue{Value: false}
54+
})
55+
56+
It("does not append ProxyProtocol listener filter", func() {
57+
err := p.ProcessListener(params, in, out)
58+
Expect(err).NotTo(HaveOccurred())
59+
60+
Expect(out.ListenerFilters).To(HaveLen(0))
61+
})
62+
63+
})
64+
65+
When("UseProxyProto is not defined on the listener", func() {
66+
67+
BeforeEach(func() {
68+
in.UseProxyProto = nil
69+
})
70+
71+
It("does not append ProxyProtocol listener filter", func() {
72+
err := p.ProcessListener(params, in, out)
73+
Expect(err).NotTo(HaveOccurred())
74+
75+
Expect(out.ListenerFilters).To(HaveLen(0))
76+
})
77+
78+
})
79+
80+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package proxyprotocol_test
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo"
7+
"github.com/onsi/ginkgo/reporters"
8+
. "github.com/onsi/gomega"
9+
)
10+
11+
func TestProxyProtocol(t *testing.T) {
12+
RegisterFailHandler(Fail)
13+
junitReporter := reporters.NewJUnitReporter("junit.xml")
14+
RunSpecsWithDefaultAndCustomReporters(t, "Proxy Protocol Suite", []Reporter{junitReporter})
15+
}

projects/gloo/pkg/plugins/registry/registry.go

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/solo-io/gloo/projects/gloo/pkg/plugins/metadata"
2929
"github.com/solo-io/gloo/projects/gloo/pkg/plugins/pipe"
3030
"github.com/solo-io/gloo/projects/gloo/pkg/plugins/protocoloptions"
31+
"github.com/solo-io/gloo/projects/gloo/pkg/plugins/proxyprotocol"
3132
"github.com/solo-io/gloo/projects/gloo/pkg/plugins/ratelimit"
3233
"github.com/solo-io/gloo/projects/gloo/pkg/plugins/rest"
3334
"github.com/solo-io/gloo/projects/gloo/pkg/plugins/shadowing"
@@ -61,6 +62,7 @@ var globalRegistry = func(opts bootstrap.Opts, pluginExtensions ...func() plugin
6162
rest.NewPlugin(&transformationPlugin.RequireTransformationFilter),
6263
hcmPlugin,
6364
als.NewPlugin(),
65+
proxyprotocol.NewPlugin(),
6466
tls_inspector.NewPlugin(),
6567
pipe.NewPlugin(),
6668
tcp.NewPlugin(utils.NewSslConfigTranslator()),

projects/gloo/pkg/plugins/tcp/plugin.go

+2-10
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
envoyauth "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
88
"github.com/envoyproxy/go-control-plane/pkg/wellknown"
99
"github.com/golang/protobuf/proto"
10-
"github.com/golang/protobuf/ptypes/wrappers"
1110
"github.com/hashicorp/go-multierror"
1211
"github.com/rotisserie/eris"
1312
v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1"
@@ -193,26 +192,20 @@ func (p *Plugin) computerTcpFilterChain(
193192
sslConfig := host.GetSslConfig()
194193
if sslConfig == nil {
195194
return &envoy_config_listener_v3.FilterChain{
196-
Filters: listenerFilters,
197-
UseProxyProto: listener.GetUseProxyProto(),
195+
Filters: listenerFilters,
198196
}, nil
199197
}
200198

201199
downstreamConfig, err := p.sslConfigTranslator.ResolveDownstreamSslConfig(snap.Secrets, sslConfig)
202200
if err != nil {
203201
return nil, InvalidSecretsError(err, listener.GetName())
204202
}
205-
return p.newSslFilterChain(downstreamConfig,
206-
sslConfig.GetSniDomains(),
207-
listener.GetUseProxyProto(),
208-
listenerFilters,
209-
), nil
203+
return p.newSslFilterChain(downstreamConfig, sslConfig.GetSniDomains(), listenerFilters), nil
210204
}
211205

212206
func (p *Plugin) newSslFilterChain(
213207
downstreamConfig *envoyauth.DownstreamTlsContext,
214208
sniDomains []string,
215-
useProxyProto *wrappers.BoolValue,
216209
listenerFilters []*envoy_config_listener_v3.Filter,
217210
) *envoy_config_listener_v3.FilterChain {
218211

@@ -231,7 +224,6 @@ func (p *Plugin) newSslFilterChain(
231224
Name: wellknown.TransportSocketTls,
232225
ConfigType: &envoy_config_core_v3.TransportSocket_TypedConfig{TypedConfig: utils.MustMessageToAny(downstreamConfig)},
233226
},
234-
UseProxyProto: useProxyProto,
235227
}
236228
}
237229

projects/gloo/pkg/translator/listener.go

+2-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
envoyauth "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
1111
"github.com/envoyproxy/go-control-plane/pkg/wellknown"
1212
"github.com/golang/protobuf/proto"
13-
"github.com/golang/protobuf/ptypes/wrappers"
1413
validationapi "github.com/solo-io/gloo/projects/gloo/pkg/api/grpc/validation"
1514
v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1"
1615
"github.com/solo-io/gloo/projects/gloo/pkg/plugins"
@@ -151,8 +150,7 @@ func (t *translatorInstance) computeFilterChainsFromSslConfig(
151150
// if no ssl config is provided, return a single insecure filter chain
152151
if len(listener.SslConfigurations) == 0 {
153152
return []*envoy_config_listener_v3.FilterChain{{
154-
Filters: listenerFilters,
155-
UseProxyProto: listener.GetUseProxyProto(),
153+
Filters: listenerFilters,
156154
}}
157155
}
158156

@@ -166,7 +164,7 @@ func (t *translatorInstance) computeFilterChainsFromSslConfig(
166164
validationapi.ListenerReport_Error_SSLConfigError, err.Error())
167165
continue
168166
}
169-
filterChain := newSslFilterChain(downstreamConfig, sslConfig.SniDomains, listener.UseProxyProto, listenerFilters)
167+
filterChain := newSslFilterChain(downstreamConfig, sslConfig.GetSniDomains(), listenerFilters)
170168

171169
secureFilterChains = append(secureFilterChains, filterChain)
172170
}
@@ -245,7 +243,6 @@ func validateListenerPorts(proxy *v1.Proxy, listenerReport *validationapi.Listen
245243
func newSslFilterChain(
246244
downstreamConfig *envoyauth.DownstreamTlsContext,
247245
sniDomains []string,
248-
useProxyProto *wrappers.BoolValue,
249246
listenerFilters []*envoy_config_listener_v3.Filter,
250247
) *envoy_config_listener_v3.FilterChain {
251248

@@ -265,8 +262,6 @@ func newSslFilterChain(
265262
Name: wellknown.TransportSocketTls,
266263
ConfigType: &envoy_config_core_v3.TransportSocket_TypedConfig{TypedConfig: utils.MustMessageToAny(downstreamConfig)},
267264
},
268-
269-
UseProxyProto: useProxyProto,
270265
}
271266
}
272267

0 commit comments

Comments
 (0)