使用 vpn 將埠轉發到網路命名空間中的應用程序
我能夠設置一個網路命名空間,使用 openvpn 建立一個隧道,並在命名空間內啟動一個使用該隧道的應用程序。到目前為止一切順利,但是可以通過 Web 界面訪問此應用程序,我不知道如何將請求路由到 LAN 內的 Web 界面。
我按照@schnouki 的指南解釋瞭如何設置網路命名空間並在其中執行 OpenVPN
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
之後,我可以檢查我的外部 ip 並在命名空間內外得到不同的結果,正如預期的那樣:
curl -s ipv4.icanhazip.com <my-isp-ip> ip netns exec myvpn curl -s ipv4.icanhazip.com <my-vpn-ip>
應用程序已啟動,我在此範例中使用 deluge。我嘗試了幾個帶有 Web 界面的應用程序,以確保它不是特定於洪水的問題。
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
如果我指定 veth vpn1 的 ip,我可以從命名空間內部和外部訪問埠 8112 上的 Web 界面。
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
但我確實想將埠 8112 從我的伺服器重定向到命名空間中的應用程序。目標是在區域網路內的電腦上打開瀏覽器並使用http://my-server-ip:8112獲取 Web 界面(my-server-ip 是實例化網路介面的伺服器的靜態 IP)
編輯:我刪除了創建 iptables 規則的嘗試。上面解釋了我想要做的事情,以下命令應該輸出 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
我嘗試了 DNAT 和 SNAT 規則,並使用 MASQUERADE 進行了很好的衡量,但由於我不知道自己在做什麼,所以我的嘗試是徒勞的。也許有人可以幫我把這個結構放在一起。
編輯: 的 tcpdump 輸出
tcpdump -nn -q tcp port 8112
。不出所料,第一個命令返回 HTTP 200,第二個命令以拒絕連接終止。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
編輯:@schnouki 本人向我指出了一篇解釋通用 iptables TCP 代理的 Debian 管理文章。應用於手頭的問題,他們的腳本將如下所示:
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
不幸的是,veth 介面之間的流量被擷取,沒有其他任何事情發生。但是,@schnouki 也建議使用
socat
TCP 代理,這非常有效。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
當流量通過 veth 介面時,我還沒有理解奇怪的埠改組,但我的問題現在解決了。
我一直有 iptables 重定向的問題(可能是我的錯,我很確定它是可行的)。但是對於像你這樣的情況,IMO 更容易在沒有 iptables 的使用者空間中進行操作。
基本上,您需要在“預設”工作區中有一個守護程序,監聽 TCP 埠 8112 並將所有流量重定向到 10.200.200.2 埠 8112。所以它是一個簡單的 TCP 代理。
以下是使用socat的方法:
socat tcp-listen:8112,reuseaddr,fork tcp-connect:10.200.200.2:8112
(
fork
需要該選項以避免socat
在第一個代理連接關閉後停止)。編輯:
reuseaddr
按照評論中的建議添加。如果你絕對想用 iptables 來做,Debian 管理網站上有一個指南。但我仍然更喜歡
socat
更高級的東西——比如將 IPv4 代理到 IPv6,或者剝離 SSL 以允許舊的 Java 程序連接到安全服務……但是請注意,Deluge 中的所有連接都來自您的伺服器 IP,而不是真實的客戶端 IP。如果您想避免這種情況,您將需要使用真正的 HTTP 反向代理,將原始客戶端 IP 添加到 HTTP 標頭中的代理請求。
將網路命名空間與主命名空間互連總是困擾著我。我通常創建命名空間的原因是因為我希望它被隔離。根據您嘗試通過創建互連的名稱空間實現的目標可能會破壞該目的。
但即使是孤立的,為了方便起見,我仍然想通過網路戳它。
此解決方案可讓您保持隔離並將一些連接轉發給它。 您不需要為了轉發一個埠而在兩個網路命名空間之間創建所有網路。 在要接受連接的命名空間中執行它。必須以 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
它在您執行它的一個網路命名空間中偵聽連接,在埠 8112 上,然後連接的客戶端
exec
開始執行ip netns exec myvpn ...
以在網路命名空間內執行其餘部分myvpn
,然後一旦進入myvpn
網路命名空間,它就會再次與另一個創建第二個連接socat
。或將其作為 systemd 服務執行
這也使用
socat
.創建包含內容的服務配置文件
/etc/systemd/system/deluge-web-netns.service
:[Unit] Description=Forwarder to deluge-web in netns After=network-online.target #Requires=deluge-web.service #After=deluge-web.service [Service] Type=simple ExecStart=/usr/bin/socat tcp-listen:8112,fork,reuseaddr exec:'ip netns exec vpn-netns socat STDIO "tcp-connect:127.0.0.1:8112"',nofork #User=deluge #Group=deluge SyslogIdentifier=deluge-web-fwd Restart=on-failure # Time to wait before forcefully stopped. TimeoutStopSec=300 [Install] WantedBy=multi-user.target
根據.
ExecStart=/path/to/socat
_ _ _man systemd.service
考慮設置正確的值並啟用指令
Requires
和After
.然後啟用並使用命令開始:
systemctl daemon-reload systemctl enable deluge-web-netns systemctl start deluge-web-netns
或者在下面執行它
xinetd
這也使用
socat
.創建conf文件,例如
/etc/xinetd.d/deluge-web-fwd
內容service deluge-web-vpn-netns { type = UNLISTED socket_type = stream protocol = tcp port = 8112 flags = IPv4 KEEPALIVE wait = no user = root server = /sbin/ip server_args = netns exec vpn-netns socat STDIO tcp-connect:127.0.0.1:8112 }
重新開始
xinetd
service xinetd restart
程序
ncat
也可以使用類似的socat
。