Network Security
Security in service-to-service communication: TLS, mTLS, service mesh, network policies, and segmentation in distributed architectures.
Why the network is an attack vector
In a monolithic architecture, communication between components happens within the same process — there’s no network involved. In microservices, every call between services travels over the network, which introduces new attack vectors:
- Interception: an attacker can capture traffic between services
- Impersonation: a malicious service can pose as another
- Man-in-the-middle: an attacker can modify data in transit
- Lateral movement: if a service is compromised, the attacker can access other services on the same network
Network security in microservices isn’t optional — it’s fundamental.
TLS (Transport Layer Security)
TLS encrypts communication between two endpoints, guaranteeing confidentiality and integrity.
How TLS works
sequenceDiagram
participant C as Cliente
participant S as Servidor
C->>S: ClientHello (versiones TLS, cipher suites)
S->>C: ServerHello (versión elegida, cipher suite)
S->>C: Certificado del servidor
C->>C: Verificar certificado contra CA
C->>S: Clave pre-master cifrada con clave pública del servidor
Note over C,S: Ambos derivan la clave de sesión
C->>S: Datos cifrados con clave de sesión
S->>C: Datos cifrados con clave de sesión
Recommended configuration
# Configuración TLS moderna
tls:
min_version: TLSv1.2 # Mínimo TLS 1.2, preferir 1.3
cipher_suites:
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- TLS_AES_128_GCM_SHA256
certificate: /etc/certs/server.crt
private_key: /etc/certs/server.key
ca_certificate: /etc/certs/ca.crt
TLS in practice
- TLS termination at the Gateway: external traffic arrives encrypted at the API Gateway, which terminates TLS and routes internally
- End-to-end TLS: traffic stays encrypted from the client all the way to the final service
- Re-encryption: the Gateway terminates external TLS and establishes a new internal TLS connection
mTLS (Mutual TLS)
In standard TLS, only the server presents a certificate. In mTLS, both parties authenticate each other.
Why mTLS in microservices
On an internal network with dozens of services, you need to guarantee that:
- The calling service is who it claims to be
- The responding service is who it claims to be
- No one can intercept or modify the communication
sequenceDiagram
participant A as Servicio A
participant B as Servicio B
A->>B: ClientHello
B->>A: ServerHello + Certificado de B
A->>A: Verificar certificado de B
B->>A: Solicitar certificado de A
A->>B: Certificado de A
B->>B: Verificar certificado de A
Note over A,B: Ambos verificados, comunicación cifrada
A->>B: Request cifrado
B->>A: Response cifrado
Certificate management
The biggest challenge with mTLS is managing certificates at scale:
- Each service needs its own certificate
- Certificates must be renewed before they expire
- An internal Certificate Authority (CA) is required
- Certificate revocation must be fast
# Ejemplo: certificado por servicio
service: orders-service
certificate:
common_name: orders-service.internal
san:
- orders-service.default.svc.cluster.local
- orders-service.production.svc.cluster.local
validity: 24h # Certificados de corta duración
auto_renewal: true # Renovación automática
issuer: internal-ca
Tools for mTLS
- cert-manager (Kubernetes): automates certificate issuance and renewal
- Vault (HashiCorp): PKI as a service, generates certificates on demand
- SPIFFE/SPIRE: identity framework for workloads, generates SVIDs (verifiable identities)
Service Mesh
A service mesh is a dedicated infrastructure layer for handling communication between services. It implements mTLS, observability, and traffic policies transparently.
How it works
Each service has a sidecar proxy that intercepts all network traffic:
[Servicio A] ←→ [Proxy A] ←→ [Red] ←→ [Proxy B] ←→ [Servicio B]
(Envoy) (Envoy)
The service doesn’t need to implement TLS, retries, circuit breaking, or metrics — the proxy handles it.
Security benefits
- Automatic mTLS: the mesh manages certificates and encrypts all traffic between services
- Access policies: define which services can communicate with each other
- Observability: full visibility into traffic between services
- Transparent encryption: services don’t need additional security code
Example: access policy in Istio
# Solo el BFF puede llamar al servicio de órdenes
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: orders-service-policy
namespace: production
spec:
selector:
matchLabels:
app: orders-service
rules:
- from:
- source:
principals: ["cluster.local/ns/production/sa/bff-service"]
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/orders/*"]
Popular service meshes
| Mesh | Characteristics |
|---|---|
| Istio | The most complete, built on Envoy, large community |
| Linkerd | Lighter-weight, focused on simplicity and performance |
| Consul Connect | Integrated with HashiCorp Consul, good for hybrid environments |
Network Policies
In Kubernetes, Network Policies control which pods can communicate with each other at the network level.
By default: everything open
Without Network Policies, any pod can communicate with any other pod in the cluster. This is dangerous: if a pod is compromised, the attacker has access to the entire internal network.
Example: restricting access to the database service
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-access-policy
namespace: production
spec:
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: orders-service
- podSelector:
matchLabels:
app: users-service
ports:
- protocol: TCP
port: 5432
This policy states: only the orders-service and users-service pods can connect to the postgres pod on port 5432. Everything else is blocked.
Segmentation strategy
Zona pública: [API Gateway]
↓
Zona de aplicación: [BFF] [Auth Service]
↓
Zona de servicios: [Orders] [Users] [Payments]
↓
Zona de datos: [PostgreSQL] [Redis] [Kafka]
Each zone has policies that restrict access:
- The public zone can only talk to the application zone
- The application zone can talk to the services zone
- Only the services zone can talk to the data zone
- The data zone doesn’t initiate outbound connections
DNS and secure service discovery
In microservices, services are discovered dynamically. This mechanism must also be secure:
- Internal DNS: use private DNS within the cluster, don’t expose internal service names
- Encrypted service discovery: discovery queries must be authenticated
- Endpoint validation: verify that the discovered service is legitimate before sending data
# Kubernetes: los servicios se resuelven por DNS interno
# orders-service.production.svc.cluster.local
# Este DNS no es accesible desde fuera del cluster
Network security best practices
- Encrypt all traffic: use TLS or mTLS for all communication, even internal
- Apply least-privilege access: each service can only communicate with the services it needs
- Segment the network: separate services into zones with different trust levels
- Monitor traffic: detect anomalous patterns that might indicate an attack
- Rotate certificates frequently: short-lived certificates (hours, not years)
- Use a service mesh: simplifies implementing network security at scale
- Deny by default: Network Policies should deny everything and explicitly allow
Summary
Network security in distributed architectures requires encrypting all communication (TLS/mTLS), authenticating every service, segmenting the network into trust zones, and monitoring traffic. A service mesh greatly simplifies this task by handling mTLS, access policies, and observability transparently. Kubernetes Network Policies complement the mesh by controlling access at the network level. The fundamental rule is: never trust the network, even if it’s “internal.”