fbpx
维基百科

原始套接字

计算机网络中, 原始套接字(raw socket)是一种网络套接字,允许直接发送/接收IP协议数据包而不需要任何传输层协议格式。

简介

对于标准的套接字,通常数据按照选定的传输层协议(例如TCPUDP)自动封装,socket用户并不知道在网络介质上广播的数据包含了这种协议包头。

从原始套接字读取数据包含了传输层协议包头。用原始套接字发送数据,是否自动增加传输层协议包头是可选的。

原始套接字用于安全相关的应用程序,如nmap。原始套接字一种可能的用例是在用户空间实现新的传输层协议。[1] 原始套接字常在网络设备上用于路由协议,例如IGMPv4、开放式最短路径优先协议 (OSPF)、互联网控制消息协议 (ICMP)。Ping就是发送一个ICMP响应请求包然后接收ICMP响应回复.[2]

实现

大部分套接字API都支持原始套接字功能。Winsock自2001年起在Windows XP上支持原始套接字。但由于安全原因,2004年微软限制了Winsock的原始套接字功能。[3]

例子

下例在Linux上实现了Ping程序的主要功能:

#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包头获取IP包的长度,从而确定icmp包头的开始位置 */  recv_icmphdr = (struct icmphdr *)(buf + (recv_iphdr->ihl << 2));  insaddr.s_addr = recv_iphdr->saddr;  /* 检查送信包的源地址匹配受信包的目的地址 */  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; } 

下例是binding一个原始套接字并使用:

#include<stdio.h> #include<stdlib.h> #include<sys/socket.h> #include<features.h> #include<linux/if_packet.h> #include<linux/if_ether.h> #include<errno.h> #include<sys/ioctl.h> #include<net/if.h>   #define PACKET_LENGTH 1024   int CreateRawSocket(int protocol_to_sniff) {  int rawsock;  if((rawsock = socket(PF_PACKET, SOCK_RAW, htons(protocol_to_sniff)))== -1) {  perror("Error creating raw socket: ");  exit(-1);  }  return rawsock; }   int BindRawSocketToInterface(char *device, int rawsock, int protocol) {  struct sockaddr_ll sll;  struct ifreq ifr;  memset(&sll, 0, sizeof(sll));  memset(&ifr, 0, sizeof(ifr));  /* First Get the Interface Index */  strncpy((char *)ifr.ifr_name, device, IFNAMSIZ);  if((ioctl(rawsock, SIOCGIFINDEX, &ifr)) == -1) {  printf("Error getting Interface index !\n");  exit(-1);  }  /* Bind our raw socket to this interface */  sll.sll_family = AF_PACKET;  sll.sll_ifindex = ifr.ifr_ifindex;  sll.sll_protocol = htons(protocol);  if((bind(rawsock, (struct sockaddr *)&sll, sizeof(sll)))== -1) {  perror("Error binding raw socket to interface\n");  exit(-1);  }  return 1; }   int SendRawPacket(int rawsock, unsigned char *pkt, int pkt_len) {  int sent= 0;  /* A simple write on the socket ..thats all it takes ! */  if((sent = write(rawsock, pkt, pkt_len)) != pkt_len) {  return 0;  }  return 1; } /* argv[1] is the device e.g. eth0  argv[2] is the number of packets to send */   main(int argc, char **argv) {  int raw;  unsigned char packet[PACKET_LENGTH];  int num_of_pkts;  /* Set the packet to all A's */  memset(packet, 'A', PACKET_LENGTH);  /* Create the raw socket */  raw = CreateRawSocket(ETH_P_ALL);  /* Bind raw socket to interface */  BindRawSocketToInterface(argv[1], raw, ETH_P_ALL);  num_of_pkts = atoi(argv[2]);  while((num_of_pkts--)>0) {  if(!SendRawPacket(raw, packet, PACKET_LENGTH)) {  perror("Error sending packet");  } else {  printf("Packet sent successfully\n");  }  }  close(raw);  return 0; } 

参见

