waf 引擎 云原生平台tproxy 实现调研

了解了基本 云原生架构,不清楚的查看之前的文章:https://www.cnblogs.com/codestack/p/13914134.html

现在来看看云原生平台tproxy waf引擎串联实现:也就是 报文劫持转发到对应的接口------本地socket捕获数据包

tproxy方式

iptables -t mangle -N DIVERT #在nat表上新建名为DIVERT自定义链
iptables -t mangle -A PREROUTING -p tcp -m socket --transparent -j DIVERT #已建立的socket且被tproxy标记过的数据包执行DIVERT
iptables -t mangle -A DIVERT -j MARK --set-xmark 0x10000000/0xf0000000 #进入DIVERT设置标记
iptables -t mangle -A DIVERT -j ACCEPT
iptables -t mangle -N MY_TCP
iptables -t mangle -p tcp -A MY_TCP -j TPROXY --on-port 8081 --tproxy-mark 0x10000000/0xf0000000
#MY_TCP执行TPROXY转发为8081端口并进行标记
iptables -t mangle -A MY_TCP -j ACCEPT
iptables -t mangle -N MYMANGLE
iptables -t mangle -A PREROUTING -p tcp -j MYMANGLE #MYMANGLE链加入到PREROUTING
iptables -t mangle -A MYMANGLE -p tcp -m multiport --dports 80 -j MY_TCP #80端口的包执行MY_TCP
ip rule add fwmark 0x10000000/0xf0000000 table 200 pref 200 #对标记过的数据包执行序号为200的规则
ip route add local default dev lo table 200 #200规则:数据包发送到本地回环

 

那么问题来了,应用程序怎么编写?假如需要连接1.1.1.1:80这个端口,就算数据包到了本地,但是本地并没有1.1.1.1这个IP地址啊,程序是怎么能拿到数据的?不是应该直接丢弃这个数据包么?

  Linux提供了一个选项IP_TRANSPARENT,可以让程序bind一个不属于本机的地址,作为客户端,它可以使用一个不属于本机地址的IP地址作为源IP发起连接,作为服务端,它可以侦听在一个不属于本机的IP地址上,而这正是透明代理所必须的
setsockopt(fd,SOL_IP, TRANSPARENT,&opt,sizeof(opt));
setsockopt之后,作为代理服务器bind真实服务器addr,作为代理客户端bind真实客户端addr。

而由于TPROXY模式并没有改变数据包,所以直接通过getsockname获取到原始的IP端口信息:

 //Socket is bound to original destination
    if(getsockname(sockfd, (struct sockaddr*) orig_dst, &addrlen)
            < 0){
        perror("getsockname: ");
        return -1;
    } else {
        if(orig_dst->ss_family == AF_INET){
            inet_ntop(AF_INET,
                    &(((struct sockaddr_in*) orig_dst)->sin_addr),
                    orig_dst_str, INET_ADDRSTRLEN);
            fprintf(stderr, "Original destination %s\n", orig_dst_str);
        } else if(orig_dst->ss_family == AF_INET6){
            inet_ntop(AF_INET6,
                    &(((struct sockaddr_in6*) orig_dst)->sin6_addr),
                    orig_dst_str, INET6_ADDRSTRLEN);
            fprintf(stderr, "Original destination %s\n", orig_dst_str);
        }

参考:

https://www.kernel.org/doc/Documentation/networking/tproxy.txt

posted @ 2020-11-02 17:22  codestacklinuxer  阅读(577)  评论(0编辑  收藏  举报