Skip to main content

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.