Skip to content
agentgateway has joined the Agentic AI Foundation — Learn more

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.
Page as Markdown

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

  1. Follow the Get started guide to install agentgateway.

  2. Follow the Sample app guide to create a gateway proxy with an HTTP listener and deploy the httpbin sample app.

  3. Get the external address of the gateway and save it in an environment variable.

    Tip

    Kind cluster? Kind does not support LoadBalancer services by default. To use this option with a Kind cluster, install and run cloud-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

  1. 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: {}
    EOF
  2. Create 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
  1. 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 as httpbin.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 typeIPv4IPv6
Loopback127.0.0.0/8::1
Link-local, including the cloud metadata server169.254.0.0/16fe80::/10
Unspecified, which connects to the local host0.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:8000 still 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.

  1. 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 allowed
    
  2. Check the proxy logs for the reason.

    kubectl logs deployment/agentgateway-proxy -n agentgateway-system | grep loopback

    Example 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=NoHealthyBackend
    
  3. Create 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
    EOF

    Review the following table to understand this configuration.

    SettingDescription
    spec.rawConfig.config.backend.allowDynamicLoopbackSet to true to let every Dynamic Forward Proxy on the Gateway connect to loopback, link-local, and unspecified addresses. The default is false.
  4. Reference the AgentgatewayParameters resource from the Gateway. If a reference already exists, add the setting to that resource instead.

    The Gateway’s rawConfig replaces the GatewayClass’s entire rawConfig. 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 patched
    
  5. Wait for the proxy to restart. The rawConfig change rolls out new proxy pods.

    kubectl rollout status deployment/agentgateway-proxy -n agentgateway-system

    Example output:

    Waiting for deployment "agentgateway-proxy" rollout to finish: 1 old replicas are pending termination...
    deployment "agentgateway-proxy" successfully rolled out
    
  6. If using port-forwarding, restart kubectl port-forward to 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 httpbin

If you allowed loopback destinations, revert the setting.

  • If you added the setting to an existing AgentgatewayParameters resource, remove config.backend.allowDynamicLoopback from its rawConfig.
  • If you created the dfp-loopback resource, 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
Was this page helpful?
Agentgateway assistant

Ask me anything about agentgateway configuration, features, or usage.

Note: AI-generated content might contain errors; please verify and test all returned information.

Tip: one topic per conversation gives the best results. Use the + button in the chat header to start a new conversation.

Switching topics? Starting a new conversation improves accuracy.
↑↓ navigate ↵ select esc dismiss

What could be improved?

Your feedback helps us improve assistant answers and identify docs gaps we should fix.

Need more help? Join us on Discord: https://discord.gg/y9efgEmppm

Want to use your own agent? Add the Solo MCP server to query our docs directly. Get started here: https://search.solo.io/.