Túnel IP muy sencillo, basado en DTLS.
Si no es necesario un cifrado seguro, ¿puede considerar utilizar el utun más ligero?
go install github.com/taoso/dtun/cmd/dtun
# 服务端
dtun -key foo
# 客户端
dtun -connect addr:port -key foo
Aquí hay una lista rápida de algunos factores a considerar.
No es fácil lograr un cifrado de datos de capa de transporte estable y confiable, por lo que siempre he usado TLS como protocolo subyacente.
TLS usa TCP y los datos cifrados también son datos TCP en gran medida. De esta manera, la transmisión de un paquete de datos de capa superior requiere la confirmación de las conexiones TCP internas y externas. El problema de implementación de este tipo de TCP sobre TCP no es pequeño. Para más detalles, consulte: Referencia http://sites.inka.de/~bigred/devel/tcp-tcp.html.
Por lo tanto, es mejor utilizar la transmisión UDP. Naturalmente, DTLS se utiliza para el cifrado. Actualmente, DTLS no es compatible con 1.3 y el idioma go no lo admite oficialmente. Solo puede utilizar esta implementación de terceros https://github.com/pion/dtls.
Ya sea TLS o DTLS, generalmente es necesario crear un certificado. Este proceso ahora es gratuito, pero aún es complicado de configurar. Además, el certificado sólo resuelve el problema de cifrado y no resuelve el problema de autenticación. Normalmente sólo el cliente verifica el certificado del servidor. También puede dejar que el servidor verifique el certificado del cliente, pero esto es demasiado problemático.
Además, DTLS no tiene conexión y no solo puede realizar autenticación al crear una conexión como una conexión TCP.
Por lo tanto, es mejor completar la autenticación de ambos extremos al mismo tiempo durante el protocolo de enlace DTLS. Entonces elijo el modo de clave precompartida (PSK). Solo necesitamos usar -key
para especificar la clave maestra en ambos extremos para completar la autenticación de doble extremo. No se puede establecer una sesión DTLS si el cliente no conoce el PSK.
Además, PSK también necesita especificar un parámetro de sugerencia. Simplemente puedes considerarlo como el nombre de PSK. DTLS no está conectado, por lo que es difícil determinar si el cliente ha estado desconectado. Decidí tener un parámetro de sugerencia único para cada cliente. El servidor asigna dispositivos tun para obtener sugerencias. Si el cliente se desconecta y se vuelve a conectar, no se crearán varios dispositivos tun. Pero el efecto secundario es que los clientes del mismo hindit no pueden iniciar sesión al mismo tiempo.
Para admitir macos, el dispositivo tun solo se puede configurar en modo punto a punto. Si queremos hacer un enrutamiento y reenvío transparente, mire la imagen a continuación
pc <-----------> router <====== dtun ======> pc2 <---------> www
10.0.0.2/16 10.0.0.1/16 10.1.0.1/16 10.1.0.2/16
Esperamos que los paquetes enviados por la PC se reenvíen a la PC2 a través del enrutador y luego a la red externa. Generalmente, haremos NAT una vez en el enrutador y luego una vez en la pc2. La ventaja de esto es que pc2 no necesita conocer la configuración de red de la pc al enrutador. Pero las desventajas también son obvias: hay dos nat. El rendimiento de los enrutadores generalmente no es bueno, por lo que se debe evitar NAT tanto como sea posible.
Entonces, mi plan es enviar directamente el segmento de red 10.0.0.0/16 donde se encuentra la PC a la PC2 y agregar una ruta en la PC2.
ip route add 10.0.0.0/16 via 10.1.0.1
De esta manera, el enrutador puede reenviar los paquetes de la PC a la PC2 intactos y solo necesita realizar NAT una vez en la PC2.
A veces necesitamos especificar una lista blanca de enrutamiento. Utilice la ruta predeterminada en los segmentos de red de la lista blanca y reenvíe los demás a través del túnel.
Primero podemos agregar una ruta de lista blanca al enrutador y configurar el siguiente salto en la ruta predeterminada del enrutador. Luego especifique la IP pública de pc2 para tomar la ruta predeterminada del enrutador (¡clave!). agregado por última vez
ip route add 0.0.0.0/1 via 10.1.0.2
ip route add 128.0.0.0/1 via 10.1.0.2
0.0.0.0/1
y 128.0.0.1/1
aquí solo cubren todo el segmento de red. El efecto es equivalente al predeterminado, pero no sobrescribirá la ruta predeterminada. Si el túnel se cierra de forma anormal, todas las rutas relacionadas se eliminarán automáticamente, lo cual es muy estable.
Puede escribirlo como un script y ejecutarlo usando el parámetro -up
. Mi guión es el siguiente:
#! /bin/sh
# curl -S https://cdn.jsdelivr.net/gh/misakaio/chnroutes2@master/chnroutes.txt|grep -v '#'|xargs -I % ip route add % via $DEFAULT_GW 2>/dev/null
VPN_IP= $( ping your-server-name -c 1 | grep from | cut -d ' ' -f4 | cut -d: -f1 )
DEFAULT_GW= $( ip route | grep default | cut -d ' ' -f3 )
ip route add $VPN_IP /32 via $DEFAULT_GW
ip route add 0.0.0.0/1 via $PEER_IP
ip route add 128.0.0.0/1 via $PEER_IP