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.Respostas:
Sempre tive problemas com os redirecionamentos do iptables (provavelmente minha culpa, tenho certeza de que é possível). Mas para um caso como o seu, é IMO mais fácil fazê-lo na terra do usuário sem o iptables.
Basicamente, você precisa ter um daemon no seu espaço de trabalho "padrão" escutando na porta TCP 8112 e redirecionando todo o tráfego para a porta 8112 10.200.200.2. Portanto, é um proxy TCP simples.
Veja como fazer isso com o socat :
(A
fork
opção é necessária para evitar asocat
interrupção após o fechamento da primeira conexão com proxy).EDIT : adicionado
reuseaddr
como sugerido nos comentários.Se você absolutamente deseja fazê-lo com o iptables, há um guia no site de Administração Debian . Mas ainda prefiro
socat
coisas mais avançadas - como proxy de IPv4 para IPv6 ou remoção de SSL para permitir que programas Java antigos se conectem a serviços seguros ...Cuidado, porém, que todas as conexões no Deluge serão do IP do servidor em vez do IP do cliente real. Se você quiser evitar isso, precisará usar um proxy reverso HTTP real que inclua o IP do cliente original na solicitação em proxy em um cabeçalho HTTP.
fonte
socat
e ele realiza exatamente o que eu estava tentando fazer com o iptables há algum tempo. Testei vários aplicativos e todos eles estão funcionando perfeitamente, conectando-se ao mundo exterior através do tun0, enquanto ainda fornece acesso à sua interface da web através do veth1.reuseaddr
bandeira. Isso evitaport already in use
erros ao iniciar e parar o socat em rápida sucessão:socat -4 TCP-LISTEN:8112,reuseaddr,fork TCP:10.200.200.2:8112
Interconectar o namespace da rede com o namespace principal sempre me incomoda. O motivo pelo qual eu geralmente crio um espaço para nome é porque o quero isolado. Dependendo do que você está tentando obter com os namespaces, a criação de interconexões pode derrotar esse objetivo.
Mas, mesmo isolado, ainda quero cutucá-lo pela rede, por conveniência.
Esta solução permite manter o isolamento e encaminhar algumas conexões a ele de qualquer maneira. Você não precisa criar toda essa rede entre os dois namespaces de rede apenas para encaminhar uma porta. Execute isso no espaço para nome em que deseja aceitar conexões. Deve ser executado como root para
ip netns exec
funcionar.Ele escuta conexões em um namespace de rede em que você o executa, na porta 8112, e o cliente conectado começa
exec
a executarip netns exec myvpn ...
para executar o restante dentro domyvpn
namespace de rede e, uma vez dentro domyvpn
namespace de rede, cria a segunda conexão novamente com outrasocat
.fonte
:
caracteres entre aspas simples ou você pode encontrar um erro dizendo... wrong number of parameters (2 instead of 1)
(2 ou 3). Caso contrário: funciona muito bem! Muito obrigado!Para dilúvio aqui é a minha solução. Não há necessidade de iptables. Aqui estão os passos:
Voila! Você ficou protegido por trás da VPN enquanto a sua rede de dilúvio está disponível gratuitamente em sua rede doméstica
fonte
A resposta de @ AndrDevEK é útil. Para expandir isso, você pode não querer instalar
socat
. Nesse caso, você pode conseguir o mesmo com uma configuração de encaminhamento de porta SSH levemente complicada. Em particular, o recurso de encaminhamento de porta para / de um soquete de domínio unix é útil aqui, porque os soquetes de domínio unix operam independentemente dos namespaces de rede:Limpar:
O primeiro
ssh -N -L
é iniciado no espaço de nomes myvpn. Isso cria um soquete de domínio unix/tmp/myunixsock
e o escuta. As conexões de entrada são encaminhadas para localhost: 8112 (dentro do espaço para nome myvpn). O segundossh -N -L
é iniciado no espaço para nome padrão. Isso cria uma porta TCP de escuta e encaminha as conexões de entrada para o soquete do domínio unix.Deve-se observar que, para que isso funcione,
ssh
o espaço para nome da rede precisará estar funcionando se ainda não estiver (e a operação pubkey sem senha é útil):fonte