RAW_SOCKET 我不是女神ヾ 2022-08-10 06:26 179阅读 0赞 sock\_raw原始套接字编程可以接收到本机网卡上的数据帧或者数据包,对与监听网络的流量和分析是很有作用的.一共可以有3种方式创建这种socket 1.socket(AF\_INET, SOCK\_RAW, IPPROTO\_TCP|IPPROTO\_UDP|IPPROTO\_ICMP)发送接收ip数据包 2.socket(PF\_PACKET, SOCK\_RAW, htons(ETH\_P\_IP|ETH\_P\_ARP|ETH\_P\_ALL))发送接收以太网数据帧 3.socket(AF\_INET, SOCK\_PACKET, htons(ETH\_P\_IP|ETH\_P\_ARP|ETH\_P\_ALL))过时了,不要用啊 理解一下SOCK\_RAW的原理, 比如网卡收到了一个 14+20+8+100+4 的udp的以太网数据帧. 首先,网卡对该数据帧进行硬过滤(根据网卡的模式不同会有不同的动作,如果设置了promisc混杂模式的话,则不做任何过滤直接交给下一层输 入例程,否则非本机mac或者广播mac会被直接丢弃).按照上面的例子,如果成功的话,会进入ip输入例程.但是在进入ip输入例程之前,系统会检查系 统中是否有通过socket(AF\_PACKET, SOCK\_RAW, ..)创建的套接字.如果有的话并且协议相符,在这个例子中就是需要ETH\_P\_IP或者ETH\_P\_ALL类型.系统就给每个这样的socket接收缓 冲区发送一个数据帧拷贝.然后进入下一步. 其次,进入了ip输入例程(ip层会对该数据包进行软过滤,就是检查校验或者丢弃非本机ip或者广播ip的数据包等,具体要参考源代码),例子 中就是如果成功的话会进入udp输入例程.但是在交给udp输入例程之前,系统会检查系统中是否有通过socket(AF\_INET, SOCK\_RAW, ..)创建的套接字.如果有的话并且协议相符,在这个例子中就是需要IPPROTO\_UDP类型.系统就给每个这样的socket接收缓冲区发送一个数据 帧拷贝.然后进入下一步. 最后,进入udp输入例程 ... ps:如果校验和出错的话,内核会直接丢弃该数据包的.而不会拷贝给sock\_raw的套接字,因为校验和都出错了,数据肯定有问题的包括所有信息都没有意义了. 进一步分析他们的能力. 1. socket(AF\_INET, SOCK\_RAW, IPPROTO\_UDP); 能:该套接字可以接收协议类型为(tcp udp icmp等)发往本机的ip数据包,从上面看的就是20+8+100. 不能:不能收到非发往本地ip的数据包(ip软过滤会丢弃这些不是发往本机ip的数据包). 不能:不能收到从本机发送出去的数据包. 发送的话需要自己组织tcp udp icmp等头部.可以setsockopt来自己包装ip头部 这种套接字用来写个ping程序比较适合 2. socket(PF\_PACKET, SOCK\_RAW, htons(x)); 这个套接字比较强大,创建这种套接字可以监听网卡上的所有数据帧.从上面看就是20+20+8+100.最后一个以太网crc从来都不算进来的,因为内核已经判断过了,对程序来说没有任何意义了. 能: 接收发往本地mac的数据帧 能: 接收从本机发送出去的数据帧(第3个参数需要设置为ETH\_P\_ALL) 能: 接收非发往本地mac的数据帧(网卡需要设置为promisc混杂模式) 协议类型一共有四个 ETH\_P\_IP 0x800 只接收发往本机mac的ip类型的数据帧 ETH\_P\_ARP 0x806 只接受发往本机mac的arp类型的数据帧 ETH\_P\_ARP 0x8035 只接受发往本机mac的rarp类型的数据帧 ETH\_P\_ALL 0x3 接收发往本机mac的所有类型ip arp rarp的数据帧, 接收从本机发出的所有类型的数据帧.(混杂模式打开的情况下,会接收到非发往本地mac的数据帧) 发送的时候需要自己组织整个以太网数据帧.所有相关的地址使用struct sockaddr\_ll 而不是struct sockaddr\_in(因为协议簇是PF\_PACKET不是AF\_INET了),比如发送给某个机器,对方的地址需要使用struct sockaddr\_ll. 这种socket大小通吃,强悍 下面是一段相关的代码: <table style="font-family:Arial; font-size:14px; line-height:26px; color:rgb(51,51,51); border-collapse:collapse"> <tbody> <tr> <td> <p style="margin:5px; line-height:21px"><code><span style="color:rgb(0,0,0)"><span style="color:rgb(0,0,204)"> </span></span></code><code><span style="color:rgb(0,0,0)"><span style="color:rgb(0,0,204)"> .</span><span style="color:rgb(0,0,204)">.</span><span style="color:rgb(0,0,204)">.</span><br> <span style="color:rgb(0,0,255)">int</span> <span style="font-family:新宋体">sockfd </span><span style="color:rgb(0,0,204)">=</span> socket<span style="color:rgb(0,0,204)">(</span>PF_PACKET<span style="color:rgb(0,0,204)">,</span> SOCK_RAW<span style="color:rgb(0,0,204)">,</span> htons<span style="color:rgb(0,0,204)">(</span>ETH_P_ALL<span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">;</span><br> <span style="color:rgb(0,0,255)">struct</span> sockaddr_ll sll<span style="color:rgb(0,0,204)">;</span><br> memset<span style="color:rgb(0,0,204)">(</span> &sll<span style="color:rgb(0,0,204)">,</span> 0<span style="color:rgb(0,0,204)">,</span> <span style="color:rgb(0,0,255)">sizeof</span><span style="color:rgb(0,0,204)">(</span>sll<span style="color:rgb(0,0,204)">)</span> <span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">;</span><br> sll<span style="color:rgb(0,0,204)">.</span>sll_family <span style="color:rgb(0,0,204)">=</span> AF_PACKET<span style="color:rgb(0,0,204)">;</span><br> <span style="color:rgb(0,0,255)">struct</span> ifreq ifstruct<span style="color:rgb(0,0,204)">;</span><br> strcpy<span style="color:rgb(0,0,204)">(</span>ifstruct<span style="color:rgb(0,0,204)">.</span>ifr_name<span style="color:rgb(0,0,204)">,</span> <span style="color:rgb(255,0,255)">"eth0"</span><span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">;</span><br> ioctl<span style="color:rgb(0,0,204)">(</span>sockfd<span style="color:rgb(0,0,204)">,</span> SIOCGIFINDEX<span style="color:rgb(0,0,204)">,</span> &ifstruct<span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">;</span><br> sll<span style="color:rgb(0,0,204)">.</span>sll_ifindex <span style="color:rgb(0,0,204)">=</span> ifstruct<span style="color:rgb(0,0,204)">.</span>ifr_ifindex<span style="color:rgb(0,0,204)">;</span><br> sll<span style="color:rgb(0,0,204)">.</span>sll_protocol <span style="color:rgb(0,0,204)">=</span> htons<span style="color:rgb(0,0,204)">(</span>ETH_P_ALL<span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">;</span><br> <span style="color:rgb(0,0,255)">if</span><span style="color:rgb(0,0,204)">(</span>bind<span style="color:rgb(0,0,204)">(</span>fd<span style="color:rgb(0,0,204)">,</span> <span style="color:rgb(0,0,204)">(</span><span style="color:rgb(0,0,255)">struct</span> sockaddr <span style="color:rgb(0,0,204)">*</span><span style="color:rgb(0,0,204)">)</span> &sll<span style="color:rgb(0,0,204)">,</span> <span style="color:rgb(0,0,255)">sizeof</span><span style="color:rgb(0,0,204)">(</span>sll<span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">)</span> <span style="color:rgb(0,0,204)">=</span><span style="color:rgb(0,0,204)">=</span> <span style="color:rgb(0,0,204)">-</span>1 <span style="color:rgb(0,0,204)">)</span> { <br> <span style="color:rgb(0,0,204)"> perror("bind()");</span><br> <span style="color:rgb(0,0,204)">.</span><span style="color:rgb(0,0,204)">.</span><span style="color:rgb(0,0,204)">.</span></span></code></p> </td> </tr> </tbody> </table> <table style="font-family:Arial; font-size:14px; line-height:26px; color:rgb(51,51,51); border-collapse:collapse"> <tbody> <tr> <td> <p style="margin:5px; line-height:21px"><code><span style="color:rgb(0,0,0)"><span style="color:rgb(0,0,255)">int</span> set_promisc<span style="color:rgb(0,0,204)">(</span>char <span style="color:rgb(0,0,204)">*</span>interface<span style="color:rgb(0,0,204)">,</span> <span style="color:rgb(0,0,255)">int</span> fd<span style="color:rgb(0,0,204)">)</span> { <br> <span style="color:rgb(0,0,255)">struct</span> ifreq ifr<span style="color:rgb(0,0,204)">;</span><br> strcpy<span style="color:rgb(0,0,204)">(</span>ifr<span style="color:rgb(0,0,204)">.</span>ifr_name<span style="color:rgb(0,0,204)">,</span> interface<span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">;</span><br> <span style="color:rgb(0,0,255)">if</span><span style="color:rgb(0,0,204)">(</span>ioctl<span style="color:rgb(0,0,204)">(</span>fd<span style="color:rgb(0,0,204)">,</span> SIOCGIFFLAGS<span style="color:rgb(0,0,204)">,</span> &ifr<span style="color:rgb(0,0,204)">)</span> <span style="color:rgb(0,0,204)">=</span><span style="color:rgb(0,0,204)">=</span> <span style="color:rgb(0,0,204)">-</span>1<span style="color:rgb(0,0,204)">)</span> { <br> perror<span style="color:rgb(0,0,204)">(</span><span style="color:rgb(255,0,255)">"iotcl()"</span><span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">;</span><br> return <span style="color:rgb(0,0,204)">-</span>1<span style="color:rgb(0,0,204)">;</span><br> }<br> ifr<span style="color:rgb(0,0,204)">.</span>ifr_flags <span style="color:rgb(0,0,204)">|</span><span style="color:rgb(0,0,204)">=</span> IFF_PROMISC<span style="color:rgb(0,0,204)">;</span><br> <span style="color:rgb(0,0,255)">if</span><span style="color:rgb(0,0,204)">(</span>ioctl<span style="color:rgb(0,0,204)">(</span>fd<span style="color:rgb(0,0,204)">,</span> SIOCSIFFLAGS<span style="color:rgb(0,0,204)">,</span> &ifr<span style="color:rgb(0,0,204)">)</span> <span style="color:rgb(0,0,204)">=</span><span style="color:rgb(0,0,204)">=</span> <span style="color:rgb(0,0,204)">-</span>1<span style="color:rgb(0,0,204)">)</span> { <br> perror<span style="color:rgb(0,0,204)">(</span><span style="color:rgb(255,0,255)">"iotcl()"</span><span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">;</span><br> return <span style="color:rgb(0,0,204)">-</span>1<span style="color:rgb(0,0,204)">;</span><br> }<br> return 0<span style="color:rgb(0,0,204)">;</span><br> }<br> <br> <span style="color:rgb(0,0,255)">int</span> unset_promisc<span style="color:rgb(0,0,204)">(</span>char <span style="color:rgb(0,0,204)">*</span>interface<span style="color:rgb(0,0,204)">,</span> <span style="color:rgb(0,0,255)">int</span> fd<span style="color:rgb(0,0,204)">)</span> { <br> <span style="color:rgb(0,0,255)">struct</span> ifreq ifr<span style="color:rgb(0,0,204)">;</span><br> strcpy<span style="color:rgb(0,0,204)">(</span>ifr<span style="color:rgb(0,0,204)">.</span>ifr_name<span style="color:rgb(0,0,204)">,</span> interface<span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">;</span><br> <span style="color:rgb(0,0,255)">if</span><span style="color:rgb(0,0,204)">(</span>ioctl<span style="color:rgb(0,0,204)">(</span>fd<span style="color:rgb(0,0,204)">,</span> SIOCGIFFLAGS<span style="color:rgb(0,0,204)">,</span> &ifr<span style="color:rgb(0,0,204)">)</span> <span style="color:rgb(0,0,204)">=</span><span style="color:rgb(0,0,204)">=</span> <span style="color:rgb(0,0,204)">-</span>1<span style="color:rgb(0,0,204)">)</span> { <br> perror<span style="color:rgb(0,0,204)">(</span><span style="color:rgb(255,0,255)">"iotcl()"</span><span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">;</span><br> return <span style="color:rgb(0,0,204)">-</span>1<span style="color:rgb(0,0,204)">;</span><br> }<br> ifr<span style="color:rgb(0,0,204)">.</span>ifr_flags &<span style="color:rgb(0,0,204)">=</span> ~IFF_PROMISC<span style="color:rgb(0,0,204)">;</span><br> <span style="color:rgb(0,0,255)">if</span><span style="color:rgb(0,0,204)">(</span>ioctl<span style="color:rgb(0,0,204)">(</span>fd<span style="color:rgb(0,0,204)">,</span> SIOCSIFFLAGS<span style="color:rgb(0,0,204)">,</span> &ifr<span style="color:rgb(0,0,204)">)</span> <span style="color:rgb(0,0,204)">=</span><span style="color:rgb(0,0,204)">=</span> <span style="color:rgb(0,0,204)">-</span>1<span style="color:rgb(0,0,204)">)</span> { <br> perror<span style="color:rgb(0,0,204)">(</span><span style="color:rgb(255,0,255)">"iotcl()"</span><span style="color:rgb(0,0,204)">)</span><span style="color:rgb(0,0,204)">;</span><br> return <span style="color:rgb(0,0,204)">-</span>1<span style="color:rgb(0,0,204)">;</span><br> }<br> return 0<span style="color:rgb(0,0,204)">;</span><br> }</span></code></p> </td> </tr> </tbody> </table> 3. socket(AF\_INET, SOCK\_PACKET, htons(ETH\_P\_ALL))这个最好不要用,反正我不用... 总结使用方法: 1.只想收到发往本机某种协议的ip数据包的话用第一种就足够了 2. 更多的详细的内容请使用第二种.包括ETH\_P\_ALL参数和混杂模式都可以使它的能力不断的加强. ps:很多自己的想法.虚拟机测试环境.有错欢迎指出交流 qq:110024218 我写的ping `#include "stdio.h" #include "stdlib.h" #include "string.h" #include "unistd.h" #include "sys/types.h" #include "sys/socket.h" #include "netinet/in.h" #include "netinet/ip.h" #include "netinet/ip_icmp.h" #include "netdb.h" #include "errno.h" #include "arpa/inet.h" #include "signal.h" #include "sys/time.h" extern int errno; int sockfd; struct sockaddr_in addr; //peer addr char straddr[128]; //peer addr ip(char*) char sendbuf[2048]; char recvbuf[2048]; int sendnum; int recvnum; int datalen = 30; unsigned short my_cksum(unsigned short *data, int len) { int result = 0; for(int i=0; i<len/2; i++) { result += *data; data++; } while(result >> 16)result = (result&0xffff) + (result>>16); return ~result; } void tv_sub(struct timeval* recvtime, const struct timeval* sendtime) { int sec = recvtime->tv_sec - sendtime->tv_sec; int usec = recvtime->tv_usec - sendtime->tv_usec; if(usec >= 0) { recvtime->tv_sec = sec; recvtime->tv_usec = usec; } else { recvtime->tv_sec = sec-1; recvtime->tv_usec = -usec; } } void send_icmp() { struct icmp* icmp = (struct icmp*)sendbuf; icmp->icmp_type = ICMP_ECHO; icmp->icmp_code = 0; icmp->icmp_cksum = 0; icmp->icmp_id = getpid(); //needn't use htons() call, because peer networking kernel didn't handle this data and won't make different meanings(bigdian litteldian) icmp->icmp_seq = ++sendnum; //needn't use hotns() call too. gettimeofday((struct timeval*)icmp->icmp_data, NULL); int len = 8+datalen; icmp->icmp_cksum = my_cksum((unsigned short*)icmp, len); int retval = sendto(sockfd, sendbuf, len, 0, (struct sockaddr*)&addr, sizeof(addr)); if(retval == -1){ perror("sendto()"); exit(-1); } else { // printf("send icmp request to %s(%d) bytes/n", straddr, len); } } void recv_icmp() { struct timeval *sendtime; struct timeval recvtime; for(;;) { int n = recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, 0, 0); if(n == -1) { if(errno == EINTR)continue; else { perror("recvfrom()"); exit(-1); } } else { gettimeofday(&recvtime, NULL); struct ip *ip = (struct ip*)recvbuf; if(ip->ip_src.s_addr != addr.sin_addr.s_addr) { // printf("ip_src is not : %s/n", straddr); continue; } struct icmp *icmp = (struct icmp*)(recvbuf + ((ip->ip_hl)<<2)); if(icmp->icmp_id != getpid()) { // printf("icmp_id is not :%d/n", getpid()); continue; } recvnum++; sendtime = (struct timeval*)icmp->icmp_data; tv_sub(&recvtime, sendtime); printf("imcp echo from %s(%dbytes)/tttl=%d/tseq=%d/ttime=%d.%06d s/n",straddr, n, ip->ip_ttl, icmp->icmp_seq, recvtime.tv_sec, recvtime.tv_usec); } } } void catch_sigalrm(int signum) { send_icmp(); alarm(1); } void catch_sigint(int signum) { printf("/nPing statics:send %d packets, recv %d packets, %d%% lost.../n", sendnum,recvnum, (int)((float)(sendnum-recvnum)/sendnum)*100); exit(0); } int main(int argc, char **argv) { if(argc != 2) { printf("please use format: ping hostname/n"); exit(-1); } sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if(sockfd == -1) { perror("socket()"); return -1; } /* int sendbufsize = 180; socklen_t sendbufsizelen = sizeof(sendbufsize); if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &sendbufsize, sendbufsizelen) ==-1)perror("setsockopt()"); int recvbufsize; socklen_t recvbufsizelen; if(getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &recvbufsize, &recvbufsizelen) ==-1)perror("getsockopt()"); */ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; int retval = inet_pton(AF_INET, argv[1], &addr.sin_addr); if(retval == -1 || retval == 0) { struct hostent* host = gethostbyname(argv[1]); if(host == NULL) { fprintf(stderr, "gethostbyname(%s):%s/n", argv[1], strerror(errno)); exit(-1); } /* if(host->h_name != NULL)printf("hostent.h_name:%s/n", host->h_name); if(host->h_aliases != NULL && *(host->h_aliases) !=NULL)printf("hostent.h_aliases:%s/n", *(host->h_aliases)); printf("hostent.h_addrtype:%d/n", host->h_addrtype); printf("hostent.h_length:%d/n", host->h_length); */ if(host->h_addr_list != NULL && *(host->h_addr_list) != NULL) { strncpy((char*)&addr.sin_addr, *(host->h_addr_list), 4); inet_ntop(AF_INET, *(host->h_addr_list), straddr, sizeof(straddr)); } printf("Ping address:%s(%s)/n/n", host->h_name, straddr); } else { strcpy(straddr, argv[1]); printf("Ping address:%s(%s)/n/n", straddr, straddr); } struct sigaction sa1; memset(&sa1, 0, sizeof(sa1)); sa1.sa_handler = catch_sigalrm; sigemptyset(&sa1.sa_mask); sa1.sa_flags = 0; if(sigaction(SIGALRM, &sa1, NULL) == -1)perror("sigaction()"); struct sigaction sa2; memset(&sa2, 0, sizeof(sa2)); sa2.sa_handler = catch_sigint; sigemptyset(&sa2.sa_mask); sa2.sa_flags = 0; if(sigaction(SIGINT, &sa2, NULL) == -1)perror("sigaction()"); alarm(1); recv_icmp(); return 0; }`
还没有评论,来说两句吧...