
Probablemente esta sea una pregunta bastante novata, pero...
Estoy en Ubuntu 18.04.3 LTS y tengo unvpnque quiero usar para algunas aplicaciones. revisénamespaced-openvpn
¡y funciona! La advertencia es que no puedo conectarme a esta aplicación localmente (para fines de administración).
¿Hay alguna manera de reenviar un determinado puerto dentro del túnel VPN al host local?¿Sin que el túnel VPN lo utilice para otros fines y, por lo tanto, filtre demasiada información?
Lo que ya puedo hacer:
- correr
namespaced-openvpn
-guion:sudo ./namespaced-openvpn --namespace vpn --config /etc/openvpn/vpn-xxxxx.ovpn
- Ejecute la aplicación dentro del espacio de nombres de la red:
sudo ip netns exec vpn application
Lo que quiero lograr:
- conectarse a la aplicación iniciada dentro del túnel VPN (por ejemplo, en el puerto
1234
) desde el host local real (enp3s0
adaptador ethernet) - reenviar este puerto de una manera que me permita acceder a él desde mis otras computadoras en mi LAN
Respuesta1
Con muchos años de retraso, pero en caso de que alguien se encuentre con esto, como desearía haberlo hecho durante los últimos días.
Espero que ayude a alguien.
Primero, aquí está namespaced-vpn, que realiza el 90% del trabajo de hacer que todo funcione.
https://github.com/slingamn/namespaced-openvpn
Y aquí hay una respuesta a una pregunta casi exactamente como esta que me ayudó mucho aunque no entendía qué y por qué se estaban haciendo las cosas. https://unix.stackexchange.com/questions/391193/how-to-forward-traffic-between-linux-network-namespaces
Intentaré explicar lo que he llegado a comprender después de muchas pruebas y errores utilizando los fragmentos de información que he encontrado en mis búsquedas.
Creo que la parte más relevante para reenviar conexiones a su servicio (no desde la PC en la que se ejecuta el servicio) es esta (observe el signo de exclamación después de PREROUTING):
iptables -t nat -A PREROUTING ! -s 10.0.0.0/24 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
Donde, 10.0.0.0/24
representa los rangos de IP que NO DESEA que se reenvíen.
Esto es principalmente para evitar un bucle de enrutamiento, donde cualquier servicio accesible mediante 10.0.0.0/24
la subred se enruta de regreso a sí mismo.
--dport 80 solo reenvía paquetes que buscan el puerto 80, es decir, una conexión de servidor web.
10.0.0.2
es la quinta interfaz que se ha movido DENTRO del espacio de nombres que ejecuta su servidor.
Esto hace que los paquetes que ingresan, NO de 10.0.0.0/24
la subred, que buscan el servicio del puerto 80 obtengan su IP de destino traducida a 10.0.0.2
. Ejemplo: 192.168.1.200:80
se convierte 10.0.0.2:80
en la que presumiblemente es la interfaz dentro del espacio de nombres en el que vive su servidor.
Tengo varios túneles VPN en funcionamiento en varios espacios de nombres. Si no agrego la regla PREROUTING a mis iptables, no puedo acceder al recurso desde fuera de mi PC en mi LAN.
Si desea que sea accesible desde su propia PC, debe agregar una regla como:
iptables --table nat --append OUTPUT --destination 192.168.1.2 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
Entonces, si escribe en el navegador, en la PC en la que está el servidor, 192.168.1.2
para acceder a su servidor, se enrutará 10.0.0.2
.
Intentaré explicar una parte de mi configuración...
Espacio de nombres de ejemplo:ip netns add ns_example
Crea el quinto par. Un lado permanecerá en el espacio de nombres raíz/normal (yo lo llamo host
), el otro lado irá al espacio de nombres con VPN.
ip link add dev ihost type veth peer name ivpn
Mueva el lado vpn del par veth al espacio de nombres de destino:
ip link set dev ivpn netns ns_example
Asigne ips al quinto par que ha creado.
Utilizo /32 porque sólo quiero asignar esta IP exacta y no un rango. De lo contrario, cuando abro los dispositivos, hay algunas rutas insertadas automáticamente en mi ip route
tabla y estropea mi enrutamiento para mis otros espacios de nombres.
Para asignar al lado anfitrión.
ip addr add 10.0.0.1/32 dev ihost
Para asignar al lado vpn, que se ha movido al espacio de nombres, debe anteponer el comando con ..
ip netns exec TARGET_NAMESPACE
Entonces, para asignar ip al lado vpn:
ip netns exec ns_example ip addr add 10.0.0.2/32 dev ivpn
Ahora abra las interfaces.
ip link set dev ihost up
ip netns exec ns_example ip link set dev ivpn up
Aquí agrego rutas e iptables para que el tráfico fluya entre ellas.
Desde el espacio de nombres raíz, para llegar al lado VPN ( 10.0.0.2
), use la interfaz ihost y reescriba la dirección de origen en el lado del espacio de nombres raíz ( 10.0.0.1
).
ip route add 10.0.0.2/32 dev ihost src 10.0.0.1
Haga exactamente lo mismo pero desde una perspectiva opuesta dentro del espacio de nombres de VPN.
ip netns exec ns_example ip route add 10.0.0.1/32 dev ivpn src 10.0.0.2
Ahora, agrego las mismas operaciones iptables
que están separadas ip route
pero realizo tareas similares.
Cualquier paquete que se envíe 10.0.0.2
obtiene su dirección de origen reescrita en10.0.0.1
iptables --table nat --append POSTROUTING --destination 10.0.0.2/32 --jump SNAT --to-source 10.0.0.1
Exactamente lo mismo, pero en perspectiva opuesta y dentro del espacio de nombres.
ip netns exec ns_example iptables --table nat --append POSTROUTING --destination 10.0.0.1/32 --jump SNAT --to-source 10.0.0.2
Si entiendo correctamente, las reescrituras de la dirección de origen son solo para asegurarse de que el paquete sepa cómo salir del espacio de nombres y viceversa.
Ahora, por ejemplo: para acceder a una webui de torrent en el espacio de nombres en el puerto 8080, hago esto.
Cualquier paquete que vaya a mi IP de LAN (Ejemplo: escribo 192.168.1.2:8080
en el navegador). Reescribirá el destino en el espacio de nombres que está ejecutando mi cliente torrent (Ejemplo 10.0.0.2
:).
iptables --table nat --append OUTPUT --destination 192.168.1.2/32 --protocol tcp --match tcp --dport 8080 --jump DNAT --to-destination 10.0.0.2
Esta regla específicamente solo reenvía el puerto 8080 y esta regla es para que usted pueda acceder al servicio EN LA PC en la que se ejecuta el servicio. Cualquier otra PC con acceso a la red 192.168.1.2:8080
necesita la regla PREROUTING que mencioné en la parte superior de la respuesta (simplemente cambie --dport 80 a --dport 8080 o cualquier puerto/protocolo que necesite).
Para las personas que utilizan este método y el script namespaced-vpn.py. Es posible que tengas problemas si alguna vez tienes que restablecer tu VPN. La VPN con espacio de nombres genera una excepción cuando detecta interfaces dentro de su espacio de nombres de destino distintas de la lo
interfaz de bucle invertido.
Aquí está la parte que me genera excepciones cuando uso namespaced-vpn.py cuando mi espacio de nombres de destino ya existe y tiene mis cinco pares.
if os.path.exists(os.path.join('/var/run/netns', namespace)):
adapters = _adapter_names(namespace)
if adapters != [b'lo']:
LOG.error('Namespace %s already has adapters %s, exiting.' % (namespace, adapters))
raise Exception
Aquí hay una modificación de ejemplo que he usado.
allowed_adapters = [b'lo', b'ivpn']
if os.path.exists(os.path.join('/var/run/netns', namespace)):
adapters = _adapter_names(namespace)
# Iterate and ensure all are in allowed list
for a in adapters:
if not a.split(b'@')[0] in allowed_adapters:
LOG.error('Namespace %s has non-whitelisted adapters %s, exiting.' % (namespace, adapters))
raise Exception
Solo asegúrese de agregar una llamada como esta para cada interfaz que espera que ya exista en la parte inferior de la función `def setup_namespace(namespace)`. reemplace LO con el nombre del dispositivo
subprocess.check_call(_enter_namespace_cmd(namespace) + [IP_CMD, 'link', 'set', 'LO', 'up'])
Ejemplo:
subprocess.check_call(_enter_namespace_cmd(namespace) + [IP_CMD, 'link', 'set', 'ivpn', 'up'])
Para las personas que ejecutan un cliente bittorrent conectado a la interfaz vpn, es posible que tengan problemas de que su cliente bloquee las conexiones aleatoriamente por cualquier motivo. Por ejemplo, te despiertas por la mañana y ves que todas tus hermosas descargas se congelaron 10 minutos después de que te fuiste.
Creo que este problema se debe al software vpn IE openvpn, que se vuelve a conectar al proveedor de vpn por cualquier motivo (error, reinicio de ping, etc.) y se le asigna una nueva dirección IP. Es posible que sea necesario desconectar la interfaz vpn durante una fracción de segundo para restablecer la configuración y esto falla en el cliente (qBittorrent hace esto con seguridad). Una "solución" que he empezado a investigar es escribir un script que detecte cuando la interfaz vpn recibe una nueva dirección IP o se desconecta por cualquier motivo. El script debe salir correctamente (importante: correctamente para evitar dañar algo/error del sistema de archivos) del cliente torrent y luego reiniciarlo. Todavía no tengo un script que funcione, pero parece ser un vector decente para resolver este problema.
Respuesta2
Bueno. Parece que esta pregunta es demasiado complicada para que alguien la responda o tal vez ya se haya respondido antes y nadie quiso responder.
De todos modos: trabajé en ello un día más y pensé que, dado que solo estoy interesado en exponer un puerto para la interfaz web de una aplicación, también puedo usarsocat
. Así que lo hice.
Después de crear la conexión namespaced-openvpn e iniciar la aplicación dentro de ese espacio de nombres de red, ejecuté el siguiente comando en una terminal dedicada:
sudo socat tcp-listen:PORT-TO-FORWARD-TO,fork,reuseaddr exec:'ip netns exec vpn socat STDIO tcp-connect\:127.0.0.1\:PORT-TO-LISTEN-TO',nofork
Notas:
PORT-TO-FORWARD-TO
es el puerto al que quiero que se reenvíe el puerto (en el espacio de nombres de la red raíz)PORT-TO-LISTEN-TO
es el puerto de la aplicación, que quiero exponer en el espacio de nombres raíz127.0.0.1
Tuve que usar la IP localhost real (nilocalhost
un nombre, porque no parece resolverse correctamente)- asegúrese de evitar el carácter de punto doble (
:
) dentro de las comillas simples - No estoy seguro de si esto provoca fugas de DNS; Por lo que he comprobado no es así, pero no puedo estar seguro porque no sé cómo probarlo.
Lo que queda por hacer:
- automatizar todos los comandos para iniciar la aplicación y reenviar el puerto al inicio: no necesito esto actualmente, pero si/cuando descubra cómo hacerlo, lo agregaré aquí