TCP/IP raw ソケット

生ソケットは、基になるトランスポート プロバイダーへのアクセスを許可するソケットの一種です。 このトピックでは、生のソケットと IPv4 および IPv6 プロトコルについてのみ説明します。 これは、ATM を除く他のプロトコルのほとんどは、生のソケットをサポートしていないためです。 生のソケットを使用するには、使用されている基になるプロトコルに関する詳細情報がアプリケーションに必要です。

IP プロトコルの Winsock サービス プロバイダーは、ソケットの 種類SOCK_RAWをサポートしている場合があります。 Windows に含まれる TCP/IP 用 Windows ソケット 2 プロバイダーでは、この SOCK_RAW ソケットの種類がサポートされています。

このような生ソケットには、次の 2 つの基本的な種類があります。

  • 最初の型は、Winsock サービス プロバイダーによって認識される IP ヘッダーに書き込まれた既知のプロトコル型を使用します。 最初の種類のソケットの例として、ICMP プロトコル (IP プロトコルの種類 = 1) または ICMPv6 プロトコル (IP プロコトルの種類 = 58) のソケットがあります。
  • 2 番目の型では、任意のプロトコルの種類を指定できます。 2 番目の種類の例は、ストリーム制御伝送プロトコル (SCTP) などの Winsock サービス プロバイダーによって直接サポートされていない実験用プロトコルです。

生ソケットがサポートされているかどうかを判断する

Winsock サービス プロバイダーがAF_INETまたはAF_INET6 アドレス ファミリのSOCK_RAW ソケットをサポートしている場合、使用可能な 1 つ以上のトランスポート プロバイダーの WSAEnumProtocols 関数によって返されるWSAPROTOCOL_INFO構造体に、SOCK_RAWのソケットの種類を含める必要があります。

WSAPROTOCOL_INFO構造体の iAddressFamily メンバーは、AF_INETまたはAF_INET6を指定する必要があり、WSAPROTOCOL_INFO構造体の iSocketType メンバーは、トランスポート プロバイダーの 1 つにSOCK_RAWを指定する必要があります。

WSAPROTOCOL_INFO構造体の iProtocol メンバーは、IPROTO_IPに設定できます。 サービス プロバイダーがアドレス ファミリのインターネット プロトコル以外の他のネットワーク プロトコルにSOCK_RAWソケットの種類を使用できるようにする場合、WSAPROTOCOL_INFO構造体の iProtocol メンバーも 0 に設定できます。

WSAPROTOCOL_INFO構造体の他のメンバーは、SOCK_RAWのプロトコル サポートの他のプロパティを示し、SOCK_RAWのソケットの処理方法を示します。 SOCK_RAWWSAPROTOCOL_INFOの他のメンバーは、通常、プロトコルがコネクションレスでメッセージ指向であり、ブロードキャスト/マルチキャストをサポートすることを指定します (XP1_CONNECTIONLESS、XP1_MESSAGE_ORIENTED、XP1_SUPPORT_BROADCAST、XP1_SUPPORT_MULTIPOINT ビットは dwServiceFlags1 メンバーに設定されます)。最大メッセージ サイズは 65,467 バイトです。

Windows XP 以降では、 NetSh.exe コマンドを使用して、生のソケットがサポートされているかどうかを判断できます。 CMD ウィンドウから次のコマンドを実行すると、コンソールに Winsock カタログのデータが表示されます。

netsh winsock show catalog

出力には、ローカル コンピューターでサポートされている WSAPROTOCOL_INFO 構造からのデータの一部を含むリストが含まれます。 [説明] フィールドで RAW/IP または RAW/IPv6 という用語を検索して、生ソケットをサポートするプロトコルを見つけます。

生ソケットの作成

SOCK_RAW型のソケットを作成するには、af パラメーター (アドレス ファミリ) を AF_INET または AF_INET6 に設定し、type パラメーターをSOCK_RAWに設定し、protocol パラメーターを必要なプロトコル番号に設定して、socket または WSASocket 関数を呼び出します。 protocol パラメーターは、IP ヘッダーのプロトコル値になります (たとえば、SCTP は 132 です)。

Note

type パラメーターが SOCK_RAW に設定されている場合、ソケットWSASocketWSPSocket 関数のプロトコル パラメーターとしてゼロ (0) をアプリケーションで指定することはできません。

 

生ソケットは、基になるトランスポートを操作する機能を提供するため、セキュリティ上の脅威を引き起こす悪意のある目的で使用できます。 したがって、Windows 2000 以降でSOCK_RAW型のソケットを作成できるのは Administrators グループのメンバーだけです。

送信および受信操作

