背景
途中で無くなったり、歯抜けになってもいいけど、素早くデータを送りたい場合に必要なUDPをNAT越しでクライアントに送る場合のお話。
環境
.NetCore3.1
検証環境
クライアント | サーバ | |
---|---|---|
Privateアドレス | Privateアドレス | |
Privateアドレス | NAT | Privateアドレス |
Privateアドレス | NAT | Azure VM(Ubuntu) |
Privateアドレス | DockerのNAT | Docker |
UDP Hole Punching
NATをどうしたら外側から超えられるか。
NATはクライアントのアドレスおよびポート番号を変換しサーバに転送するので、サーバからクライアントに向けて(IPアドレス)パケットを送っても到達しません(そもそもクライアントはプライベートIPの場合も)。
そこでネットを漁るとUDP Hole Punchingなるキーワードが。
NATの変換の癖を利用した方法で、一度クライアントからサーバにパケットを送るとNATに変換テーブルが作成され穴が開いた状態になるので、
その穴に向かってパケットを発射するとクライアントに転送されるといった技だそうです。
サンプルについて
ネットを探すといろいろ情報があるけど、サンプルを実行しても動かない。
一番近いサンプルでした。
調査すると、どうやらサーバ側のUDPにソースアドレスが設定されていないため、NATが変換できないことが判明。
簡単なコアサンプルを作成しましたので、ご自身のプログラムに組み込んではいかがでしょうか。
コアサンプルソース
使い方
- サーバを起動
- クライアントを起動
- サーバの時間をクライアントに1秒間隔で送信
- クライアントで受信した文字列を表示
設定
- サーバは内部で受信するIPアドレスを動的に決めています。うまく行かない場合は
54: internal List<IPAddress> IPAddresses
のプロパティを変更してみてください。
- クライアントは実行時にサーバのIPアドレスをしてくしてください
以上です。
コアサンプルにコメントを書いておいたのでそちらを参照してください。
P2P
うまくクライアントを制御すれば、サーバを返さずP2Pでクライアント同士がおしゃべりできるかも。
最後に
いろいろな環境(NAT)で試したわけではないので、動かない環境もあるやもしれません。