TCP/IP 生ソケット
生ソケットは、基になるトランスポート プロバイダーへのアクセスを許可するソケットの一種です。 このトピックでは、生のソケットと IPv4 および IPv6 プロトコルについてのみ説明します。 これは、ATM を除く他のほとんどのプロトコルが生ソケットをサポートしていないためです。 生のソケットを使用するには、使用されている基になるプロトコルに関する詳細情報がアプリケーションに必要です。
IP プロトコルの Winsock サービス プロバイダーは、SOCK_RAWのソケット 型 をサポートできます。 Windows に含まれる TCP/IP 用の Windows Sockets 2 プロバイダーでは、この SOCK_RAW ソケットの種類がサポートされています。
このような生ソケットには、次の 2 つの基本的な種類があります。
- 最初の型は、Winsock サービス プロバイダーによって認識される IP ヘッダーに記述された既知のプロトコル型を使用します。 最初の種類のソケットの例は、ICMP プロトコル (IP プロトコルの種類 = 1) または ICMPv6 プロトコル (IP プロコトルの種類 = 58) のソケットです。
- 2 番目の型では、任意のプロトコルの種類を指定できます。 2 番目の種類の例は、ストリーム制御伝送プロトコル (SCTP) などの Winsock サービス プロバイダーによって直接サポートされていない実験用プロトコルです。
生ソケットがサポートされているかどうかを判断する
Winsock サービス プロバイダーがAF_INETまたはAF_INET6 アドレス ファミリの SOCK_RAW ソケットをサポートしている場合、SOCK_RAW のソケットの種類は、使用可能な 1 つ以上のトランスポート プロバイダー WSAEnumProtocols 関数によって返される WSAPROTOCOL_INFO 構造体に含める必要があります。
WSAPROTOCOL_INFO 構造体の iAddressFamily メンバーは、AF_INETまたはAF_INET6を指定する必要があり、WSAPROTOCOL_INFO 構造体の iSocketType メンバーは、トランスポート プロバイダーの SOCK_RAW を指定する必要があります。
WSAPROTOCOL_INFO 構造体の iProtocol メンバーを IPROTO_IPに設定できます。 WSAPROTOCOL_INFO 構造体の iProtocol メンバーは、サービス プロバイダーがアプリケーションがアドレス ファミリのインターネット プロトコル以外の他のネットワーク プロトコルに SOCK_RAW ソケットの種類を使用できるようにする場合にも、0 に設定できます。
WSAPROTOCOL_INFO 構造体の他のメンバーは、SOCK_RAW のプロトコル サポートの他のプロパティを示し、SOCK_RAW のソケットの処理方法を示します。 SOCK_RAW の WSAPROTOCOL_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 に設定し、型 パラメーターを SOCK_RAWに設定し、プロトコル パラメーターを必要なプロトコル番号に設定して、ソケット または WSASocket 関数を呼び出します。 プロトコル パラメーターは、IP ヘッダーのプロトコル値になります (SCTP は 132 など)。
手記
アプリケーションでは、ソケットの プロトコル パラメーターとして 0 (0) を指定したり、WSASocketをしたり、型の パラメーターが SOCK_RAWに設定されている場合は WSPSocket関数をすることはできません。
生ソケットは、基になるトランスポートを操作する機能を提供するため、セキュリティ上の脅威を引き起こす悪意のある目的で使用できます。 そのため、Windows 2000 以降でSOCK_RAW型のソケットを作成できるのは Administrators グループのメンバーだけです。
送信操作と受信操作
アプリケーションが SOCK_RAW型のソケットを作成すると、このソケットを使用してデータを送受信できます。 SOCK_RAW タイプのソケットで送受信されるすべてのパケットは、接続されていないソケット上のデータグラムとして扱われます。
次の規則は、SOCK_RAW ソケットに対する操作に適用されます。
sendto または WSASendTo 関数は、通常、SOCK_RAW型のソケットでデータを送信するために使用されます。 宛先アドレスには、ブロードキャストまたはマルチキャスト・アドレスを含め、ソケットのアドレス・ファミリー内の任意の有効なアドレスを指定できます。 ブロードキャスト アドレスに送信するには、SO_BROADCASTが有効になっている setsockoptアプリケーションが使用されている必要があります。 それ以外の場合、または 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 ヘッダーで指定されたソース アドレスに対応する必要があります。 アプリケーションは、接続 または WSAConnect関数呼び出すことによって、外部 IP アドレスを指定できます。 ソケットに外部 IP アドレスが指定されていない場合、受信したデータグラムの IP ヘッダー内のソース IP アドレスに関係なく、データグラムがソケットにコピーされます。
SOCK_RAW 型の一部のソケットでは、予期しないデータグラムが多数受信される可能性があることを理解しておくことが重要です。 たとえば、PING プログラムでは、ICMP エコー要求を送信して応答を受信する SOCK_RAW 型のソケットを作成できます。 アプリケーションが ICMP エコー応答を期待している間は、他のすべての ICMP メッセージ (ICMP HOST_UNREACHABLEなど) もこのアプリケーションに配信される場合があります。 さらに、複数の SOCK_RAW ソケットが同時にコンピューター上で開かれている場合は、開いているすべてのソケットに同じデータグラムを配信できます。 アプリケーションには、関心のあるデータグラムを認識し、他のすべてのデータグラムを無視するメカニズムが必要です。 PING プログラムの場合、このようなメカニズムには、受信した IP ヘッダーで ICMP ヘッダー内の一意の識別子 (アプリケーションのプロセス ID など) の検査が含まれる場合があります。
手記
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 Service Pack 3 (SP3) では、未加工のソケット経由でトラフィックを送信する機能は、いくつかの方法で制限されています。
未加工のソケット経由で TCP データを送信することはできません。
ソース アドレスが無効な UDP データグラムは、生のソケット経由で送信できません。 送信 UDP データグラムの IP ソース アドレスは、ネットワーク インターフェイスに存在する必要があります。または、データグラムが削除されます。 この変更は、悪意のあるコードが分散型サービス拒否攻撃を作成する機能を制限し、スプーフィングされたパケット (偽造されたソース IP アドレスを持つ TCP/IP パケット) を送信する機能を制限するために行われました。
IPPROTO_TCP プロトコルの未加工のソケットバインド関数の呼び出しは許可されません。
上記の制限は、Windows Server 2008 R2、Windows Server 2008、Windows Server 2003、または SP2 を使用する Windows XP より前のバージョンのオペレーティング システムには適用されません。
手記
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 のセクションを参照してください。
また、アプリケーションでは、未加工のソケットを使用したパケットの送受信にファイアウォール設定が与える可能性がある影響を認識する必要があります。