IP_TRANSPARENT SYN在本地主机上未获得SYN + ACK响应

时间:2019-10-13 19:32:05

标签: linux tcp transparentproxy

我正在编写以下程序(尽管我不认为这是问题所在):

#include <arpa/inet.h>
#include <netinet/ip.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <stdio.h>
#include <stdlib.h>

int main() {
    int sock=socket(AF_INET, SOCK_STREAM, 0);
    if( sock<0 ) {
        perror("socket creation failed");
        return 1;
    }

    int ip_transparent_enabled = 1;
    if( setsockopt(sock, IPPROTO_IP, IP_TRANSPARENT, &ip_transparent_enabled, sizeof(ip_transparent_enabled))<0 ) {
        perror("Setting IP_TRANSPARENT failed");
        return 1;
    }

    struct sockaddr_in bind_addr = { AF_INET, htons(31337) };
    inet_aton("93.184.216.34", &bind_addr.sin_addr); // example.com

    if( bind(sock, (const struct sockaddr *)&bind_addr, sizeof(bind_addr))<0 ) {
        perror("bind failed");
        return 1;
    }

    struct sockaddr_in dest = { AF_INET, htons(7007) };
    inet_aton("127.0.0.1", &dest.sin_addr);

    if( connect(sock, (const struct sockaddr *)&dest, sizeof(dest))<0 ) {
        perror("Connect failed");
        return 1;
    }
}

端口7007正在运行回显服务器,但这并不重要,因为那里的程序从不接收连接。

运行tcpdump时,我看到发送的SYN具有正确的(组成的)源地址,但是SYN + ACK既不在环回也不在eth0上发出:

$ sudo tcpdump -i any port 31337                                                                                                                                                       
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode                                                                                                                                        
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes                                                                                                                                   
22:22:41.475942 IP 93.184.216.34.31337 > localhost.afs3-bos: Flags [S], seq 2953286612, win 65495, options [mss 65495,sackOK,TS val 443673031 ecr 0,nop,wscale 7], length 0                                       
22:22:42.478172 IP 93.184.216.34.31337 > localhost.afs3-bos: Flags [S], seq 2953286612, win 65495, options [mss 65495,sackOK,TS val 443674033 ecr 0,nop,wscale 7], length 0                                       
22:22:44.494174 IP 93.184.216.34.31337 > localhost.afs3-bos: Flags [S], seq 2953286612, win 65495, options [mss 65495,sackOK,TS val 443676049 ecr 0,nop,wscale 7], length 0                                       
22:22:48.590423 IP 93.184.216.34.31337 > localhost.afs3-bos: Flags [S], seq 2953286612, win 65495, options [mss 65495,sackOK,TS val 443680145 ecr 0,nop,wscale 7], length 0                                       

如果我注释掉bind,那么一切都会按预期进行。似乎没有相关的防火墙端口,并且rp_filter在环回时设置为0。

为什么不接受连接?这是我的代码中的错误,还是该配置相关?

2 个答案:

答案 0 :(得分:1)

您正在尝试创建从某个外部地址(93.184.216.34)到127.0.0.1的TCP连接。因此,必须使用源127.0.0.1和外部地址作为目标来创建SYN + ACK。只是,没有使用回送接口(127.0.0.1)到此外部地址的路由,因此无法发送SYN + ACK。

答案 1 :(得分:1)

缺少的SYN + ACK应该具有以下信息:

127.0.0.1:7007 -> 93.184.216.34:31337

遍历路由表时,目标IP将与默认路由匹配,并被安排在eth0上出局(如预期)。

但是,eth0(与系统中的所有其他接口一样)已启用Martian packet保护。由于源地址为127.0.0.1,因此该数据包永远不会出去,并且tcpdump也不会报告。

一种解决方案是关闭eth0的火星数据包保护:

# echo 0 > /proc/sys/net/ipv4/conf/eth0/route_localnet

但是,这会禁用非常有用的保护。更好的解决方案是将流量定向到环回接口,首先使用源路由:

# ip rule add from 127.0.0.1 lookup 100
# ip route add local default dev lo table 100

在此位置上,将使用外部IP地址和端口在透明代理和本地服务之间建立实际连接。