【问题标题】:Why doesn't router forward my packet?为什么路由器不转发我的数据包?
【发布时间】:2013-07-05 09:25:18
【问题描述】:

我使用原始套接字将 TCP 数据包从计算机 B 发送到计算机 A。

首先,我创建一个套接字

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

并告诉内核不要为我填写 ip header,因为我的数据包括 ip header 和 tcp header

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));

我的网络环境如下图

在案例 A 中,两台计算机通过交换机连接。而在案例 B 中,计算机 B 连接到路由器,路由器连接到交换机。

我的程序在案例 A 中运行良好。我可以使用原始套接字在计算机 A 上接收数据包,并且可以使用 wireshark 捕获该数据包。

在案例 B 中,我可以从计算机 B ping 到计算机 A,并从 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)你enabled IP forwarding在路由器上,并且(ii)你的程序以root权限运行(原始套接字需要)?
  • 你能添加那个数据包的wireshark输出吗?您描述为header length 的50 是data offset。检查tools.ietf.org/html/rfc793 - 最后,TCP 是面向连接的,你不想用 UDP 代替吗?
  • @MatthiasVallentin (i) IP 转发已启用,否则我无法从 B 向 A 进行 ssh 和 ping(我的路由器是 CISCO WRVS4400N)。 (ii) 我以 root 身份运行我的程序,否则 socket() 的返回值为 -1。
  • @ott-- 在案例 A 中,wireshark 输出与我发送的相同,包括以太网标头。在案例 B 中,wireshark 无法捕获该包。那篇文章说数据偏移量是“TCP Header中32位字的数量”,它们是相同的。我只是想测试一下 TCP 的一些特性。
  • 最后,在套接字调用上使用不同的地址族(AF_PACKET 而不是 IPPROTO_TCP)。有关有效值,请参阅 linux.die.net/man/2/socket。发送 PC 上是否正在运行 wireshark?

标签: c linux networking


【解决方案1】:
  1. 路由器 192.168.1.1 应该是您的默认路由器。检查机器 A 中的配置。

【讨论】:

    【解决方案2】:

    您的 TCP 标头错误,因为它缺少标志。对于您的测试,您至少应该设置 SYN 标志。标题可能还有其他不正确的地方。

    因此,如果路由器实际上正在检查 TCP 标头,它可能会丢弃您的数据包。如果您的路由器实际上没有路由但使用 NAT 进行数据包转发,或者如果有检查端口或连接状态的防火墙,则会检查 TCP 标头。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-13
      • 2021-10-16
      • 1970-01-01
      • 1970-01-01
      • 2018-10-31
      • 2020-04-14
      • 1970-01-01
      相关资源
      最近更新 更多