Migración de OpenVPN a WireGuard para consolidar redes en una red L2

Migración de OpenVPN a WireGuard para consolidar redes en una red L2

Me gustaría compartir mi experiencia de combinar redes en tres apartamentos geográficamente distantes, cada uno de los cuales usa enrutadores con OpenWRT como puerta de enlace, en una red común. Al elegir un método para combinar redes entre L3 con enrutamiento de subred y L2 con puente, cuando todos los nodos de la red estarán en la misma subred, se dio preferencia al segundo método, que es más difícil de configurar, pero brinda más oportunidades, ya que transparente Se planeó el uso de tecnologías en la red creada Wake-on-Lan y DLNA.

Parte 1: Antecedentes

Inicialmente, se eligió OpenVPN como protocolo para implementar esta tarea, ya que, en primer lugar, puede crear un dispositivo tap que se puede agregar al puente sin ningún problema y, en segundo lugar, OpenVPN admite la operación sobre el protocolo TCP, que también era importante, porque ninguno de los apartamentos tenía una dirección IP dedicada y no pude usar STUN porque, por alguna razón, mi ISP bloquea las conexiones UDP entrantes de sus redes, mientras que el protocolo TCP me permitió reenviar el puerto del servidor VPN en VPS alquilado usando SSH. Sí, este enfoque genera una gran carga, ya que los datos se cifran dos veces, pero no quería introducir el VPS en mi red privada, ya que aún existía el riesgo de que terceros obtuvieran el control sobre él, por lo tanto, tener tal dispositivo en la red doméstica era extremadamente indeseable y se decidió pagar por la seguridad con una gran sobrecarga.

Para reenviar el puerto en el enrutador en el que se planeó implementar el servidor, se utilizó el programa sshtunnel. No describiré las complejidades de su configuración; esto se hace con bastante facilidad, solo noto que su tarea era reenviar el puerto TCP 1194 desde el enrutador al VPS. A continuación, se configuró el servidor OpenVPN en el dispositivo tap0, que se conectó al puente br-lan. Después de verificar la conexión al servidor recién creado desde la computadora portátil, quedó claro que la idea del reenvío de puertos se justificaba y mi computadora portátil se convirtió en miembro de la red del enrutador, aunque no estaba físicamente en ella.

El asunto se quedó pequeño: era necesario distribuir las direcciones IP en diferentes apartamentos para que no entraran en conflicto y configurar los enrutadores como clientes OpenVPN.
Se seleccionaron las siguientes direcciones IP de enrutadores y rangos de servidores DHCP:

  • 192.168.10.1 con una gama 192.168.10.2 - 192.168.10.80 para servidor
  • 192.168.10.100 con una gama 192.168.10.101 - 192.168.10.149 para un enrutador en el apartamento No. 2
  • 192.168.10.150 con una gama 192.168.10.151 - 192.168.10.199 para un enrutador en el apartamento No. 3

También era necesario asignar exactamente estas direcciones a los enrutadores del cliente del servidor OpenVPN agregando la línea a su configuración:

ifconfig-pool-persist /etc/openvpn/ipp.txt 0

y agregando las siguientes líneas al archivo /etc/openvpn/ipp.txt:

flat1_id 192.168.10.100
flat2_id 192.168.10.150

donde flat1_id y flat2_id son los nombres de dispositivos especificados al generar certificados para conectarse a OpenVPN

Luego, los clientes OpenVPN se configuraron en los enrutadores, los dispositivos tap0 en ambos se agregaron al puente br-lan. En esta etapa, todo parecía estar en orden, ya que las tres redes se ven y funcionan como un todo. Sin embargo, resultó un detalle no muy agradable: a veces los dispositivos podían obtener una dirección IP que no era de su enrutador, con todas las consecuencias consiguientes. Por alguna razón, el enrutador en uno de los apartamentos no tuvo tiempo de responder a DHCPDISCOVER a tiempo y el dispositivo recibió la dirección incorrecta. Me di cuenta de que necesito filtrar tales solicitudes en tap0 en cada uno de los enrutadores, pero resultó que iptables no puede funcionar con un dispositivo si es parte de un puente y ebtables debería venir a mi rescate. Lamentablemente, no estaba en mi firmware y tuve que reconstruir las imágenes para cada dispositivo. Al hacer esto y agregar estas líneas a /etc/rc.local de cada enrutador, se resolvió el problema:

