API7 Docs
Ingress ControllerHow-To GuidesTraffic ManagementProxy UDP Traffic by Port

Proxy UDP Traffic by Port

Learn how to configure APISIX or API7 Ingress Controller to proxy UDP traffic by port.

Route UDP traffic to an echo Service based on the incoming gateway port using either a Gateway API UDPRoute or an APISIX CRD stream route.

Prerequisite

  1. Complete Set Up Ingress Controller and Gateway.

Start an Example Upstream Service

Create a Kubernetes manifest for a UDP echo server that listens on port 9000:

udp-echo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: udp-echo
  namespace: aic
spec:
  replicas: 1
  selector:
    matchLabels:
      app: udp-echo
  template:
    metadata:
      labels:
        app: udp-echo
    spec:
      containers:
        - name: udp-echo
          image: python:3-alpine
          command: ["python", "-u", "-c"]
          args:
            - |
              import socket
              sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
              sock.bind(('', 9000))
              print("UDP echo server listening on port 9000")
              while True:
                  data, addr = sock.recvfrom(1024)
                  sock.sendto(data, addr)
          ports:
            - containerPort: 9000
              protocol: UDP
---
apiVersion: v1
kind: Service
metadata:
  name: udp-echo
  namespace: aic
spec:
  selector:
    app: udp-echo
  ports:
    - name: udp
      port: 9000
      targetPort: 9000
      protocol: UDP

Apply the configuration to your cluster:

kubectl apply -f udp-echo.yaml

Enable Gateway Stream Proxy

Upgrade your gateway to enable stream mode and set UDP listening port 9300:

helm upgrade -n aic apisix apisix/apisix \
  --set ... \ # add other parameters
  --set "service.stream.enabled=true" \
  --set "service.stream.udp[0]=9300"

Configure UDP Routing

In this section, you will configure a route that listens for UDP traffic on port 9300.

Update your Gateway manifest file to define a listener for UDP traffic:

gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  namespace: aic
  name: apisix
spec:
  gatewayClassName: apisix
  listeners:
  - name: http
    protocol: HTTP
    port: 80
  - name: udp
    protocol: UDP
    port: 9300
    allowedRoutes:
      kinds:
      - kind: UDPRoute
  infrastructure:
    parametersRef:
      group: apisix.apache.org
      kind: GatewayProxy
      name: apisix-config

Create a Kubernetes manifest for a UDPRoute:

udp-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: UDPRoute
metadata:
  name: stream-route-udp
  namespace: aic
spec:
  parentRefs:
  - name: apisix
    sectionName: udp
  rules:
  - backendRefs:
    - name: udp-echo
      port: 9000

When listener_port_match_mode is explicit or auto, the sectionName: udp reference adds a server_port match for 9300. The Gateway listener port must equal the physical APISIX stream listener port. The default off mode does not add this match.

Apply the configuration to your cluster:

kubectl apply -f gateway.yaml -f udp-route.yaml

Set the Upstream Transport

Set the backend scheme to udp. L4 schemes apply only to stream routes.

Attach a BackendTrafficPolicy to the backend Service:

udp-upstream-policy.yaml
apiVersion: apisix.apache.org/v1alpha1
kind: BackendTrafficPolicy
metadata:
  name: udp-echo-transport
  namespace: aic
spec:
  targetRefs:
  - group: ""
    kind: Service
    name: udp-echo
    sectionName: udp
  scheme: udp

Apply the policy:

kubectl apply -f udp-upstream-policy.yaml

To attach stream plugins to the UDPRoute, see Apply Plugins to L4 Routes.

Verify

kubectl port-forward supports only TCP and cannot verify UDP proxying. Run a temporary pod inside the cluster to send UDP packets to the gateway:

kubectl run -it --rm test-udp-proxy --image=busybox --namespace=aic -- /bin/sh

Once inside the pod, run the following command to send a UDP packet to the gateway:

echo "UDP Testing" | nc -u -w1 <gateway-service-name> 9300

You should see the message UDP Testing echoed back.