For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
HTTP CONNECT tunnels
Tunnel connections to a Static backend through an HTTP CONNECT forward proxy.
About HTTP CONNECT tunnels
If your environment requires egress traffic to leave through a forward proxy, you can tunnel connections from a Static Backend through that proxy. The gateway proxy sends an HTTP CONNECT request to the forward proxy, and the forward proxy opens the connection to the destination. Without a tunnel, the gateway proxy connects to the destination directly.
You configure the tunnel by using the spec.tunnel field of a BackendConfigPolicy and reference the forward proxy. You can optionally add headers to the CONNECT request, such as Proxy-Authorization. The headers are sent to the forward proxy only, not to the destination.
Follow these rules when you configure a tunnel:
- The destination that you want to tunnel must be a Static Backend that has exactly one host. Other destination types, and Static destinations with multiple hosts, are not supported.
- Do not set
healthCheck,tcpKeepalive, orupstreamProxyProtocolin any BackendConfigPolicy that applies to the same Backend. - Reference a forward proxy that the gateway proxy can resolve. The forward proxy must be a Service or a Static Backend.
- Do not tunnel the connection to the forward proxy itself.
Note
Looking to accept CONNECT requests from clients at the gateway? See the HTTP protocol upgrades guide instead.
Before you begin
Follow the Get started guide to install kgateway.
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.
export INGRESS_GW_ADDRESS=$(kubectl get svc -n kgateway-system http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo $INGRESS_GW_ADDRESS
Tunnel a Static backend through a forward proxy
Send connections for a Static Backend through the forward proxy. In this example, the destination is the httpbin app. Only the CONNECT request includes the Proxy-Authorization header, and the header value comes from a Secret.
Deploy a forward proxy. In this guide, you use Squid as the forward proxy. The configuration allows
CONNECTrequests to port 8000 only, which is the port of the httpbin sample app, and logs theProxy-Authorizationheader so that you can verify later that the tunnel was used.The following Squid configuration does not enforce authentication or check credentials. In a production environment, configure your forward proxy to authenticate requests.
kubectl apply -f- <<EOF apiVersion: v1 kind: ConfigMap metadata: name: egress-proxy-config namespace: httpbin data: squid.conf: | max_filedescriptors 1024 http_port 3128 acl httpbin_port port 8000 acl connect_method method CONNECT http_access allow connect_method httpbin_port http_access deny all logformat tunnel %>a %rm %ru %>Hs "Proxy-Authorization: %{Proxy-Authorization}>h" access_log stdio:/var/log/squid/access.log tunnel cache deny all --- apiVersion: apps/v1 kind: Deployment metadata: name: egress-proxy namespace: httpbin spec: replicas: 1 selector: matchLabels: app: egress-proxy template: metadata: labels: app: egress-proxy spec: containers: - name: squid image: ubuntu/squid:latest ports: - containerPort: 3128 volumeMounts: - name: config mountPath: /etc/squid/squid.conf subPath: squid.conf volumes: - name: config configMap: name: egress-proxy-config --- apiVersion: v1 kind: Service metadata: name: egress-proxy namespace: httpbin spec: selector: app: egress-proxy ports: - port: 3128 targetPort: 3128 EOFVerify that the forward proxy is running.
kubectl get pods -n httpbin -l app=egress-proxyExample output:
NAME READY STATUS RESTARTS AGE egress-proxy-59c7db587b-4jzsq 1/1 Running 0 20sCreate a Static Backend for the httpbin app.
kubectl apply -f- <<EOF apiVersion: gateway.kgateway.dev/v1alpha1 kind: Backend metadata: name: httpbin-via-proxy namespace: httpbin spec: type: Static static: hosts: - host: httpbin.httpbin.svc.cluster.local port: 8000 EOFCreate a Secret with a sample credential for the forward proxy. The Squid proxy in this guide does not check credentials, so the Secret is not required for the tunnel to work. You add it to show how to send a header, such as
Proxy-Authorization, with theCONNECTrequest without putting the value in the policy.kubectl apply -f- <<EOF apiVersion: v1 kind: Secret metadata: name: egress-proxy-credentials namespace: httpbin type: Opaque stringData: authorization: Basic dXNlcjpwYXNz EOFCreate a BackendConfigPolicy that tunnels connections to the Backend through the forward proxy.
Review the following table to understand this configuration.kubectl apply -f- <<EOF apiVersion: gateway.kgateway.dev/v1alpha1 kind: BackendConfigPolicy metadata: name: httpbin-tunnel namespace: httpbin spec: targetRefs: - group: gateway.kgateway.dev kind: Backend name: httpbin-via-proxy tunnel: proxy: backendRef: name: egress-proxy port: 3128 headers: - name: Proxy-Authorization secretRef: name: egress-proxy-credentials key: authorization EOFField Description targetRefsTargets the httpbin-via-proxyStatic Backend.tunnel.proxy.backendRefThe egress-proxyService on port 3128, which exposes the Squid forward proxy that you deployed earlier. The gateway proxy sends theCONNECTrequest to this forward proxy.tunnel.headersAdds the Proxy-Authorizationheader to theCONNECTrequest. The value comes from theegress-proxy-credentialsSecret. Note that any headers in thespec.tunnel.headersfield are part of theCONNECTrequest. They are not sent to the destination.Verify that the BackendConfigPolicy is accepted. If the status shows
Accepted=False, check the message for the reason, such as an unsupported destination setting.kubectl get backendconfigpolicy httpbin-tunnel -n httpbin -o jsonpath='{.status.ancestors[0].conditions[?(@.type=="Accepted")]}'Example output:
{"message":"Policy accepted","reason":"Valid","status":"True","type":"Accepted", ...}Create an HTTPRoute that routes requests for the
tunnel.examplehostname to the Backend.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: tunnel namespace: httpbin spec: parentRefs: - name: http namespace: kgateway-system hostnames: - tunnel.example rules: - backendRefs: - name: httpbin-via-proxy group: gateway.kgateway.dev kind: Backend EOFSend a request to the httpbin app through the gateway proxy. Verify that you get back a 200 HTTP response.
curl -i http://$INGRESS_GW_ADDRESS:8080/headers -H "host: tunnel.example"Example output:
HTTP/1.1 200 OK ...Check the access log of the forward proxy. Verify that the log contains a
CONNECTrequest to the httpbin app and that you see theProxy-Authorizationheader. This log entry confirms that the gateway proxy connected to httpbin through the forward proxy.kubectl exec -n httpbin deploy/egress-proxy -- cat /var/log/squid/access.logExample output:
10.244.0.32 CONNECT httpbin.httpbin.svc.cluster.local:8000 200 "Proxy-Authorization: Basic dXNlcjpwYXNz"
Cleanup
You can remove the resources that you created in this guide.kubectl delete httproute tunnel -n httpbin --ignore-not-found
kubectl delete backendconfigpolicy httpbin-tunnel -n httpbin --ignore-not-found
kubectl delete Backend httpbin-via-proxy -n httpbin --ignore-not-found
kubectl delete secret egress-proxy-credentials -n httpbin --ignore-not-found
kubectl delete deployment,service egress-proxy -n httpbin --ignore-not-found
kubectl delete configmap egress-proxy-config -n httpbin --ignore-not-found