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

答え2

私はiptablesリダイレクトに問題がありました(おそらく私は間違っているでしょう。これが可能であると確信しています)。しかし、あなたのような場合は、iptablesなしでユーザースペースで実行する方が簡単です。

デフォルトでは、TCPポート8112でリッスンし、すべてのトラフィックを10.200.200.2ポート8112にリダイレクトする「デフォルト」ワークスペースにデーモンが必要です。したがって、これは単純なTCPプロキシです。

実行方法は次のとおりです。ソカット:

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

(このオプションは、最初のプロキシ接続が閉じられた後に停止するのをfork防ぐために必要です。)socat

編集するreuseaddr:コメントに提案されているように追加されました。

iptablesでこれを行うには、次のガイドを参照してください。Debian 管理場所。しかし、私はまだsocatIPv4をIPv6にプロキシしたり、SSLを削除して以前のJavaプログラムがセキュリティサービスに接続できるようにするなど、より高度な機能を好みます。

ただし、Delugeのすべての接続は実際のクライアントIPではなくサーバーIPから来ていることに注意してください。これを回避するには、実際のHTTPリバースプロキシを使用してHTTPヘッダーのプロキシ要求に元のクライアントIPを追加する必要があります。

答え3

洪水の場合、これは私の解決策です。 iptableは必要ありません。次のように進んでください。

  1. OpenVPNトンネルを開始
  2. 名前空間を作成し、openvpnトンネルをその名前空間にインポートします。
ip netns $NSを追加
#TUNが表示されるのを待ちます
そして[[ $(ip Routing|grep $TUN|wc -l) == 0 ]];
MY_IP=$(IP アドレスは $TUN|grep inet|cut -d' ' -f6|cut -d'/' -f1 を表示します。)
#ゲートウェイIPを抽出する方法は、openvpn接続によって異なります。
GATEWAY_IP=$MY_IP
#私の$ TUN(VPNインターフェイス)を名前空間に閉じ込める
IP リンクの設定 $TUN netns $NS
#インターフェイスのサブネットを設定します(VPNサーバーによって提供されたサブネットと同じ)。
ip netns exec $NS ifconfig $TUN $MY_IP/24 先頭へ
#ループバックの開始
ip netns exec $NS ifconfig lo 127.0.0.1/8 先頭へ
#リモートゲートウェイ設定(サイト間VPN IPアドレス)
ip netns exec $NS ルーティングはデフォルトゲートウェイ $GATEWAY_IP を追加します。
  1. デフォルトの名前空間と作成した名前空間の間に veth 接続を確立します。
#名前空間間通信のためのvethインタフェースの設定
IP リンクの追加 veth0 タイプ veth ピア名 veth1
#2番目のvethを名前空間に移動
IPリンク設定 veth1 netns $NS
#未使用のIP範囲のIPを最初のベスに提供します。
ifconfig veth0 10.1.1.1/24以降
#second
ip netns exec $NS ifconfig veth1 10.1.1.2/24 先頭へ
#TODO:veth1とethインターフェイスの間にブリッジを作成して、LANと通信できるようにします。
#DNSクライアントを設定します。 ip netnsはこのファイルを使用して/etc/resolv.confをエミュレートします。
mkdir -p /etc/netns/$NS
echo "nameserver8.8.4.4">/etc/netns/$NS/resolv.conf
  1. $ NSでdelugedを実行し、デフォルトの名前空間でdeluge-webを実行します。 Deluge-web が Deluged が接続を受信する 10.1.1.2 veth IP アドレスを指すようにします。

望むより!洪水ネットワークはVPNで保護されており、洪水ネットワークはホームネットワークから自由にアクセスできます。

答え4

@AndrDevEKの答えが役に立ちます。これを拡張するにはsocat。特に、Unixドメインソケットを使用してポートを転送する機能は、ここで非常に便利です。なぜなら、Unixドメインソケットはネットワークネームスペースとは独立して動作するからです。

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=$!

大掃除:

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

最初のものはssh -N -Lmyvpn名前空間内で始まります。これにより、Unixドメインソケットが作成され/tmp/myunixsock受信されます。着信接続はlocalhost:8112(myvpn名前空間内)に渡されます。 2番目はssh -N -Lデフォルトのネームスペースから始まります。これによりリッスン TCP ポートが作成され、着信接続が Unix ドメインソケットに転送されます。

これが機能するには、sshネットワークネームスペースの内部がまだ機能していない場合は機能する必要があることに注意する必要があります(そしてパスワードなしの公開鍵操作が役立ちます)。

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

関連情報