Share via


TCP/IP 원시 소켓

원시 소켓은 기본 전송 공급자에 대한 액세스를 허용하는 소켓의 유형입니다. 이 항목에서는 원시 소켓 및 IPv4 및 IPv6 프로토콜에만 중점을 둡니다. ATM을 제외한 대부분의 다른 프로토콜은 원시 소켓을 지원하지 않기 때문입니다. 원시 소켓을 사용하려면 애플리케이션에 사용 중인 기본 프로토콜에 대한 자세한 정보가 있어야 합니다.

IP 프로토콜에 대한 Winsock 서비스 공급자는 소켓 유형의SOCK_RAW 지원할 수 있습니다. Windows에 포함된 TCP/IP용 Windows 소켓 2 공급자는 이 SOCK_RAW 소켓 유형을 지원합니다.

이러한 원시 소켓에는 두 가지 기본 유형이 있습니다.

  • 첫 번째 형식은 Winsock 서비스 공급자가 인식하는 IP 헤더에 기록된 알려진 프로토콜 형식을 사용합니다. 첫 번째 소켓 유형의 예로는 ICMP 프로토콜(IP 프로토콜 유형 = 1) 또는 ICMPv6 프로토콜(IP procotol 형식 = 58)에 대한 소켓이 있습니다.
  • 두 번째 형식을 사용하면 모든 프로토콜 형식을 지정할 수 있습니다. 두 번째 형식의 예로는 SCTP(Stream Control Transmission Protocol)와 같은 Winsock 서비스 공급자가 직접 지원하지 않는 실험적 프로토콜이 있습니다.

원시 소켓이 지원되는지 확인

Winsock 서비스 공급자가 AF_INET 또는 AF_INET6 주소 패밀리에 대한 SOCK_RAW 소켓을 지원하는 경우 사용 가능한 전송 공급자 중 하나 이상에 대해 WSAEnumProtocols 함수에서 반환하는 WSAPROTOCOL_INFO 구조에 SOCK_RAW 소켓 유형을 포함해야 합니다.

WSAPROTOCOL_INFO 구조체의 iAddressFamily 멤버는 AF_INET 또는 AF_INET6 지정해야 하며 WSAPROTOCOL_INFO 구조체의 iSocketType 멤버는 전송 공급자 중 하나에 대한 SOCK_RAW 지정해야 합니다.

WSAPROTOCOL_INFO 구조체의 iProtocol 멤버는 IPROTO_IP 설정할 수 있습니다. 서비스 공급자가 애플리케이션이 주소 패밀리에 대한 인터넷 프로토콜 이외의 다른 네트워크 프로토콜에 SOCK_RAW 소켓 형식을 사용하도록 허용하는 경우 WSAPROTOCOL_INFO 구조의 iProtocol 멤버도 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).

참고

형식 매개 변수가 SOCK_RAW 설정된 경우 애플리케이션은 소켓, WSASocketWSPSocket 함수에 대한 프로토콜 매개 변수로 0을 지정하지 않을 수 있습니다.

 

원시 소켓은 기본 전송을 조작하는 기능을 제공하므로 보안 위협을 야기하는 악의적인 용도로 사용할 수 있습니다. 따라서 Administrators 그룹의 구성원만 Windows 2000 이상에서 SOCK_RAW 유형의 소켓을 만들 수 있습니다.

보내기 및 받기 작업

애플리케이션이 SOCK_RAW 형식의 소켓을 만들면 이 소켓을 사용하여 데이터를 보내고 받을 수 있습니다. SOCK_RAW 유형의 소켓에서 보내거나 받은 모든 패킷은 연결되지 않은 소켓에서 데이터그램으로 처리됩니다.

다음 규칙은 SOCK_RAW 소켓을 통해 작업에 적용됩니다.

  • sendto 또는 WSASendTo 함수는 일반적으로 SOCK_RAW 형식의 소켓에 데이터를 보내는 데 사용됩니다. 대상 주소는 브로드캐스트 또는 멀티캐스트 주소를 포함하여 소켓의 주소 패밀리에서 유효한 주소일 수 있습니다. 브로드캐스트 주소로 보내려면 애플리케이션에서 SO_BROADCAST 사용하도록 설정된 setsockopt 를 사용해야 합니다. 그렇지 않으면 오류 코드 WSAEACCESsendto 또는 WSASendTo가 실패합니다. 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 헤더에 지정된 대상 주소에 해당해야 합니다. 애플리케이션은 bind 함수를 호출하여 로컬 IP 주소를 지정할 수 있습니다. 소켓에 대한 로컬 IP 주소가 지정되지 않은 경우 수신된 데이터그램의 IP 헤더에 있는 대상 IP 주소에 관계없이 데이터그램이 소켓에 복사됩니다.
    • 외래 주소가 소켓에 대해 정의된 경우 수신된 데이터그램의 IP 헤더에 지정된 원본 주소와 일치해야 합니다. 애플리케이션은 connect 또는 WSAConnect 함수를 호출하여 외래 IP 주소를 지정할 수 있습니다. 소켓에 대한 외래 IP 주소가 지정되지 않은 경우 수신된 데이터그램의 IP 헤더에 있는 원본 IP 주소에 관계없이 데이터그램이 소켓에 복사됩니다.