ebtables -A INPUT --in-interface tap0 --protocol ipv4 --ip-protocol udp --ip-destination-port 67:68 -j DROP
ebtables -A INPUT --in-interface tap0 --protocol ipv4 --ip-protocol udp --ip-source-port 67:68 -j DROP
ebtables -A FORWARD --out-interface tap0 --protocol ipv4 --ip-protocol udp --ip-destination-port 67:68 -j DROP
ebtables -A FORWARD --out-interface tap0 --protocol ipv4 --ip-protocol udp --ip-source-port 67:68 -j DROP

Esta configuración duró tres años.

Parte 2: Presentación de WireGuard

Recientemente, Internet ha estado hablando cada vez más sobre WireGuard, admirando la simplicidad de su configuración, alta velocidad de transferencia, bajo ping con seguridad comparable. Al buscar más información al respecto, quedó claro que no admite el trabajo como miembro del puente ni el trabajo sobre el protocolo TCP, lo que me hizo pensar que todavía no hay alternativas a OpenVPN para mí. Así que dejé de conocer WireGuard.

Hace unos días, se difundió la noticia a través de los recursos de una forma u otra relacionada con TI de que WireGuard finalmente se incluirá en el kernel de Linux, a partir de la versión 5.6. Los artículos de noticias, como siempre, elogiaron a WireGuard. Nuevamente me sumergí en la búsqueda de formas de reemplazar el viejo OpenVPN. Esta vez me encontré este articulo. Hablaba sobre la creación de un túnel Ethernet sobre L3 usando GRE. Este artículo me dio esperanza. No quedó claro qué hacer con el protocolo UDP. La búsqueda me llevó a artículos sobre el uso de socat junto con un túnel SSH para reenviar un puerto UDP; sin embargo, notaron que este enfoque solo funciona en modo de conexión única, lo que significa que varios clientes VPN serían imposibles. Se me ocurrió la idea de configurar un servidor VPN en un VPS y configurar GRE para los clientes, pero resultó que GRE no admite el cifrado, lo que conducirá al hecho de que si terceros obtienen acceso al servidor , todo el tráfico entre mis redes está en sus manos, lo que no me convenía en absoluto.

Nuevamente, se tomó la decisión a favor del cifrado redundante, utilizando VPN sobre VPN de acuerdo con el siguiente esquema:

VPN de capa XNUMX:
VPS es servidor con dirección interna 192.168.30.1
MS es por cliente VPS con dirección interna 192.168.30.2
MK2 es por cliente VPS con dirección interna 192.168.30.3
MK3 es por cliente VPS con dirección interna 192.168.30.4

VPN de capa XNUMX:
MS es servidor con dirección externa 192.168.30.2 e interna 192.168.31.1
MK2 es por cliente MS con la dirección 192.168.30.2 y tiene una IP interna de 192.168.31.2
MK3 es por cliente MS con la dirección 192.168.30.2 y tiene una IP interna de 192.168.31.3

* MS - enrutador-servidor en el apartamento 1, MK2 - enrutador en el apartamento 2, MK3 - enrutador en el apartamento 3
* Las configuraciones de dispositivos se publican en el spoiler al final del artículo.

Y así, los pings entre los nodos de la red 192.168.31.0/24 van, es hora de pasar a configurar el túnel GRE. Antes de eso, para no perder el acceso a los enrutadores, vale la pena configurar túneles SSH para reenviar el puerto 22 al VPS, de modo que, por ejemplo, un enrutador del apartamento 10022 estará disponible en el puerto 2 del VPS, y un el router del apartamento 11122 estará disponible en el puerto 3 del VPS router del apartamento XNUMX. Lo mejor es configurar el reenvío con el mismo sshtunnel, ya que restaurará el túnel en caso de que se caiga.

