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
  • 相关阅读:
    如何在服务器上添加本地驱动器
    JQ查找到带有某个字符,并起类名,然后替换这个某个字符
    使用IWMS的网站打开显示“未能加载文件或程序集”,解决方案
    表头固顶结构
    在页面中有overflow-y:auto属性的div,当出现滚动条,点击返回顶部按钮,内容回这个div最顶部
    在文档页面整个区域出现导航随内容滚动高亮显示效果
    在文档页面局部出现导航随内容滚动高亮显示效果
    在Hmtl页面中只让其中单独的一个div隐藏滚动条但是仍可滚动浏览下边的内容
    GC参考手册 —— GC 调优(工具篇)
    GC参考手册 —— GC 算法(实现篇)
  • 原文地址:https://www.cnblogs.com/cklxmu/p/3965063.html
Copyright © 2011-2022 走看看