• 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
  • 相关阅读:
    条件运算符 (?:)
    SVN地址修改
    dev -gridview隐藏子表标题
    继承与 Data Member(3)
    继承与 Data Member(2)
    继承与 Data Member(1)
    Data Member 的存取
    Data Member 的布局
    Data Member 的绑定
    对于 sizeof(class_name) 值的讨论(2)
  • 原文地址:https://www.cnblogs.com/cklxmu/p/3965063.html
Copyright © 2020-2023  润新知