For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
Dynamic Forward Proxy (DFP)
Verified : Code examples on this page have been automatically tested and verified.Route traffic dynamically to upstream servers based on request characteristics.
Dynamically resolve upstream hosts at request time.
About Dynamic Forward Proxy
Dynamic Forward Proxy (DFP) is a filter in Envoy that allows a gateway proxy to act as a generic HTTP(S) forward proxy without the need to preconfigure all possible upstream hosts. Instead, the DFP dynamically resolves the upstream host at request time by using DNS.
DFPs are especially useful in highly dynamic environments where services come up and down frequently. Such churn makes it hard for a service registry to list all available endpoints at a given time. With DFP, you do not need to have pre-defined destinations. This approach gives you more flexibility to resolve endpoints as the request comes in.
Another common use case for DFPs is to control and monitor all egress traffic. For example, you can apply policies, such as rate limiting, authentication, authorization, and access logging. You can also easily access metrics for the egress traffic that is routed through the forward proxy.
DFPs are configured in a Backend resource and an HTTPRoute that routes traffic to the DFP Backend. If a request reaches the gateway proxy, the proxy extracts the host header value from the request and uses DNS to resolve the host to an IP address. Then, the request is forwarded to the resolved IP address.
Considerations
DFPs offer great flexibility for defining routing patterns for your upstream hosts. However, consider the following downsides when using a DFP:
- You cannot configure failover or client-side load balancing policies for DFP-configured routes because no pre-defined upstream hosts exist that determine the desired upstream service.
- DNS resolution is done at runtime, which can have performance implications. If Envoy detects a new domain name, Envoy pauses the request and synchronously resolves this domain to get the IP address of the endpoint. Then, Envoy caches the IP address locally.
Before you begin
Follow the Get started guide to install agentgateway.
Follow the Sample app guide to create a gateway proxy with an HTTP listener and deploy the httpbin sample app.
Get the external address of the gateway and save it in an environment variable.
Tip
Kind cluster? Kind does not support
LoadBalancerservices by default. To use this option with a Kind cluster, install and runcloud-provider-kind.export INGRESS_GW_ADDRESS=$(kubectl get svc -n agentgateway-system agentgateway-proxy -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo $INGRESS_GW_ADDRESS
Set up a Dynamic Forward Proxy
Create a Backend for the Dynamic Forward Proxy.
kubectl apply -f- <<EOF apiVersion: agentgateway.dev/v1alpha1 kind: AgentgatewayBackend metadata: name: dfp-backend namespace: httpbin spec: dynamicForwardProxy: {} EOFCreate an HTTPRoute that routes incoming traffic to the DFP Backend.
kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: namespace: httpbin name: dfp-httproute spec: parentRefs: - name: agentgateway-proxy namespace: agentgateway-system rules: - backendRefs: - name: dfp-backend group: agentgateway.dev kind: AgentgatewayBackend EOF
Send a request to a hostname of your choice, such as
httpbin.org. The Dynamic Forward Proxy resolves the host at request time and forwards the request to it, so the host’s welcome page is returned. Because no upstream hosts are pre-defined in the Backend, you can send a request to any reachable host without changing the configuration. For example, for quick testing, you might send a request with the host header set to an in-cluster service, such ashttpbin.httpbin.svc.cluster.local:8000.curl -vik http://$INGRESS_GW_ADDRESS:80 -H "host: httpbin.org"Example output:
* Request completely sent off < HTTP/1.1 200 OK HTTP/1.1 200 OK ... <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>httpbin.org</title> <link rel="stylesheet" type="text/css" href="/flasgger_static/swagger-ui.css"> <link rel="icon" type="image/png" href="/static/favicon.ico" sizes="64x64 32x32 16x16" /> <style> ...
Loopback and link-local destinations
A Dynamic Forward Proxy uses the destination named in each request. Without restrictions, clients could reach services inside the proxy pod or on its node.
Examples include the admin interface on localhost:15000 and the cloud metadata server at 169.254.169.254, which can issue cloud credentials. This is called server-side request forgery (SSRF).
To prevent this attack, a Dynamic Forward Proxy refuses to connect to the following addresses.
| Address type | IPv4 | IPv6 |
|---|---|---|
| Loopback | 127.0.0.0/8 | ::1 |
| Link-local, including the cloud metadata server | 169.254.0.0/16 | fe80::/10 |
| Unspecified, which connects to the local host | 0.0.0.0 | :: |
The check has the following scope:
- Checks run after DNS resolution. Hostnames resolving to blocked addresses, such as
localhost, are also blocked. The check covers IPv4-mapped forms of blocked addresses, such as::ffff:127.0.0.1. - Pod and Service addresses remain reachable. For example, requests to
httpbin.httpbin.svc.cluster.local:8000still work. - Only the Dynamic Forward Proxy is checked. Other backends, such as a Service or a static AgentgatewayBackend, are not affected.
A refused request fails with a 503 response and the body backend not allowed.
Allow loopback destinations
To allow local destinations, set config.backend.allowDynamicLoopback in the AgentgatewayParameters resource’s rawConfig. There is no dedicated field for this setting.
Warning
This setting affects every Dynamic Forward Proxy route on the Gateway. Clients using these routes can reach the cloud metadata server at 169.254.169.254 and every service inside the proxy pod, including the admin interface. Restrict destinations with HTTPRoute hostnames and restrict clients with an authorization policy.
These steps first verify the default behavior using the proxy’s readiness endpoint at localhost:15021.
Send a request with the host header set to the proxy’s own readiness endpoint. The request is refused.
curl -i http://$INGRESS_GW_ADDRESS:80/healthz/ready -H "host: localhost:15021"Example output:
HTTP/1.1 503 Service Unavailable content-type: text/plain content-length: 19 backend not allowedCheck the proxy logs for the reason.
kubectl logs deployment/agentgateway-proxy -n agentgateway-system | grep loopbackExample output:
error request gateway=agentgateway-system/agentgateway-proxy listener=http route=httpbin/dfp-httproute endpoint=localhost:15021 ... http.status=503 protocol=http error="dynamic backend resolved to a loopback or link-local address" reason=NoHealthyBackendCreate an AgentgatewayParameters resource that allows loopback destinations.
kubectl apply -f- <<EOF apiVersion: agentgateway.dev/v1alpha1 kind: AgentgatewayParameters metadata: name: dfp-loopback namespace: agentgateway-system spec: rawConfig: config: backend: allowDynamicLoopback: true EOFReview the following table to understand this configuration.
Setting Description spec.rawConfig.config.backend.allowDynamicLoopbackSet to trueto let every Dynamic Forward Proxy on the Gateway connect to loopback, link-local, and unspecified addresses. The default isfalse.Reference the AgentgatewayParameters resource from the Gateway. If a reference already exists, add the setting to that resource instead.
The Gateway’s
rawConfigreplaces the GatewayClass’s entirerawConfig. The two are not merged.kubectl patch gateway agentgateway-proxy -n agentgateway-system --type merge \ -p '{"spec":{"infrastructure":{"parametersRef":{"group":"agentgateway.dev","kind":"AgentgatewayParameters","name":"dfp-loopback"}}}}'Example output:
gateway.gateway.networking.k8s.io/agentgateway-proxy patchedWait for the proxy to restart. The
rawConfigchange rolls out new proxy pods.kubectl rollout status deployment/agentgateway-proxy -n agentgateway-systemExample output:
Waiting for deployment "agentgateway-proxy" rollout to finish: 1 old replicas are pending termination... deployment "agentgateway-proxy" successfully rolled outIf using port-forwarding, restart
kubectl port-forwardto connect to a new pod. Send the request again. The proxy now forwards it to the readiness endpoint.curl -i http://$INGRESS_GW_ADDRESS:80/healthz/ready -H "host: localhost:15021"Example output:
HTTP/1.1 200 OK content-type: text/plain content-length: 6 ready
Cleanup
You can remove the resources that you created in this guide.kubectl delete AgentgatewayBackend dfp-backend -n httpbin
kubectl delete httproute dfp-httproute -n httpbinIf you allowed loopback destinations, revert the setting.
- If you added the setting to an existing AgentgatewayParameters resource, remove
config.backend.allowDynamicLoopbackfrom itsrawConfig. - If you created the
dfp-loopbackresource, remove the reference from the Gateway and delete the resource.kubectl patch gateway agentgateway-proxy -n agentgateway-system --type json \ -p '[{"op":"remove","path":"/spec/infrastructure/parametersRef"}]' kubectl delete AgentgatewayParameters dfp-loopback -n agentgateway-system