Ksniff: capturando tráfico en Kubernetes

Miguel Fontanilla
Computación en la nube
Ksniff se distribuye como un plugin de kubectl (sí, kubectl puede extender sus funcionalidades con plugins 😉)

Ksniff: capturando tráfico en Kubernetes 🕵️‍♂️📦

Si trabajas en tu día a día con Kubernetes, seguramente tengas que lidiar con problemas en los contenedores y aplicaciones desplegadas regularmente. Las herramientas de logging y monitorización son especialmente útiles en este tipo de situaciones, ya que ayudan a interpretar lo que está pasando en el clúster o dentro de los propios contenedores. Además, es posible obetener información valiosa, de una forma sencilla, utilizando los clásicos subcomandos de kubectl como: kubectl describe, kubectl logs o kubectl exec.

Sin embargo, en ciertos escenarios, estas herramientas no son suficientes, ya que puede ser necesario examinar el tráfico entrante y saliente de los propios contenedores en los pods, por ejemplo para identificar problemas a nivel de protocolo TCP. En estos casos ¿Qué podemos hacer para inspeccionar este tipo de tráfico?

La respuesta es sencilla, seguir la misma estrategia que usaríamos para una máquina virtual o un ordenador físico: un capturador de paquetes. En este artículo se presenta Ksniff, un capturador de paquetes que se integra con kubectl desarrollado por Eldad Rudich.

¿Cómo funciona? 💻🤔

Ksniff se distribuye como un plugin de kubectl (sí, kubectl puede extender sus funcionalidades con plugins 😉) que permite utilizar tcpdump y Wireshark para capturar tráfico en un pod específico dentro del clúster. Ksniff utiliza kubectl para copiar el binario de tcpdump (el capturador de paquetes) al contenedor seleccionado, y puede redireccionar la información capturada a una instancia local de Wireshark.

Puede que te preguntes ahora, ¿cómo funcionaría el binario en contenedores sin shell, o en contenedores que no disponen de permisos para capturar tráfico de red? Para este tipo de casos, Ksniff cuenta con un flag (-p) que permite capturar tráfico en modo 'privilegiado'. Este mecanismo es muy útil para capturar tráfico en contenedores distroless, que solo incorporan la aplicación a ejecutar y las librerías y dependencias necesarias.

Al utilizar el flag -p , Ksniff desplegará un pod en el mismo nodo en el que el pod seleccionado se encuentre, proporcionándole al primero acceso al demonio Docker del nodo. El contenedor de este 'pod auxiliar' se crea dentro del mismo namespace de red en el que se encuentra el contenedor objetivo, permitiendo la captura de tráfico.

Wireshark 📡🦈

Wireshark es un analizador de paquetes que se basa en pcap, una API para la captura de paquetes de red. Si no tienes experiencia previa con Wireshark, puedes encontrar bastante información y tutoriales en su documentación oficial.

Resumiendo, además de incorporar capacidades de captura de paquetes, Wireshark incluye un interfaz gráfico muy útil para analizar los paquetes capturados, filtrando por protocolo, puerto y un gran rango de atributos de los paquetes.

Para instalar Wireshark, solo necesitas descargar el instalador para tu SO en esta documentación y seguir los pasos indicados por el propio instalador.

Instalando Ksniff ⬇️⚙️

La forma más sencilla de instalar Ksniff es utilizar Krew, un gestor de plugins para kubectl. Si no lo has instalado aún, puedes hacerlo ejecutando los siguientes comandos. Asegúrate de que git está instalado en tu máquina.

(
 set -x; cd "$(mktemp -d)" &&
 curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/krew.tar.gz" &&
 tar zxvf krew.tar.gz &&
 KREW=./krew-"$(uname | tr '[:upper:]' '[:lower:]')_$(uname -m | sed -e 's/x86_64/amd64/' -e 's/arm.*$/arm/')" &&
 "$KREW" install krew
)
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"

Una vez que Krew haya sido instalado, solo necesitarás ejecutar el siguiente comando para instalar Ksniff.

kubectl krew install sniff

Si todo ha funcionado como debe, deberías ver una salida similar en tu terminal al ejecutar el comando kubectl sniff.

Capturando tráfico 🕵️‍♂️💻