アプリケーションがSOCK_RAW型のソケット 作成すると、このソケットを使用してデータの送受信を行う場合があります。 SOCK_RAWタイプのソケットで送受信されるすべてのパケットは、接続されていないソケット上のデータグラムとして扱われます。

SOCK_RAW ソケットに対する操作には、次 規則が適用されます。

  • sendto 関数または WSASendTo 関数は、通常、SOCK_RAW型のソケットでデータを送信するために使用されます。 宛先アドレスには、ブロードキャストまたはマルチキャスト アドレスを含む、ソケットのアドレス ファミリ内の任意の有効なアドレスを指定できます。 ブロードキャスト アドレスに送信するには、アプリケーションで setsockopt を使用し、SO_BROADCAST有効にする必要があります。 それ以外の場合、 sendto または WSASendTo はエラー コード WSAEACCES で失敗します。 IP の場合、アプリケーションは任意のマルチキャスト アドレスに送信できます (グループ メンバーになることはありません)。

  • IPv4 データを送信する場合、アプリケーションでは、パケットの送信データグラムの先頭に IPv4 ヘッダーを指定するかどうかを選択できます。 IPv4 ソケット (AF_INETのアドレス ファミリ) に対して IP_HDRINCL ソケット オプションが true に設定されている場合、アプリケーションは送信操作のために送信データに IPv4 ヘッダーを指定する必要があります。 このソケット オプションが false (既定の設定) の場合、IPv4 ヘッダーを送信操作の送信データに含めないようにする必要があります。

  • IPv6 データを送信する場合、アプリケーションでは、パケットの送信データグラムの先頭に IPv6 ヘッダーを指定するかどうかを選択できます。 IPv6 ソケット (AF_INET6 のアドレス ファミリ) に対して IPV6_HDRINCL ソケット オプションが true に設定されている場合、アプリケーションは送信操作のために送信データに IPv6 ヘッダーを指定する必要があります。 このオプションの既定の設定は false です。 このソケット オプションが false (既定の設定) の場合、送信操作の送信データに IPv6 ヘッダーを含めないようにする必要があります。 IPv6 の場合、IPv6 ヘッダーを含める必要はありません。 ソケット関数を使用して情報を使用できる場合は、将来互換性の問題を回避するために IPv6 ヘッダーを含めないでください。 これらの問題については、IETF によって公開されている RFC 3542 で説明されています。 IPV6_HDRINCL ソケット オプションの使用は推奨されず、今後非推奨になる可能性があります。

  • 通常、recvfrom または WSARecvFrom 関数は、SOCK_RAW型のソケットでデータを受信するために使用されます。 これらの両方の関数には、パケットが送信された送信元 IP アドレスを返すオプションがあります。 受信したデータは、接続されていないソケットからのデータグラムです。

  • IPv4 (AF_INET のアドレス ファミリ) の場合、アプリケーションは、 IP_HDRINCL ソケット オプションに関係なく、受信した各データグラムの先頭で IP ヘッダーを受信します。

  • IPv6 (AF_INET6 のアドレス ファミリ) の場合、アプリケーションは、 IPV6_HDRINCL ソケット オプションに関係なく、受信した各データグラムで最後の IPv6 ヘッダーの後のすべてを受信します。 アプリケーションは、生のソケットを使用して IPv6 ヘッダーを受信しません。

  • 受信したデータグラムは、次の条件を満たす すべてのSOCK_RAW ソケットにコピーされます。

    • ソケットの作成時にプロトコル パラメーターで指定された プロトコル 番号は、受信したデータグラムの IP ヘッダーのプロトコル番号と一致する必要があります。
    • ソケットに対してローカル IP アドレスが定義されている場合は、受信したデータグラムの IP ヘッダーで指定された宛先アドレスに対応する必要があります。 アプリケーションは 、バインド 関数を呼び出すことによってローカル IP アドレスを指定できます。 ソケットにローカル IP アドレスが指定されていない場合、受信したデータグラムの IP ヘッダー内の宛先 IP アドレスに関係なく、データグラムがソケットにコピーされます。
    • ソケットに対して外部アドレスが定義されている場合は、受信したデータグラムの IP ヘッダーで指定されたソース アドレスに対応する必要があります。 アプリケーションは、 connect 関数または WSAConnect 関数を呼び出すことによって、外部 IP アドレスを指定できます。 ソケットに外部 IP アドレスが指定されていない場合、受信したデータグラムの IP ヘッダー内のソース IP アドレスに関係なく、データグラムがソケットにコピーされます。

