Este repositorio contiene un cliente y un servidor que le permiten canalizar el tráfico TCP y UDP a través de otros protocolos de red.
Actualmente, los túneles admitidos son:
La herramienta principal está escrita en Rust y las pruebas de un extremo a otro están escritas en Python.
docker pull ghcr.io/dlemel8/tunneler-server:latest
docker pull ghcr.io/dlemel8/tunneler-client:latest
cargo --version || curl --proto ' =https ' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo build --release
También hay un archivo acoplable si prefiere crear una imagen acoplable local.
docker run -e LOCAL_PORT=45301
-e REMOTE_PORT=5201
-e REMOTE_ADDRESS=localhost
-e TUNNELED_TYPE=udp
--rm -p 45301:45301 ghcr.io/dlemel8/tunneler-server:latest tcp
./target/release/client
--tunneled-type tcp
--remote-address 1.1.1.1
--remote-port 53
--log-level debug
dns
--read-timeout-in-milliseconds 100
--idle-client-timeout-in-milliseconds 30000
Ejecute la imagen de Docker o el binario compilado con --help
para obtener más información
cargo test --all-targets
python3 -m pip install -r e2e_tests/requirements.txt
PYTHONPATH=. python3 -m pytest -v
Este repositorio contiene algunos ejemplos de implementación de servidores usando Docker Compose:
Puede ejecutar cada ejemplo localmente o implementarlo usando Terraform y Ansible. Ver más información aquí.
Cada ejecutable contiene 2 componentes que se comunican a través de un canal de flujos de cliente (una tupla de lector y escritor de bytes):
El tráfico basado en TCP se convierte trivialmente en flujo. La conversión de tráfico basada en UDP depende del protocolo del túnel.
El tráfico basado en UDP también necesita una forma de identificar a los clientes existentes para continuar con sus sesiones. La solución es una caché de clientes en memoria que asigna un identificador del cliente a su flujo.
Para convertir el tráfico UDP en una secuencia, un encabezado de 2 bytes (en big endian) precede a cada carga útil del paquete.
UDP Listener utiliza la dirección del par del paquete entrante como clave para su caché de clientes.
Tenemos algunos desafíos aquí:
Para resolver esos desafíos, cada sesión de cliente comienza generando una ID de cliente aleatoria (4 caracteres alfanuméricos). El cliente lee los datos para hacer un túnel y los ejecuta a través de una canalización de codificadores:
Luego, los datos codificados se utilizan como nombre de una consulta DNS TXT.
Si posee un servidor DNS autorizado, el cliente puede enviar la solicitud a un solucionador de DNS recursivo. Resolver obtendrá su IP de su registrador de nombres de dominio y reenviará la solicitud a su IP. Otra opción (más rápida pero más obvia para cualquier analizador de tráfico) es configurar el cliente para que envíe la solicitud directamente a su IP (en el puerto UDP/53 o en cualquier otro puerto que el servidor esté escuchando).
El servidor decodifica los datos (ignorando cualquier tráfico que no sea del cliente) y utiliza la ID del cliente como clave para la caché de sus clientes.
Para manejar respuestas grandes del servidor y ACK TCP vacíos, se utiliza el tiempo de espera de lectura tanto en el cliente como en el servidor. Si el tiempo de espera de lectura expira, se enviará un mensaje vacío. Tanto el cliente como el servidor utilizan el tiempo de espera de inactividad para detener el reenvío y limpiar los recursos locales.
Para implementar la autenticación mutua, utilizamos una Autoridad de certificación privada:
Tanto el cliente como el servidor están configurados para usar su clave y certificado en el protocolo de enlace TLS. El certificado de CA se utiliza como certificado raíz.
Dado que se utiliza la extensión de indicación de nombre de servidor, el cliente solicita un nombre de servidor específico y el servidor entrega su certificado solo si se solicitó ese nombre. El nombre del servidor también debe formar parte del certificado, por ejemplo como nombre alternativo del sujeto.