VPNを使用してネットワーク名前空間のアプリケーションにポートを転送する

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をリダイレクトしたいと思います。目標は、LAN内のコンピュータでブラウザを開き、次のコマンドを使用してWebインターフェイスを取得することです。http://マイサーバーIP:8112(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 を返し、2 番目のコマンドは接続が拒否されたときに終了します。

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自身が私に一つを指摘しました。Universal 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はこれをsocatTCPプロキシとして使用することを提案しました。

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インターフェイスを通過するときに奇妙なポートシャッフリングが発生することを理解できませんでしたが、これで問題は解決しました。

ベストアンサー1

ネットワークネームスペースをデフォルトのネームスペースと相互接続することは常に面倒です。私が主に名前空間を作成する理由は、それが隔離されたいからです。名前空間を使用して達成したい目的に応じて相互接続を作成すると、その目的が無効になる可能性があります。

しかし、孤立した状態でも便宜上、ウェブを通じて内容を刺してみたいと思います。

このソリューションを使用すると、分離された状態を維持し、いくつかの接続を転送できます。 2つのネットワーク名前空間の間にすべてのネットワークを作成する必要はなく、ポートのみを渡すだけです。 接続を許可する名前空間でこのコマンドを実行します。機能するには、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

実行中のネットワーク名前空間の1つで、ポート8112で接続をリッスンし、接続されたクライアントが実行され、残りのネットワーク名前exec空間を実行しip netns exec myvpn ...てから、ネットワーク名前空間から別のクライアントと通信します。myvpnmyvpnsocat

またはシステムサービスとして実行

これも使用されます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

正しい値を設定してディレクティブを有効にすることを検討してくださいRequiresAfter

その後、コマンドを有効にして開始します。

systemctl daemon-reload
systemctl enable deluge-web-netns
systemctl start  deluge-web-netns

または、以下で実行してみてくださいxinetd

これも使用されますsocat

/etc/xinetd.d/deluge-web-fwd次の内容でconfファイルを作成します。

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

おすすめ記事