SOCK_RAW型の一部のソケットでは、予期しないデータグラムが多数受信される可能性があることを理解しておくことが重要です。 たとえば、PING プログラムでは、ICMP エコー要求を送信して応答を受信する SOCK_RAW 型のソケットを作成できます。 アプリケーションが ICMP エコー応答を予期している間は、他のすべての ICMP メッセージ (ICMP HOST_UNREACHABLEなど) もこのアプリケーションに配信される可能性があります。 さらに、複数 のSOCK_RAW ソケットが同時にコンピューター上で開かれている場合は、開いているすべてのソケットに同じデータグラムを配信できます。 アプリケーションには、関心のあるデータグラムを認識し、他のすべてのデータグラムを無視するメカニズムが必要です。 PING プログラムの場合、このようなメカニズムには、受信した IP ヘッダーで ICMP ヘッダー内の一意の識別子 (アプリケーションのプロセス ID など) の検査が含まれる場合があります。

Note

SOCK_RAW型のソケットを使用するには、管理者権限が必要です。 未加工のソケットを使用する Winsock アプリケーションを実行しているユーザーは、ローカル コンピューターの Administrators グループのメンバーである必要があります。そうしないと、未加工のソケット呼び出しは WSAEACCES のエラー コードで失敗します。 Windows Vista 以降では、未加工のソケットへのアクセスは、ソケットの作成時に適用されます。 以前のバージョンの Windows では、他のソケット操作中に生ソケットへのアクセスが適用されます。

 

生ソケットの一般的な用途

生ソケットの一般的な用途の 1 つは、IP パケットとヘッダーを詳しく調べる必要があるアプリケーションのトラブルシューティングです。 たとえば、未加工のソケットを SIO_RCVALL IOCTL と共に使用して、ソケットがネットワーク インターフェイスを通過するすべての IPv4 または IPv6 パケットを受信できるようにします。 詳細については、「 SIO_RCVALL リファレンス」を参照してください。

生ソケットに関する制限事項

Windows 7、Windows Vista、Windows XP Service Pack 2 (SP2)、Windows XP with Service Pack 3 (SP3) では、未加工のソケット経由でトラフィックを送信する機能は、いくつかの方法で制限されています。

  • 未加工のソケット経由で TCP データを送信することはできません。

  • ソース アドレスが無効な UDP データグラムは、生のソケット経由で送信できません。 送信 UDP データグラムの IP ソース アドレスは、ネットワーク インターフェイス上に存在する必要があります。または、データグラムが削除されます。 この変更は、悪意のあるコードが分散型サービス拒否攻撃を作成する機能を制限し、スプーフィングされたパケット (偽造されたソース IP アドレスを持つ TCP/IP パケット) を送信する機能を制限するために行われました。

  • IPPROTO_TCP プロトコルの生ソケットを使用した バインド 関数の呼び出しは許可されません。

    Note

    生のソケットを持つ バインド 関数は、他のプロトコル (IPPROTO_IP、IPPROTO_UDP、IPPROTO_SCTPなど) に対して許可されます。

     

上記の制限は、Windows Server 2008 R2、Windows Server 2008、Windows Server 2003、または SP2 を使用する Windows XP より前のバージョンのオペレーティング システムには適用されません。

Note

Windows での TCP/IP の Microsoft 実装では、上記の制限に基づいて生の UDP または TCP ソケットを開く機能があります。 他の Winsock プロバイダーは、生のソケットの使用をサポートしていない場合があります。

 

SOCK_RAW型のソケットを使用するアプリケーションには、さらに制限があります。 たとえば、特定のプロトコルをリッスンしているすべてのアプリケーションは、このプロトコルで受信したすべてのパケットを受信します。 これは、プロトコルを使用する複数のアプリケーションでは望ましくない場合があります。 これは、高性能アプリケーションにも適していません。 これらの問題を回避するには、特定のネットワーク プロトコルの Windows ネットワーク プロトコル ドライバー (デバイス ドライバー) を記述することが必要な場合があります。 Windows Vista 以降の Winsock カーネル (WSK) では、新しいトランスポートに依存しないカーネル モードのネットワーク プログラミング インターフェイスを使用して、ネットワーク プロトコル ドライバーを記述できます。 Windows Server 2003 以前では、トランスポート ドライバー インターフェイス (TDI) プロバイダーと Winsock ヘルパー DLL を記述して、ネットワーク プロトコルをサポートできます。 その後、ネットワーク プロトコルは、サポートされているプロトコルとして Winsock カタログに追加されます。 これにより、複数のアプリケーションでこの特定のプロトコルのソケットを開くことができます。また、デバイス ドライバーは、特定のパケットとエラーを受け取るソケットを追跡できます。 ネットワーク プロトコル プロバイダーの作成の詳細については、Windows ドライバー キット (WDK) の WSK と TDI に関するセクションを参照してください。

アプリケーションでは、生ソケットを使用したパケットの送受信に対するファイアウォール設定の影響も認識する必要があります。