2013-07-05 2 views
4

Я использую сокеты для отправки TCP-пакетов от компьютера В к компьютеру А.Почему маршрутизатор не перенаправляет мой пакет?

Во-первых, я создаю сокет

int s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); 

и сообщить ядру не заполнять заголовке IP для меня, потому что мои данные включают в себя как IP-заголовка и TCP заголовка

int optval = 1; 
setsockopt(s, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval)); 

и установить адрес назначения

struct sockaddr_in addr; 
memset(&addr, 0, sizeof(addr)); 
addr.sin_family = AF_INET; 
addr.sin_port = htons(33333); 
addr.sin_addr.s_addr = inet_addr("192.168.200.135"); 

и отправить данные

sendto(s, data, len, 0, (struct sockaddr*)&addr, sizeof(addr)); 

Моя сетевая среда как на рисунке ниже network environment

В случае, если два компьютера соединены с помощью переключателя. В то время как в случае B компьютер B подключается к маршрутизатору, а маршрутизатор подключается к коммутатору.

Моя программа отлично работает в случае А. Я могу использовать сырой сокет, чтобы получить пакет на компьютере А, и может использовать wirehark для захвата этого пакета.

В случае B я могу выполнить ping от компьютера B до компьютера A и ssh от B до A. И я могу использовать как raw socket, так и wirehark на компьютере A для захвата некоторого TCP-пакета, посланного между B и A. Однако, пакеты, отправленные моим сырым сокетом на компьютере B, не могут быть записаны на A. Кажется, что маршрутизатор не отправляет мой пакет. Что-то не так с моим пакетом?

Моя посыла программа с пакетом данных выглядит следующим образом:

//data to send 
char data[48] = 
{ 
    //iphdr: 
    0x45, 0x00, 0x00, 0x30, //version:4 header_length:5 TOS:0 length:0x30 
    0x00, 0x01, 0x00, 0x00, //identification:1 flags:0 fragment_offset:0 
    0x40, 0x06, 0x2f, 0x47, //TTL:0x40 protocol:6(TCP) header_checksum:0x2f47 
    0xc0, 0xa8, 0x01, 0xa8, //source_IP:192.168.1.168 
    0xc0, 0xa8, 0xc8, 0x87, //destination_IP:192.168.200.135 
    //tcphdr: 
    0x56, 0xce, 0x82, 0x35, //source_port:22222 destination_port:33333 
    0x00, 0x00, 0x00, 0x00, //sequence_number:0 
    0x00, 0x00, 0x00, 0x00, //ack_number:0 
    0x50, 0x00, 0xaa, 0xaa, //header_length:5 window_size:0xaaaa 
    0xeb, 0xbd, 0x00, 0x00, //checksum:0xebbd urgent_pointer:0 
    //tcp content: 
    0x7a, 0x68, 0x73, 0x00, 
    0x39, 0x30, 0xce, 0x56, 
}; 
int len = 48; 
//open the socket 
int s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); 
//don't fill header 
int optval = 1; 
setsockopt(s, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval)); 
//destination addr 
struct sockaddr_in addr; 
memset(&addr, 0, sizeof(addr)); 
addr.sin_family = AF_INET; 
addr.sin_addr.s_addr = inet_addr("192.168.200.135"); 
//send 
sendto(s, data, len, 0, (struct sockaddr*)&addr, sizeof(addr)); 
+0

Вы убедитесь, что * (i) * вы [включено переадресация IP] (http://linuxpoison.blogspot.de/2008/01/how-to-enable-ip-forwarding.html) на маршрутизаторе, и * (ii) * ваша программа работает с привилегиями root (что требуется для сырых сокетов)? – mavam

+0

Можете ли вы добавить вывод проводов для этого пакета? «50», которые вы описываете как «длина заголовка», - это «смещение данных». Проверьте http://tools.ietf.org/html/rfc793. Наконец, TCP ориентирован на соединение, не хотите ли вы использовать UDP? –

+0

@MatthiasVallentin (i) Переадресация IP включена, в противном случае я не могу ssh и ping от B до A (мой маршрутизатор - CISCO WRVS4400N). (ii) Я запускаю свою программу как root, иначе возвращаемое значение socket() будет равно -1. – Haoshu

ответ

0
  1. маршрутизатор 192.168.1.1 должен быть маршрутизатор по умолчанию. Проверьте свою конфигурацию в машине A.
0

Ваш TCP-заголовок ошибочен, так как он пропускает флаги. Для вашего теста вы должны по крайней мере установить флаг SYN. В заголовке могут быть и другие вещи.

Итак, если маршрутизатор действительно проверяет заголовок TCP, он, вероятно, отбрасывает ваш пакет. Проверка заголовка TCP происходит, если ваш маршрутизатор фактически не маршрутизируется, но использует NAT для пересылки пакетов, или если есть брандмауэр, который проверяет наличие портов или состояний соединения.

Смежные вопросы