参考文献

  1. ^ raw(7): IPv4 raw sockets - Linux man page. die.net. [2017-03-14]. (原始内容于2016-09-07). 
  2. ^ Raw IP Networking FAQ. faqs.org. [2017-03-14]. (原始内容于2012-01-19). 
  3. ^ Ian Griffiths for IanG on Tap. 12 August, 2004. Raw Sockets Gone in XP SP2 (页面存档备份,存于互联网档案馆

外部链接

  • Net::RawIP; module for Perl applications. Created by .
  • Network Programming for Microsoft Windows (ISBN 0-7356-1579-9)
  • 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.

原始套接字, 在计算机网络中, socket, 是一种网络套接字, 允许直接发送, 接收ip协议数据包而不需要任何传输层协议格式, 目录, 简介, 实现, 例子, 参见, 参考文献, 外部链接简介, 编辑对于标准的套接字, 通常数据按照选定的传输层协议, 例如tcp, 自动封装, socket用户并不知道在网络介质上广播的数据包含了这种协议包头, 从读取数据包含了传输层协议包头, 用发送数据, 是否自动增加传输层协议包头是可选的, 用于安全相关的应用程序, 如nmap, 一种可能的用例是在用户空间实现新的传输层协议. 在计算机网络中 原始套接字 raw socket 是一种网络套接字 允许直接发送 接收IP协议数据包而不需要任何传输层协议格式 目录 1 简介 2 实现 3 例子 4 参见 5 参考文献 6 外部链接简介 编辑对于标准的套接字 通常数据按照选定的传输层协议 例如TCP UDP 自动封装 socket用户并不知道在网络介质上广播的数据包含了这种协议包头 从原始套接字读取数据包含了传输层协议包头 用原始套接字发送数据 是否自动增加传输层协议包头是可选的 原始套接字用于安全相关的应用程序 如nmap 原始套接字一种可能的用例是在用户空间实现新的传输层协议 1 原始套接字常在网络设备上用于路由协议 例如IGMPv4 开放式最短路径优先协议 OSPF 互联网控制消息协议 ICMP Ping就是发送一个ICMP响应请求包然后接收ICMP响应回复 2 实现 编辑大部分套接字API都支持原始套接字功能 Winsock自2001年起在Windows XP上支持原始套接字 但由于安全原因 2004年微软限制了Winsock的原始套接字功能 3 例子 编辑下例在Linux上实现了Ping程序的主要功能 include lt stdio h gt include lt stdlib h gt include lt string h gt include lt errno h gt include lt unistd h gt include lt sys types h gt include lt sys stat h gt include lt sys socket h gt include lt netinet in h gt include lt netinet ip h gt include lt netinet ip icmp h gt include lt arpa inet h gt include lt netdb h gt 校验和計算 u int16 t checksum unsigned short buf int size unsigned long sum 0 while size gt 1 sum buf buf size 2 if size 1 sum unsigned char buf sum sum amp 0xffff sum gt gt 16 sum sum amp 0xffff sum gt gt 16 return sum protocol指定的raw socket创建 int make raw socket int protocol int s socket AF INET SOCK RAW protocol if s lt 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 gt type type icmphdr gt code code icmphdr gt checksum 0 icmphdr gt un echo id id icmphdr gt un echo sequence seq icmphdr gt 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 lt 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 amp icmphdr ICMP包的送信 n sendto soc char amp icmphdr sizeof icmphdr 0 struct sockaddr amp addr sizeof addr if n lt 1 perror sendto return 1 ICMP包的受信 n recv soc buf sizeof buf 0 if n lt 1 perror recv return 1 recv iphdr struct iphdr buf 从IP包头获取IP包的长度 从而确定icmp包头的开始位置 recv icmphdr struct icmphdr buf recv iphdr gt ihl lt lt 2 insaddr s addr recv iphdr gt saddr 检查送信包的源地址匹配受信包的目的地址 if strcmp argv 1 inet ntoa insaddr amp amp recv icmphdr gt type ICMP ECHOREPLY printf icmp echo reply from s n argv 1 close soc return 0 下例是binding一个原始套接字并使用 include lt stdio h gt include lt stdlib h gt include lt sys socket h gt include lt features h gt include lt linux if packet h gt include lt linux if ether h gt include lt errno h gt include lt sys ioctl h gt include lt net if h gt define PACKET LENGTH 1024 int CreateRawSocket int protocol to sniff int rawsock if rawsock socket PF PACKET SOCK RAW htons protocol to sniff 1 perror Error creating raw socket exit 1 return rawsock int BindRawSocketToInterface char device int rawsock int protocol struct sockaddr ll sll struct ifreq ifr memset amp sll 0 sizeof sll memset amp ifr 0 sizeof ifr First Get the Interface Index strncpy char ifr ifr name device IFNAMSIZ if ioctl rawsock SIOCGIFINDEX amp ifr 1 printf Error getting Interface index n exit 1 Bind our raw socket to this interface sll sll family AF PACKET sll sll ifindex ifr ifr ifindex sll sll protocol htons protocol if bind rawsock struct sockaddr amp sll sizeof sll 1 perror Error binding raw socket to interface n exit 1 return 1 int SendRawPacket int rawsock unsigned char pkt int pkt len int sent 0 A simple write on the socket thats all it takes if sent write rawsock pkt pkt len pkt len return 0 return 1 argv 1 is the device e g eth0 argv 2 is the number of packets to send main int argc char argv int raw unsigned char packet PACKET LENGTH int num of pkts Set the packet to all A s memset packet A PACKET LENGTH Create the raw socket raw CreateRawSocket ETH P ALL Bind raw socket to interface BindRawSocketToInterface argv 1 raw ETH P ALL num of pkts atoi argv 2 while num of pkts gt 0 if SendRawPacket raw packet PACKET LENGTH perror Error sending packet else printf Packet sent successfully n close raw return 0 参见 编辑IPv4包格式 IPv6包格式 英语 IPv6 packet 参考文献 编辑 raw 7 IPv4 raw sockets Linux man page die net 2017 03 14 原始内容存档于2016 09 07 Raw IP Networking FAQ faqs org 2017 03 14 原始内容存档于2012 01 19 Ian Griffiths for IanG on Tap 12 August 2004 Raw Sockets Gone in XP SP2 页面存档备份 存于互联网档案馆 外部链接 编辑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 取自 https zh wikipedia org w index php title 原始套接字 amp oldid 67208769, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。