port forwarding all'applicazione nello spazio dei nomi di rete con vpn


13

Sono stato in grado di impostare uno spazio dei nomi di rete, stabilire un tunnel con openvpn e avviare un'applicazione che utilizza questo tunnel all'interno dello spazio dei nomi. Fin qui tutto bene, ma questa applicazione è accessibile tramite un'interfaccia web e non riesco a capire come instradare le richieste all'interfaccia web all'interno della mia LAN.

Ho seguito una guida di @schnouki che spiega come impostare uno spazio dei nomi di rete ed eseguire OpenVPN al suo interno

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

Successivamente, posso controllare il mio IP esterno e ottenere risultati diversi all'interno e all'esterno dello spazio dei nomi, proprio come previsto:

curl -s ipv4.icanhazip.com
<my-isp-ip>
ip netns exec myvpn curl -s ipv4.icanhazip.com
<my-vpn-ip>

L'applicazione è avviata, sto usando diluvio per questo esempio. Ho provato diverse applicazioni con un'interfaccia web per assicurarmi che non si trattasse di un diluvio specifico.

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

Sono in grado di accedere all'interfaccia web sulla porta 8112 dallo spazio dei nomi e dall'esterno se specifico l'ip di 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

Ma voglio reindirizzare la porta 8112 dal mio server all'applicazione nello spazio dei nomi. L'obiettivo è aprire un browser su un computer all'interno della mia LAN e ottenere l'interfaccia web con http: // my-server-ip: 8112 (my-server-ip è l'IP statico del server che ha istanziato l'interfaccia di rete)

EDIT: ho rimosso i miei tentativi di creare regole iptables. Quello che sto cercando di fare è spiegato sopra e i seguenti comandi dovrebbero generare 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

Ho provato le regole DNAT e SNAT e ho lanciato una MASQUERADE per buona misura, ma dal momento che non so cosa sto facendo, i miei tentativi sono inutili. Forse qualcuno può aiutarmi a mettere insieme questo costrutto.

EDIT: l'output di tcpdump di tcpdump -nn -q tcp port 8112. Non sorprende che il primo comando restituisca un HTTP 200 e il secondo comando termina con una connessione rifiutata.

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: @schnouki stesso mi ha indicato un articolo dell'Amministrazione Debian che spiega un proxy TCP iptables generico . Applicato al problema attuale, la loro sceneggiatura sarebbe simile a questa:

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

Sfortunatamente, il traffico tra le interfacce veth è stato sequestrato e non è successo nient'altro. Tuttavia, @schnouki ha anche suggerito l'uso di socatcome proxy TCP e questo funziona perfettamente.

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

Devo ancora capire la strana porta che si mescola mentre il traffico attraversa le interfacce Veth, ma il mio problema è risolto ora.


Disclaimer: non ho alcuna esperienza con i vethdispositivi (trovo questo molto interessante, però ... ;-)). Hai tcpdumpmai usato per controllare quanto arrivano i pacchetti in arrivo? Se tcpdump -i veth0non mostra nulla, tcpdumo -i lopotrebbe essere necessario.
Hauke ​​Laging,

Ho aggiunto l'output non dettagliato di tcpdump
pskiebe il

Risposte:


9

Ho sempre avuto problemi con i reindirizzamenti di iptables (probabilmente è colpa mia, sono abbastanza sicuro che sia fattibile). Ma per un caso come il tuo, è più facile IMO farlo nella terra dell'utente senza iptables.

Fondamentalmente, devi avere un demone nel tuo spazio di lavoro "predefinito" in ascolto sulla porta TCP 8112 e reindirizzare tutto il traffico sulla porta 10.200.200.2 8112. Quindi è un semplice proxy TCP.

Ecco come farlo con socat :

socat tcp-listen:8112,reuseaddr,fork tcp-connect:10.200.200.2:8112

(L' forkopzione è necessaria per evitare l' socatarresto dopo la chiusura della prima connessione proxy).

EDIT : aggiunto reuseaddrcome suggerito nei commenti.

Se vuoi assolutamente farlo con iptables, c'è una guida sul sito di amministrazione Debian . Ma preferisco ancora socatcose più avanzate - come il proxy da IPv4 a IPv6 o lo stripping di SSL per consentire ai vecchi programmi Java di connettersi a servizi sicuri ...

Fai attenzione, tuttavia, che tutte le connessioni in Deluge verranno dall'IP del tuo server anziché dall'IP del client reale. Se si desidera evitare ciò, sarà necessario utilizzare un proxy inverso HTTP reale che aggiunge l'IP client originale alla richiesta proxy in un'intestazione HTTP.


1
Mi hai migliorato la giornata! Non mi sono mai imbattuto socate realizza esattamente quello che stavo cercando di fare con iptables ormai da un po 'di tempo. Ho testato diverse applicazioni e tutte funzionano perfettamente, connettendosi al mondo esterno tramite tun0, fornendo comunque accesso alla loro interfaccia web tramite veth1.
pskiebe,

1
Dopo aver eseguito alcuni test, ho aggiunto la reuseaddrbandiera. Questo evita port already in useerrori durante l'avvio e l'arresto di socat in rapida successione:socat -4 TCP-LISTEN:8112,reuseaddr,fork TCP:10.200.200.2:8112
pskiebe,

8

L'interconnessione dello spazio dei nomi di rete con lo spazio dei nomi principale mi disturba sempre. Il motivo per cui di solito creo uno spazio dei nomi è perché lo voglio isolato. A seconda di ciò che stai cercando di ottenere con gli spazi dei nomi, la creazione di interconnessioni può vanificare tale scopo.

