Raw socket

raw socket はコンピュータネットワークにおいて、生のネットワークパケットのダイレクトな送信と受信を可能にするインターネットソケット（英語版）である。 標準のソケットでは、送信するペイロードは選択したトランスポート層のプロトコル（例: TCP、UDP）によってカプセル化される。 対照的にraw socketは通常ヘッダを含んだ生のパケットを受信する。パケットを送るとき、ヘッダの自動的な追加はソケットの変更可能なオプションとなるだろう。 raw socketのひとつの可能な用途としてユーザー空間での新しいトランスポート層の実装が挙げられる。 raw socketは典型的にネットワーク装置において利用でき、Internet Group Management Protocol (IGMP) や Open Shortest Path First (OSPF) のようなルーティングプロトコル、そして Internet Control Message Protocol (ICMP, Pingとしてよく知られている) に使用されている。 ほとんどのソケットAPI、特にBSDソケットを基本にしたものでは、raw socketがサポートされている。 下記は第一引数のIPアドレスで指定されたホストにicmp echoパケットを送信し、replyが返ってくるのを待つプログラムである。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <arpa/inet.h> #include <netdb.h> /* チェックサムの計算 */ u_int16_t checksum(unsigned short *buf, int size) { unsigned long sum = 0; while (size > 1) { sum += *buf; buf++; size -= 2; } if (size == 1) { sum += *(unsigned char *)buf; } sum = (sum & 0xffff) + (sum >> 16); sum = (sum & 0xffff) + (sum >> 16); return ~sum; } /* protocolで指定されたプロトコルのraw socketを作成する */ int make_raw_socket(int protocol) { int s = socket(AF_INET, SOCK_RAW, protocol); if (s < 0) { perror("socket"); exit(EXIT_FAILURE); } return s; } /* ICMPヘッダの作成 */ void setup_icmphdr(u_int8_t type, u_int8_t code, u_int16_t id, u_int16_t seq, struct icmphdr *icmphdr) { memset(icmphdr, 0, sizeof(struct icmphdr)); icmphdr->type = type; icmphdr->code = code; icmphdr->checksum = 0; icmphdr->un.echo.id = id; icmphdr->un.echo.sequence = seq; icmphdr->checksum = checksum((unsigned short *)icmphdr, sizeof(struct icmphdr)); } int main(int argc, char **argv) { int n, soc; char buf[1500]; struct sockaddr_in addr; struct in_addr insaddr; struct icmphdr icmphdr; struct iphdr *recv_iphdr; struct icmphdr *recv_icmphdr; if (argc < 2) { printf("Usage : %s IP_ADDRESS\n", argv[0]); return 1; } addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(argv[1]); soc = make_raw_socket(IPPROTO_ICMP); setup_icmphdr(ICMP_ECHO, 0, 0, 0, &icmphdr); /* ICMPパケットの送信 */ n = sendto(soc, (char *)&icmphdr, sizeof(icmphdr), 0, (struct sockaddr *)&addr, sizeof(addr)); if (n < 1) { perror("sendto"); return 1; } /* ICMPパケットの受信 */ n = recv(soc, buf, sizeof(buf), 0); if (n < 1) { perror("recv"); return 1; } recv_iphdr = (struct iphdr *)buf; /* IPヘッダからヘッダ長を求め、icmpヘッダの開始位置を調べる */ recv_icmphdr = (struct icmphdr *)(buf + (recv_iphdr->ihl << 2)); insaddr.s_addr = recv_iphdr->saddr; /* 送信先と受信したパケットの送信源が一致するかと受信したパケットがICMP ECHO REPLYか確認 */ if (!strcmp(argv[1], inet_ntoa(insaddr)) && recv_icmphdr->type == ICMP_ECHOREPLY) { printf("icmp echo reply from %s\n", argv[1]); } close(soc); return 0; } 実行例 以下はwikipedia.org (208.80.152.201) を指定した出力例である。 [ping@icmp] # ./ping 208.80.152.201 icmp echo reply from 208.80.152.201 マイクロソフトが2001年にWindows XPをリリースした際、Winsock APIにてraw socketのサポートを実装していた。このときメディアは、raw socketはハッカーがTCPリセット攻撃（英語版）を行う役にしか立たないと主張してマイクロソフトを非難した。[要出典] Windows XPのリリースから3年後、マイクロソフトは取消不可能なホットフィックスの中でWinsockにおけるraw socketサポートを黙って制限し、それまでこれを利用していたアプリケーションに対してサポートや回避策を何ら提供しなかった。なお、raw socketサポートの制限について、のちにサポート技術情報が公開されていた。 Windows XP SP2以降のOSにおいてもraw socketにはいくつかの制限事項があるが、Windows Server 2003などのサーバー系OSにおいては適用されない。Winsockアプリケーションにおけるraw socketの使用は非推奨とされている。 ^ Linux man page raw(7) ^ Raw IP Networking FAQ ^ Microsoft Tightens the Noose on Raw Sockets ^ “Windows XP Service Pack 1 が実行されているコンピュータにセキュリティ更新プログラム MS05-019 を適用すると、TCP パケットまたは UDP パケットを RAW IP ソケット経由で送信するネットワーク プログラムが機能しなくなることがある”. 2016年10月18日閲覧。[リンク切れ] ^ Networking programs that send TCP packets or UDP packets over raw IP sockets may stop working after you apply security update MS05-019 to a computer that is running Windows XP with Service Pack 1, Internet Archive ^ TCP/IP Raw Sockets - Win32 apps | Microsoft Docs ^ Raw Sockets - Win32 apps | Microsoft Docs ポータル Internet Internet Protocol ソケット (BSD) Video Tutorials on Programming with Raw Sockets Net::RawIP; module for Perl applications. Created by Sergey Kolychev. Network Programming for Microsoft Windows (ISBN 0-7356-1579-9) A little more info on raw sockets and Windows XP SP2 - Michael Howard's Web Log an indication of what's actually allowed on Windows. SOCK_RAW Demystified: article describing inner workings of Raw Sockets C language examples of Linux raw sockets for IPv4 and IPv6 - David Buchan's C language examples of IPv4 and IPv6 raw sockets for Linux.