Consegui configurar um namespace de rede, estabelecer um encapsulamento com openvpn e iniciar um aplicativo que usa esse encapsulamento dentro do namespace. Até aí tudo bem, mas esse aplicativo pode ser acessado através de uma interface web e não consigo descobrir como rotear solicitações para a interface web dentro da minha LAN.
Segui um guia do @schnouki explicando como configurar um namespace de rede e executar o OpenVPN dentro dele
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
Depois disso, posso verificar meu ip externo e obter resultados diferentes dentro e fora do espaço para nome, da maneira que pretendemos:
curl -s ipv4.icanhazip.com
<my-isp-ip>
ip netns exec myvpn curl -s ipv4.icanhazip.com
<my-vpn-ip>
O aplicativo é iniciado, estou usando o dilúvio para este exemplo. Eu tentei vários aplicativos com uma interface da web para garantir que não seja um problema específico do dilúvio.
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
Consigo acessar a interface da web na porta 8112 de dentro do namespace e de fora se eu especificar o ip do 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
Mas eu quero redirecionar a porta 8112 do meu servidor para o aplicativo no espaço para nome. O objetivo é abrir um navegador em um computador dentro da minha LAN e obter a interface da web com http: // my-server-ip: 8112 (my-server-ip é o ip estático do servidor que instancia a interface de rede)
Edição: Eu removi minhas tentativas de criar regras de iptables. O que estou tentando fazer é explicado acima e os seguintes comandos devem gerar um 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
Tentei as regras DNAT e SNAT e instalei um MASQUERADE por uma boa medida, mas como não sei o que estou fazendo, minhas tentativas são inúteis. Talvez alguém possa me ajudar a montar essa construção.
EDIT: A saída tcpdump de tcpdump -nn -q tcp port 8112
. Sem surpresa, o primeiro comando retorna um HTTP 200 e o segundo comando termina com uma conexão recusada.
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
EDIT: O próprio @schnouki me indicou um artigo da Administração Debian que explica um proxy TCP genérico do iptables . Aplicado ao problema em questão, o script deles ficaria assim:
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
Infelizmente, o tráfego entre as interfaces veth apreendeu e nada mais aconteceu. No entanto, o @schnouki também sugeriu o uso socat
como proxy TCP e está funcionando perfeitamente.
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
Ainda não entendi o estranho embaralhamento de porta enquanto o tráfego atravessa as interfaces veth, mas meu problema está resolvido agora.
veth
dispositivos (acho isso muito interessante ... ;-)). Você já usoutcpdump
para verificar até onde os pacotes recebidos chegam? Setcpdump -i veth0
não mostrar nada,tcpdumo -i lo
pode ser necessário.