El túnel está configurado, puede conectarse a SSH a través del puerto reenviado:

ssh root@МОЙ_VPS -p 10022

A continuación, deshabilite OpenVPN:

/etc/init.d/openvpn stop

Ahora configuremos un túnel GRE en el enrutador del apartamento 2:

ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.2
ip link set grelan0 up

Y agregue la interfaz creada al puente:

brctl addif br-lan grelan0

Realicemos un procedimiento similar en el enrutador del servidor:

ip link add grelan0 type gretap remote 192.168.31.2 local 192.168.31.1
ip link set grelan0 up

Y, además, agregue la interfaz creada al puente:

brctl addif br-lan grelan0

a partir de este momento, los pings comienzan a ir con éxito a la nueva red y yo, con satisfacción, voy a tomar un café. Luego, para ver cómo funciona la red en el otro extremo del cable, trato de SSH en una de las computadoras en el apartamento 2, pero el cliente ssh se congela sin pedirme una contraseña. Intento conectarme a esta computadora a través de telnet en el puerto 22 y veo una línea desde la cual se puede entender que se está estableciendo la conexión, el servidor SSH está respondiendo, pero por alguna razón no me ofrece ingresar.

$ telnet 192.168.10.110 22
SSH-2.0-OpenSSH_8.1

Estoy tratando de conectarme a través de VNC y veo una pantalla negra. Me convenzo de que el problema está en la computadora remota, porque puedo conectarme fácilmente al enrutador desde este apartamento usando la dirección interna. Sin embargo, decido usar SSH en esta computadora a través del enrutador y me sorprende descubrir que la conexión se realiza correctamente y que la computadora remota funciona bien, pero tampoco se conecta a mi computadora.

Saco el dispositivo grelan0 del puente e inicio OpenVPN en el enrutador del apartamento 2 y me aseguro de que la red vuelva a funcionar correctamente y que las conexiones no se caigan. Buscando me encuentro con foros donde la gente se queja de los mismos problemas, donde se les aconseja subir la MTU. Dicho y hecho. Sin embargo, hasta que la MTU se configuró en un valor suficientemente grande de 7000 para dispositivos gretap, se observaron conexiones TCP interrumpidas o transmisiones lentas. Debido a la alta MTU para gretap, las MTU para las conexiones WireGuard del primer y segundo nivel se establecieron en 8000 y 7500, respectivamente.

Hice una configuración similar en el enrutador del apartamento 3, con la única diferencia de que se agregó una segunda interfaz gretap llamada grelan1 al enrutador del servidor, que también se agregó al puente br-lan.

Todo está funcionando. Ahora puede poner el ensamblado gretap en carga automática. Para esto:

Coloque estas líneas en /etc/rc.local en el enrutador en el apartamento 2:

ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.2
ip link set dev grelan0 mtu 7000
ip link set grelan0 up
brctl addif br-lan grelan0

Agregué esto a /etc/rc.local en el enrutador en el apartamento 3:

ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.3
ip link set dev grelan0 mtu 7000
ip link set grelan0 up
brctl addif br-lan grelan0

Y en el enrutador del servidor:

ip link add grelan0 type gretap remote 192.168.31.2 local 192.168.31.1
ip link set dev grelan0 mtu 7000
ip link set grelan0 up
brctl addif br-lan grelan0

ip link add grelan1 type gretap remote 192.168.31.3 local 192.168.31.1
ip link set dev grelan1 mtu 7000
ip link set grelan1 up
brctl addif br-lan grelan1

