在 TCP/IP 模型中,应用层如何将目的 IP 地址告知 Internet 层?

网络工程 ip 通讯协议 第3层 奥西 第4层
2021-07-24 04:58:29

网络新手。

  1. 应用层如何将目的IP地址告知Internet层?假设我向 www.google.com 发出 Http 请求,应用层通过 DNS 将其解析为 8.8.8.8。如果数据在层间封装,这个 IP 地址如何传递到 Internet 层?

  2. 服务器的应用层如何知道客户端在HTTP请求中的源IP地址?我知道客户端的 Internet 层将源 IP 地址添加到 IP 数据包中,但是它是如何附加到传入的 HTTP 请求标头(例如 XForwardedFor)的 Internet 层是否以某种方式将源 IP 附加到应用程序数据中HTTP 标头?如果是这样,互联网层如何知道应用层正在使用的协议?

4个回答

除了数据之外,还必须在应用程序、传输层和 Internet 层之间传输一些元数据。

从技术上讲,元数据如何在层之间进行通信是一个实现细节。在实践中,应用层几乎总是使用 berkerly 套接字 API 的一些变体来与传输层通信。

对于 TCP 客户端,目标 IP 和端口作为“连接”API 调用的一部分指定给传输层。对于 UDP 客户端,可以使用“连接”来创建伪连接,或者可以使用“sendto”api 调用在每个数据包的基础上指定目标 IP 和端口。

对于 TCP 服务器,应用程序可以在接受连接后调用 getpeername 来读取 IP 和端口。UDP 服务器可以通过使用 recvfrom API 调用读取数据包来读取每个数据包的 IP 和端口。

不幸的是 sendto 和 recvfrom 有一个设计缺陷。它们只传递远程地址,而不是本地地址,这会导致多宿主主机上的服务器出现问题。服务器可能会从错误的 IP 地址发送回复,导致它们被网络或客户端丢弃。有更新的 API 可以解决这个问题,但细节因操作系统而异。

传输层将依次将传出数据包的 IP 地址通知 Internet 层,而 Internet 层将传入数据包的 IP 地址通知传输层。由于传输层和 Internet 层通常都是 TCP/IP 堆栈的一部分,因此如何完成此操作的细节是堆栈内部的实现细节。

x-forwarded-for 是 http 代理使用的 http 标头。代理将使用 getpeername 检索客户端 IP 地址,然后将其编码为 http 标头以将其传递给下一个服务器。

  1. 在客户端,信息向下流经每一层。即您的浏览器形成一个 HTTP 请求并将其作为应用程序有效负载向下推送到传输层,并带有附加信息,例如传输协议 (TCP) 目标端口 (80) 和目标地址。

传输层协议 (TCP) 将应用程序负载封装到一个段中,并使用从应用程序层(目标端口)接收到的一些信息来添加传输层报头。然后它将段连同一些附加信息(例如目标地址)一起向下传递到网络层。

网络层协议 (IP) 将传输层段封装在 IP 数据包/数据报中,并使用它从传输层(目标地址)接收到的一些附加信息来添加 IP 报头。它将它下推到链路层。

链路层协议(以太网)将网络层数据报封装在一个帧中。然后,它使用从其他协议 (ARP) 获取的一些数据来使用正确的目标地址(MAC 地址)填充链路层协议标头。

所描述的过程通常由操作系统实现(例如 Unix 套接字)和 NIC 驱动程序完成。

  1. 因为在服务器端,上述过程是相反的。应用程序不仅从底层接收应用程序数据,还接收一些附加信息,如源IP地址和源端口。

请注意,操作系统 TCP/IP 实现和 NIC 驱动程序不会改变应用程序负载。因此,它们不会使用任何类型的数据填充 X-Forwarded-For HTTP 标头。IP 地址数据沿有效负载传递。在您的情况下,这是由客户端和服务器之间的代理完成的。由于代理被视为网络层的源 IP 地址,代理确保原始源 IP 地址在应用程序数据负载中传递给服务器。

  1. 正如您在上面看到的,TCP/IP 层的实现并不像 ISO/OSI 理论中那样清晰——应用程序确实需要知道一些理论上应该包含在较低层中的数据。这就是为什么需要重写应用程序以支持 IPv6 的原因(即使这应该是透明的网络层传输更改,但不会影响应用程序层)。

我认为您不了解 DNS 查询和 HTTP 请求是不同的数据包,这让您感到困惑。

如果您尝试访问 www.cool-site.com 并且您不知道其 IP 地址,那么首先会发生 DNS。DNS 过程像任何其他数据包一样遵循整个封装/解封装过程。

您的机器将意识到它没有 www.cool-site.com 的 IP。您的机器将构建一个 DNS 查询并将其发送到您指定的 DNS 服务器(静态或通过 DHCP 获取的服务器)。假设 DNS 服务器知道地址,它将使用包含域名和 IP 地址的 DNS 响应回复您。现在机器知道 IP 地址,它可以为 HTTP 请求构建一个新数据包,并将 IP 地址作为数据包中的目标 IP。

服务器知道在哪里响应,因为在 HTTP 请求数据包中,IP 标头中有一个源 IP 和目标 IP(就像所有数据包一样)。服务器会响应并将自己的IP作为源,并使用前一个数据包中的源IP作为目的地。

关于获取从 DNS 查询接收到的 IP 并将其放入数据包目标 IP 字段的数据包究竟是如何构建的,我不清楚。操作系统网络堆栈显然会处理这个问题,但我不能提供更多信息,因为我不确定整个过程。也许有人可以评论一些额外的信息。

简化:

  1. 应用程序使用套接字调用打开 TCP 连接。此调用的参数之一是指向套接字描述符结构的指针。套接字描述符在建立连接之前由客户端应用程序(包括服务器 IP 地址)部分填充。该结构可供应用程序和操作系统内的 IP 堆栈(软件)使用。

  2. 服务器还具有与其侦听套接字相关联的套接字结构。建立连接时,IP 堆栈会填充源 IP 地址和端口。应用程序可以从套接字结构中读取值。