Pude configurar un espacio de nombres de red, establecer un túnel con openvpn e iniciar una aplicación que usa este túnel dentro del espacio de nombres. Hasta ahora todo bien, pero se puede acceder a esta aplicación a través de una interfaz web y no puedo entender cómo enrutar las solicitudes a la interfaz web dentro de mi LAN.
Seguí una guía de @schnouki que explicaba cómo configurar un espacio de nombres de red y ejecutar OpenVPN dentro de él.
ip netns add myvpn
ip netns exec myvpn ip addr add 127.0.0.1/8 dev lo
ip netns exec myvpn ip link set lo up
ip link add vpn0 type veth peer name vpn1
ip link set vpn0 up
ip link set vpn1 netns myvpn up
ip addr add 10.200.200.1/24 dev vpn0
ip netns exec myvpn ip addr add 10.200.200.2/24 dev vpn1
ip netns exec myvpn ip route add default via 10.200.200.1 dev vpn1
iptables -A INPUT \! -i vpn0 -s 10.200.200.0/24 -j DROP
iptables -t nat -A POSTROUTING -s 10.200.200.0/24 -o en+ -j MASQUERADE
sysctl -q net.ipv4.ip_forward=1
mkdir -p /etc/netns/myvpn
echo 'nameserver 8.8.8.8' > /etc/netns/myvpn/resolv.conf
Después de eso, puedo verificar mi ip externa y obtener diferentes resultados dentro y fuera del espacio de nombres, tal como estaba previsto:
curl -s ipv4.icanhazip.com
<my-isp-ip>
ip netns exec myvpn curl -s ipv4.icanhazip.com
<my-vpn-ip>
La aplicación se inició, estoy usando diluvio para este ejemplo. Probé varias aplicaciones con una interfaz web para asegurarme de que no sea un problema específico de diluvio.
ip netns exec myvpn sudo -u <my-user> /usr/bin/deluged
ip netns exec myvpn sudo -u <my-user> /usr/bin/deluge-web -f
ps $(ip netns pids myvpn)
PID TTY STAT TIME COMMAND
1468 ? Ss 0:13 openvpn --config /etc/openvpn/myvpn/myvpn.conf
9302 ? Sl 10:10 /usr/bin/python /usr/bin/deluged
9707 ? S 0:37 /usr/bin/python /usr/bin/deluge-web -f
Puedo acceder a la interfaz web en el puerto 8112 desde dentro del espacio de nombres y desde afuera si especifico la ip de veth vpn1.
ip netns exec myvpn curl -Is localhost:8112 | head -1
HTTP/1.1 200 OK
ip netns exec myvpn curl -Is 10.200.200.2:8112 | head -1
HTTP/1.1 200 OK
curl -Is 10.200.200.2:8112 | head -1
HTTP/1.1 200 OK
Pero sí quiero redirigir el puerto 8112 desde mi servidor a la aplicación en el espacio de nombres. El objetivo es abrir un navegador en una computadora dentro de mi LAN y obtener la interfaz web con http: // my-server-ip: 8112 (my-server-ip es la ip estática del servidor que instancia la interfaz de red)
EDITAR: eliminé mis intentos de crear reglas de iptables. Lo que intento hacer se explica anteriormente y los siguientes comandos deberían generar un HTTP 200:
curl -I localhost:8112
curl: (7) Failed to connect to localhost port 8112: Connection refused
curl -I <my-server-ip>:8112
curl: (7) Failed to connect to <my-server-ip> port 8112: Connection refused
Intenté las reglas DNAT y SNAT y agregué una MASQUERADA por si acaso, pero como no sé lo que estoy haciendo, mis intentos son inútiles. Quizás alguien pueda ayudarme a armar esta construcción.
EDITAR: la salida de tcpdump de tcpdump -nn -q tcp port 8112
. Como era de esperar, el primer comando devuelve un HTTP 200 y el segundo comando termina con una conexión rechazada.
curl -Is 10.200.200.2:8112 | head -1
listening on vpn0, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 10.200.200.1.36208 > 10.200.200.2.8112: tcp 82
IP 10.200.200.2.8112 > 10.200.200.1.36208: tcp 145
curl -Is <my-server-ip>:8112 | head -1
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
IP <my-server-ip>.58228 > <my-server-ip>.8112: tcp 0
IP <my-server-ip>.8112 > <my-server-ip>.58228: tcp 0
EDITAR: @schnouki mismo me señaló un artículo de la Administración de Debian que explica un proxy TCP genérico de iptables . Aplicado al problema en cuestión, su script se vería así:
YourIP=<my-server-ip>
YourPort=8112
TargetIP=10.200.200.2
TargetPort=8112
iptables -t nat -A PREROUTING --dst $YourIP -p tcp --dport $YourPort -j DNAT \
--to-destination $TargetIP:$TargetPort
iptables -t nat -A POSTROUTING -p tcp --dst $TargetIP --dport $TargetPort -j SNAT \
--to-source $YourIP
iptables -t nat -A OUTPUT --dst $YourIP -p tcp --dport $YourPort -j DNAT \
--to-destination $TargetIP:$TargetPort
Desafortunadamente, el tráfico entre las interfaces veth se detuvo y no sucedió nada más. Sin embargo, @schnouki también sugirió el uso de socat
un proxy TCP y esto funciona perfectamente.
curl -Is <my-server-ip>:8112 | head -1
IP 10.200.200.1.43384 > 10.200.200.2.8112: tcp 913
IP 10.200.200.2.8112 > 10.200.200.1.43384: tcp 1495
Todavía tengo que entender el extraño desplazamiento de puertos mientras el tráfico atraviesa las interfaces veth, pero mi problema está resuelto ahora.
veth
dispositivos en absoluto (aunque esto es muy interesante ... ;-)). ¿Ha utilizadotcpdump
para verificar qué tan lejos llegan los paquetes entrantes? Sitcpdump -i veth0
no muestra nada, entoncestcpdumo -i lo
puede ser necesario.Respuestas:
Siempre he tenido problemas con las redirecciones de iptables (probablemente es mi culpa, estoy bastante seguro de que es factible). Pero para un caso como el suyo, es IMO más fácil hacerlo en tierra de usuario sin iptables.
Básicamente, necesita tener un demonio en su espacio de trabajo "predeterminado" que escuche en el puerto TCP 8112 y redirija todo el tráfico al puerto 10.200.200.2 8112. Por lo tanto, es un proxy TCP simple.
Aquí se explica cómo hacerlo con socat :
(La
fork
opción es necesaria para evitarsocat
detenerse después de que se cierra la primera conexión proxy).EDITAR : agregado
reuseaddr
como se sugiere en los comentarios.Si quiere hacerlo con iptables, hay una guía en el sitio de Administración de Debian . Pero aún prefiero
socat
cosas más avanzadas, como proxy de IPv4 a IPv6, o quitar SSL para permitir que los viejos programas Java se conecten a servicios seguros ...Sin embargo, tenga en cuenta que todas las conexiones en Deluge serán desde la IP de su servidor en lugar de la IP real del cliente. Si desea evitar eso, necesitará usar un proxy inverso HTTP real que agregue la IP del cliente original a la solicitud proxy en un encabezado HTTP.
fuente
socat
y hace exactamente lo que estaba tratando de hacer con iptables desde hace bastante tiempo. Probé varias aplicaciones y todas funcionan sin problemas, conectándose al mundo exterior a través de tun0, al tiempo que proporcionan acceso a su interfaz web a través de veth1.reuseaddr
bandera. Esto evitaport already in use
errores al iniciar y detener socat en rápida sucesión:socat -4 TCP-LISTEN:8112,reuseaddr,fork TCP:10.200.200.2:8112
Interconectar el espacio de nombres de red con el espacio de nombres principal siempre me molesta. La razón por la que generalmente creo un espacio de nombres es porque lo quiero aislado. Dependiendo de lo que esté tratando de lograr con espacios de nombres, la creación de interconexiones puede vencer ese propósito.
Pero incluso aislado, todavía quiero meterlo en la red, por conveniencia.
Esta solución le permite mantener el aislamiento y reenviarle algunas conexiones de todos modos. No necesita crear toda esa red entre los dos espacios de nombres de red solo para reenviar un puerto. Ejecute esto en el espacio de nombres donde desea aceptar conexiones. Debe ejecutarse como root para
ip netns exec
trabajar.Escucha las conexiones en un espacio de nombres de red donde lo ejecuta, en el puerto 8112, luego el cliente conectado se
exec
ejecutaip netns exec myvpn ...
para ejecutar el resto dentro delmyvpn
espacio de nombres de la red, luego, una vez dentro delmyvpn
espacio de nombres de la red, crea una segunda conexión nuevamente con otrosocat
.fuente
:
caracteres dentro de las comillas simples o de lo contrario podría encontrar un error que dice... wrong number of parameters (2 instead of 1)
(2 o 3). De lo contrario: funciona muy bien! Enormes gracias!Para diluvio aquí es mi solución. No hay necesidad de iptables. Aquí están los pasos:
Voila! Te has inundado de forma segura detrás de la VPN mientras tu web de diluvio es accesible libremente en tu red doméstica
fuente
La respuesta de @ AndrDevEK es útil. Para ampliar eso, es posible que no desee instalar
socat
. En ese caso, puede lograr lo mismo con una configuración de reenvío de puerto SSH ligeramente enrevesada. En particular, la característica de reenvío de puertos a / desde un socket de dominio unix es útil aquí, porque los sockets de dominio unix operan independientemente de los espacios de nombres de red:Limpiar:
El primero
ssh -N -L
se inicia dentro del espacio de nombres myvpn. Esto crea un socket de dominio unix/tmp/myunixsock
y lo escucha. Las conexiones entrantes se reenvían a localhost: 8112 (dentro del espacio de nombres myvpn). El segundossh -N -L
se inicia en el espacio de nombres predeterminado. Esto crea un puerto TCP de escucha y reenvía las conexiones entrantes al socket de dominio unix.Debe tenerse en cuenta que para que esto funcione,
ssh
dentro del espacio de nombres de su red tendrá que funcionar si aún no lo está (y la operación de clave pública sin contraseña es útil):fuente