Después de reiniciar los enrutadores del cliente, descubrí que, por alguna razón, no se conectaron al servidor. Al conectarse a su SSH (afortunadamente, había configurado previamente sshtunnel para esto), se descubrió que WireGuard, por alguna razón, crea una ruta para el punto final, aunque es incorrecta. Entonces, para 192.168.30.2, la tabla de rutas se especificó en la tabla de rutas a través de la interfaz pppoe-wan, es decir, a través de Internet, aunque la ruta debería haber sido dirigida a través de la interfaz wg0. Después de eliminar esta ruta, se restauró la conexión. No pude encontrar instrucciones en ninguna parte sobre cómo obligar a WireGuard a no crear estas rutas. Además, ni siquiera entendí si esta es una característica de OpenWRT o de WireGuard en sí. Sin tener que lidiar con este problema durante mucho tiempo, simplemente agregué a ambos enrutadores en un script en bucle por un temporizador, una línea que eliminó esta ruta:

route del 192.168.30.2

En resumen

Todavía no he logrado un rechazo completo de OpenVPN, ya que a veces necesito conectarme a una nueva red desde una computadora portátil o un teléfono, y generalmente es imposible configurar un dispositivo gretap en ellos, pero a pesar de esto, obtuve una ventaja en la transferencia de datos la velocidad entre apartamentos y, por ejemplo, usar VNC ya no es un inconveniente. El ping disminuyó ligeramente, pero se volvió más estable:

Al usar OpenVPN:

[r0ck3r@desktop ~]$ ping -c 20 192.168.10.110
PING 192.168.10.110 (192.168.10.110) 56(84) bytes of data.
64 bytes from 192.168.10.110: icmp_seq=1 ttl=64 time=133 ms
...
64 bytes from 192.168.10.110: icmp_seq=20 ttl=64 time=125 ms

--- 192.168.10.110 ping statistics ---
20 packets transmitted, 20 received, 0% packet loss, time 19006ms
rtt min/avg/max/mdev = 124.722/126.152/136.907/3.065 ms

Al usar WireGuard:

[r0ck3r@desktop ~]$ ping -c 20 192.168.10.110
PING 192.168.10.110 (192.168.10.110) 56(84) bytes of data.
64 bytes from 192.168.10.110: icmp_seq=1 ttl=64 time=124 ms
...
64 bytes from 192.168.10.110: icmp_seq=20 ttl=64 time=124 ms
--- 192.168.10.110 ping statistics ---
20 packets transmitted, 20 received, 0% packet loss, time 19003ms
rtt min/avg/max/mdev = 123.954/124.423/126.708/0.675 ms

Se ve afectado principalmente por un ping alto a VPS, que es de aproximadamente 61.5 ms.

Sin embargo, la velocidad ha aumentado significativamente. Entonces, en un apartamento con router-servidor, tengo una velocidad de conexión a Internet de 30 Mbps, y en otros apartamentos, 5 Mbps. Al mismo tiempo, mientras usaba OpenVPN, no pude lograr una tasa de transferencia de datos entre redes de más de 3,8 Mbps según iperf, mientras que WireGuard la “bombeó” hasta los mismos 5 Mbps.

Configuración de WireGuard en VPS[Interface] Address = 192.168.30.1/24
ListenPort = 51820
PrivateKey = <ЗАКРЫТЫЙ_КЛЮЧ_ДЛЯ_VPS>

[Peer] PublicKey = <ОТКРЫТЫЙ_КЛЮЧ_VPN_1_МС>
AllowedIPs = 192.168.30.2/32

[Peer] PublicKey = <ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК2>
AllowedIPs = 192.168.30.3/32

[Peer] PublicKey = <ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК3>
AllowedIPs = 192.168.30.4/32

Configuración de WireGuard en MS (agregado a /etc/config/network)

#VPN первого уровня - клиент
config interface 'wg0'
        option proto 'wireguard'
        list addresses '192.168.30.2/24'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_1_МС'
        option auto '1'
        option mtu '8000'

config wireguard_wg0
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_1_VPS'
        option endpoint_port '51820'
        option route_allowed_ips '1'
        option persistent_keepalive '25'
        list allowed_ips '192.168.30.0/24'
        option endpoint_host 'IP_АДРЕС_VPS'

