Files
kubernetes/wireguard

WireGuard en Kubernetes (wg-easy)

Este despliegue proporciona acceso VPN mediante WireGuard dentro de un clúster Kubernetes, utilizando la imagen wg-easy, expuesto por un Service tipo NodePort y gestionado con reglas de iptables en el host.

🔐 ¿Qué es WireGuard?

WireGuard es un protocolo de VPN moderno, rápido y seguro, que utiliza criptografía de última generación para establecer túneles cifrados entre dispositivos.

Este despliegue usa wg-easy, una interfaz web y API para administrar fácilmente instancias de WireGuard.


⚖️ Estructura del despliegue

.
├── daemonset
│   └── iptables-daemonset.yaml     # Reglas de NAT
├── deployments
│   └── deployment.yaml             # Despliegue de wg-easy
├── ingress
│   └── ingress.yaml                # (opcional)
├── pvc
│   └── pvc.yaml                    # Configuración persistente
├── services
│   └── service.yaml                # Service tipo NodePort
├── secret.yaml                    # HASH de contraseña para interfaz web
├── namespace.yaml
└── kustomization.yaml

🚫 Seguridad y acceso

Contraseña

Para acceder a la interfaz web protegida de wg-easy, se define un Secret con un hash de contraseña.

Puedes generar el hash con htpasswd (instalado con apache2-utils):

apt install apache2-utils
htpasswd -nBC 10 "admin"

Copia el resultado (sin el admin:) en el archivo secret.yaml como PASSWORD_HASH.


📁 Volúmenes

La configuración de WireGuard se guarda en /etc/wireguard dentro del contenedor. Esto se monta con un PersistentVolumeClaim para que los peers se conserven aunque se reinicie el pod.


🛂 Puertos y exposición

El Service es tipo NodePort, lo que significa:

  • Puerto del contenedor WireGuard: 51820/UDP

  • Puerto de la interfaz web: 51821/TCP

  • Puerto NodePort expuesto:

    • UDP: 31820 (WireGuard)
    • TCP: 31821 (Interfaz Web)

Los NodePort deben estar en el rango 3000032767 (por defecto en Kubernetes).

El router debe redirigir estos puertos al nodo donde corre wg-easy.

Ejemplo de reenvío:

  • 31820/UDP → nodo tartaro, puerto 31820
  • 31821/TCP → nodo tartaro, puerto 31821

🚀 Reenvío de tráfico y NAT

WireGuard entrega a los clientes direcciones como 192.168.200.x, pero por defecto no tendrían acceso a otras redes como:

  • Red de administración: 192.168.1.0/24
  • Red de pods (Flannel): 10.42.0.0/16
  • Red Multus (ejemplo): 192.168.201.0/24

Para ello, se despliega un DaemonSet que aplica reglas iptables directamente en el host físico:

iptables -t nat -A POSTROUTING -s 192.168.200.0/24 -d 192.168.1.0/24 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.200.0/24 -d 10.42.0.0/16 -j MASQUERADE

Con esto, los paquetes generados por los clientes WireGuard se traducen a la IP del host, y así acceden a otras redes internas.


🛠️ Acceso a redes aisladas con Multus

Si se desea permitir acceso a una red definida por un NetworkAttachmentDefinition (NAD) con Multus, como por ejemplo:

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: br-servicios
  namespace: default
spec:
  config: '{
    "cniVersion": "0.3.1",
    "type": "bridge",
    "bridge": "br-servicios",
    "ipam": {
      "type": "host-local",
      "subnet": "192.168.201.0/24",
      "rangeStart": "192.168.201.100",
      "rangeEnd": "192.168.201.199"
    }
  }'

Entonces basta con añadir una regla más en el DaemonSet:

iptables -t nat -A POSTROUTING -s 192.168.200.0/24 -d 192.168.201.0/24 -j MASQUERADE

No es necesario conectar el contenedor de wg-easy directamente a esta red: el tráfico se enruta y NATea desde el host físico.


🔄 Reaplicar cambios

Siempre que modifiques el DaemonSet o el Deployment, puedes aplicar los cambios con:

kubectl apply -k .

Resultado

Una vez desplegado y con el reenvío del router correctamente configurado, puedes acceder a la interfaz web en:

https://manabo.org:31821

Y configurar tus clientes WireGuard escaneando el QR generado, o descargando el archivo de configuración.

Los clientes podrán acceder a:

  • 192.168.1.0/24 (red local)
  • 10.42.0.0/16 (pods del clúster)
  • 192.168.201.0/24 (red multus, si se añade la regla correspondiente)