Skip to content

Commit f53b0dc

Browse files
committed
remove DFP filter
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
1 parent ac18feb commit f53b0dc

5 files changed

Lines changed: 102 additions & 220 deletions

File tree

internal/xds/translator/dynamic_forward_proxy.go

Lines changed: 2 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,16 @@ package translator
77

88
import (
99
"errors"
10-
"fmt"
11-
"sort"
1210

1311
cncfv3 "github.com/cncf/xds/go/xds/core/v3"
1412
matcherv3 "github.com/cncf/xds/go/xds/type/matcher/v3"
1513
rbacconfigv3 "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3"
1614
routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
17-
commondfpv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/common/dynamic_forward_proxy/v3"
18-
dfpv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/dynamic_forward_proxy/v3"
1915
rbacv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/rbac/v3"
2016
hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
2117
envoymatcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
2218
"google.golang.org/protobuf/types/known/anypb"
2319

24-
egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
2520
"github.com/envoyproxy/gateway/internal/ir"
2621
"github.com/envoyproxy/gateway/internal/utils/proto"
2722
"github.com/envoyproxy/gateway/internal/xds/types"
@@ -39,7 +34,7 @@ type dynamicForwardProxy struct{}
3934

4035
var _ httpFilter = &dynamicForwardProxy{}
4136

42-
// patchHCM appends the Dynamic Forward Proxy filter to the HTTP Connection Manager if applicable.
37+
// patchHCM appends the loopback protection filter to the HTTP Connection Manager if applicable.
4338
func (*dynamicForwardProxy) patchHCM(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListener) error {
4439
if mgr == nil {
4540
return errors.New("hcm is nil")
@@ -49,7 +44,7 @@ func (*dynamicForwardProxy) patchHCM(mgr *hcmv3.HttpConnectionManager, irListene
4944
return errors.New("ir listener is nil")
5045
}
5146

52-
// Add the RBAC filter once (no-op by default); per-route config will enable it only for DFP routes.
47+
// Add the RBAC filter once (no-op by default); per-route config will enable it only for dynamic resolver routes.
5348
if listenerHasDynamicResolverRoute(irListener) {
5449
loopbackRBAC, err := buildDFPLoopbackRBAC()
5550
if err != nil {
@@ -60,47 +55,9 @@ func (*dynamicForwardProxy) patchHCM(mgr *hcmv3.HttpConnectionManager, irListene
6055
}
6156
}
6257

63-
if !listenerRequireDFP(irListener) {
64-
return nil
65-
}
66-
67-
// Create a DFP filter for each unique DNS cache config needed by the listener's routes.
68-
// This is because DFP filter and Cluster must have consistent cache config.
69-
// Reference: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/clusters/dynamic_forward_proxy/v3/cluster.proto
70-
cacheCfgs := dfpCacheConfigs(irListener.Routes)
71-
72-
for _, cacheCfg := range cacheCfgs {
73-
cacheName := cacheCfg.GetName()
74-
filterName := dfpFilterName(cacheName)
75-
if hcmContainsFilter(mgr, filterName) {
76-
continue
77-
}
78-
79-
filterCfg := &dfpv3.FilterConfig{
80-
ImplementationSpecifier: &dfpv3.FilterConfig_DnsCacheConfig{
81-
DnsCacheConfig: cacheCfg,
82-
},
83-
}
84-
85-
filterAny, err := anypb.New(filterCfg)
86-
if err != nil {
87-
return err
88-
}
89-
90-
mgr.HttpFilters = append(mgr.HttpFilters, &hcmv3.HttpFilter{
91-
Name: filterName,
92-
ConfigType: &hcmv3.HttpFilter_TypedConfig{
93-
TypedConfig: filterAny,
94-
},
95-
Disabled: true,
96-
})
97-
}
98-
9958
return nil
10059
}
10160

102-
// patchRoute adds per-route host rewrite configuration so DNS resolution can
103-
// use rewritten hostnames when configured.
10461
func (*dynamicForwardProxy) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute, _ *ir.HTTPListener) error {
10562
if route == nil {
10663
return errors.New("xds route is nil")
@@ -131,50 +88,13 @@ func (*dynamicForwardProxy) patchRoute(route *routev3.Route, irRoute *ir.HTTPRou
13188
}
13289
}
13390

134-
if !routeRequireDFP(irRoute) {
135-
return nil
136-
}
137-
138-
perRouteCfg := buildDFPPerRouteConfig(irRoute)
139-
if perRouteCfg == nil {
140-
return nil
141-
}
142-
143-
perRouteAny, err := anypb.New(perRouteCfg)
144-
if err != nil {
145-
return err
146-
}
147-
148-
if route.TypedPerFilterConfig == nil {
149-
route.TypedPerFilterConfig = make(map[string]*anypb.Any)
150-
}
151-
filterName := dfpFilterName(dfpCacheName(determineIPFamily(irRoute.Destination.Settings), routeDNS(irRoute)))
152-
route.TypedPerFilterConfig[filterName] = perRouteAny
153-
154-
// Clear out any existing host rewrite specifier to avoid conflicts.
155-
routeAction := route.GetRoute()
156-
if routeAction != nil {
157-
routeAction.HostRewriteSpecifier = nil
158-
routeAction.AppendXForwardedHost = false
159-
}
160-
16191
return nil
16292
}
16393

16494
func (*dynamicForwardProxy) patchResources(_ *types.ResourceVersionTable, _ []*ir.HTTPRoute) error {
16595
return nil
16696
}
16797

168-
// listenerRequireDFP checks if a given listener requires the dynamic forward proxy filter.
169-
func listenerRequireDFP(listener *ir.HTTPListener) bool {
170-
for _, route := range listener.Routes {
171-
if routeRequireDFP(route) {
172-
return true
173-
}
174-
}
175-
return false
176-
}
177-
17898
// listenerHasDynamicResolverRoute checks if a given listener has any route with a dynamic resolver backend.
17999
func listenerHasDynamicResolverRoute(listener *ir.HTTPListener) bool {
180100
for _, route := range listener.Routes {
@@ -185,97 +105,6 @@ func listenerHasDynamicResolverRoute(listener *ir.HTTPListener) bool {
185105
return false
186106
}
187107

188-
// routeRequireDFP check if a given route requires the dynamic forward proxy filter.
189-
// A dynamic forward proxy is required when:
190-
// * The route has a dynamic resolver backend.
191-
// * The route needs DFP to rewrite the host header based on a header or literal name.
192-
func routeRequireDFP(route *ir.HTTPRoute) bool {
193-
if route == nil || route.Destination == nil {
194-
return false
195-
}
196-
197-
if !route.IsDynamicResolverRoute() {
198-
return false
199-
}
200-
201-
if route.URLRewrite != nil && route.URLRewrite.Host != nil &&
202-
(route.URLRewrite.Host.Header != nil || route.URLRewrite.Host.Name != nil) {
203-
return true
204-
}
205-
206-
return false
207-
}
208-
209-
// dfpCacheConfigs builds a sorted list of unique DFP DNS cache configs needed by the given routes.
210-
func dfpCacheConfigs(routes []*ir.HTTPRoute) []*commondfpv3.DnsCacheConfig {
211-
cacheCfgs := make(map[string]*commondfpv3.DnsCacheConfig)
212-
213-
for _, route := range routes {
214-
if !routeRequireDFP(route) {
215-
continue
216-
}
217-
218-
dns := routeDNS(route)
219-
ipFamily := determineIPFamily(route.Destination.Settings)
220-
cacheName := dfpCacheName(ipFamily, dns)
221-
if _, existing := cacheCfgs[cacheName]; existing {
222-
continue
223-
}
224-
225-
routeCfg := buildDFPDNSCacheConfig(cacheName, dns, computeDNSLookupFamily(ipFamily, dns))
226-
cacheCfgs[cacheName] = routeCfg
227-
}
228-
229-
if len(cacheCfgs) == 0 {
230-
return nil
231-
}
232-
233-
cfgs := make([]*commondfpv3.DnsCacheConfig, 0, len(cacheCfgs))
234-
for _, cfg := range cacheCfgs {
235-
cfgs = append(cfgs, cfg)
236-
}
237-
238-
// Sort the configs by name to ensure deterministic order for xDS generation.
239-
sort.Slice(cfgs, func(i, j int) bool {
240-
return cfgs[i].GetName() < cfgs[j].GetName()
241-
})
242-
243-
return cfgs
244-
}
245-
246-
func buildDFPPerRouteConfig(irRoute *ir.HTTPRoute) *dfpv3.PerRouteConfig {
247-
switch {
248-
case irRoute.URLRewrite == nil || irRoute.URLRewrite.Host == nil:
249-
return nil
250-
case irRoute.URLRewrite.Host.Header != nil:
251-
return &dfpv3.PerRouteConfig{
252-
HostRewriteSpecifier: &dfpv3.PerRouteConfig_HostRewriteHeader{
253-
HostRewriteHeader: *irRoute.URLRewrite.Host.Header,
254-
},
255-
}
256-
case irRoute.URLRewrite.Host.Name != nil:
257-
return &dfpv3.PerRouteConfig{
258-
HostRewriteSpecifier: &dfpv3.PerRouteConfig_HostRewriteLiteral{
259-
HostRewriteLiteral: *irRoute.URLRewrite.Host.Name,
260-
},
261-
}
262-
default:
263-
return nil
264-
265-
}
266-
}
267-
268-
func routeDNS(route *ir.HTTPRoute) *ir.DNS {
269-
if route == nil || route.Traffic == nil {
270-
return nil
271-
}
272-
return route.Traffic.DNS
273-
}
274-
275-
func dfpFilterName(cacheName string) string {
276-
return fmt.Sprintf("%s.%s", string(egv1a1.EnvoyFilterDynamicForwardProxy), cacheName)
277-
}
278-
279108
func buildDFPLoopbackRBAC() (*hcmv3.HttpFilter, error) {
280109
rbac := &rbacv3.RBAC{
281110
// No policies: acts as a placeholder; per-route config enables denial.

internal/xds/translator/route.go

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -578,24 +578,19 @@ func buildXdsURLRewriteAction(route *ir.HTTPRoute, urlRewrite *ir.URLRewrite, pa
578578
}
579579

580580
if urlRewrite.Host != nil {
581-
// For DFP use cases, route-level host literal/header rewrites are not used, and instead DFP per-filter config is used, see here:
582-
// https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/dynamic_forward_proxy/v3/dynamic_forward_proxy.proto#envoy-v3-api-msg-extensions-filters-http-dynamic-forward-proxy-v3-perrouteconfig
583-
// Auto Host rewrites are only supported for strict/logical DNS clusters, so not relevant for DFP, see here:
584-
// https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-field-config-route-v3-routeaction-auto-host-rewrite
585-
if !route.IsDynamicResolverRoute() {
586-
switch {
587-
case urlRewrite.Host.Name != nil:
588-
routeAction.HostRewriteSpecifier = &routev3.RouteAction_HostRewriteLiteral{
589-
HostRewriteLiteral: *urlRewrite.Host.Name,
590-
}
591-
case urlRewrite.Host.Header != nil:
592-
routeAction.HostRewriteSpecifier = &routev3.RouteAction_HostRewriteHeader{
593-
HostRewriteHeader: *urlRewrite.Host.Header,
594-
}
595-
case urlRewrite.Host.Backend != nil:
596-
routeAction.HostRewriteSpecifier = &routev3.RouteAction_AutoHostRewrite{
597-
AutoHostRewrite: wrapperspb.Bool(true),
598-
}
581+
switch {
582+
case urlRewrite.Host.Name != nil:
583+
routeAction.HostRewriteSpecifier = &routev3.RouteAction_HostRewriteLiteral{
584+
HostRewriteLiteral: *urlRewrite.Host.Name,
585+
}
586+
case urlRewrite.Host.Header != nil:
587+
routeAction.HostRewriteSpecifier = &routev3.RouteAction_HostRewriteHeader{
588+
HostRewriteHeader: *urlRewrite.Host.Header,
589+
}
590+
case urlRewrite.Host.Backend != nil && !route.IsDynamicResolverRoute():
591+
// Auto Host rewrite is only supported for non-dynamic resolver routes.
592+
routeAction.HostRewriteSpecifier = &routev3.RouteAction_AutoHostRewrite{
593+
AutoHostRewrite: wrapperspb.Bool(true),
599594
}
600595
}
601596

internal/xds/translator/route_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,3 +309,82 @@ func TestBuildXdsURLRewriteAction_AppendXForwardedHost(t *testing.T) {
309309
})
310310
}
311311
}
312+
313+
func TestBuildXdsURLRewriteAction_DynamicResolverHostRewrite(t *testing.T) {
314+
baseRoute := &ir.HTTPRoute{
315+
Name: "test-route",
316+
Destination: &ir.RouteDestination{
317+
Name: "test-dest",
318+
Settings: []*ir.DestinationSetting{
319+
{
320+
IsDynamicResolver: true,
321+
},
322+
},
323+
},
324+
}
325+
326+
tests := []struct {
327+
name string
328+
urlRewrite *ir.URLRewrite
329+
wantSpecifier *routev3.RouteAction
330+
wantAppendXForwardedHost bool
331+
}{
332+
{
333+
name: "header rewrite uses route action",
334+
urlRewrite: &ir.URLRewrite{
335+
Host: &ir.HTTPHostModifier{
336+
Header: ptr.To("x-dynamic-host"),
337+
},
338+
},
339+
wantSpecifier: &routev3.RouteAction{
340+
HostRewriteSpecifier: &routev3.RouteAction_HostRewriteHeader{
341+
HostRewriteHeader: "x-dynamic-host",
342+
},
343+
AppendXForwardedHost: true,
344+
},
345+
wantAppendXForwardedHost: true,
346+
},
347+
{
348+
name: "literal rewrite uses route action",
349+
urlRewrite: &ir.URLRewrite{
350+
Host: &ir.HTTPHostModifier{
351+
Name: ptr.To("rewritten.example.com"),
352+
},
353+
},
354+
wantSpecifier: &routev3.RouteAction{
355+
HostRewriteSpecifier: &routev3.RouteAction_HostRewriteLiteral{
356+
HostRewriteLiteral: "rewritten.example.com",
357+
},
358+
AppendXForwardedHost: true,
359+
},
360+
wantAppendXForwardedHost: true,
361+
},
362+
{
363+
name: "append x-forwarded-host respects explicit false",
364+
urlRewrite: &ir.URLRewrite{
365+
Host: &ir.HTTPHostModifier{
366+
Header: ptr.To("x-dynamic-host"),
367+
},
368+
AppendXForwardedHost: ptr.To(false),
369+
},
370+
wantSpecifier: &routev3.RouteAction{
371+
HostRewriteSpecifier: &routev3.RouteAction_HostRewriteHeader{
372+
HostRewriteHeader: "x-dynamic-host",
373+
},
374+
},
375+
wantAppendXForwardedHost: false,
376+
},
377+
}
378+
379+
for _, tt := range tests {
380+
t.Run(tt.name, func(t *testing.T) {
381+
got := buildXdsURLRewriteAction(baseRoute, tt.urlRewrite, nil)
382+
if !reflect.DeepEqual(got.HostRewriteSpecifier, tt.wantSpecifier.HostRewriteSpecifier) {
383+
t.Fatalf("HostRewriteSpecifier = %#v, want %#v", got.HostRewriteSpecifier, tt.wantSpecifier.HostRewriteSpecifier)
384+
}
385+
if got.AppendXForwardedHost != tt.wantAppendXForwardedHost {
386+
t.Fatalf("AppendXForwardedHost = %v, want %v", got.AppendXForwardedHost, tt.wantAppendXForwardedHost)
387+
}
388+
})
389+
}
390+
}

internal/xds/translator/testdata/out/xds-ir/http-route-dynamic-resolver-with-host-rewriting.listeners.yaml

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,6 @@
2020
- name: envoy.filters.http.rbac.dfp_loopback_deny
2121
typedConfig:
2222
'@type': type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC
23-
- disabled: true
24-
name: envoy.filters.http.dynamic_forward_proxy.envoy-gateway-dfp-cache-all-1000ms-default/dns-policy-for-httproute-2
25-
typedConfig:
26-
'@type': type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig
27-
dnsCacheConfig:
28-
dnsLookupFamily: ALL
29-
dnsRefreshRate: 1s
30-
name: envoy-gateway-dfp-cache-all-1000ms-default/dns-policy-for-httproute-2
31-
- disabled: true
32-
name: envoy.filters.http.dynamic_forward_proxy.envoy-gateway-dfp-cache-v4_preferred-30000ms-default
33-
typedConfig:
34-
'@type': type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig
35-
dnsCacheConfig:
36-
dnsLookupFamily: V4_PREFERRED
37-
dnsRefreshRate: 30s
38-
name: envoy-gateway-dfp-cache-v4_preferred-30000ms-default
3923
- name: envoy.filters.http.router
4024
typedConfig:
4125
'@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

0 commit comments

Comments
 (0)