Cloud Native 19 min read

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.

Raymond Ops
Raymond Ops
Raymond Ops
How Istio Sidecar Hijacks Traffic: Deep Dive into iptables and xDS

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

test

accesses the

nginx

service, 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_OUTPUT

chain, 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_INBOUND

chain, 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-forward

and

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.

Traffic flow diagram
Traffic flow diagram
kubernetesistioService MeshEnvoySidecarxDS
Raymond Ops
Written by

Raymond Ops

Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.