zoukankan      html  css  js  c++  java
  • icmp 流量抓取 转发 代理

    通过以下步骤,将经过本机的(设置本机为网关)icmp流量抓取,并获取其目标地址,可以用来做icmp代理。
    1. iptables 在 mangle 表的 prerouting链中添加规则,给icmp包做标记,比如0x15
         
    iptables -t mangle -A PREROUTING -p icmp -j MARK --set-mark 0x15
     
    2. ip rule 添加规则:标记0x15的包查询路由表100
        ip route 添加规则:将目的地址为0.0.0.0/0(即所有目的地址)的包通过回环发给本机
    ip rule add fwmark 0x15 lookup 100
    ip route add local 0.0.0.0/0 dev lo table 100
     
    3. 代码中使用raw socket 监听icmp的数据包
        //ICMP协议
        if((protocol = getprotobyname("icmp")) == NULL)
        {
            perror("getprotobyname");
            exit(1);
        }

        //raw socket监听icmp协议,需要root权限
        if((sockfd = socket(AF_INET,SOCK_RAW,protocol->p_proto)) < 0)
        {
            perror("socket error");
            exit(1);
        }

        //回收root权限
        setuid(getuid());
     
         3.1 setsockopt选项 IP_RECVORIGDSTADDR或者IP_PKTINFO
              int opt = 1;
              setsockopt(sockfd,IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt));
              setsockopt(sockfd, SOL_IP, IP_RECVORIGDSTADDR, &opt, sizeof(opt));
     
         3.2 使用recvmsg,遍历msg的cmsghdr,选取特定的cmsg
        socklen_t sender_len;
        struct msghdr msg;
        struct iovec iov;
        struct sockaddr_in sender_addr;
        sender_len = sizeof(sender_addr);
        char buf[2048] = {0};
        int len = 0;
        char cmsg_buf[2048] = {0};

        msg.msg_name = &sender_addr;
        msg.msg_namelen = sender_len;
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
        msg.msg_iov->iov_base = buf;
        msg.msg_iov->iov_len = 2048;
        msg.msg_control = cmsg_buf;
        msg.msg_controllen = 2048;
        msg.msg_flags = 0;

        len = recvmsg(sockfd,&msg,0);
        if (len == -1) {
            perror("recvmsg()");
        } else if (len == 0) {
            printf("Connection Closed ");
        } else {
            printf("Read from Client: len [%d] --content:", len);
            print_data(buf,len);

            //方法1:使用IP_PKTINFO
            struct cmsghdr * cmsg = NULL;
            for (cmsg = CMSG_FIRSTHDR(&msg);
                cmsg != NULL;
                cmsg = CMSG_NXTHDR(&msg, cmsg))
            {
                // ignore the control headers that don't match what we want
                if (cmsg->cmsg_level != IPPROTO_IP ||
                    cmsg->cmsg_type != IP_PKTINFO)
                {
                    continue;
                }
                struct in_pktinfo *pi = CMSG_DATA(cmsg);
                printf("ipi_spec_dst:%s ", inet_ntoa(pi->ipi_spec_dst));
                printf("ipi_addr:%s ", inet_ntoa(pi->ipi_addr));
                char sender_ip[32] = {0};
                int sender_port = 0;
                transfer_sock_addr(&sender_addr, sender_ip, 32, &sender_port);
                printf("source ip:%s port:%d ",sender_ip,sender_port);
                // at this point, peeraddr is the source sockaddr
                // pi->ipi_spec_dst is the destination in_addr
                // pi->ipi_addr is the receiving interface in_addr
            }

            //方法2:使用IP_RECVORIGDSTADDR
            char orig_ip[32] = {0};
            int orig_port = 0;
            struct sockaddr_in *orig_addr;
            for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
                    cmsg = CMSG_NXTHDR(&msg,cmsg)) {
                if (cmsg->cmsg_level == SOL_IP
                        && cmsg->cmsg_type == IP_ORIGDSTADDR) {
                    orig_addr = (struct sockaddr_in *) CMSG_DATA(cmsg);
                    transfer_sock_addr(orig_addr, orig_ip, 32, &orig_port);
                    break;
                }
            }
            if (cmsg == NULL) {
                printf("IP_ORIGDSTADDR not enabled or small buffer or I/O error");
                return;
            }
            printf("original destination ip:%s - port:%d ", orig_ip, orig_port);

     
    部分代码参考:http://www.oschina.net/code/snippet_80184_1511
  • 相关阅读:
    eclipse如何与git 配合工作。
    git托管代码(二)
    PPC2003 安装 CFNET 3.5成功
    我的Window Mobile WCF 項目 第三篇 WM窗体设计
    我的Window Mobile WCF 項目 第一篇Mobile开发和WinForm开发的区别
    我的Window Mobile WCF 項目 第七天
    我的Window Mobile WCF 項目 第二篇 WindowsMobile访问WCF
    WCF 用vs2010 和 vs2008的简单对比测试
    vs2010beta1 和 搜狗输入法 冲突,按下 Ctrl 键就报错,重装搜狗解决
    我的Window Mobile WCF 項目 第六天 (二)
  • 原文地址:https://www.cnblogs.com/cklxmu/p/3965063.html
Copyright © 2011-2022 走看看