Para desarrollar este ejemplo, utilicé un clúster local de Kubernetes (Docker Desktop), pero puede replicarse en cualquier tipo de clúster, tanto gestionado como no gestionado.

En primer lugar tendremos que desplegar una aplicación que genere y reciba tráfico en el clúster. En este caso desplegaremos un servidor web apache. Para mantener el ejemplo lo más sencillo posible, utilizaremos el Helm Chart de apache desarrollado por Bitnami. Si no has instalado Helm aún (venga, ¿quién se va a creer eso?😉), puedes descargarlo aquí. Además, puedes encontrar una introducción a Helm si lo necesitas en este artículo.

helm repo add bitnami https://charts.bitnami.com/bitnami
helm install web-server bitnami/apache

Tras ejecutar los comandos anteriores deberías tener un deployment de apache corriendo en tu clúster. En este caso, se expone como un servicio de tipo LoadBalancer. Puedes comprobar si el servidor es alcanzable a través del nombre de DNS o la IP del load balancer.

Una vez que el servicio haya sido desplegado, es el momento de lanzar el pod 'capturador' utilizando Ksniff. Para hacerlo, ejecuta el siguiente comando. Tras unos segundos, el pod arrancará y se lanzará Wireshark en tu máquina local, capturando tráfico en tiempo real.

kubectl sniff  <your-apache-pod-name> -p

Prueba a acceder al servidor utilizando un navegador; verás como aparecen nuevos paquetes HTTP en Wireshark. En la siguiente imagen puedes ver la respuesta HTTP que contiene el cuerpo (body) de la página.

Si inspeccionas el clúster mientras se lleva a cabo la captura (en un terminal diferente), podrás comprobar que se ha creado un pod de Ksniff en el mismo namespace en el que se encuentra el pod 'objetivo'.

Una vez que hayas acabado con la captura de paquetes, párala y cierra Wireshak. Ksniff eliminará el pod empleado para capturar tráfico una vez que se cierre Wireshark.

Ksniff soporta filtros basados en la sintaxis de tcpdump, por lo que por ejemplo, es posible capturar exclusivamente el tráfico dirigido al puerto 8080 (puerto del contenedor apache) ejecutando el siguiente comando.

kubectl sniff <your-apache-pod-name>  -f "port 8080" -p

Por último, capturaremos otro tipo de tráfico. En este caso, nos centraremos en el tráfico DNS del clúster. Para hacerlo, el pod 'objetivo' será uno de los pods del deployment de CoreDNS , que funciona como el resolver de DNS interno del clúster. Además, redireccionaremos la captura a un fichero pcap en lugar de mostrar la captura en tiempo real. Pero, no te preocupes, es posible importar dichas capturas posteriormente a Wireshark para analizarlas.

kubectl sniff <your-coredns-pod-name> -p -n kube-system -o dns.pcap

En este caso, el pod de Ksniff se despliega en el namespace kube-system, como puede observarse en la siguiente imagen.

Mientras Ksniff captura tráfico, generemos peticiones de resolución de DNS dentro del clúster ejecutando el siguiente comando en el contenedor de apache.

kubectl exec -it <your-apache-pod-name> -- curl kubesandclouds.com

Cuando acabes con la captura de tráfico, impórtala a Wireshark. La siguiente imagen muestra las peticiones y respuestas de DNS (utilizando el filtro dns) que se generaron para que el contenedor de apache pudiera conocer la IP de kubesandclouds.com.

TRUQUILLO: Puedes utilizar el flag -c en los contenedores multi pod para seleccionar un contenedor específico del que capturar tráfico.

Sigue aprendiendo👩‍💻👨‍💻

Si te ha gustado Ksniff, tómate tu tiempo para probarlo en tus clústers y descubrir las diferentes opciones que ofrece. Basándome en mi propia experiencia, puedo asegurar que a pesar de ser una herramienta sencilla, puede proporcionar un gran valor para el troubleshooting a nivel de red. Puedes obtener más información en el Repositorio de GitHub de Ksniff.

Miguel Fontanilla

DevOps/Cloud Engineer at Orange. Cloud Architecture, Virtualization, Services Orchestration, Automation and Optimization. Always learning.

Related Posts

Únete a nuestra Newsletter

Lidera la Conversación en la Nube