Gonc – P2P NATトラバーサル対応のNetcat
Gonc – Netcat with P2P Nat Traversal (github.com)
要約
Goncは、NATトラバーサル機能を備えたGolangベースのNetcatツールです。パスフレーズを共有するだけで、複雑な設定なしにP2P接続を自動で確立できます。TLS/DTLSによるエンドツーエンド暗号化や相互認証もサポートしており、リモートシェル、SOCKS5プロキシ、HTTPファイルサーバーなど、柔軟なサービス設定が可能です。
全文翻訳
goncの紹介
gonc は、ピアツーピア(P2P)通信を容易にするために設計された、Golangベースのnetcatツールです。主な機能は以下の通りです。
-
🔁 自動NATトラバーサル: 設定不要。両方のピアはパスフレーズを共有するだけで済みます。
-p2pパラメータを使用すると、ピアはパブリックSTUNおよびMQTTサービスを利用して、アドレス交換のために自動的に互いのネットワークアドレスを発見し、NATトラバーサルを介してポイントツーポイント接続を確立できます。 -
🔒 相互認証付きエンドツーエンド暗号化: TCPにはTLS、UDPにはDTLSによる暗号化伝送をサポートし、パスフレーズベースの相互ID認証を備えています。
-
🧩 柔軟なサービス設定:
-eパラメータを使用すると、各接続に対してアプリケーションを柔軟に設定できます。例えば、-e /bin/shはリモートのコマンドシェルを提供できます。便利なSOCKS5サービス、HTTPファイルサービス、トラフィック転送のために、組み込みの仮想コマンドを使用することもできます。
関連プロジェクト
- gonc-gui —
goncをベースにしたデスクトップ(Windows)およびAndroidアプリ:便利なクロスデバイス、クロスネットワークP2P直接接続とセキュアなファイル転送。パスフレーズを共有する(またはQRコードをスキャンする)だけで、コマンドラインは不要です。
使用例
基本的な使い方
-
ncのように使用します:gonc www.baidu.com 80 gonc -tls www.baidu.com 443IPアドレスとポートに基づいたポイントツーポイント接続のみを確立できます。
-
現在では、共有パスフレーズに基づいたポイントツーポイント接続も確立でき、自動NATトラバーサルも利用できます。
以下の図は、ホームブロードバンドネットワーク(ハードNAT)とモバイルネットワーク(シンメトリックNAT)上のピアとの間でgoncがP2P接続を確立するプロセスを示しています。両方のエンドがIPv6を持っているため、NATトラバーサルを実証するために、両方のエンドで
-4オプションを使用してIPv4を強制しています。
P2PトンネルとHTTPファイルサーバー
-
両方のピアが同じパスフレーズに同意します。送信側では、共有したいファイルまたはディレクトリを公開するためにHTTPファイルサーバーを起動します。
-httpserverオプションは複数のパスを受け入れることができ、それぞれが単一のファイルまたはディレクトリになります:gonc -p2p <passphrase> -httpserver c:/RootDir1 c:/RootDir2
-受信側には2つのオプションがあります:
-
ディレクトリ全体を自動的にダウンロードする
以下のコマンドを実行すると、すべてのファイルがローカルマシンに再帰的にダウンロードされます。プロセスが中断された場合、コマンドを再実行すると中断したところから自動的に再開されます:
gonc -p2p <passphrase> -download c:/SavePath -
ブラウザ経由で閲覧し、選択的にダウンロードする
このオプションは自動的にダウンロードを開始しません。代わりに、手動でブラウザを開き、http://127.0.0.1:9999にアクセスして、ピアのファイルリストを表示し、必要に応じてファイルをダウンロードする必要があります:
gonc -p2p <passphrase> -httplocal-port 9999特定のサブディレクトリをダウンロードする必要がある場合、ブラウザは不便ですが、次のように行うことができます:
gonc -http-download c:/SavePath http://127.0.0.1:9999/subdir
セキュアな暗号化P2P通信
-
パスフレーズを共有して、2つの異なるネットワーク間でセキュアな暗号化P2P通信を確立します(高エントロピーのパスフレーズを生成するには
gonc -psk .を使用し、<passphrase>に置き換えてください)。このパスフレーズは、相互検出と証明書派生に使用され、TLS 1.3による通信セキュリティを確保します。gonc -p2p passphrase反対側では、同じパラメータを使用します(プログラムは自動的にTCPまたはUDP通信(TCP優先)を試行し、ロール(TLSクライアント/サーバー)をネゴシエートし、TLSプロトコルを完了します):
gonc -p2p passphrase反対側が実行時間を遅延させた場合、約半分の時間内に相互作用する情報を見つけられないと終了することに注意してください。そのため、MQTTメッセージサブスクリプションに基づいた待機メカニズムもサポートしており、
-mqtt-waitと-mqtt-helloを使用して、両当事者がP2Pを開始するタイミングを同期させます。例えば、以下は継続的に待機するために-mqtt-waitを使用しています。gonc -p2p passphrase -mqtt-wait反対側では、
gonc -p2p passphrase -mqtt-hello -
NATタイプを確認します
gonc -nat-checkerこれにより、IPv6およびIPv4のTCPおよびUDP NATアドレスがチェックされ、NAT後のポート変更が分析されます。TCP6またはUDP6アドレスがリストにない場合は、IPv6がないことを意味します。各プロトコルアドレスは「(easy)」で終わっており、ホールパンチングの成功率が最も高いことを示しています。「(hard)」は成功率が高いことを示し、「(symm)」は最も困難です。シンメトリックNATの場合、P2Pを機能させるには相手側が「easy」または「hard」である必要があります。
リバースシェル(UNIXライクシステム向けの疑似端末サポート)
-
リスナー(
-keep-openを使用せず、1つの接続のみを受け入れます。-pskによる認証はありません):gonc -tls -exec ":sh /bin/bash" -l 1234 -
シェルを取得するために接続します(TAB、Ctrl+Cなどをサポート):
gonc -tls -pty x.x.x.x 1234 -
リバースシェルにP2Pを使用します(
passphraseは認証に使用され、TLS 1.3によるセキュアな通信を保証します):gonc -exec ":sh /bin/bash" -p2p passphrase反対側では:
gonc -pty -p2p passphrase
送信速度テスト
-
データを送信し、送信速度を測定します(組み込みの
/dev/zeroと/dev/urandomを使用):gonc.exe -send /dev/zero -P x.x.x.x 1234例:
IN: 76.8 MiB (80543744 bytes), 3.3 MiB/s | OUT: 0.0 B (0 bytes), 0.0 B/s | 00:00:23受信側では:
gonc -P -l 1234 > NUL
P2PトンネルとSOCKS5 / HTTPプロキシ
-
トンネルが確立されるのを待ちます:
gonc -p2p passphrase -linkagent -
反対側では、リモートネットワークにアクセスするためにポート3080でローカルSOCKS5 / HTTPプロキシサービスを開始します:
# linkオプションは、ローカルおよびリモートのプロキシエンドポイントがどのように作成されるかを制御します。 # noneを使用すると、その側でリスニングポートが開かれないことを示します: gonc -p2p passphrase -link "3080;none"次に、例えばリモートネットワークの
10.0.0.1:3389に接続したい場合、ローカルのRemote Desktopクライアントに次のアドレスを入力するだけです:10.0.0.1-3389.gonc.cc:3080このドメインは
127.b.c.dの形式のIPに解決されます。その結果、Remote Desktopクライアントはポート3080のローカルSOCKS5プロキシに接続し、goncはドメイン名から10.0.0.1-3389という情報を抽出するために127.b.c.dアドレスを逆解析します。 -
link設定フォーマット
# 確立されたトンネルに基づいて、ローカルとリモートの両方の側がポート1080でリッスンします。 # プロキシはHTTPとSOCKS5の両方のプロトコルをサポートし、透過プロキシ機能が有効になっています。 gonc -p2p <passphrase> -link "1080;1080" # 以下はURL形式の設定方法です。-linkのパラメータ値は引用符で囲む必要があります。そうしないと、解析の問題が発生する可能性があります。 # 左側の x://0.0.0.0:1080?tproxy=1 は、単に1080と書くのと同じです。 # 右側はリモートホストでポート1080を有効にしますが、透過プロキシのサポートはありません。 gonc -p2p <passphrase> -link "x://0.0.0.0:1080?tproxy=1;x://127.0.0.1:1080" # 左側の f://127.0.0.1:1080?to=1.2.3.4:80 # は、ローカルでポート1080をリッスンし、リモート側で1.2.3.4:80にトラフィックを転送することを意味します。 # 右側の 'none' は、リモートでポートが開かれないことを示します。 gonc -p2p <passphrase> -link "f://127.0.0.1:1080?to=1.2.3.4:80;none" # 右側の f://0.0.0.0:80?to=127.0.0.1:80 # は、リモート側でポート80をリッスンし、ローカルの127.0.0.1:80にトラフィックを転送することを意味します。 gonc -p2p <passphrase> -link "none;f://0.0.0.0:80?to=127.0.0.1:80" # 左側の x+tls は、TLS暗号化付きのプロキシプロトコルを意味し、証明書設定が可能です。右側は `outbound_bind` を介して送信元IPアドレスを指定します(マルチIP環境に適しています)。 gonc -p2p <口令> -link "x+tls://user:pass@0.0.0.0:1080?cert=ca.pem&key=key.pem;none?outbound_bind=10.0.0.5"
柔軟なサービス設定
-
-execを使用して、各接続にサービスを提供するためにアプリケーションを柔軟に設定できます。例えば、シェルコマンドの/bin/bashを指定する代わりに、ポート転送にも使用できます。ただし、以下の例では、接続ごとに新しいgoncプロセスが起動されます:gonc -keep-open -exec "gonc -tls www.baidu.com 443" -l 8000 -
複数の子プロセスを生成しないようにするには、組み込みの
ncモジュールを使用します:gonc -keep-open -exec ":nc -tls www.baidu.com 443" -l 8000
Socks5プロキシサービス
-
クライアントモードを設定します:
gonc -x s.s.s.s:port x.x.x.x 1234 -
組み込みSocks5サーバー:
-e :s5sを使用して標準のSocks5サービスを提供します。-authをサポートし、Socks5のユーザー名とパスワードを設定できます。-keep-openを使用して、Socks5サーバーへのクライアント接続を継続的に受け入れます。Golangのゴルーチンのおかげで、良好なマルチクライアント同時実行パフォーマンスを実現しています:gonc -e ":s5s -auth user:passwd" -keep-open -l 1080 -
TLS経由のセキュアSocks5:標準のSocks5は暗号化されていないため、
-e :s5sと-tlsおよび-pskを使用して、TLS経由のカスタムセキュアSocks5通信を行います。-Pを使用して接続転送情報を監視し、-aclを使用して着信接続とプロキシ宛先のアクセス制御を実装します。acl.txtファイルのフォーマットについては、acl-example.txtを参照してください。gonc.exe -tls -psk passphrase -e :s5s -keep-open -acl acl.txt -P -l 1080反対側では、
:s5c(組み込みのs5cコマンド)を使用して、TLS経由のSocks5を標準Socks5に変換し、127.0.0.1:3080でローカルクライアントアクセスを提供します:gonc.exe -e ":s5c -tls -psk passphrase x.x.x.x 1080" -keep-open -l -local 127.0.0.1:3080
他のアプリケーションのためのトンネルの確立
-
NATトラバーサルを支援してVPNを形成するWireGuard
パッシブ(リスニング)側であるPC-Sで、以下のコマンドを実行します(WireGuardピアの公開鍵をパスフレーズとして使用し、WireGuardがポート51820でリッスンしていると仮定します):
gonc -p2p <PublicKey-of-PS-S> -mqtt-wait -u -k -e ":nc -u 127.0.0.1 51820"アクティブ(開始)側であるPC-Cで、WireGuardピア(PS-S)のエンドポイントを
127.0.0.1:51821に設定し、自身のWireGuardインターフェースを51820でリッスンさせます。次に、以下のコマンドを実行します。-kフラグは、ネットワークが切断された場合にgoncが自動的に再接続できるようにします:gonc -p2p <PublicKey-of-PS-S> -mqtt-hello -u -k -e ":nc -u -local 127.0.0.1:51821 127.0.0.1 51820"
P2P NATトラバーサル機能
goncはどのようにP2P接続を確立しますか?
- 複数のパブリックSTUNサーバーを同時に使用して、ローカルのTCP/UDP NATマッピングを検出し、NATタイプをインテリジェントに判断します。
- セッションキーから派生したハッシュを共有トピックとして使用し、パブリックMQTTサーバーを介して安全にアドレス情報を交換します。
- 以下の優先順序で直接接続を試みます:IPv6 TCP > IPv4 TCP > IPv4 UDP。真のピアツーピア通信を目指します。
- リレーサーバーは使用せず、フォールバックメカニズムも提供しません。接続が失敗するか、真のP2Pが成功するかのどちらかです。
P2Pが実現できない場合のフォールバックリレーサーバーのデプロイ方法
-
UDP ASSOCIATEサポート付きのSOCKS5サーバーをパブリックIPで実行すれば、リレーとして十分です。または、VPSでgoncの組み込みSOCKS5プロキシを実行してリレーサーバーとして機能させることもできます。
以下のコマンドは、UDP転送のみをサポートするSOCKS5プロキシを開始します。
-pskおよび-tlsオプションは、暗号化とPSKベースの認証を有効にします。注意:ファイアウォールでポート1080を開くだけでは不十分です。UDP転送はセッションごとにランダムなポートを使用します。gonc -e ":s5s -u -c=0" -psk <password> -tls -k -l 1080 -
P2Pが失敗した場合、goncの片側だけで
-xオプションを使用してSOCKS5リレー経由でルーティングするようにP2Pプロセスを再試行するだけで済みます:gonc -p2p <passphrase> -x "-psk <password> -tls <socks5server-ip>:1080"または、UDP転送をサポートする標準のSOCKS5プロキシサーバーを使用することもできます:
gonc -p2p <passphrase> -x "<socks5server-ip>:1080" -auth "user:password"例えば、両方のピアがシンメトリックNATの背後にあり、P2Pが失敗した場合、片側がSOCKS5 UDPリレーを使用するだけで、そのNAT動作が「easy」に変わり、接続の確立がはるかに容易になります。データはエンドツーエンドで暗号化されたままです。
使用されているパブリックサーバー(STUN & MQTT):
"tcp://turn.cloudflare.com:80",
"udp://turn.cloudflare.com:53",
"udp://stun.l.google.com:19302",
"stun.gonc.cc:3478",
"global.turn.twilio.com:3478",
"stun.nextcloud.com:443",
"tcp://broker.hivemq.com:1883",
"tcp://broker.emqx.io:1883",
"tcp://test.mosquitto.org:1883",
"tcp://mqtt.gonc.cc:1883"
NATトラバーサルにおけるgoncの効果はどの程度ですか?
両端がシンメトリックNATである場合を除き、goncは非常に高い成功率を達成します
goncはNATタイプを3つのカテゴリに分類します:
-
Easy:単一の内部ポートが複数のSTUNサーバー間で同じ外部ポートにマッピングされる
-
Hard:単一の内部ポートがSTUNサーバー間で一貫した、しかし異なる外部ポートにマッピングされる — タイプ1より困難
-
Symmetric:単一の内部ポートが宛先によって異なる外部ポートにマッピングされる — 最も困難なタイプ
これらのNATタイプを処理するために、goncはいくつかのトラバーサル戦略を採用しています:
- 複数のSTUNサーバーを使用してNATの動作を検出し、マルチエグジットIPシナリオを特定します。
- 両方のピアがサポートしている場合、IPv6接続を優先します(例:TCP6からTCP6への直接ダイヤル)。
- 両方のピアがTCPでリッスンし、同時に互いにダイヤルすることで、TCPホールパンチングの成功率を高めます。
- より簡単なNATを持つピアは、より困難な側のポート変更をトリガーしないように、初期UDPパケットを遅延させます。
- より困難なNATを持つピアは、リモートファイアウォールからの干渉を減らすために、低いTTLでUDPパケットを送信します。
- 最後の手段として、「バースデーパラドックス」戦略を使用します。困難な側は600個のランダムなソースポートを使用し、もう一方の側は600個のランダムな宛先ポートを試行し、UDPポート衝突の成功確率を高めます。