SOCK_RAW 형식의 일부 소켓은 많은 예기치 않은 데이터그램을 수신할 수 있음을 이해하는 것이 중요합니다. 예를 들어 PING 프로그램은 SOCK_RAW 형식의 소켓을 만들어 ICMP 에코 요청을 보내고 응답을 받을 수 있습니다. 애플리케이션에서 ICMP 에코 응답을 예상하는 동안 다른 모든 ICMP 메시지(예: ICMP HOST_UNREACHABLE)도 이 애플리케이션에 배달될 수 있습니다. 또한 여러 SOCK_RAW 소켓이 동시에 컴퓨터에 열려 있는 경우 동일한 데이터그램이 열려 있는 모든 소켓에 배달될 수 있습니다. 애플리케이션에는 관심 있는 데이터그램을 인식하고 다른 모든 데이터를 무시하는 메커니즘이 있어야 합니다. PING 프로그램의 경우 이러한 메커니즘에는 수신된 IP 헤더에서 ICMP 헤더의 고유 식별자(예: 애플리케이션의 프로세스 ID)를 검사하는 것이 포함될 수 있습니다.

참고

SOCK_RAW 유형의 소켓을 사용하려면 관리 권한이 필요합니다. 원시 소켓을 사용하는 Winsock 애플리케이션을 실행하는 사용자는 로컬 컴퓨터에서 Administrators 그룹의 구성원이어야 합니다. 그렇지 않으면 원시 소켓 호출이 WSAEACCES 오류 코드와 함께 실패합니다. Windows Vista 이상에서는 소켓을 만들 때 원시 소켓에 대한 액세스가 적용됩니다. 이전 버전의 Windows에서는 다른 소켓 작업 중에 원시 소켓에 대한 액세스가 적용됩니다.

 

원시 소켓의 일반적인 사용

원시 소켓의 일반적인 용도 중 하나는 IP 패킷 및 헤더를 자세히 검사해야 하는 애플리케이션 문제 해결입니다. 예를 들어 원시 소켓을 SIO_RCVALL IOCTL과 함께 사용하여 소켓이 네트워크 인터페이스를 통과하는 모든 IPv4 또는 IPv6 패킷을 수신할 수 있도록 할 수 있습니다. 자세한 내용은 SIO_RCVALL 참조를 참조하세요.

원시 소켓에 대한 제한 사항

Windows 7, Windows Vista, SP2(서비스 팩 2)가 있는 Windows XP 및 SP3(서비스 팩 3)가 있는 Windows XP에서는 원시 소켓을 통해 트래픽을 보내는 기능이 여러 가지 방법으로 제한되었습니다.

  • TCP 데이터는 원시 소켓을 통해 보낼 수 없습니다.

  • 원본 주소가 잘못된 UDP 데이터그램은 원시 소켓을 통해 보낼 수 없습니다. 나가는 UDP 데이터그램의 IP 원본 주소가 네트워크 인터페이스에 있어야 하거나 데이터그램이 삭제됩니다. 이 변경은 분산 서비스 거부 공격을 만드는 악성 코드의 기능을 제한하고 스푸핑된 패킷(위조된 원본 IP 주소가 있는 TCP/IP 패킷)을 보내는 기능을 제한하기 위해 변경되었습니다.

  • IPPROTO_TCP 프로토콜에 대한 원시 소켓을 사용하여 바인딩 함수를 호출할 수 없습니다.

    참고

    원시 소켓을 사용하는 바인딩 함수는 다른 프로토콜(예: IPPROTO_IP, IPPROTO_UDP 또는 IPPROTO_SCTP)에 대해 허용됩니다.

     

위의 제한 사항은 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 이상에서는 WSK(Winsock Kernel)에서 새로운 전송 독립적 커널 모드 네트워크 프로그래밍 인터페이스를 사용하여 네트워크 프로토콜 드라이버를 작성할 수 있습니다. Windows Server 2003 이하에서는 TDI(전송 드라이버 인터페이스) 공급자와 Winsock 도우미 DLL을 작성하여 네트워크 프로토콜을 지원할 수 있습니다. 그러면 네트워크 프로토콜이 Winsock 카탈로그에 지원되는 프로토콜로 추가됩니다. 이렇게 하면 여러 애플리케이션이 이 특정 프로토콜에 대한 소켓을 열 수 있으며 디바이스 드라이버는 특정 패킷 및 오류를 수신하는 소켓을 추적할 수 있습니다. 네트워크 프로토콜 공급자를 작성하는 방법에 대한 자세한 내용은 WDK(Windows 드라이버 키트)의 WSK 및 TDI 섹션을 참조하세요.

또한 애플리케이션은 방화벽 설정이 원시 소켓을 사용하여 패킷을 보내고 받는 데 미칠 수 있는 영향을 알고 있어야 합니다.