#VPN второго уровня - сервер
config interface 'wg1'
        option proto 'wireguard'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_2_МС'
        option listen_port '51821'
        list addresses '192.168.31.1/24'
        option auto '1'
        option mtu '7500'

config wireguard_wg1
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК2'
        list allowed_ips '192.168.31.2'

config wireguard_wg1ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.3

        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК3'
        list allowed_ips '192.168.31.3'

Configuración de WireGuard en MK2 (agregado a /etc/config/network)

#VPN первого уровня - клиент
config interface 'wg0'
        option proto 'wireguard'
        list addresses '192.168.30.3/24'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_1_МК2'
        option auto '1'
        option mtu '8000'

config wireguard_wg0
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_1_VPS'
        option endpoint_port '51820'
        option persistent_keepalive '25'
        list allowed_ips '192.168.30.0/24'
        option endpoint_host 'IP_АДРЕС_VPS'

#VPN второго уровня - клиент
config interface 'wg1'
        option proto 'wireguard'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_2_МК2'
        list addresses '192.168.31.2/24'
        option auto '1'
        option listen_port '51821'
        option mtu '7500'

config wireguard_wg1
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МС'
        option endpoint_host '192.168.30.2'
        option endpoint_port '51821'
        option persistent_keepalive '25'
        list allowed_ips '192.168.31.0/24'

Configuración de WireGuard en MK3 (agregado a /etc/config/network)

#VPN первого уровня - клиент
config interface 'wg0'
        option proto 'wireguard'
        list addresses '192.168.30.4/24'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_1_МК3'
        option auto '1'
        option mtu '8000'

config wireguard_wg0
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_1_VPS'
        option endpoint_port '51820'
        option persistent_keepalive '25'
        list allowed_ips '192.168.30.0/24'
        option endpoint_host 'IP_АДРЕС_VPS'

#VPN второго уровня - клиент
config interface 'wg1'
        option proto 'wireguard'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_2_МК3'
        list addresses '192.168.31.3/24'
        option auto '1'
        option listen_port '51821'
        option mtu '7500'

config wireguard_wg1
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МС'
        option endpoint_host '192.168.30.2'
        option endpoint_port '51821'
        option persistent_keepalive '25'
        list allowed_ips '192.168.31.0/24'

En las configuraciones descritas para la VPN de segundo nivel, especifico el puerto 51821 para los clientes de WireGuard, en teoría esto no es necesario, ya que el cliente establecerá una conexión desde cualquier puerto libre no privilegiado, pero lo hice para que todas las conexiones entrantes se puede denegar en las interfaces wg0 de todos los enrutadores, excepto las conexiones UDP entrantes en el puerto 51821.

Espero que el artículo sea útil para alguien.

PS Además, quiero compartir mi script que me envía una notificación PUSH a mi teléfono en la aplicación WirePusher cuando aparece un nuevo dispositivo en mi red. Aquí hay un enlace al guión: github.com/r0ck3r/device_discover.

ACTUALIZACIÓN: Configuración de servidores y clientes OpenVPN

Servidor OpenVPN

client-to-client

ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/vpn-server.crt
dh /etc/openvpn/server/dh.pem
key /etc/openvpn/server/vpn-server.key

dev tap
ifconfig-pool-persist /etc/openvpn/ipp.txt 0
keepalive 10 60
proto tcp4
server-bridge 192.168.10.1 255.255.255.0 192.168.10.80 192.168.10.254
status /var/log/openvpn-status.log
verb 3
comp-lzo

Cliente OpenVPN

client
tls-client
dev tap
proto tcp
remote VPS_IP 1194 # Change to your router's External IP
resolv-retry infinite
nobind

ca client/ca.crt
cert client/client.crt
key client/client.key
dh client/dh.pem

comp-lzo
persist-tun
persist-key
verb 3

Usé easy-rsa para generar certificados.

Fuente: habr.com

Añadir un comentario