プロバイダーの NAT の背後で VPN サーバーを実行する

ホーム プロバイダーの NAT の背後で (ホワイト IP アドレスなしで) VPN サーバーを実行する方法についての記事。すぐに予約しましょう: この実装のパフォーマンスは、ルーターだけでなく、プロバイダーが使用する NAT のタイプにも直接依存します。.
そのため、Android スマートフォンから自宅のコンピュータに接続する必要がありました。両方のデバイスはプロバイダー NAT を介してインターネットに接続され、さらにコンピュータはホーム ルーターを介して接続されており、ホーム ルーターも NAT 接続します。
ホワイト IP アドレスを持つリース VPS/VDS を使用したり、プロバイダーからホワイト IP アドレスをレンタルしたりする古典的なスキームは、いくつかの理由から考慮されませんでした。
の観点から 過去記事からの体験談、プロバイダーの STUN と NAT を使用していくつかの実験を実施しました。 OpenWRT ファームウェアを実行しているホーム ルーターでコマンドを実行して、ちょっとした実験を行うことにしました。

$ stun stun.sipnet.ru

結果が得られました:

STUNクライアントバージョン0.97
プライマリ: 独立したマッピング、独立したフィルター、ランダム ポート、ヘアピンします
戻り値は 0x000002

直訳:
独立したマッピング - 独立したマッピング
独立したフィルター - 独立したフィルター
ランダムポート - ランダムポート
ヘアピンになります - ヘアピンがあります
PC で同様のコマンドを実行すると、次の結果が得られました。

STUNクライアントバージョン0.97
プライマリ: 独立したマッピング、ポート依存フィルター、ランダム ポート、ヘアピン
戻り値は 0x000006

ポート依存フィルター - ポート依存フィルター
コマンド出力の結果の違いは、ホーム ルーターがインターネットからパケットを送信するプロセスに「貢献」していることを示しており、これは、コンピューターでコマンドを実行したときに次のような事実が現れました。

stun stun.sipnet.ru -p 11111 -v

私は結果を得ていました:

...
マップされたアドレス = XX.1XX.1X4.2XX:4398
...

この時点で、しばらくの間 UDP セッションが開かれていました。この時点で UDP リクエスト (例: netcat XX.1XX.1X4.2XX 4398 -u) を送信すると、リクエストはホーム ルーターに届きます。 TCPDump が実行されていることを確認しましたが、リクエストはコンピュータに到達しませんでした。ルーター上の NAT トランスレータとしての IPtables がリクエストをドロップしました。
プロバイダーの NAT の背後で VPN サーバーを実行する
しかし、UDP リクエストがプロバイダーの NAT を通過したという事実自体が、成功への希望を与えました。ルーターは私の管轄内にあるため、UDP/11111 ポートをコンピューターにリダイレクトすることで問題を解決しました。

iptables -t nat -A PREROUTING -i eth1 -p udp -d 10.1XX.2XX.XXX --dport 11111 -j DNAT --to-destination 192.168.X.XXX

したがって、UDP セッションを開始し、任意の IP アドレスからインターネットからのリクエストを受信することができました。この時点で、UDP/11111 ポートをリッスンする OpenVPN サーバー (事前に構成済み) を起動し、スマートフォン上の外部 IP アドレスとポート (XX.1XX.1X4.2XX:4398) を指定し、スマートフォンから正常に接続しました。コンピュータ。しかし、この実装では問題が発生しました: OpenVPN クライアントがサーバーに接続するまで、何らかの方法で UDP セッションを維持する必要がありました。STUN クライアントを定期的に起動するオプションが気に入らなかったので、負荷を無駄にしたくありませんでした。 STUNサーバー。
「」というエントリーにも注目しました。ヘアピンになります - ヘアピンがあります"、このモード

ヘアピニングを使用すると、NAT の背後にあるローカル ネットワーク上の XNUMX つのマシンが、ルーターの外部アドレスにある同じネットワーク上の別のマシンにアクセスできるようになります。

プロバイダーの NAT の背後で VPN サーバーを実行する
その結果、UDP セッションの維持の問題を単純に解決しました。サーバーと同じコンピューター上でクライアントを起動しました。
それは次のように機能しました:

  • ローカルポート11111でSTUNクライアントを起動しました
  • 外部 IP アドレスとポート XX.1XX.1X4.2XX:4398 を含む応答を受信しました
  • スマートフォンで設定された電子メールへの外部 IP アドレスとポート (他のサービスも可能) を使用してデータを送信
  • UDP/11111ポートをリッスンするコンピュータ上でOpenVPNサーバーを起動しました
  • 接続に XX.1XX.1X4.2XX:4398 を指定して、コンピューター上で OpenVPN クライアントを起動しました
  • いつでもスマートフォンで OpenVPN クライアントを起動し、接続するための IP アドレスとポート (私の場合は IP アドレスは変更されませんでした) を指定します

プロバイダーの NAT の背後で VPN サーバーを実行する
これでスマホからパソコンに接続できるようになりました。この実装により、任意の OpenVPN クライアントに接続できるようになります。

練習

あなたが必要になります。

# apt install openvpn stun-client sendemail

いくつかのスクリプト、いくつかの構成ファイルを作成し、必要な証明書を生成すると (スマートフォン上のクライアントは証明書でのみ動作するため)、OpenVPN サーバーの通常の実装が得られました。

コンピュータ上のメインスクリプト

