Я использую сокеты для отправки 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));
Моя сетевая среда как на рисунке ниже
В случае, если два компьютера соединены с помощью переключателя. В то время как в случае 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));
Вы убедитесь, что * (i) * вы [включено переадресация IP] (http://linuxpoison.blogspot.de/2008/01/how-to-enable-ip-forwarding.html) на маршрутизаторе, и * (ii) * ваша программа работает с привилегиями root (что требуется для сырых сокетов)? – mavam
Можете ли вы добавить вывод проводов для этого пакета? «50», которые вы описываете как «длина заголовка», - это «смещение данных». Проверьте http://tools.ietf.org/html/rfc793. Наконец, TCP ориентирован на соединение, не хотите ли вы использовать UDP? –
@MatthiasVallentin (i) Переадресация IP включена, в противном случае я не могу ssh и ping от B до A (мой маршрутизатор - CISCO WRVS4400N). (ii) Я запускаю свою программу как root, иначе возвращаемое значение socket() будет равно -1. – Haoshu