I was able to set up a network namespace, establish a tunnel with openvpn and start an application that uses this tunnel inside the namespace. So far so good, but this application can be accessed via a web interface and I cant't figure out how to route requests to the web interface inside my LAN.
I followed a guide from @schnouki explaining how to set up a network namespace and run OpenVPN inside of it
ip netns add myvpnip netns exec myvpn ip addr add 127.0.0.1/8 dev loip netns exec myvpn ip link set lo upip link add vpn0 type veth peer name vpn1ip link set vpn0 upip link set vpn1 netns myvpn upip addr add 10.200.200.1/24 dev vpn0ip netns exec myvpn ip addr add 10.200.200.2/24 dev vpn1ip netns exec myvpn ip route add default via 10.200.200.1 dev vpn1iptables -A INPUT \! -i vpn0 -s 10.200.200.0/24 -j DROPiptables -t nat -A POSTROUTING -s 10.200.200.0/24 -o en+ -j MASQUERADEsysctl -q net.ipv4.ip_forward=1mkdir -p /etc/netns/myvpnecho 'nameserver 8.8.8.8'> /etc/netns/myvpn/resolv.conf
After that, I can check my external ip and get different results inside and outside of the namespace, just as intended:
curl -s ipv4.icanhazip.com<my-isp-ip>ip netns exec myvpn curl -s ipv4.icanhazip.com<my-vpn-ip>
The application is started, I'm using deluge for this example. I tried several applications with a web interface to make sure it's not a deluge specific problem.
ip netns exec myvpn sudo -u <my-user> /usr/bin/delugedip netns exec myvpn sudo -u <my-user> /usr/bin/deluge-web -fps $(ip netns pids myvpn) PID TTY STAT TIME COMMAND1468 ? Ss 0:13 openvpn --config /etc/openvpn/myvpn/myvpn.conf9302 ? Sl 10:10 /usr/bin/python /usr/bin/deluged9707 ? S 0:37 /usr/bin/python /usr/bin/deluge-web -f
I'm able to access the web interface on port 8112 from within the namespace and from outside if I specify the ip of veth vpn1.
ip netns exec myvpn curl -Is localhost:8112 | head -1HTTP/1.1 200 OKip netns exec myvpn curl -Is 10.200.200.2:8112 | head -1HTTP/1.1 200 OKcurl -Is 10.200.200.2:8112 | head -1HTTP/1.1 200 OK
But I do want to redirect port 8112 from my server to the application in the namespace. The goal is to open a browser on a computer inside my LAN and get the web interface with http://my-server-ip:8112 (my-server-ip being the static ip of the server that instantiated the network interface)
EDIT: I removed my attempts to create iptables rules. What I'm trying to do is explained above and the following commands should output a HTTP 200:
curl -I localhost:8112curl: (7) Failed to connect to localhost port 8112: Connection refusedcurl -I <my-server-ip>:8112curl: (7) Failed to connect to <my-server-ip> port 8112: Connection refused
I tried DNAT and SNAT rules and threw in a MASQUERADE for good measure, but since I don't know what I'm doing, my attempts are futile. Perhaps someone can help me put together this construct.
EDIT: The tcpdump output of tcpdump -nn -q tcp port 8112
. Unsurprisingly, the first command returns a HTTP 200 and the second command terminates with a refused connection.
curl -Is 10.200.200.2:8112 | head -1listening on vpn0, link-type EN10MB (Ethernet), capture size 262144 bytesIP 10.200.200.1.36208 > 10.200.200.2.8112: tcp 82IP 10.200.200.2.8112 > 10.200.200.1.36208: tcp 145curl -Is <my-server-ip>:8112 | head -1listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytesIP <my-server-ip>.58228 > <my-server-ip>.8112: tcp 0IP <my-server-ip>.8112 > <my-server-ip>.58228: tcp 0
EDIT: @schnouki himself pointed me to a Debian Administration article explaining a generic iptables TCP proxy. Applied to the problem at hand, their script would look like this:
YourIP=<my-server-ip>YourPort=8112TargetIP=10.200.200.2TargetPort=8112iptables -t nat -A PREROUTING --dst $YourIP -p tcp --dport $YourPort -j DNAT \--to-destination $TargetIP:$TargetPortiptables -t nat -A POSTROUTING -p tcp --dst $TargetIP --dport $TargetPort -j SNAT \--to-source $YourIPiptables -t nat -A OUTPUT --dst $YourIP -p tcp --dport $YourPort -j DNAT \--to-destination $TargetIP:$TargetPort
Unfortunately, traffic between the veth interfaces seized and nothing else happened. However, @schnouki also suggested the use of socat
as a TCP proxy and this is working perfectly.
curl -Is <my-server-ip>:8112 | head -1IP 10.200.200.1.43384 > 10.200.200.2.8112: tcp 913IP 10.200.200.2.8112 > 10.200.200.1.43384: tcp 1495
I have yet to understand the strange port shuffling while traffic is traversing through the veth interfaces, but my problem is solved now.