diary2020-06-28UDPでNAT超えあらすじNAT超えという技術を知り、いったいどういうものなのか?を調べて、Goで簡単に実装してみました。NATNATというのはグローバルIPとローカルIPを変換する機構です。グローバルIPの枯渇を防ぐため、ローカルIP以下のデバイスに対して同じグローバルIPを割り振るための仕組み提供します。最近はIPだけではなくポートも変換するNAPTというタイプが主流のようです。2台のパソコンがNAT下にぶら下がっていてそれぞれがサーバーにアクセスするような場合は以下のような構成になります。PC1がWEBサーバーにアクセスする時、アクセス要求はNATを経由してインターネットを通じてサーバーに到達します。サーバーは要求を処理し応答を返します。応答はインターネットを経由してNATまで届きます。NATはその応答をPC1に送り、無事に通信ができます。NATがどのように応答を振り分けるというと、NAT内部にグローバルIPとローカルIPの変換表を持っていてそれをもとに応答を振り分けています。TCP/IPやUDP/IPの場合、変換表には以下の情報が記録されます。プロトコル送信元IP送信元ポートグローバルIPグローバルポート相手先IP相手先ポートPC1がWEBサーバーにアクセスした場合は以下のような情報が変換表に記録されます。80サーバー側からの応答は送信先IPと相手先IPが変換表とは逆になって返信されます。NATはそれを考慮して変換表に当てはまるものがあるかを調べ、当てはまるものがあったなら、そのデバイスへ応答を渡します。なかった場合はその時点で破棄されます。グローバルポートは基本的に同じになります。別々のローカルIPで同じポート番号から通信が来た場合にのみ変換されます。PC1とPC2が同じ送信元ポートで通信をした場合、ポートを変換せずに変換表に記録した場合、以下のようになります。返信されるので、NATは変換表をチェックしたときに1番目にも2番目にも対象のIPがヒットするので応答を振り分けることができません。そこで、以下のようにグローバル側に見せるポートを変換することで、この問題を解決します。返されるため、NATは問題なく応答を振り分けることができるというわけです。ポートマッピングNATは基本的にグローバル側からアクセスは受け付けません。いうのも、グローバル側から唐突に通信が来ても変換表から対応するローカルIPを割り出せないため、すべて破棄されるためです。これだと、ローカルにWEBサーバーを立てても外部に公開できなくて不便ですよね。NATにはポートマッピングという機能があるものがあります。これは、特定のポートにやってきた通信を対応するIPのデバイスに転送する機能です。以下のようなマッピングテーブルがあったとします。WEBサーバーが起動していれば要求は処理され応答が返ります。P2PP2Pとは、サーバーを持たず、クライアント同士が通信する方法のことを指します。サーバー運営コストが少ない、サーバーの処理性能に左右されない等のメリットがあります。そのままではクライアント間で通信はできないため、古き良きインターネッツ時代にあったP2P型ファイル共有ソフトではポート開放(ポートマッピング)を行うことで各ノード間の通信を可能にしていました。一方で、ポート開放はセキュリティリスクが高く、悪意のあるユーザーがそのポートに対してアクセスして悪意のある操作を可能にする可能性があるため、ユーザーとしてはあまりやりたいことではないと思います。そこで出てくるのがNAT超えです。NAT超えNAT超えとは、ポート開放せずにP2Pを可能にする技術のことです。クライアントだけではNAT越えは難しいので、STUNサーバーやTURNサーバーを使ってNAT超えを行うのがセオリーのようです。STUNサーバーやTURNサーバーのRFCがあるようです。私はまだ見れていません。UDPでのNAT超えUDPはコネクションレスなので内側からデータを送信するだけでNATはポートを開放します。相手側にはデータは届きませんが応答を待っている状態ですので、相手側からも同じようにデータを送信することで通信が可能となります。内から外への通信によってポートが自動で開放されるとしても、相手のIPアドレスとポートを知る方法が必要です。相手のIPアドレスとポートを知るためにサーバーを一つ用意します。そのサーバーに自分のIPアドレスとポートを登録しておき、相手から自由に取得できるようにしておきます。PC2からPC1に伝えられたポートで通信このような感じでPC1とPC2の疎通が可能となります。Goのサンプル上記を実装したのが以下になります。UDPまとめUDPでNAT越えをするための理屈を説明しました。Goでのサンプルを実装しました。こんな記事を書きました。入ってるものとします。4はてなブログをはじめよう!bamch0hさんは、はてなブログを使っています。ブログを報告する引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。