# cat vpn11.sh

#!/bin/bash
until [[ -n "$iftosrv" ]]; do echo "$(date) Определяю сетевой интерфейс"; iftosrv=`ip route get 8.8.8.8 | head -n 1 | sed 's|.*dev ||' | awk '{print $1}'`; sleep 5; done
ABSOLUTE_FILENAME=`readlink -f "$0"`
DIR=`dirname "$ABSOLUTE_FILENAME"`
localport=11111
until [[ $a ]]; do
	address=`stun stun.sipnet.ru -v -p $localport 2>&1 | grep "MappedAddress" | sort | uniq | head -n 1 | sed 's/:/ /g' | awk '{print $3" "$4}'`
        ip=`echo "$address" | awk {'print $1'}`
        port=`echo "$address" | awk {'print $2'}`
	srv="openvpn --config $DIR/server.conf --port $localport --daemon"
	$srv
	echo "$(date) Сервер запущен с внешним адресом $ip:$port"
	$DIR/sendemail.sh "OpenVPN-Server" "$ip:$port"
	sleep 1
	openvpn --config $DIR/client.conf --remote $ip --port $port
	echo "$(date) Cоединение клиента с сервером разорвано"
	for i in `ps xa | grep "$srv" | grep -v grep | awk '{print $1}'`; do
		kill $i && echo "$(date) Завершен процесс сервера $i ($srv)"
		done
	echo "Жду 15 сек"
	sleep 15
	done

データを電子メールで送信するためのスクリプト:

# cat sendemail.sh 

#!/bin/bash
from="От кого"
pass="Пароль"
to="Кому"
theme="$1"
message="$2"
server="smtp.yandex.ru:587"
sendEmail -o tls=yes -f "$from" -t "$to" -s "$server" -xu "$from" -xp "$pass" -u "$theme" -m "$message"

サーバー構成ファイル:

# cat server.conf

proto udp
dev tun
ca      /home/vpn11-srv/ca.crt
cert    /home/vpn11-srv/server.crt
key     /home/vpn11-srv/server.key
dh      /home/vpn11-srv/dh2048.pem
server 10.2.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
tls-server
tls-auth /home/vpn11-srv/ta.key 0
tls-timeout 60
auth    SHA256
cipher  AES-256-CBC
client-to-client
keepalive 10 30
comp-lzo
max-clients 10
user nobody
group nogroup
persist-key
persist-tun
log /var/log/vpn11-server.log
verb 3
mute 20

クライアント設定ファイル:

# cat client.conf

client
dev tun
proto udp
ca      "/home/vpn11-srv/ca.crt"
cert    "/home/vpn11-srv/client1.crt"
key     "/home/vpn11-srv/client1.key"
tls-client
tls-auth "/home/vpn11-srv/ta.key" 1
auth SHA256
cipher AES-256-CBC
auth-nocache
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
log /var/log/vpn11-clent.log
verb 3
mute 20
ping 10
ping-exit 30

証明書は次を使用して生成されました この記事.
スクリプトの実行:

# ./vpn11.sh

まず実行可能にすることで、

# chmod +x vpn11.sh

スマートフォン側では

アプリケーションをインストールすることで Android 用 OpenVPN、構成ファイル、証明書をコピーして構成すると、次のようになります。
スマホでメールチェックしてるプロバイダーの NAT の背後で VPN サーバーを実行する
設定でポート番号を編集しますプロバイダーの NAT の背後で VPN サーバーを実行する
クライアントを起動して接続しますプロバイダーの NAT の背後で VPN サーバーを実行する

この記事を書いている間、構成をコンピューターから Raspberry Pi 3 に転送し、すべてを LTE モデムで実行しようとしましたが、うまくいきませんでした。コマンドの結果

# stun stun.ekiga.net -p 11111

STUNクライアントバージョン0.97
プライマリ: 独立したマッピング、ポート依存フィルター、ランダム ポート、ヘアピン
戻り値は 0x000006

значение ポート依存フィルター システムの起動を許可しませんでした。
しかし、ホームプロバイダーは、システムが問題なく Raspberry Pi 3 で起動することを許可しました。
ウェブカメラ、VLC と併用すると、
WebカメラからRTSPストリームを作成する

$ cvlc v4l2:///dev/video0:chroma=h264 :input-slave=alsa://hw:1,0 --sout '#transcode{vcodec=x264,venc=x264{preset=ultrafast,profile=baseline,level=31},vb=2048,fps=12,scale=1,acodec=mpga,ab=128,channels=2,samplerate=44100,scodec=none}:rtp{sdp=rtsp://10.2.0.1:8554/}' --no-sout-all --sout-keep

視聴用にスマートフォン上の VLC (ストリーム rtsp://10.2.0.1:8554/) を使用すると、優れたリモート ビデオ監視システムであることが判明しました。また、Samba をインストールしたり、VPN 経由でトラフィックをルーティングしたり、コンピューターをリモート制御したりすることもできます。もっと...

出力

実践が示しているように、VPN サーバーを構成するには、レンタル VPS/VDS と同様に、外部 IP アドレスを支払う必要がなくても実行できます。しかし、それはすべてプロバイダー次第です。もちろん、使用されているさまざまなプロバイダーや NAT の種類についてもっと詳しく知りたかったのですが、これは単なる始まりにすぎません...
ありがとうございました!

出所: habr.com

コメントを追加します