监听所有rtp/rtcp包
来源:互联网 发布:ubuntu修改ssh端口 编辑:程序博客网 时间:2024/06/05 09:34
监听所有的udp包,需要在数据链路层做,如果在网络层,不是发往本地的IP包都上不来; 另外,网络监听一个问题是上来的数据包太多, 处理不过来,会导致丢包,需要过滤。如果在应用层做,会有内核空间拷贝到用户空间的开销,最好内核里面做, linux已经原生提供了Linux Packet Filter。表示方式采用BPF。
BPF 原始格式看起来像汇编语言, tcpdump -dd可以把如下的编译成BPF:
src host 192.168.2.1 and tcp port 8000-9000 #端口范围
'(((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' #ip包长度-ip头长度-tcp头长度
'tcp[20:2]=0x4745 or tcp[20:2]=0x4854' #tcp内容开头为"GE"或"HT", http get/http ok
然后SO_ATTACH_FILTER到socket就开始过滤了。
rtp包的特征是udp包地9个字节是0x80, rtcp是0x81, 我们根据这个来作为过滤条件。测试发现dns也可能是0x81开头,
81 93 01 00 //dns query, Transaction ID:0x8193, dst.port = 53
81 93 81 80 //dns response, srt.port = 53
因此还要加上端口号的判断[3]。
下面的代码参考[1], 删掉了tcp,icmp相关部分:
#include<errno.h>#include<netdb.h>#include<stdio.h> //For standard things#include<stdlib.h> //malloc#include<string.h> //strlen #include<netinet/in.h>#include<netinet/ip_icmp.h> //Provides declarations for icmp header#include<netinet/udp.h> //Provides declarations for udp header#include<netinet/tcp.h> //Provides declarations for tcp header#include<netinet/ip.h> //Provides declarations for ip header#include<netinet/if_ether.h> //For ETH_P_ALL#include<net/ethernet.h> //For ether_header#include<sys/socket.h>#include<arpa/inet.h>#include<sys/ioctl.h>#include<sys/time.h>#include<sys/types.h>#include<unistd.h>#include <linux/filter.h> //struct sock_fprog#include<netpacket/packet.h> //struct packet_mreq#include<net/if.h> //struct ifreq static FILE *logfile;void PrintData (unsigned char* data , int Size){int i , j;for(i=0 ; i < Size ; i++){if( i!=0 && i%16==0) //if one line of hex printing is complete...{fprintf(logfile , " ");for(j=i-16 ; j<i ; j++){if(data[j]>=32 && data[j]<=128)fprintf(logfile , "%c",(unsigned char)data[j]); //if its a number or alphabetelse fprintf(logfile , "."); //otherwise print a dot}fprintf(logfile , "\n");} if(i%16==0) fprintf(logfile , " ");fprintf(logfile , " %02X",(unsigned int)data[i]);if( i==Size-1) //print the last spaces{for(j=0;j<15-i%16;j++) { fprintf(logfile , " "); //extra spaces}fprintf(logfile , " ");for(j=i-i%16 ; j<=i ; j++){if(data[j]>=32 && data[j]<=128) { fprintf(logfile , "%c",(unsigned char)data[j]);}else { fprintf(logfile , ".");}}fprintf(logfile , "\n" );}}}void print_udp_packet(unsigned char *Buffer , int Size){ unsigned short iphdrlen; struct iphdr *iph = (struct iphdr *)(Buffer + sizeof(struct ethhdr)); iphdrlen = iph->ihl*4; struct udphdr *udph = (struct udphdr*)(Buffer + iphdrlen + sizeof(struct ethhdr)); int header_size = sizeof(struct ethhdr) + iphdrlen + sizeof(*udph);char source[16], dest[16];inet_ntop(AF_INET, &iph->saddr, source, sizeof(source));inet_ntop(AF_INET, &iph->daddr, dest, sizeof(dest));fprintf(logfile, "UDP %s:%u --> %s:%u len %u:%u\n", source,ntohs(udph->source), dest,ntohs(udph->dest), ntohs(udph->len), Size - header_size);//PrintData(Buffer + header_size , (Size - header_size) );}void ProcessPacket(unsigned char* buffer, int size){static int tcp=0,udp=0,icmp=0,others=0,igmp=0,total=0; struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr)); ++total; switch (iph->protocol){ case 1: ++icmp; break; case 2: ++igmp; break; case 6: ++tcp; break; case 17: ++udp; print_udp_packet(buffer , size); break; default: //Some Other Protocol like ARP etc. ++others; break; } //printf("TCP : %d UDP : %d ICMP : %d IGMP : %d Others : %d Total : %d\r", tcp , udp , icmp , igmp , others , total);} int get_iface_index(int fd, const char* iface_name){struct ifreq ifr;if (iface_name == NULL){return -1;}memset(&ifr, 0, sizeof(ifr));strcpy(ifr.ifr_name, iface_name);if(ioctl(fd, SIOCGIFINDEX, &ifr) == -1){printf("get index error\n");return -1;}return ifr.ifr_ifindex;}int set_iface_promisc(int fd, int dev_id){struct packet_mreq mr;memset(&mr,0,sizeof(mr));mr.mr_ifindex = dev_id;mr.mr_type = PACKET_MR_PROMISC;if(setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0){fprintf(stderr,"set promisc failed");return -1;}return 0;} int main(int ac, char **av){ int saddr_size , data_size; struct sockaddr saddr; unsigned char *buffer = (unsigned char *)malloc(65536); char *iface_name = ac > 1 ? av[1] : "eth0"; if(ac > 2){logfile = fopen(av[2],"w");}else{logfile = stdout;} if(!logfile){ printf("Unable to create log.txt file.");return -1; } /*ETH_P_IP |ETH_P_ARP -- cant receive multicast*/ int sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)); if(sock_raw < 0){ perror("Socket Error"); return 1; }int iface_idx = get_iface_index(sock_raw, iface_name); setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , iface_name , strlen(iface_name)+1);set_iface_promisc(sock_raw, iface_idx);struct sock_filter BPF_code[] = {//sudo tcpdump -s 65535 -dd 'udp && udp[0:2] > 1024 && udp[2:2] > 1024 && (udp[8] == 0x80 || udp[8] == 0x81)'{ 0x28, 0, 0, 0x0000000c },{ 0x15, 14, 0, 0x000086dd },{ 0x15, 0, 13, 0x00000800 },{ 0x30, 0, 0, 0x00000017 },{ 0x15, 0, 11, 0x00000011 },{ 0x28, 0, 0, 0x00000014 },{ 0x45, 9, 0, 0x00001fff },{ 0xb1, 0, 0, 0x0000000e },{ 0x48, 0, 0, 0x0000000e },{ 0x25, 0, 6, 0x00000400 },{ 0x48, 0, 0, 0x00000010 },{ 0x25, 0, 4, 0x00000400 },{ 0x50, 0, 0, 0x00000016 },{ 0x15, 1, 0, 0x00000080 },{ 0x15, 0, 1, 0x00000081 },{ 0x6, 0, 0, 0x0000ffff },{ 0x6, 0, 0, 0x00000000 },}; struct sock_fprog sfilter = {.len = sizeof(BPF_code)/sizeof(BPF_code[0]),.filter = BPF_code,};int ret = setsockopt(sock_raw, SOL_SOCKET, SO_ATTACH_FILTER, &sfilter, sizeof(sfilter));if(ret < 0){perror("attach filter");return -1;} while(1){ saddr_size = sizeof saddr; data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr, (socklen_t*)&saddr_size); if(data_size < 0){ printf("failed to get packets\n"); return 1; } ProcessPacket(buffer, data_size); } close(sock_raw); return 0;}
windows下只能从IP层开始过滤[2], 如果非要统一linux和windows, 目前可选择libpcap/winpcap。网上说linux libpcap 默认的mem map方式可能会丢包, windows版的有一些限制,暂时不打算统一搞。
[1] http://www.binarytides.com/packet-sniffer-code-in-c-using-linux-sockets-bsd-part-2/
[2] http://blog.csdn.net/cyberhero/article/details/5785158
[3] https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports
- 监听所有rtp/rtcp包
- IP/TCP/UDP/RTP/RTCP 包结构图
- IP/TCP/UDP/RTP/RTCP包结构
- IP/TCP/UDP/RTP/RTCP 包结构图
- IP/TCP/UDP/RTP/RTCP 包结构图
- RTP/RTCP
- RTP&RTCP
- RTP/RTCP
- RTP/RTCP
- RTP & RTCP
- RTP&RTCP
- RTP&RTCP
- rtp rtcp
- RTP/RTCP
- rfc 定义的rtp和rtcp协议基本包格式
- RTP/RTCP包的识别以及流的识别
- Wireshark 抓包分析 RTSP/RTP/RTCP 基本工作过程
- Wireshark 抓包分析 RTSP/RTP/RTCP 基本工作过程
- 【CCF】数字排序
- 和芯星通科技(北京)有限公司
- 1054. The Dominant Color (20)
- Android截屏方法汇总
- hdu 3127 WHU girls 2009武汉网络赛 dp
- 监听所有rtp/rtcp包
- Apache Spark入门攻略
- Stanford机器学习---第一讲. Linear Regression with one variable
- Spring JTA multiple resource transactions in Tomcat with Atomikos example
- COCI试后心得
- LeetCode || Single Number III
- Windows下搭建IOS开发环境(一)
- android ui ->>Dialog对话框
- android中的一些小技巧