IP_TRANSPARENT SYN не получает ответа SYN + ACK на локальном хосте - PullRequest
0 голосов
/ 13 октября 2019

Я пишу следующую программу (хотя я не думаю, что именно в этом проблема):

#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 не выдается ни по loopback, ни по 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, то все работает как положено. Нет порта брандмауэра, который кажется релевантным, а * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 по обратной связи.

. Почему соединение не принято? Это ошибка в моем коде или эта конфигурация связана?

Ответы [ 2 ]

1 голос
/ 14 октября 2019

Отсутствующий SYN + ACK должен был содержать следующую информацию:

127.0.0.1:7007 -> 93.184.216.34:31337

При обходе таблицы маршрутизации IP-адрес назначения будет соответствовать маршруту по умолчанию и будет запланирован для выхода на eth0(как и ожидалось).

Однако eth0 имеет (как и все другие интерфейсы в системе) Марсианский пакет защита включена. Так как адрес источника 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-адрес и порт.

1 голос
/ 13 октября 2019

Вы пытаетесь создать TCP-соединение от некоторого внешнего адреса (93.184.216.34) до 127.0.0.1. Поэтому необходимо создать SYN + ACK с источником 127.0.0.1 и внешним адресом в качестве пункта назначения. Только нет маршрута с использованием интерфейса обратной связи (127.0.0.1) к этому внешнему адресу, и поэтому SYN + ACK не может быть отправлено.

...