私が最初のモデムを手に入れてからしばらくして、彼らはインターネットプロトコルがすぐに新しいものに置き換えられると私に言った。 これを説明する人は、実際には自分が何が良くなるかを知りませんでしたが、彼は優秀であり、近い将来に普遍的に使用されるようになると確信していました。 ほぼ20年後、今でも主にIPv4を使用しています。これは、最初のモデムで使用したプロトコルと同じです。
IPv6と呼ばれる新しいプロトコルは、現在ほとんどの最新のオペレーティングシステムで最終的に承認およびサポートされていますが、まだ広く使用されていません。 この記事では、それが提供する利点のいくつかと、アプリケーションでサポートを提供する方法について説明します。
IPv6エッセンス
IPv6の最も宣伝されている機能は、より大きなアドレス空間です。 IPv6について読んでいると、アドレスサイズが32ビットから128ビットに増加していることがわかるでしょう。 これは、生まれたすべての人が現在のインターネットよりも大きなプライベートネットワークを持つのに十分です。 持っているものすべて(電子機器を含まないものを含む)が独自のIPv6アドレスを持っている場合でも、アドレス空間のごく一部しか使用しません。
これはルーティングを簡素化できるため、非常に重要です。 ルーターは通常、比較的少数のネットワークに接続します。 最も単純な例は、ローカルネットワークをインターネットに接続するホームルーターです。 受信したパケットごとに、次の3つのいずれかを実行する必要があります。ドロップ、内部ネットワークへのリダイレクト、または外部ネットワークへのリダイレクト。
一般的なホームネットワークの場合、これは非常に簡単なソリューションです。 受信者のアドレスが予約済みの内部範囲のいずれかにある場合は内部に送信し、そうでない場合は外部に送信します。 大規模な商用ルーターでは、より複雑な決定を下す必要があります。 90年代半ば以降、IPv4アドレスが限られたリソースと見なされるようになったとき、それらは8ビットの範囲に分割されました。 つまり、完全に異なるネットワーク上で3つの隣接するブロックを取得できます。 この割り当てスキームを使用すると、2 ^ 24の可能なネットワークが取得され、ルーターは、どの接続を経由してパケットを送信するかを決定できます。 2 ^ 24は1,700万を少し下回ります。 幸いなことに、簡単にするためにノードをマージできますが、それでもルートに関する決定を単純化しません。
現在、IPv6には十分なアドレスがあるため、各国または大規模なネットワークに広範囲を割り当てることができます。 次に、接続されたネットワークのサブバンドを選択できます。 (少なくとも理論的には)この階層的な割り当てにより、ルーティングが簡素化されます。
IPv6に関する主な不満の1つは、NATがセキュリティツールであり、「ルーティング可能な」と「手頃な価格」を混同していると考える人々から来ています。 IPv4では、ほとんどのホームユーザー(およびほぼすべてのモバイルユーザー)がネットワークアドレス変換(NAT)を使用します。 コンピューターにはプライベートIPアドレスがあり、ルーターにはパブリックアドレスがあります。 プライベートIPの各接続ポートは、パブリックIPアドレスのポートにマップされます。 これはセキュリティを提供しません。 また、ほとんどのNAT実装はデフォルトで外部から開始された接続を拒否しますが、一部の実装はデフォルトホストに接続をリダイレクトします。
外部から開始された接続を拒否するポリシーはセキュリティを提供しますが、これはルーターのファイアウォールによって保証されており、NATに固有のものではありません。 ほとんどの非NATファイアウォールでも同じことが行われます。
コンピューターに外部のルーティング可能なIPv6アドレスがあるからといって、外部からアクセスできるというわけではありません。 インターネットに接続しているファイアウォールは、接続可能なポリシーを決定します。 VoIPなど、物事を機能させるためにNATを突破するために使用されたハックの数を考えると。 NATがセキュリティを追加すると他の誰かがまだ考えているのは驚くべきことですが、どうやらそう思う人もいます。
デフォルトのセキュリティ
IPv6に対するいくつかの変更は比較的単純であり、IPv4の必須ではない部分を必須にするために必要です。 最も興味深いものの1つはIPsecです。 現在、主にVPNで使用され、2つのルーター間に暗号化された接続を作成し、中間パケットの傍受を防ぎます。
IPv6を使用すると、すべてのエンドポイントがIPsecをサポートしていることを確認できます。つまり、常に暗号化された接続を確立できます。 IPv4では、主に暗号化にSSLを使用します。 これは、プロトコルスタックのわずかに高いレベルで発生し、暗号化を使用するすべてのアプリケーションをこのために特別に構成する必要があります。
現在、IPsecはグループに共通の暗号化キーで最も一般的に使用されています。 別の用途の1つは、IPsec接続の確立に使用できる公開キーをDNSレコードに導入することです。 これが機能するためには、DNSSECを使用してDNSレコード自体に署名する必要があります。
IPsecを介してDNSクエリを行う場合、暗号化された要求と応答があるため、探しているサイトを誰も知ることができません(ただし、明らかに、プロバイダーは接続したIPアドレスを知っています)。 SSLとは異なり、IPsecはUDPを含むすべての種類の接続で機能するため、VoIPなどはIPv6を使用することで大きなメリットを得ることができます。 エンドポイントは、NATを必要とせずに直接接続でき、すべての接続を暗号化できます。
別の追加はマルチキャストです。 IPv4では、各サブネット上の1つのアドレスがブロードキャストアドレスとして予約されています。 このアドレスに送信されたパケットは、サブネット上の各コンピューターに配信されます。 これは、ほとんどのネットワークが共有バスの場合に非常に意味がありました。 いずれの場合でも、すべてのパケットは送信され、各受信者にパケットを受け入れるよう指示しただけです。 ブロードキャストアドレスへの送信は、2人が受信したい場合にパケットのコピーを2つ送信するよりも効率的でした。
スイッチドネットワークの場合、これは当てはまりません。 各コンピューターは一定量のデータを送受信でき、スイッチはこれらのパケットをマシン間で配信します。 したがって、100 Mb / sネットワーク上の4台のコンピューターは、100 Mb / sごとに2つの独立した転送を行うことができます。 ブロードキャストアドレスにパケットを送信すると、それを受信したくない人も含め、全員に送信されます。
グループ送信は少し賢くなります。 コンピューターのグループを識別し、それらに共通のIPアドレスを割り当てます。 このアドレスに送信されたパケットは、グループに入ることを決定した各コンピューターに送信されます。 ブロードキャストとは異なり、マルチキャストはルーティング可能です。 マルチキャストグループ内の異なるネットワークに多数のコンピューターを配置し、2つのダウンストリームネットワークに参加している参加者がいるルーターにソースパケットが到達した場合にのみ2つのパケットを生成できます。 たとえば、インターネットラジオステーションがIPv6マルチキャストを使用している場合、ラジオステーションは単一のパケットストリームをプロバイダーに送信します。 プロバイダーは、このステーションを聴いている各顧客にストリームのコピーを送信する必要があります。 パケットがルーターに到着すると、このストリームをリッスンしているネットワーク上のすべてのマシンにコピーを送信します。
電話会議などに同じメカニズムを使用できます。 現在、ビデオ会議セッションに10人いる場合、全員がカメラからストリームのコピーを10個配布するか、リレーを処理できるサーバーが必要です。 グループメーリングでは、全員が10人分のコピーを1通送信します。 通常、リターンよりも広い受信チャネルを持つコンシューマネットワークでは、これは特に魅力的です。
ブロードキャストは、たとえば、どのコンピューターを使用してサービスを検出する必要があるかわからない場合にも使用されます。 IPv6は、このメソッドをエニーキャストに置き換えます。 エニーキャストは、エニーキャストアドレスに関連付けられたアドレスグループのマルチキャストに似ていますが、マルチキャストとは異なり、このアドレスに送信されるパケットは1台のマシンにのみ配信されます。 これは、たとえば自動構成などに役立ちます。
ソケットとプロトコル
これで、IPv6サポートが役立つことがわかると思います。 その後、質問が発生します-どのように? ほとんどのネットワークコードは、Berkeleyソケットまたはその上に構築された高レベルAPIを使用します。 高レベルのAPIを使用している場合、おそらく他の誰かによってIPv6サポートが既に提供されています。 ソケットを使用する場合は、コードに小さな変更を加える必要があります。
Berkeley Sockets APIは、すべてがファイルであるというUNIXの考え方に基づいていました。 いくつかの追加機能を備えた記述子を使用して、リモートマシンと通信します。 ソケットがある場合、APIは完全にプロトコルに依存しません。 IPv4、IPv6、AppleTalk、または他のプロトコルを使用するかどうかにかかわらず、コードは同じです。
残念ながら、ソケットの作成は問題の始まりです。 この関数を使用してソケットを作成します。
int socket(int domain, int type, int protocol);
3つのパラメーターは、プロトコルのいくつかの側面を完全に定義します。 ほとんどの場合、ドメインをPF_INETに厳密に設定することになり、IPv4を意味します。 ソケットをローカルアドレスにバインドし、接続するか接続を受け入れると、事態はさらに悪化します。 関連するすべての関数は、引数としてsockaddr構造体へのポインターを受け入れます。
この構造は非常に単純ですが、直接使用することはできません。 代わりに、sockaddr_in構造のようなものを使用します。これは、sockaddr構造と同じ方法で(サイズとアドレスファミリを使用)、IPv4アドレスとポート番号を含みます。 通常、gethostbyname()を使用してこれらのパラメーターを決定します。
別のプロトコルをサポートする場合は、異なる検出メカニズムを備えたコードの別のブランチを追加する必要があります。 2004 POSIXバージョンの最新の拡張機能の1つは、getaddrinfo()関数の定義です。 アドレスとサービスの文字列の説明で指定されたサーバーを定義します。 つまり、ポート番号をハードコーディングする必要はありません。 使い方はとても簡単です。 このコードは、利用可能な接続を使用してHTTP経由でInformITサーバーに接続します。
struct addrinfo hints, *results;
memset(&hints, 0, sizeof (hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int error = getaddrinfo( "informit.com" , "http" , &hints, &results);
if (error) { /* fail */ return -1; }
int s = -1;
for ( struct addrinfo *res = results;
res != NULL && s < 0 ;
res = res->ai_next)
{
s = socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
//If the socket failed, try the next address
if (s < 0) { continue ; }
//If the connection failed, try the next address
if (connect(s, res->ai_addr, res->ai_addrlen) < 0)
{
close(s);
s = -1;
continue ;
}
}
freeaddrinfo(results);
return s;
* This source code was highlighted with Source Code Highlighter .
getaddrinfo()の最初の2つの引数は、サーバー名とプロトコル名です。 コンバーターは、サーバーアドレスとサービスの組み合わせを見つけます。 OS Xなどの一部のプラットフォームでは、これにはDNS SRVレコードの定義も含まれているため、DNSレコードにこの事実が含まれている間にサーバーが非標準ポートで実行されている場合でも、この操作によりポートが正しく構成されます。 ヒント構造は、返されるアドレス情報にいくつかの制限を設定するために使用されます。 この場合、ストリーミングソケットのみが必要であり、ネットワークスタックでサポートされるあらゆるプロトコルでソケットを受け入れる準備ができています。 最後の引数は、アドレス情報構造の配列を返すために使用されるポインターです。
socket()およびconnect()のすべての引数は、getaddrinfo()の呼び出しによって返される完全にアドレスデータであることに注意してください。 このコードはいずれも、IPv4、IPv6、またはその他の新しいプロトコルを使用しているかどうかをまったく示していません。 オペレーティングシステムがプロトコルをサポートしている限り、このコードを使用できます。
IPv6:現在のプロトコル
この記事で、IPv6がサポートに値するエキサイティングな機能を提供していることを願っています。 そして、最も重要なことは、彼をサポートすることはそれほど努力する価値がないことです。 IPv6をサポートしない新しいソケットコードを記述する理由はありません。 また、古いコードを更新してサポートするだけでも簡単です。
この記事を書いたときにgetaddrinfo()関数を検討する必要がありました。これは、ホスト名とプロトコル名を引数として受け取り、しばらくすると接続されたソケットを返すクラスにラップし、今ではこのクラスをネットワーク全体で使用するためですコード。
無料のIPv4アドレスはますます少なくなり、すべてのクライアントにNATを使用するプロバイダーが増えているようです。 ある時点で、そのままIPv6をサポートするアプリケーションを使用するユーザーのみが、直接エンドツーエンド接続を確立できます。 それでもコードでこれができない場合は、今が修正の時です。