How Istio Sidecar Hijacks Traffic: Deep Dive into iptables and xDS
This article explains how Istio's sidecar proxy uses Envoy, iptables rules, and the xDS API to intercept and redirect traffic between Kubernetes pods, detailing the startup injection, traffic hijacking process, and how configuration is dynamically generated by istiod.
What is Istio
Istio is an open‑source service mesh that provides a uniform way to connect, protect, monitor and manage micro‑service applications. It solves the complexity of service‑to‑service communication by offering load balancing, mutual authentication, observability and resilience features such as retries and circuit breaking.
What is a sidecar
A sidecar is a design pattern where an auxiliary container runs alongside the business container. All inbound and outbound traffic passes through the sidecar, which can implement functions like circuit breaking, rate limiting, monitoring and logging, keeping the business container lightweight.
In Istio the sidecar uses Envoy, a high‑performance proxy that supports HTTP/1.1, HTTP/2, gRPC, TCP and provides load balancing, circuit breaking, rate limiting and monitoring. Envoy is a C++ project with excellent performance. Istiod updates Envoy configuration via a gRPC stream.
Startup method
When a namespace has the label
istio-injection=enabled, Istio’s mutating admission webhook automatically injects the sidecar container and an init container into each pod. The init container configures the network namespace, which is shared by all containers in the pod.
Traffic hijacking method
In the example where a pod in namespace
testaccesses the
nginxservice, the request first goes through the pod’s sidecar, is DNAT‑ed to port 15006 (Envoy), which forwards it to the nginx pod IP (10.244.0.73). Inside the nginx pod, the inbound sidecar again intercepts the traffic, DNAT‑s it to port 15006, and finally forwards it to the nginx container.
Outbound traffic from the test container hits the
ISTIO_OUTPUTchain, is redirected to
ISTIO_REDIRECT, DNAT‑ed to port 15001 (Envoy) and sent to the nginx pod IP.
Inbound traffic to the nginx pod hits the
ISTIO_INBOUNDchain, is redirected to
ISTIO_IN_REDIRECT, DNAT‑ed to port 15006 (Envoy) and then to the nginx container.
xDS
Istio uses the xDS API to dynamically configure Envoy. The main discovery services are:
CDS – Cluster Discovery Service
EDS – Endpoint Discovery Service
LDS – Listener Discovery Service
RDS – Route Discovery Service
SDS – Secret Discovery Service
HDS – Health Discovery Service
ADS – Aggregated Discovery Service
Listeners define which ports Envoy listens on; routes map requests to clusters; clusters describe upstream services and endpoints. Istiod watches Kubernetes resources (services, endpoints, CRDs) and pushes configuration to sidecars via gRPC.
Data source
All xDS configuration originates from istiod, the control‑plane component of Istio. It aggregates service information such as the ClusterIP of a Service (e.g., 10.102.168.134 for
nginx) and the pod IP of its backing pod (10.244.0.73) and distributes it to the sidecars.
Configuration inspection
Envoy’s admin API can be accessed with
kubectl port-forwardand
curl localhost:15000/config_dump. Istioctl provides convenient commands to view listeners, routes, clusters and endpoints for a given pod.
Listener 15001
<code>ADDRESSES PORT MATCH DESTINATION
0.0.0.0 15001 ALL PassthroughCluster
0.0.0.0 15001 Addr:*:15001 Non-HTTP/Non-TCP
</code>Listener for service IP 10.102.168.134:80
<code>ADDRESSES PORT MATCH DESTINATION
10.102.168.134 80 Trans:raw_buffer; App:http/1.1,h2c Route:nginx.test.svc.cluster.local:80
10.102.168.134 80 ALL Cluster:outbound|80||nginx.test.svc.cluster.local
</code>Route configuration
<code>virtualHosts:
- domains: ["*"]
routes:
- match: { prefix: "/" }
route:
cluster: outbound|80||nginx.test.svc.cluster.local
</code>Cluster definition
<code>name: outbound|80||nginx.test.svc.cluster.local
type: EDS
edsServiceName: outbound|80||nginx.test.svc.cluster.local
</code>Endpoint
<code>address: 10.244.0.73
portValue: 80
edsHealthStatus: HEALTHY
</code>Server sidecar handling
Inbound listener on port 80 forwards traffic to the
inbound|80||cluster, which ultimately routes to the nginx container’s port 80.
Raymond Ops
Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.