外部からホーム ネットワークにアクセスできるように、自宅でワイヤーガード サーバーを実行しています。 Wireguard は UDP を使用しています。残念ながら、プロバイダーが CG-NAT を使用しているため、昔のようにフリッツ ボックスで IPv4 UDP ポートを開くことはできません。IPv6 を使用する必要がありますが、職場ではまだ IPv6 が使用できません。
そのため、自宅では IPv6 を使用し、職場では IPv4 を使用していますが、ホーム ネットワークにアクセスする方法がありません。
また、TCP トラフィック用のリバース SSH トンネルを確立できるパブリック IPv4 を備えた VPS もあります。残念ながら、SSH トンネルは TCP のみをサポートしているため、TCP 経由で VPN 接続を行うべきではありません。これが、ワイヤーガードが UDP のみを使用する理由です。
VPN-Server VPN-Client
(UDP) | | (IPv4 UDP)
| | | not possible |
-----------|--------| <-------------------
| |
NAT CG-NAT
VPN-Server VPN-Client
(UDP) (IPv4 UDP)
| |
| |
inside agent outside agent
tunnel tunnel
|| | | ||
|| punch| punch| ||
| --------->|-------->|-------------------- |
-----------|<--------|<--------------------
| |
| |
NAT CG-NAT
外部エージェントはパブリック IPv4 を備えた VPS 上で実行されています
内部エージェントは UDP データグラムを外部エージェントのパブリック IP とポートに送信します。これにより両方の NAT に穴が開きます。外部エージェントはこれらのデータグラムを受信し、送信元アドレスとポートから内部エージェントにデータグラムを送信する方法を学習します。 。
VPN クライアントは UDP を外部エージェントに送信でき、これらのデータグラムは内部エージェントに転送され、そこから VPN サーバーに転送されます。VPN サーバーは内部エージェントに応答でき、これらは外部エージェントに転送され、そこから VPN サーバーに送信されます。 VPN クライアント。
外部エージェントはクライアントに対して VPN サーバーとして認識され、内部エージェントはサーバーに対して VPN クライアントとして認識されます。
外部に接続する新しいクライアントごとに内部エージェントのトンネルと新しいソケットを使用するため、複数のクライアント接続が可能です。そのため、サーバーからは複数のクライアントが内部エージェントのホストで実行されているように見えます。
両方のマシンでコードを複製または解凍し、ビルドします。少なくとも make と gcc が必要です。ソースディレクトリを入力してコマンドを使用します
$ make
ビルドが成功すると、同じフォルダーにバイナリのudp-tunnel
が作成されます。これで、ターミナルから直接起動して (もちろん適切なオプションを使用して) いくつかの簡単なテストを行うことも、メイクファイルを使用してインストールすることもできます。
コンパイルされたバイナリudp-tunnel
コマンド ラインで渡すオプションに応じて、内部エージェントまたは外部エージェントとして機能します。
例として、VPN サーバーが UDP 1234 でリッスンし、ローカルホスト (内部エージェントと同じ) で実行されており、外部マシンが Jump.example.com であり、それを UDP ポート 9999 でリッスンしたいとします。
内部ホストでは次のように開始します。
$ ./udp-tunnel -s localhost:1234 -o jump.example.com:9999
外部ホストでは、次のようにして開始します。
$ ./udp-tunnel -l 9999
Makefile には 3 つのインストール ターゲットが含まれています。バイナリのみをインストールするinstall
、systemd サービス ファイルもインストールするinstall-outside
およびinstall-inside
。後の 2 つは、適切に動作するために make に変数を渡す必要があります。
外部エージェントをジャンプ ホストにインストールするには (ポート 9999 が必要であると仮定して)、次のコマンドを実行します。
$ sudo make install-outside listen=9999
これにより、バイナリが/usr/local/bin/
にインストールされ、systemd サービス ファイルが/etc/systemd/system/
にインストールされます。これには、ポート 9999 を使用して外部エージェント モードで起動するために必要なコマンドが含まれています。
内部マシンに内部エージェントをインストールするには、次のコマンドを使用します (例として、VPN サーバーが localhost:1234 で、ジャンプ ホストが Jump.example.com であると仮定します)。
$ sudo make install-inside service=localhost:1234 outside=jump.example.com:9999
これにより、バイナリが/usr/local/bin/
に再度インストールされ、systemd ユニット ファイルが/etc/systemd/system/
にインストールされます。
この時点で、systemd ユニット ファイルをざっと調べて、バイナリがどのように使用されているかを確認し、オプションが正しいかどうかを確認するとよいでしょう。オプションは、上記のクイック テストで説明したようになります。
systemd ファイルがインストールされ、正しいことが確認された後、まだ自動起動が有効になっていないため、有効にして起動する必要があります。内部マシンの場合:
$ sudo systemctl enable udp-tunnel-inside.service
$ sudo systemctl start udp-tunnel-inside.service
そして外側のマシンでは
$ sudo systemctl enable udp-tunnel-outside.service
$ sudo systemctl start udp-tunnel-outside.service
暗号化はありません。パケットはそのまま転送されます。トンネリングしているサービスは、データを独自に保護または暗号化する方法を知っていると想定されます。通常、これは VPN 接続の場合に当てはまります。
さらに、攻撃者は、内部エージェントからのキープアライブ パケットをスプーフィングして外部エージェントを混乱させ、トンネルを自分のマシンに迂回させ、その結果サービスの中断を引き起こす可能性があります。この非常に単純な攻撃を防ぐために、ハッシュ ベースのメッセージ認証コードを使用してキープアライブ データグラムを認証できます。この機能を有効にするには、トンネルの両方の終端で -k オプションを使用して事前共有パスワードを使用できます。
内部ホストでは次のように使用します
$ ./udp-tunnel -s localhost:1234 -o jump.example.com:9999 -k mysecretpassword
外部ホストでは、次のようにして起動します
$ ./udp-tunnel -l 9999 -k mysecretpassword
上記のインストール手順が正常に動作したら、両方の側で systemd ファイルを手動で編集し、-k オプションを追加してから、両方の側でリロードして再起動することをお勧めします。
その後、キープアライブ メッセージには、このパスワードと、単純なリプレイ攻撃を防ぐために 1 回だけ使用できる厳密に増加するノンスの上に SHA-256 が含まれます。
どちらのエージェントも接続のリストを維持し、各接続には、その特定のクライアント接続に関連付けられたソケット アドレスとソケット ハンドルが保存されます。
起動時に、内部エージェントは外部エージェントへの送信トンネルを開始し、それを未使用としてマークし、その上でキープアライブ パケットを送信します。外部エージェントはこれらのパケットを確認し、このトンネルをその送信元アドレスとともに独自の接続リストに追加します。キープアライブ パケットはノンスと認証コードで署名されているため、なりすましや再生はできません。
クライアントが接続すると、外部エージェントはその未使用の予備トンネルにクライアント データを送信し、内部エージェントはこれを見て、トンネルをアクティブとしてマークし、サービスと通信するためのソケットを作成し、データを両方向に転送します。また、すぐに別の新しい送信予備トンネルを作成し、次の受信クライアントに備えます。
新しい予備トンネルが外部エージェントに到着すると、そのトンネルを独自の接続リストに追加して、次の接続クライアントにすぐにサービスを提供できるようにします。
この時点で、両方のエージェントのリストには 2 つのトンネルがあり、1 つはアクティブ、もう 1 つはスペアで、次のクライアント接続を待機しています。
非アクティブ タイムアウトにより、デッド トンネル (過去にアクティブとマークされていたが、しばらくの間クライアント データが存在しないトンネル) が確実に削除され、ソケットが閉じられます。内部エージェントは、長期間にわたって転送データがないことを検出し、そのデータを自身のリストから削除してソケットを閉じます。その後、しばらくして、外部エージェントがこの接続に到着するキープアライブがもうないことを検出し、自身のリストから削除します。リストも。
このコードはまだ非常に実験段階であるため、少なくとも現時点では、これをベースにして数百万ドル規模のビジネスを構築しないでください。私にとっては目的を完全に果たしていますが、あなたのサーバーがクラッシュしたり、燃えたり、爆発したりする可能性があります。あなたは警告を受けました。