数据包转发/代理服务器

网络工程 路由器 代理
2022-02-24 23:29:59

这是我的设置:

  1. 连接到我的 ISP 的 Internet 路由器
  2. 一个 Linux 机器用一个网卡连接到路由器,并用另一个连接到交换机。
  3. 一个连接到交换机的 Windows 盒子。

我正在尝试编写一个 Python 脚本,以基本上允许 Windows 7 机器与 Internet 通信,就好像 Linux 机器不存在一样;如果您愿意,可以使用透明代理。

我已将 Windows 机器的默认网关设置为 Linux 机器,因此无论何时它尝试访问 Internet,数据包都会被路由到 Linux 机器。

Linux 机器正在侦听内部网卡。它从原始套接字中取出数据包,然后重写 dst MAC 地址以将数据包转发到路由器,并将 src IP 地址替换为面向外部的网卡。然后,此数据包从外部 NIC 发送出去。src MAC 地址设置为外部网卡。

因此,就路由器而言,它正在从 Linux 机器接收这些数据。因此,路由器将其路由到 Internet,然后将响应发送回 Linux 机器。

外部网卡也在监听网络流量,任何传入的具有匹配 MAC 地址的原始数据包,它都会脱离网络,将 dst MAC 地址更改为 Windows 机器,将 dst IP 地址更改为 Windows 机器,以及 src MAC 地址作为内部网络接口。然后它通过内部卡发送它。

就 Windows 机器而言,它向 Linux 机器(默认网关)发送了一个数据包,然后收到了响应。

当我尝试 ping Internet 服务器(如8.8.8.8)时,这可以正常工作。查看 Linux 机器上的输出,我看到数据包进入内部卡,然后在外部卡上退出,并带有修改后的标头。

然后,不久之后,我看到响应从外部卡返回,经过修改,然后通过内部卡发送出去。

我已经编写了类来计算 IP 校验和等,所以这不是问题。

然后我看到 Windows 机器接收到 ping 响应。

因此,通过此设置,Ping 工作正常。我可以ping通8.8.8.8我已经将 Windows 机器配置为使用8.8.8.8我们知道它可以访问的 DNS 服务器。

然而,当我尝试使用 IE 或 Firefox 浏览 Internet 时,却不能。

我可以看到 DNS 请求通过内部网卡,被修改,然后在外部网卡上发送出去。然而,这一次,不是像 ping 那样使用协议 1,而是使用 UDP 协议 17。

不管我等待多长时间,外部卡上都不会出现响应,因为没有任何东西从8.8.8.8Linux 机器返回。

在使用 ping 时会这样做,但在进行 DNS 查找时不会。

正如我所说,DNS 已手动配置为8.8.8.8and 4.4.4.4,我看到 DNS 请求发送到 Internet 路由器。

什么都不会回来。任何想法在这里可能有什么不同,以及我应该将哪些事情视为潜在问题?

请不要推荐我使用其他一些软件包来解决这个问题,因为我已经研究过了,它们不符合我的要求。

2个回答

您的问题将是传输层协议也需要修复。例如,TCP 有一个基于包含 IP 源地址和目标地址的伪标头的校验和。您的网页浏览需要使用 TCP,因此您需要修复 TCP 标头。请参阅RFC 793,传输控制协议

校验和:16 位

校验和字段是标题和文本中所有 16 位字的反码和的 16 位反码。如果一个段包含奇数个要校验和的标题和文本八位字节,则最后一个八位字节在右侧用零填充以形成一个用于校验和目的的 16 位字。pad 不作为段的一部分传输。在计算校验和时,校验和字段本身被零替换。

校验和还涵盖概念上以 TCP 标头为前缀的 96 位伪标头。此伪标头包含源地址、目标地址、协议和 TCP 长度。这为 TCP 提供了针对错误路由段的保护。此信息在 Internet 协议中承载,并通过 TCP/网络接口在 IP 上 TCP 调用的参数或结果中传输。

             +--------+--------+--------+--------+
             |           Source Address          |
             +--------+--------+--------+--------+
             |         Destination Address       |
             +--------+--------+--------+--------+
             |  zero  |  PTCL  |    TCP Length   |
             +--------+--------+--------+--------+

TCP Length 是 TCP 标头长度加上八位字节的数据长度(这不是显式传输的数量,而是计算出来的),它不计算伪标头的 12 个八位字节。

UDP 也可以使用校验和。它对于 IPv4 上的 UDP 是可选的,但在 IPv6 上是强制性的。如果您的 UDP 使用校验和,那么您必须修复它。请参阅RFC 768,用户数据报协议

校验和是来自 IP 报头、UDP 报头和数据的伪报头信息的补码和的 16 位补码,最后用零八位字节填充(如有必要)以形成两个八位字节的倍数.

概念上以 UDP 报头为前缀的伪报头包含源地址、目的地址、协议和 UDP 长度。此信息可防止错误路由的数据报。此校验和过程与 TCP 中使用的相同。

              0      7 8     15 16    23 24    31 
             +--------+--------+--------+--------+
             |          source address           |
             +--------+--------+--------+--------+
             |        destination address        |
             +--------+--------+--------+--------+
             |  zero  |protocol|   UDP length    |
             +--------+--------+--------+--------+

如果计算的校验和为零,则将其作为全 1 传输(在一个补码算法中的等价物)。传输的校验和值全为零意味着发送器没有生成校验和(用于调试或不关心的更高级别的协议)。

您的应用程序协议(例如 HTTP/HTTPS)也可能需要修复。此外,如果您的网页浏览使用 SSL,那么您可能还会遇到其他问题,因为 TCP 有效负载将被加密,因此可能更难以处理。不幸的是,OSI 第 4 层之上的协议在这里显然是题外话。

如果 DNS 不起作用,那么任何依赖它的东西都不会起作用。显然,您在“路由”UDP 数据包方面遇到了问题(您或多或少地实现了无状态 NAT 路由器)。

UDP 使用“伪 IPv4 标头”来计算校验和。如果您不重新计算它,数据包将被丢弃。正如 Ron 所指出的,TCP 使用相同的概念并且需要在段内重新计算校验和。