raw socket in linux
来源:互联网 发布:网络通信介质 编辑:程序博客网 时间:2024/05/21 06:59
0 前言
http://www.binarytides.com/raw-sockets-c-code-linux/
In normal sockets when any data is send over the network, the kernel of the operating system adds some headers to it like IP header and TCP header. So an application only needs to take care of what data it is sending and what reply it is expecting.
But there are other cases when an application needs to set its own headers. Raw sockets are used in security related applications like nmap , packets sniffer etc.
通常情况下,我们使用socket只关心载荷部分,协议的头部信息由操作系统自动填充。有些时候程序需要自己处理header,比如安全相关的程序nmap,packet sniffer等等,此时需要使用raw socket
。
1 Raw TCP packets
一个 TCP packet结构为: Packet = IP Header + TCP Header + Data
2 Raw tcp sockets
创建一个tcp raw socket:
int s = socket (AF_INET, SOCK_RAW, IPPROTO_TCP);
程序需要提供tcp header, 而ip header 由操作系统的网络协议栈提供。
如果程序也想要接管ip header,可以通过以下两种方法:
- 使用IPPROTO_RAW :
int s = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
- 设置IP_HDRINCL socket选项为1
int s = socket (AF_INET, SOCK_RAW, IPPROTO_TCP);int one = 1;const int *val = &one;if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0){ printf ("Error setting IP_HDRINCL. Error number : %d . Error message : %s \n" , errno , strerror(errno)); exit(0);} // 当使用IP_HDRINCL, 函数socket的参数protocol不再起作用了
3 Example
/* Raw TCP packets Silver Moon (m00n.silv3r@gmail.com)*/#include<stdio.h> //for printf#include<string.h> //memset#include<sys/socket.h> //for socket ofcourse#include<stdlib.h> //for exit(0);#include<errno.h> //For errno - the error number#include<netinet/tcp.h> //Provides declarations for tcp header#include<netinet/ip.h> //Provides declarations for ip header/* 96 bit (12 bytes) pseudo header needed for tcp header checksum calculation */struct pseudo_header{ u_int32_t source_address; u_int32_t dest_address; u_int8_t placeholder; u_int8_t protocol; u_int16_t tcp_length;};/* Generic checksum calculation function*/unsigned short csum(unsigned short *ptr,int nbytes) { register long sum; unsigned short oddbyte; register short answer; sum=0; while(nbytes>1) { sum+=*ptr++; nbytes-=2; } if(nbytes==1) { oddbyte=0; *((u_char*)&oddbyte)=*(u_char*)ptr; sum+=oddbyte; } sum = (sum>>16)+(sum & 0xffff); sum = sum + (sum>>16); answer=(short)~sum; return(answer);}int main (void){ //Create a raw socket int s = socket (PF_INET, SOCK_RAW, IPPROTO_TCP); if(s == -1) { //socket creation failed, may be because of non-root privileges perror("Failed to create socket"); exit(1); } //Datagram to represent the packet char datagram[4096] , source_ip[32] , *data , *pseudogram; //zero out the packet buffer memset (datagram, 0, 4096); //IP header struct iphdr *iph = (struct iphdr *) datagram; //TCP header struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip)); struct sockaddr_in sin; struct pseudo_header psh; //Data part data = datagram + sizeof(struct iphdr) + sizeof(struct tcphdr); strcpy(data , "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); //some address resolution strcpy(source_ip , "192.168.1.2"); sin.sin_family = AF_INET; sin.sin_port = htons(80); sin.sin_addr.s_addr = inet_addr ("1.2.3.4"); //Fill in the IP Header iph->ihl = 5; iph->version = 4; iph->tos = 0; iph->tot_len = sizeof (struct iphdr) + sizeof (struct tcphdr) + strlen(data); iph->id = htonl (54321); //Id of this packet iph->frag_off = 0; iph->ttl = 255; iph->protocol = IPPROTO_TCP; iph->check = 0; //Set to 0 before calculating checksum iph->saddr = inet_addr ( source_ip ); //Spoof the source ip address iph->daddr = sin.sin_addr.s_addr; //Ip checksum iph->check = csum ((unsigned short *) datagram, iph->tot_len); //TCP Header tcph->source = htons (1234); tcph->dest = htons (80); tcph->seq = 0; tcph->ack_seq = 0; tcph->doff = 5; //tcp header size tcph->fin=0; tcph->syn=1; tcph->rst=0; tcph->psh=0; tcph->ack=0; tcph->urg=0; tcph->window = htons (5840); /* maximum allowed window size */ tcph->check = 0; //leave checksum 0 now, filled later by pseudo header tcph->urg_ptr = 0; //Now the TCP checksum psh.source_address = inet_addr( source_ip ); psh.dest_address = sin.sin_addr.s_addr; psh.placeholder = 0; psh.protocol = IPPROTO_TCP; psh.tcp_length = htons(sizeof(struct tcphdr) + strlen(data) ); int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr) + strlen(data); pseudogram = malloc(psize); memcpy(pseudogram , (char*) &psh , sizeof (struct pseudo_header)); memcpy(pseudogram + sizeof(struct pseudo_header) , tcph , sizeof(struct tcphdr) + strlen(data)); tcph->check = csum( (unsigned short*) pseudogram , psize); //IP_HDRINCL to tell the kernel that headers are included in the packet int one = 1; const int *val = &one; if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) { perror("Error setting IP_HDRINCL"); exit(0); } //loop if you want to flood :) while (1) { //Send the packet if (sendto (s, datagram, iph->tot_len , 0, (struct sockaddr *) &sin, sizeof (sin)) < 0) { perror("sendto failed"); } //Data send successfully else { printf ("Packet Send. Length : %d \n" , iph->tot_len); } } return 0;}//Complete
4 编译&运行
使用gcc编译,raw socket运行需要root权限。
5 其他参考
http://opensourceforu.com/2015/03/a-guide-to-using-raw-sockets/
- raw socket in linux
- linux下RAW SOCKET
- linux raw socket
- linux raw socket program
- Linux Raw Socket
- linux下RAW SOCKET
- Linux raw socket
- Linux raw socket
- linux raw socket
- [linux]raw socket example
- Linux Raw Socket使用总结
- Linux socket编程(TCP,UDP,RAW)
- linux利用raw socket抓包
- raw socket 编程资料(linux环境)
- Linux socket编程(TCP,UDP,RAW)
- [linux] raw socket example tcp sync
- Raw Socket
- raw socket
- Java获取客户端IP地址、MAC地址,根据IP获取地理位置信息代码
- hdu5512
- 使用mina框架内存溢出的问题
- 注册页面
- 标题の我也不知道该叫什么
- raw socket in linux
- 1M带宽、1Mbps、1Mb/s 区分
- Source map
- java通过Http get post请求url获取数据
- log4j:WARN Please initialize the log4j system properly解决办法
- 触摸屏硬件以及驱动简介
- 利用Hog特征和SVM分类器进行行人检测
- linux下安装vim8.0,支持python、perl、lua等解释器
- codeforces 136A(Presents) Java