Ma anche isolato voglio ancora spingerlo sulla rete, per comodità.

Questa soluzione consente di mantenere l'isolamento e inoltrare comunque alcune connessioni ad esso. Non è necessario creare tutta quella rete tra i due spazi dei nomi di rete solo per inoltrare una porta. Eseguilo nello spazio dei nomi in cui desideri accettare le connessioni. Per funzionare, deve essere eseguito come root ip netns exec.

socat tcp-listen:8112,fork,reuseaddr \
  exec:'ip netns exec myvpn socat STDIO tcp-connect\:127.0.0.1\:8112',nofork

Ascolta le connessioni in uno spazio dei nomi di rete in cui lo si esegue, sulla porta 8112, quindi il client connesso viene execeseguito ip netns exec myvpn ...per eseguire il resto all'interno dello myvpnspazio dei nomi di rete, quindi una volta all'interno dello myvpnspazio dei nomi di rete crea nuovamente una seconda connessione con un'altra socat.


lavorando come un incanto
approssimativo

Dal momento che non ho molta esperienza con l'amministrazione di Linux e mi è costato un po 'di tempo per scoprirlo: assicurati di sfuggire a entrambi i :caratteri tra virgolette singole oppure potresti incorrere in un errore che dice ... wrong number of parameters (2 instead of 1)(2 o 3). Altrimenti: funziona alla grande! Grazie enorme!
Igor,

2

Per diluvio ecco la mia soluzione. Non c'è bisogno di iptables. Ecco i passaggi:

  1. Inizia il tuo tunnel openvpn
  2. Crea spazio dei nomi e porta lì il tuo tunnel openvpn:
ip netns aggiungere $ NS
# Aspetta che arrivi il TUN
while [[$ (ip route | grep $ TUN | wc -l) == 0]]; dormire 1; fatto
MY_IP = $ (ip addr mostra $ TUN | grep inet | cut -d '' -f6 | cut -d '/' -f1)
# Il modo in cui estrai l'IP del gateway potrebbe essere diverso per la tua connessione openvpn
GATEWAY_IP = $ MY_IP
# jail my $ TUN (interfaccia VPN) nello spazio dei nomi
set di collegamenti ip $ TUN netns $ NS
# Visualizza l'interfaccia con una sottorete (equivalente a quella fornita dal server VPN)
ip netns exec $ NS ifconfig $ TUN $ MY_IP / 24 su
# Attiva il loopback
ip netns exec $ NS ifconfig lo 127.0.0.1/8 in su
# Imposta gateway remoto (il tuo indirizzo IP VPN pointtopoint)
ip netns exec $ NS route aggiungi default gw $ GATEWAY_IP
  1. Stabilisci la connessione tra il tuo spazio dei nomi predefinito e quello che hai creato:
# Imposta interfacce veth per la comunicazione tra spazi dei nomi
collegamento ip aggiungere veth0 digitare veth nome peer veth1
# Sposta il secondo veth nel tuo spazio dei nomi
set di collegamenti ip veth1 netns $ NS
# fornisce un IP dall'intervallo IP inutilizzato al primo tentativo
ifconfig veth0 10.1.1.1/24 in su
# E il secondo
ip netns exec $ NS ifconfig veth1 10.1.1.2/24 in su
# TODO: imposta un ponte tra veth1 e l'interfaccia eth per consentire la comunicazione con la LAN
# Imposta client DNS. ip netns emulerà /etc/resolv.conf usando questo file:
mkdir -p / etc / netns / $ NS
echo "nameserver 8.8.4.4"> /etc/netns/$NS/resolv.conf
  1. Esegui il tuo deluged in $ NS e il tuo diluvio-web nel tuo spazio dei nomi predefinito. Punta deluge-web all'indirizzo IP 10.1.1.2 veth, dove deluged ascolterà la sua connessione.

Ecco! Ti sei nascosto in sicurezza dietro la VPN mentre il tuo diluvio-web è liberamente accessibile sulla tua rete domestica


2

La risposta di @ AndrDevEK è utile. Per espanderlo, potresti non voler installare socat. Nel qual caso puoi ottenere la stessa cosa con una configurazione port-forward SSH leggermente contorta. In particolare, la funzione di port forwarding verso / da un socket di dominio unix è utile qui, poiché i socket di dominio unix funzionano indipendentemente dagli spazi dei nomi di rete:

sudo ip netns exec myvpn su -c "ssh -N -L /tmp/myunixsock:localhost:8112 localhost" $USER &
ssh_pid1=$!
ssh -N -L localhost:8112:/tmp/myunixsock localhost &
ssh_pid2=$!

Pulire:

sudo kill $ssh_pid1
kill $ssh_pid2
rm /tmp/myunixsock

Il primo ssh -N -Lviene avviato nello spazio dei nomi myvpn. Questo crea un socket di dominio unix /tmp/myunixsocke lo ascolta. Le connessioni in entrata vengono inoltrate a localhost: 8112 (all'interno dello spazio dei nomi myvpn). Il secondo ssh -N -Lviene avviato nello spazio dei nomi predefinito. Ciò crea una porta TCP in ascolto e inoltra le connessioni in entrata al socket del dominio unix.

Va notato che per farlo funzionare, sshall'interno del tuo spazio dei nomi di rete dovrà funzionare se non lo è già (e l'operazione pubkey senza password è utile):

sudo ip netns exec myvpn ip link set up dev lo
sudo ip netns exec myvpn /usr/sbin/sshd -o PidFile=/run/sshd-myvpn.pid
ssh-copy-id localhost
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.