RFC 9484 Proxying IP in HTTP October 2023
Pauly, et al. Standards Track [Page]
溪流:
互联网工程任务组 (IETF)
RFC:
9484
更新:
9298
类别:
标准轨道
发表:
国际刊号:
2070-1721
作者:
T. Pauly,编者
苹果公司。
D·斯奇纳齐
谷歌有限责任公司
A·切尔尼亚霍夫斯基
谷歌有限责任公司
M.库勒温德
爱立信
M·韦斯特伦德
爱立信

RFC 9484

HTTP 中的代理 IP

摘要

本文档介绍如何在 HTTP 中代理 IP 数据包。 该协议类似于 HTTP 中的 UDP 代理,但允许传输任意 IP 数据包。 更具体地说,本文档定义了一种协议,允许 HTTP 客户端通过充当 IP 代理的 HTTP 服务器创建 IP 隧道。 本文档更新了 RFC 9298。

本备忘录的状态

这是一份互联网标准跟踪文档。

本文档是互联网工程任务组 (IETF) 的产品。 它代表了IETF社区的共识。 它已接受公众审查,并已被互联网工程指导小组 (IESG) 批准发布。 有关互联网标准的更多信息,请参阅 RFC 7841 第 2 节。

有关本文档当前状态、任何勘误表以及如何提供反馈的信息,请访问 https://www.rfc-editor.org/info/rfc9484

目录

1. 简介

HTTP 提供 CONNECT 方法(参见 [HTTP] 的第 9.3.6 节)用于创建 TCP [TCP] 到目的地的隧道和 UDP [CONNECT-UDP] 的类似机制。 但是,这些机制无法隧道其他 IP 协议[IANA-PN],也无法传送 IP 标头的字段。

本文档描述了一种通过 HTTP 服务器传输 IP 隧道的协议,该服务器充当 HTTP 上的特定于 IP 的代理。 这可用于各种用例,例如远程访问 VPN、站点到站点 VPN、安全点对点通信或通用数据包隧道。

IP 代理的操作方式与 UDP 代理 [CONNECT-UDP] 类似,其中代理本身使用绝对 URL 进行标识,可以选择包含流量的目的地。 客户端使用 URI 模板 [TEMPLATE] 生成这些 URL,如第 3 节中所述。

此协议通过使用 HTTP 数据报 [HTTP-DGRAM] 支持所有现有版本的 HTTP。 当使用 HTTP/2 [HTTP/2] 或 HTTP/3 [HTTP/3] 时,它使用HTTP 扩展 CONNECT,如 [EXT-CONNECT2][EXT-CONNECT3] 中所述。 When using HTTP/1.x [HTTP/1.1], it uses HTTP Upgrade, as defined in Section 7.8 of [HTTP].

本文档更新了[CONNECT-UDP]以更改“masque”众所周知的URI;请参阅第 12.3 节

2. 约定和定义

关键字“必须”、“不得”、“必需”、“应当”、“不应"、"应该"、"不应"、"推荐"、"不推荐本文档中的“”、“可以”和“可选0>”应按照 BCP 14 [RFC2119 中的描述进行解释t12>]1> [RFC81744>]3> 当且仅当它们全部大写出现时,如此处所示。¶5>

在本文档中,我们使用术语“IP 代理”来指代响应 IP 代理请求的 HTTP 服务器。 术语“客户端”在 HTTP 意义上使用;客户端构造IP代理请求。 如果客户端和 IP 代理之间存在 HTTP 中介(如 [HTTP] 的第 3.7 节 中所定义),则这些中介称为本文件中的“中介机构”。 术语“IP 代理端点”指的是客户端和 IP 代理。

本文档使用[QUIC]中的术语。 本文档定义协议类型的地方,定义格式使用 [QUIC] 的第 1.3 节中的表示法。 本规范使用 [QUIC] 的 Section 16 中的可变长度整数编码。 变长整数值不需要以所需的最小字节数进行编码。

请注意,当使用的 HTTP 版本不支持复用流(例如 HTTP/1.1)时,本文档中任何对“流”的引用都代表整个连接。

3. 客户端配置

客户端配置为通过 URI 模板 [TEMPLATE] 使用 HTTP 上的 IP 代理。 URI 模板可以包含两个变量:“target”和“ipproto”;请参阅第 4.6 节 定义模板时需要考虑变量的可选性,以便变量可以自我识别或可以在语法中排除。

示例如下:

https://example.org/.well-known/masque/ip/{target}/{ipproto}/
https://proxy.example.org:4443/masque/ip?t={target}&i={ipproto}
https://proxy.example.org:4443/masque/ip{?target,ipproto}
https://masque.example.org/?user=bob
图 1:URI 模板示例

以下要求适用于 URI 模板:

客户应该验证上述要求;但是,客户端可以使用缺少此特定验证的通用 URI 模板实现。 如果客户端检测到 URI 模板不满足上述任何要求,则客户端必须拒绝其配置并中止请求,而不将其发送到 IP 代理。

与 UDP 代理一样,IP 代理的某些客户端配置仅允许用户配置代理主机和代理端口。 具有此类限制的客户端可以尝试使用默认模板访问 IP 代理功能,默认模板定义为:“https://$PROXY_HOST:$PROXY_PORT/.well-known/masque/ip/{target }/{ipproto}/",其中 $PROXY_HOST 和 $PROXY_PORT 分别是配置的 IP 代理的主机和端口。 如果 IP 代理部署需要与此类客户端进行互操作,则它们应该在此位置提供服务。

4. 通过 HTTP 建立 IP 隧道

为了允许通过 HTTP 进行 IP 隧道协商,本文档定义了“connect-ip”HTTP 升级词符。 生成的 IP 隧道使用胶囊协议(请参阅 [HTTP-DGRAM] 的第 3.2 节)以及采用 第 6 节

要启动与单个 HTTP 流关联的 IP 隧道,客户端发出包含“connect-ip”升级词符的请求。

当发送其IP代理请求时,客户端SHALL执行URI模板扩展以确定其请求的路径和查询;请参阅第 3 节

根据胶囊协议的定义(参见 [HTTP-DGRAM] 的第 3.2 节),IP 代理请求不携带任何消息内容。 同样,成功的IP代理响应也不会携带任何消息内容。

HTTP 上的 IP 代理必须通过 TLS 或 QUIC 加密或其他等效加密协议进行操作,以提供机密性、完整性和身份验证。

4.1. IP 代理处理

收到 IP 代理请求后:

  • 如果接收方配置为使用另一个 HTTP 服务器,它将充当中介,将请求转发到另一个 HTTP 服务器。 请注意,如果此类中介使用与接收请求的 HTTP 版本不同的 HTTP 版本转发请求,则可能需要重新编码请求,因为请求编码因版本而异(见下文)。
  • 否则,接收者将充当 IP 代理。 IP代理可以选择拒绝IP代理请求。 否则,它从从请求标头重建的 URI 中提取可选的“target”和“ipproto”变量,解码其百分比编码,并建立 IP 隧道。

IP 代理必须验证解码后的“target”和“ipproto”变量是否满足第 4.6 节中的要求。 如果没有,IP 代理 MUST 会将请求视为畸形;请参阅 [HTTP/2] 的 Section 8.1.1 和 [HTTP/3] 的 Section 4.1.2 如果“目标”变量是 DNS 名称,则 IP 代理必须在回复 HTTP 请求之前执行 DNS 解析(通过 A 和/或 AAAA 记录获取相应的 IPv4 和/或 IPv6 地址) 。 如果在此过程中发生错误,IP 代理必须拒绝请求并应该使用适当的代理状态标头字段[PROXY-STATUS]发送详细信息] 例如,如果 DNS 解析返回错误,则代理可以使用 [PROXY-STATUS< 的 第 2.3.2 节 中的 dns_error 代理错误类型。 /t3>].

IP 转发隧道的生命周期与 IP 代理请求流相关。 当请求流打开时,IP 代理必须维护与 IP 转发隧道相关的所有 IP 地址和路由分配。 IP 代理可以由于一段时间不活动而选择拆除隧道,但它们必须在这样做时关闭请求流。

成功的 IP 代理响应(如 4.34.5 节中定义)表示 IP 代理已建立 IP 隧道并愿意代理 IP 有效负载。 除成功的 IP 代理响应之外的任何响应都表明请求失败;因此,客户端必须中止请求。

随着成功的 IP 代理响应,IP 代理可以发送胶囊来分配地址并向客户端通告路由(第 4.7 节)。 客户端还可以向 IP 代理分配地址并向其通告路由,以实现网络到网络的路由。

4.2. HTTP/1.1 请求

当使用 HTTP/1.1 [HTTP/1.1] 时,IP 代理请求将满足以下要求:

  • 方法为“GET”。
  • 请求包含一个主机标头字段,其中包含 IP 代理的主机和可选端口。
  • 请求包含值为“Upgrade”的连接标头字段(请注意,此要求不区分大小写,根据 [第 7.6.1 节 >HTTP])。
  • 请求包含值为“connect-ip”的Upgrade标头字段。

不符合这些限制的 IP 代理请求格式错误。 此类格式错误的请求的接收者必须以错误响应,并且应该使用 400(错误请求)状态代码。

例如,如果客户端配置了 URI 模板“https://example.org/.well-known/masque/ip/{target}/{ipproto}/”,并且希望打开没有目标的 IP 转发隧道,或者协议限制,它可以发送以下请求:

GET https://example.org/.well-known/masque/ip/*/*/ HTTP/1.1
Host: example.org
Connection: Upgrade
Upgrade: connect-ip
Capsule-Protocol: ?1
图 2:HTTP/1.1 请求示例

4.3. HTTP/1.1响应

服务器通过回复以下要求来指示 IP 代理响应成功:

  • 响应上的 HTTP 状态代码为 101(切换协议)。
  • The response SHALL include a Connection header field with value "Upgrade" (note that this requirement is case-insensitive, as per Section 7.6.1 of [HTTP]).
  • 响应包含一个值为“connect-ip”的升级标头字段。
  • 响应应当满足启动胶囊协议的HTTP响应的要求;请参阅 [HTTP-DGRAM] 的第 3.2 节

如果不满足任何这些要求,客户端必须将此代理尝试视为失败并关闭连接。

例如,服务器可以响应:

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: connect-ip
Capsule-Protocol: ?1
图 3:HTTP/1.1 响应示例

4.4. HTTP/2 和 HTTP/3 请求

使用 HTTP/2 [HTTP/2] 或 HTTP/3 [HTTP/3] 时,IP 代理请求使用 HTTP 扩展 CONNECT。 这要求服务器发送 HTTP 设置,如 [EXT-CONNECT2][EXT-CONNECT3] 中指定的>,并且请求使用具有以下要求的 HTTP 伪标头字段:

  • :method 伪头字段 SHALL 为“CONNECT”。
  • :protocol 伪标头字段为“connect-ip”。
  • :authority 伪标头字段 SHALL 包含 IP 代理的权限。
  • :path 和 :scheme 伪头字段不得为空。 在 URI 模板扩展过程完成后,它们的值应当包含 URI 模板的方案和路径;请参阅第 3 节 URI Template中的变量可以确定请求的范围,例如请求全隧道IP数据包转发,或者特定的代理流;参见第 4.6 节

不符合这些限制的 IP 代理请求属于畸形请求;请参阅 [HTTP/2] 的 8.1.1 节和 [HTTP/3] 的 4.1.2 节。

例如,如果客户端配置了 URI 模板“https://example.org/.well-known/masque/ip/{target}/{ipproto}/”,并且希望打开没有目标的 IP 转发隧道,或者协议限制,它可以发送以下请求:

HEADERS
:method = CONNECT
:protocol = connect-ip
:scheme = https
:path = /.well-known/masque/ip/*/*/
:authority = example.org
capsule-protocol = ?1
图 4:HTTP/2 或 HTTP/3 请求示例

4.5. HTTP/2 和 HTTP/3 响应

服务器通过回复以下要求来指示 IP 代理响应成功:

  • 响应上的 HTTP 状态代码位于 2xx(成功)范围内。
  • 响应应当满足启动胶囊协议的HTTP响应的要求;请参阅 [HTTP-DGRAM] 的第 3.2 节

如果不满足任何这些要求,客户端必须将此代理尝试视为失败并中止请求。 例如,3xx 范围内的任何状态代码都将被视为失败并导致客户端中止请求。

例如,服务器可以响应:

HEADERS
:status = 200
capsule-protocol = ?1
图 5:HTTP/2 或 HTTP/3 响应示例

4.6. 限制请求范围

与需要指定目标主机的 UDP 代理请求不同,IP 代理请求可以允许端点向任何主机发送任意 IP 数据包。 客户端可以通过向其请求添加参数来选择将给定请求限制为特定的 IP 前缀或 IP 协议。 当 IP 代理知道请求的范围仅限于目标前缀或协议时,它可以利用此信息来优化其资源分配;例如,IP 代理可以将相同的公共 IP 地址分配给范围不同的前缀和/或不同协议的两个 IP 代理请求。

请求的范围由客户端通过 URI 模板的“target”和“ipproto”变量向 IP 代理指示;请参阅第 3 节 “target”和“ipproto”变量都是可选的;如果不包含它们,则认为它们带有通配符值“*”。

目标:

变量“target”包含客户端想要将数据包代理到的特定主机的主机名或 IP 前缀。 如果未指定“target”变量或其值为“*”,则客户端请求与任何允许的主机进行通信。 “target”支持使用 DNS 名称、IPv6 前缀和 IPv4 前缀。 请注意,不支持 IPv6 范围寻址区域标识符 [IPv6-ZONE-ID] 如果目标是 IP 前缀(IP 地址可选后跟百分比编码斜杠,后跟前缀长度(以位为单位)),则请求将仅支持单个 IP 版本。 如果目标是主机名,则 IP 代理应执行 DNS 解析以确定向客户端通告哪些路由。 IP 代理应该发送 ROUTE_ADVERTISMENT 封装,其中包含针对所请求的主机名解析的所有地址的路由,这些地址可由 IP 代理访问,并且属于 IP 代理也为其发送的地址族分配的地址。

ipproto:

变量“ipproto”包含一个互联网协议号;请参阅“分配的互联网协议号码”IANA 注册表[IANA-PN]中定义的列表。 如果存在,它指定客户端只想代理此请求的特定 IP 协议。 如果值为“*”,或者未包含该变量,则客户端正在请求使用任何 IP 协议。 “ipproto”变量中指示的IP协议表示在HTTP数据报(最外层IP报头)中直接发送的IP报头中携带的允许的下一个报头值。 无论该字段的值如何,始终允许 ICMP 流量。

使用 [URI]中的 IPv6address、IPv4address 和 reg-name 术语,"target "和 "ipproto "变量 MUST 遵循 Figure 6 中的格式,并使用 [ABNF]中的符号。 另外:

  • 如果“target”包含 IPv6 文字或前缀,则冒号(“:”)必须 采用百分比编码。 例如,如果目标主机是“2001:db8::42”,则它将在 URI 中编码为“2001%3Adb8%3A%3A42”。
  • 如果存在,“目标”中的 IP 前缀长度前面有一个百分比编码的斜杠(“/”):“%2F”。 IP 前缀长度必须表示 0 和 IP 地址长度(以位为单位)之间的十进制整数。
  • 如果“target”包含IP前缀,并且前缀长度严格小于IP地址的比特长度,则前缀长度未覆盖的IP地址的低位必须全部为设置为 0。
  • “ipproto”必须表示 0 到 255(含)之间的十进制整数或通配符值“*”。
target = IPv6prefix / IPv4prefix / reg-name / "*"
IPv6prefix = IPv6address ["%2F" 1*3DIGIT]
IPv4prefix = IPv4address ["%2F" 1*2DIGIT]
ipproto = 1*3DIGIT / "*"
图6:URI模板变量格式

IP 代理可以使用客户端提供的范围信息执行访问控制,即,如果客户端无权访问范围内包含的任何目的地,则 IP 代理可以立即拒绝该请求.

4.7. 胶囊

本文档定义了多种新的胶囊类型,允许端点交换 IP 配置信息。 两个端点可以发送任意数量的这些新胶囊。

4.7.1. ADDRESS_ASSIGN 胶囊

ADDRESS_ASSIGN 胶囊(胶囊类型 0x01)允许端点为其对等方分配 IP 地址或前缀列表。 每个胶囊包含当前分配给接收器的 IP 前缀的完整列表。 这些地址中的任何一个都可以用作由该胶囊的接收者发起的 IP 数据包的源地址。

ADDRESS_ASSIGN Capsule {
  Type (i) = 0x01,
  Length (i),
  Assigned Address (..) ...,
}
图7:ADDRESS_ASSIGN胶囊格式

ADDRESS_ASSIGN 胶囊包含零个或多个分配地址的序列。

Assigned Address {
  Request ID (i),
  IP Version (8),
  IP Address (32..128),
  IP Prefix Length (8),
}
图8:分配的地址格式

每个分配的地址包含以下字段:

请求ID:

请求标识符,编码为可变长度整数。 如果此地址分配是为了响应地址请求(请参阅第 4.7.2 节),则此字段包含请求中相应字段的值。 否则,该字段为零。

IP版本:

此地址分配的 IP 版本,编码为无符号 8 位整数。 必须是4或6。

IP地址:

分配的 IP 地址。 如果IP版本字段的值为4,则IP地址字段的长度为32位。 如果 IP 版本字段的值为 6,则 IP 地址字段的长度为 128 位。

IP 前缀长度:

IP 地址中用于定义所分配的前缀的位数,编码为无符号 8 位整数。 必须小于或等于IP 地址字段的长度(以位为单位)。 如果前缀长度等于IP地址的长度,则允许该胶囊的接收者从单个源地址发送数据包。 如果前缀长度小于IP地址的长度,则允许该胶囊的接收者从属于该前缀的任何源地址发送数据包。 如果前缀长度严格小于 IP 地址长度(以位为单位),则前缀长度未覆盖的 IP 地址字段的低位必须全部设置为 0。

如果任何胶囊字段在接收时格式错误,则胶囊的接收者必须遵循[HTTP的第3.3节中定义的错误处理过程-DGRAM].

如果一个 ADDRESS_ASSIGN 胶囊不包含先前在另一个 ADDRESS_ASSIGN 胶囊中传输的地址,则表明该地址已被删除。 ADDRESS_ASSIGN 胶囊也可以为空,表示所有地址已被删除。

在 HTTP 中的某些 IP 代理部署中,端点需要由其对等点分配一个地址,然后才能知道要在自己的数据包上设置什么源地址。 例如,在远程访问 VPN 情况下(第 8.1 节),客户端在知道要使用哪个地址之前无法发送 IP 数据包。 在这些部署中,期望地址分配的端点必须发送ADDRESS_REQUEST胶囊。 如果端点不需要任何地址分配,例如,当它使用静态地址进行带外配置时,则不需要这样做。

虽然 ADDRESS_ASSIGN 胶囊通常是为了响应 ADDRESS_REQUEST 胶囊而发送,但端点可以自动发送 ADDRESS_ASSIGN 胶囊。

4.7.2. ADDRESS_REQUEST胶囊

ADDRESS_REQUEST 胶囊(胶囊类型 0x02)允许端点向其对等点请求分配 IP 地址。 胶囊允许端点有选择地指示将分配哪个地址的首选项。

ADDRESS_REQUEST Capsule {
  Type (i) = 0x02,
  Length (i),
  Requested Address (..) ...,
}
图9:ADDRESS_REQUEST胶囊格式

ADDRESS_REQUEST 胶囊包含一系列一个或多个请求的地址。

Requested Address {
  Request ID (i),
  IP Version (8),
  IP Address (32..128),
  IP Prefix Length (8),
}
图10:请求的地址格式

每个请求的地址包含以下字段:

请求ID:

请求标识符,编码为可变长度整数。 这是该特定地址请求的标识符。 来自给定端点的每个请求都携带不同的标识符。 请求 ID不得被端点重用,并且不得为零。

IP版本:

此地址请求的 IP 版本,编码为无符号 8 位整数。 必须是4或6。

IP地址:

请求的 IP 地址。 如果IP版本字段的值为4,则IP地址字段的长度为32位。 如果 IP 版本字段的值为 6,则 IP 地址字段的长度为 128 位。

IP 前缀长度:

请求的 IP 前缀长度(以位为单位),编码为无符号 8 位整数。 必须小于或等于IP 地址字段的长度(以位为单位)。 如果前缀长度严格小于 IP 地址长度(以位为单位),则前缀长度未覆盖的 IP 地址字段的低位必须全部设置为 0。

如果 IP 地址全为零(0.0.0.0 或 ::),则表示发送方正在请求该地址族的地址,但对特定地址没有偏好。 在这种情况下,前缀长度仍然表明发送者对其请求的前缀长度的偏好。

如果任何胶囊字段在接收时格式错误,则胶囊的接收者必须遵循[HTTP的第3.3节中定义的错误处理过程-DGRAM].

收到 ADDRESS_REQUEST 胶囊后,端点应该为其对等点分配一个或多个 IP 地址,然后使用 ADDRESS_ASSIGN 胶囊进行响应,以通知对等点分配情况。 对于每个请求的地址,ADDRESS_REQUEST 胶囊的接收者应当使用具有匹配请求 ID 的分配地址进行响应。 如果请求的地址已分配,则分配地址响应中的 IP 地址和 IP 前缀长度字段应设置为分配的值。 如果未分配请求的地址,则 IP 地址全为零,并且 IP 前缀长度为最大长度(0.0.0.0/32 或 :: /128) 表示没有分配地址。 这些地址拒绝不应该包含在后续的 ADDRESS_ASSIGN 胶囊中。 请注意,不对应于任何请求 ID 的其他分配地址条目也可以包含在同一 ADDRESS_ASSIGN 响应中。

如果端点收到包含零个请求地址的 ADDRESS_REQUEST 胶囊,则它必须中止 IP 代理请求流。

请注意,请求地址的顺序不携带任何语义。 同样,Request ID 仅意味着唯一标识符;它不传达任何优先级或重要性。

4.7.3. ROUTE_ADVERTISMENT 胶囊

ROUTE_ADVERTISMENT 胶囊(胶囊类型 0x03)允许端点与其对等方进行通信,表示它愿意将流量路由到一组 IP 地址范围。 这表明发送方具有到每个地址范围的现有路由,并通知其对等方,如果 ROUTE_ADVERTISMENT 胶囊的接收方在 HTTP 数据报中发送这些范围之一的 IP 数据包,则胶囊的发送方将沿着其预先存在的路线转发它们。 地址范围之一中的任何地址都可以用作由该胶囊的接收者发起的 IP 数据包的目标地址。

ROUTE_ADVERTISEMENT Capsule {
  Type (i) = 0x03,
  Length (i),
  IP Address Range (..) ...,
}
图11:ROUTE_ADVERTISMENT胶囊格式

ROUTE_ADVERTISMENT 胶囊包含零个或多个 IP 地址范围的序列。

IP Address Range {
  IP Version (8),
  Start IP Address (32..128),
  End IP Address (32..128),
  IP Protocol (8),
}
图12:IP地址范围格式

每个 IP 地址范围包含以下字段:

IP版本:

此范围的 IP 版本,编码为无符号 8 位整数。 必须是4或6。

起始IP地址和结束IP地址:

包含通告范围的起始和结束 IP 地址。 如果 IP 版本字段的值为 4,则这些字段的长度为 32 位。 如果IP版本字段的值为6,则这些字段的长度为128位。 起始 IP 地址必须小于或等于结束 IP 地址。

IP协议:

可以发送到此范围的流量的互联网协议号,编码为无符号 8 位整数。 如果值为 0,则允许所有协议。 如果该值不为 0,则表示直接在 HTTP 数据报(最外层 IP 标头)中发送的 IP 标头中携带的允许的下一个标头值。 无论该字段的值如何,始终允许 ICMP 流量。

如果任何胶囊字段在接收时格式错误,则胶囊的接收者必须遵循[HTTP的第3.3节中定义的错误处理过程-DGRAM].

收到 ROUTE_ADVERTISMENT 封装后,端点可以更新其对等方愿意路由的本地状态(受本地策略约束),例如通过在路由表中安装条目。

每个 ROUTE_ADVERTISMENT 包含地址范围的完整列表。 如果沿一个方向发送多个 ROUTE_ADVERTISMENT 胶囊,则每个 ROUTE_ADVERTISMENT 胶囊都会取代之前的胶囊。 换句话说,如果给定的地址范围存在于先前的胶囊中,但最近接收到的 ROUTE_ADVERTISMENT 胶囊不包含该地址范围,则接收方将认为该范围已撤回。

如果使用相同 IP 协议的多个范围重叠,某些路由表实现可能会拒绝它们。 为了防止重叠,范围是有序的;这给发送者带来了负担,并使接收者的验证变得更加简单。 如果同一 ROUTE_ADVERTISMENT 封装中 IP 地址范围 A 位于 IP 地址范围 B 之前,则它们必须遵循以下要求:

  • A 的 IP 版本必须小于或等于 B 的 IP 版本。
  • 如果 A 和 B 的 IP 版本相同,则 A 的 IP 协议必须小于或等于 B 的 IP 协议。
  • 如果 A 和 B 的 IP 版本和 IP 协议都相同,则 A 的结束 IP 地址必须严格小于 B 的起始 IP 地址。

如果端点收到不满足这些要求的 ROUTE_ADVERTISMENT 封装,它必须中止 IP 代理请求流。

由于将 IP 协议设置为零表示允许所有协议,因此当一个将其 IP 协议设置为零而另一个将其设置为非零时,上述要求使得两条路由可能重叠。 端点不得发送具有以这种方式重叠的路由的ROUTE_ADVERTISMENT胶囊。 验证此要求是可选,但如果端点检测到违规,它必须中止 IP 代理请求流。

4.8. IPv6 扩展标头

请求范围界定(请参阅 Section 4.6)和 ROUTE_ADVERTISEMENT 胶囊(请参阅 Section 4.7.3)都使用 Internet 协议编号。 这些数字代表上层(如 [IPv6] 的第 2 节 中定义,示例包括 TCP 和 UDP)和 IPv6 扩展标头(如 [IPv6] 的第 4 节 中所定义,其中包含片段和选项标头的示例)。 IP 代理可以拒绝范围为用于扩展标头的协议号的请求。 收到数据包后,支持按 Internet 协议号确定范围或路由的实现必须遍历扩展链,找到最外层的非扩展 Internet 协议号以与范围规则进行匹配。 请注意,ROUTE_ADVERTISMENT 胶囊使用 Internet 协议号 0 来指示允许所有协议;它不限制到 IPv6 逐跳选项标头的路由([IPv6] 的第 4.3 节)。

5. 上下文标识符

本文档中定义的 HTTP 代理 IP 机制允许未来的扩展交换携带与 IP 有效负载不同语义的 HTTP 数据报。 其中一些扩展可以使用附加数据来增强 IP 有效负载或压缩 IP 标头字段,而其他扩展则可以交换与 IP 有效负载完全分离的数据。 为了实现这一点,与 IP 代理请求流关联的所有 HTTP 数据报都以上下文 ID 字段开头;请参阅第 6 节

上下文 ID 是 62 位整数(0 到 262-1)。 上下文 ID 被编码为可变长度整数;请参阅 [QUIC] 的第 16 节 上下文 ID 值 0 是为 IP 有效负载保留的,而非零值是动态分配的。 非零偶数上下文 ID 是客户端分配的,奇数上下文 ID 是代理分配的。 Context ID 命名空间与给定的 HTTP 请求相关联;具有相同数值的上下文 ID 可以同时分配在不同的请求中,并且可能具有不同的语义。 上下文 ID不得在给定的 HTTP 请求中重新分配,但可以以任何顺序分配。 存在对使用偶数编号和奇数编号上下文 ID 的上下文 ID 分配限制,以避免端点之间的同步需要。 然而,一旦分配了 Context ID,这些限制就不适用于 Context ID 的使用;它可以由客户端或 IP 代理使用,与最初分配它的端点无关。

注册是端点向其对等方通知给定上下文 ID 的语义和格式的操作。 本文档没有定义如何进行注册。 未来的扩展可以使用HTTP标头字段或胶囊来注册上下文ID。 根据所使用的方法,可能会接收带有尚未注册的上下文 ID 的数据报。 例如,这可能是由于在传输过程中包含数据报的数据包和包含注册消息的数据包重新排序所致。

6. HTTP 数据报负载格式

当与 IP 代理请求流关联时,HTTP 数据报的 HTTP 数据报负载字段(参见 [HTTP-DGRAM])具有图 13 中定义的格式t2>。 请注意,当使用 QUIC DATAGRAM 帧对 HTTP 数据报进行编码时,下面定义的上下文 ID 字段直接位于 QUIC DATAGRAM 帧有效负载开头的四分之一流 ID 字段之后:

IP Proxying HTTP Datagram Payload {
  Context ID (i),
  Payload (..),
}
图 13:IP 代理 HTTP 数据报格式

IP 代理 HTTP 数据报负载包含以下字段:

上下文 ID:

包含上下文 ID 值的可变长度整数。 如果接收到携带未知上下文 ID 的 HTTP/3 数据报,接收方应当默默地丢弃该数据报,或者在等待相应的注册时临时缓冲它(按往返顺序)上下文 ID。

有效负载:

数据报的有效负载,其语义取决于前一个字段的值。 请注意,该字段可以为空。

IP 数据包使用 HTTP 数据报进行编码,上下文 ID 设置为零。 当上下文 ID 设置为零时,有效负载字段包含完整的 IP 数据包(从 IP 版本字段直到 IP 有效负载的最后一个字节)。

7. IP 数据包处理

本文档定义了一种隧道机制,概念上是 IP 链路。 但是,由于链接附加到 IP 路由器,因此如果实现不将 IP 路由器的某些职责委托给其他实现(例如内核),则它们可能需要处理这些职责。

7.2. 路由操作

本节中的要求是一般适用于 IP 路由器的要求的重复,可能不适用于依赖外部软件进行路由的 IP 代理的实现。

当端点收到包含 IP 数据包的 HTTP 数据报时,它将解析数据包的 IP 标头,执行任何本地策略检查(例如源地址验证),检查其路由表以选择出站接口,然后将 IP 数据包发送到该接口或将其传递给本地应用程序。 端点还可以选择丢弃任何收到的数据包而不是转发它们。 如果收到的 IP 数据包未通过任何正确性或策略检查,则就 IP 代理而言,这是转发错误,而不是协议违规;请参见第 7.2.1 节 IP 代理端点可以对其转发的 IP 数据包实施额外的过滤策略。

另一方面,当端点接收到 IP 数据包时,它会检查该数据包是否与 IP 隧道映射的路由匹配,并在通过 HTTP 数据报传输数据包之前执行与上述相同的转发检查。

当 IP 代理端点在不同链路之间转发 IP 数据包时,它们将在封装时减少 IP 跳数(或 TTL),但在解封装时不会减少。 换句话说,跳数在 IP 数据包在 HTTP 数据报中传输之前递减。 这可以防止存在路由循环时出现无限循环,并与 IPsec [IPSEC] 中的选择相匹配。 这不适用于 IP 代理端点本身生成的 IP 数据包。

实施者需要确保他们不会将任何链路本地流量转发到接收该流量的 IP 代理接口之外。 IP 代理端点还需要正确回复发往链路本地多播地址的数据包。

IPv6 要求每个链路的 MTU 至少为 1280 字节[IPv6] 由于 HTTP 中的 IP 代理以 HTTP 数据报的形式传送 IP 数据包,而这些数据包又可以以无法分段的 QUIC DATAGRAM 帧的形式发送 [DGRAM],因此 IP 隧道的 MTU可能受到 IP 代理运行所用的 QUIC 连接的 MTU 的限制。 这可能会导致违反 IPv6 最小链路 MTU 的情况。 作为路由器运行并支持 IPv6 的 IP 代理端点必须确保 IP 隧道链路 MTU 至少为 1280 字节(即,它们可以发送有效负载至少为 1280 字节的 HTTP 数据报)。 这可以使用各种技术来完成:

  • 如果两个 IP 代理端点都确定未使用 HTTP 中介,则端点可以填充 IP 代理运行的外部 QUIC 连接的 QUIC INITIAL 数据包。 (假设使用 QUIC 版本 1,类型开销为 1 个字节,最大连接 ID 长度为 20 个字节,最大数据包编号长度为 4 个字节,DATAGRAM 帧类型为 1 个字节,最大 Quarter 为 8 个字节流 ID,1 个字节用于零上下文 ID,16 个字节用于关联数据验证加密 (AEAD) 身份验证标记,总共 51 个字节的开销,相当于将 QUIC INITIAL 数据包填充到 1331 个字节或更多。)
  • IP 代理端点还可以发送带有 1232 字节数据的 ICMPv6 回显请求,以确定链路 MTU,并在未收到响应时拆除隧道。 除非端点有带外方法来保证以前的技术足够,否则它们必须使用此方法。 如果端点不知道其对等方的 IPv6 地址,它可以将 ICMPv6 echo 请求发送到链路本地所有节点多播地址 (ff02::1)。

如果端点使用 QUIC DATAGRAM 帧来传送 IPv6 数据包,并且检测到 QUIC MTU 太低而无法发送 1280 字节,则它必须中止 IP 代理请求流。

7.2.1. 错误信号

由于 IP 代理端点经常将 IP 数据包转发到其他网络接口,因此它们需要处理转发过程中的错误。 例如,如果端点没有目标地址的路由、配置为通过策略拒绝目标前缀、或者传出链路的 MTU 低于要转发的数据包的大小,则转发可能会失败。 在这种情况下,IP 代理端点应该使用 ICMP [ICMP] [ICMPv6] 通过生成 ICMP 数据包并使用 HTTP 数据报发送它们来向其对等方发出转发错误信号。

端点可以自由选择最合适的 ICMP 错误来发送。 与 IP 代理相关的一些示例包括:

  • 对于无效源地址,请发送“目标无法到达”([ICMPv6] 的第 3.1 节),并包含代码 5“源地址入口/出口策略失败” .
  • 对于无法路由的目标地址,请发送“无法到达目标”([ICMPv6] 的第 3.1 节),并包含代码 0、“没有到目标的路由”或代码1、“行政禁止与目的地的通信”。
  • 对于无法容纳在传出链路的 MTU 范围内的数据包,请发送数据包太大([ICMPv6] 的第 3.2 节)。

为了接收这些错误,端点需要准备好接收 ICMP 数据包。 如果端点不发送 ROUTE_ADVERTISEMENT 胶囊,例如客户端通过 IP 代理打开 IP 流,则 SHOULD 处理来自其对等设备的代理 ICMP 数据包,以便接收这些错误。 请注意,ICMP 消息可以源自与 IP 代理对等方不同的源地址,如果正在使用作用域,也可以源自目标外部(请参阅第 4.6 节)。

8. 示例

HTTP 中的 IP 代理支持许多不同的用例,这些用例可以从 IP 数据包代理和隧道中受益。 提供这些示例是为了帮助说明在 HTTP 中使用 IP 代理的一些方法。

8.1. 远程访问VPN

以下示例显示了点到网络 VPN 设置,其中客户端接收一组本地地址,并可以通过 IP 代理发送到任何远程主机。 此类 VPN 设置可以是全隧道或分割隧道。

IP A IP B IP D IP IP C Client IP Subnet C ? Proxy IP E IP ...
图 14:VPN 隧道设置

在这种情况下,客户端不会在其请求中指定任何范围。 IP代理为客户端分配IPv4地址(192.0.2.11)和所有IPv4地址的全隧道路由(0.0.0.0/0)。 然后,客户端可以使用其分配的地址作为源地址发送到任何 IPv4 主机。

[[ From Client ]]             [[ From IP Proxy ]]

SETTINGS
  H3_DATAGRAM = 1

                              SETTINGS
                                ENABLE_CONNECT_PROTOCOL = 1
                                H3_DATAGRAM = 1

STREAM(44): HEADERS
:method = CONNECT
:protocol = connect-ip
:scheme = https
:path = /vpn
:authority = proxy.example.com
capsule-protocol = ?1

                              STREAM(44): HEADERS
                              :status = 200
                              capsule-protocol = ?1

STREAM(44): DATA
Capsule Type = ADDRESS_REQUEST
(Request ID = 1
 IP Version = 4
 IP Address = 0.0.0.0
 IP Prefix Length = 32)

                              STREAM(44): DATA
                              Capsule Type = ADDRESS_ASSIGN
                              (Request ID = 1
                               IP Version = 4
                               IP Address = 192.0.2.11
                               IP Prefix Length = 32)

                              STREAM(44): DATA
                              Capsule Type = ROUTE_ADVERTISEMENT
                              (IP Version = 4
                               Start IP Address = 0.0.0.0
                               End IP Address = 255.255.255.255
                               IP Protocol = 0) // Any

DATAGRAM
Quarter Stream ID = 11
Context ID = 0
Payload = Encapsulated IP Packet

                              DATAGRAM
                              Quarter Stream ID = 11
                              Context ID = 0
                              Payload = Encapsulated IP Packet
图 15:VPN 全隧道示例

分割隧道 VPN(客户端只能访问一组特定的私有子网的情况)的设置非常相似。 在这种情况下,通告的路由被限制为 192.0.2.0/24,而不是 0.0.0.0/0。

[[ From Client ]]             [[ From IP Proxy ]]

                              STREAM(44): DATA
                              Capsule Type = ADDRESS_ASSIGN
                              (Request ID = 0
                               IP Version = 4
                               IP Address = 192.0.2.42
                               IP Prefix Length = 32)

                              STREAM(44): DATA
                              Capsule Type = ROUTE_ADVERTISEMENT
                              (IP Version = 4
                               Start IP Address = 192.0.2.0
                               End IP Address = 192.0.2.41
                               IP Protocol = 0) // Any
                              (IP Version = 4
                               Start IP Address = 192.0.2.43
                               End IP Address = 192.0.2.255
                               IP Protocol = 0) // Any
图 16:VPN 分割隧道示例

8.2. 站点到站点 VPN

以下示例演示如何将分支机构网络连接到公司网络,以便这些网络上的所有计算机都可以进行通信。 在此示例中,IP 代理客户端连接到分支机构网络 192.0.2.0/24,IP 代理连接到公司网络 203.0.113.0/24。 分支机构网络上的旧客户端仅允许来自其子网中的计算机的维护请求,因此使用该子网中的 IP 地址配置 IP 代理。

192.0.2.1 203.0.113.9 IP 192.0.2.2 Client IP Proxying Proxy 203.0.113.8 192.0.2.3 203.0.113.7
图 17:站点到站点 VPN 示例

在这种情况下,客户端不会在其请求中指定任何范围。 IP 代理为客户端分配 IPv4 地址 (203.0.113.100) 和到公司网络 (203.0.113.0/24) 的分割隧道路由。 客户端为 IP 代理分配 IPv4 地址 (192.0.2.200) 和到分支机构网络 (192.0.2.0/24) 的分割隧道路由。 这允许两个网络上的主机相互通信,并允许 IP 代理对分支机构中的旧主机执行维护。 请注意,IP 代理端点在封装转发的数据包时将减少 IP 跳数(或 TTL),因此需要将该字段设置为 255 的协议将无法运行。

[[ From Client ]]             [[ From IP Proxy ]]

SETTINGS
  H3_DATAGRAM = 1

                              SETTINGS
                                ENABLE_CONNECT_PROTOCOL = 1
                                H3_DATAGRAM = 1

STREAM(44): HEADERS
:method = CONNECT
:protocol = connect-ip
:scheme = https
:path = /corp
:authority = proxy.example.com
capsule-protocol = ?1

                              STREAM(44): HEADERS
                              :status = 200
                              capsule-protocol = ?1

STREAM(44): DATA
Capsule Type = ADDRESS_ASSIGN
(Request ID = 0
IP Version = 4
IP Address = 192.0.2.200
IP Prefix Length = 32)

STREAM(44): DATA
Capsule Type = ROUTE_ADVERTISEMENT
(IP Version = 4
Start IP Address = 192.0.2.0
End IP Address = 192.0.2.255
IP Protocol = 0) // Any

                              STREAM(44): DATA
                              Capsule Type = ADDRESS_ASSIGN
                              (Request ID = 0
                               IP Version = 4
                               IP Address = 203.0.113.100
                               IP Prefix Length = 32)

                              STREAM(44): DATA
                              Capsule Type = ROUTE_ADVERTISEMENT
                              (IP Version = 4
                               Start IP Address = 203.0.113.0
                               End IP Address = 203.0.113.255
                               IP Protocol = 0) // Any

DATAGRAM
Quarter Stream ID = 11
Context ID = 0
Payload = Encapsulated IP Packet

                              DATAGRAM
                              Quarter Stream ID = 11
                              Context ID = 0
                              Payload = Encapsulated IP Packet
图 18:站点到站点 VPN 胶囊示例

8.3. IP流转发

以下示例显示了 IP 流转发设置,其中客户端请求使用流控制传输协议 (SCTP)(IP 协议 132)建立到 target.example.com 的转发隧道,并接收单个本地地址和远程地址用于传输数据包。 类似的方法可用于任何其他不易通过现有 HTTP 方法代理的 IP 协议,例如 ICMP、封装安全负载 (ESP) 等。

IP A IP B IP IP C Client IP C D Proxy IP D
图 19:代理流设置

在这种情况下,客户端在其请求范围内指定目标主机名和互联网协议号,表明它只需要与单个主机通信。 IP代理能够代表客户端执行DNS解析,并为客户端分配特定的出站套接字,而不是为客户端分配整个IP地址。 在这方面,该请求与常规 CONNECT 代理请求类似。

IP 代理将单个 IPv6 地址分配给客户端 (2001:db8:1234::a),并为 SCTP 范围内的单个 IPv6 主机 (2001:db8:3456::b) 分配路由。 客户端可以向远程主机发送和接收 SCTP IP 数据包。

[[ From Client ]]             [[ From IP Proxy ]]

SETTINGS
  H3_DATAGRAM = 1

                              SETTINGS
                                ENABLE_CONNECT_PROTOCOL = 1
                                H3_DATAGRAM = 1

STREAM(44): HEADERS
:method = CONNECT
:protocol = connect-ip
:scheme = https
:path = /proxy?target=target.example.com&ipproto=132
:authority = proxy.example.com
capsule-protocol = ?1

                              STREAM(44): HEADERS
                              :status = 200
                              capsule-protocol = ?1

                              STREAM(44): DATA
                              Capsule Type = ADDRESS_ASSIGN
                              (Request ID = 0
                               IP Version = 6
                               IP Address = 2001:db8:1234::a
                               IP Prefix Length = 128)

                              STREAM(44): DATA
                              Capsule Type = ROUTE_ADVERTISEMENT
                              (IP Version = 6
                               Start IP Address = 2001:db8:3456::b
                               End IP Address = 2001:db8:3456::b
                               IP Protocol = 132)

DATAGRAM
Quarter Stream ID = 11
Context ID = 0
Payload = Encapsulated SCTP/IP Packet

                              DATAGRAM
                              Quarter Stream ID = 11
                              Context ID = 0
                              Payload = Encapsulated SCTP/IP Packet
图 20:代理 SCTP 流程示例

8.4. 代理连接竞赛

以下示例显示了客户端通过 IP 代理代理 UDP 数据包的设置,以便通过 IP 代理控制连接建立竞赛,如 Happy Eyeballs [HEv2] 中所定义>。 此示例是代理流的变体,但重点介绍了 IP 级代理如何启用新功能,甚至对于 TCP 和 UDP 也是如此。

IP A IP B IP C IP E Client IP C E IP D F Proxy IP F IP D
图 21:代理连接赛车设置

与代理流一样,客户端在其请求范围内指定目标主机名和 Internet 协议号。 当 IP 代理代表客户端执行 DNS 解析时,它可以将各种远程地址选项作为单独的路由发送到客户端。 它还可以确保客户端同时分配了 IPv4 和 IPv6 地址。

IP代理为客户端分配IPv4地址(192.0.2.3)和IPv6地址(2001:db8:1234::a),以及IPv4路由(198.51.100.2)和IPv6路由(2001:db8) :3456::b),表示目标主机名的解析地址,范围为 UDP。 客户端可以向任一 IP 代理地址发送和接收 UDP IP 数据包,以通过 IP 代理启用 Happy Eyeballs。

[[ From Client ]]             [[ From IP Proxy ]]

SETTINGS
  H3_DATAGRAM = 1

                              SETTINGS
                                ENABLE_CONNECT_PROTOCOL = 1
                                H3_DATAGRAM = 1

STREAM(44): HEADERS
:method = CONNECT
:protocol = connect-ip
:scheme = https
:path = /proxy?target=target.example.com&ipproto=17
:authority = proxy.example.com
capsule-protocol = ?1

                              STREAM(44): HEADERS
                              :status = 200
                              capsule-protocol = ?1

                              STREAM(44): DATA
                              Capsule Type = ADDRESS_ASSIGN
                              (Request ID = 0
                               IP Version = 4
                               IP Address = 192.0.2.3
                               IP Prefix Length = 32),
                              (Request ID = 0
                               IP Version = 6
                               IP Address = 2001:db8::1234:1234
                               IP Prefix Length = 128)

                              STREAM(44): DATA
                              Capsule Type = ROUTE_ADVERTISEMENT
                              (IP Version = 4
                               Start IP Address = 198.51.100.2
                               End IP Address = 198.51.100.2
                               IP Protocol = 17),
                              (IP Version = 6
                               Start IP Address = 2001:db8:3456::b
                               End IP Address = 2001:db8:3456::b
                               IP Protocol = 17)
...

DATAGRAM
Quarter Stream ID = 11
Context ID = 0
Payload = Encapsulated IPv6 Packet

DATAGRAM
Quarter Stream ID = 11
Context ID = 0
Payload = Encapsulated IPv4 Packet

图 22:代理连接竞赛示例

9. 可扩展性注意事项

HTTP 中 IP 代理的扩展可以定义对此机制的行为更改。 此类扩展应该定义新的胶囊类型以在需要时交换配置信息。 对于修改寻址的扩展,建议指定其扩展胶囊在 ADDRESS_ASSIGN 胶囊之前发送,并且在解析 ADDRESS_ASSIGN 胶囊之前它们不会生效。 这允许对地址分配的修改以原子方式操作。 类似地,修改路由的扩展应该对于 ROUTE_ADVERTISMENT 胶囊的行为类似。

10. 性能注意事项

突发流量通常会导致时间相关的数据包丢失;反过来,这可能会导致隧道内运行的协议中的拥塞控制器的响应不理想。 为了避免这种情况,IP 代理端点应该努力避免增加 IP 流量的突发性;他们不应该对数据包进行排队,以便将批处理增加到超出利用硬件卸载所需的最小数量。

当隧道内运行的协议使用拥塞控制时(例如,[TCP][QUIC]),代理流量将产生至少两个嵌套的拥塞控制器。 当使用 QUIC DATAGRAM 帧发送隧道数据包时,外部 HTTP 连接可以对那些仅包含封装 IP 数据包的 QUIC DATAGRAM 帧的数据包禁用拥塞控制。 实施者将受益于阅读 [UDP-USAGE]第 3.1.11 节中的指南。

当隧道内运行的协议使用损失恢复时(例如,[TCP][QUIC])并且外部HTTP连接运行在TCP上,代理流量将产生至少两个嵌套的损失恢复机制。 这会降低性能,因为两者有时可以独立地重新传输相同的数据。 为了避免这种情况,IP 代理应该通过 HTTP/3 执行,以允许利用 QUIC DATAGRAM 帧。

10.1. MTU 注意事项

当使用带有 QUIC 数据报扩展 [DGRAM] 的 HTTP/3 时,IP 数据包在 QUIC DATAGRAM 帧中传输。 由于这些帧无法分段,因此它们只能携带由 QUIC 连接配置和路径 MTU (PMTU) 确定的给定长度的数据包。 如果端点正在使用 QUIC DATAGRAM 帧,并且它尝试通过不适合 QUIC DATAGRAM 帧的隧道路由 IP 数据包,则 IP 代理不应该在 DATAGRAM 胶囊中发送 IP 数据包,因为这克服了数据报分组层 PMTU 发现 (DPLPMTUD) 等方法依赖于 [DPLPMTUD] 的端到端不可靠性特征。 在这种情况下,端点应该丢弃IP数据包并向丢弃数据包的发送者发送一条ICMP数据包太大消息;请参阅 [ICMPv6] 的第 3.2 节

10.2. ECN注意事项

如果具有包含 IP 代理请求流的连接的 IP 代理端点禁用拥塞控制,则它无法在该外部连接上发出显式拥塞通知 (ECN) [ECN] 支持信号。 也就是说,QUIC 发送方必须为超出拥塞控制的 QUIC 数据包使用不支持 ECN 的传输 (Not-ECT) 代码点标记所有 IP 标头。 端点仍然可以通过 QUIC ACK_ECN 帧或 TCP ECN-Echo (ECE) 位报告 ECN 反馈,因为对等方可能没有禁用拥塞控制。

相反,如果未对外部拥塞禁用拥塞控制,则 [ECN-TUNNEL] 中有关在内部和外部 IP 标头之间传输 ECN 标记的指南不适用,因为如果外部连接使用 ECN,它将对拥塞通知做出正确反应。 内部流量也可以使用 ECN,无论其是否在外部连接上使用。

10.3. 差异化服务注意事项

隧道 IP 数据包可以在流量类别 IP 标头字段中设置差分服务代码点 (DSCP) [DSCP],以请求特定的每跳行为。 如果 IP 代理端点配置为差异化服务域的一部分,它可以基于这些标记实现流量差异化。 但是,HTTP 的使用可能会限制对 IP 代理端点之间的路径上的隧道 IP 数据包进行差异化处理的可能性。

当 HTTP 连接受到拥塞控制时,使用不同的 DSCP 标记数据包可能会导致数据包之间重新排序,进而导致底层传输连接的拥塞控制器性能不佳。 如果隧道数据包受到外部连接的拥塞控制,则它们需要避免携带转发行为不等效的 DSCP 标记,以防止这种情况。 在这种情况下,IP 代理端点不得将 DSCP 字段从内部 IP 标头复制到携带此数据包的数据包的外部 IP 标头。 相反,应用程序需要使用与代理的单独连接,每个 DSCP 一个连接。 请注意,本文档没有定义将请求范围限定为特定 DSCP 值的方法;这种支持留给未来的扩展。

如果隧道数据包使用 QUIC 数据报并且不受外部连接的拥塞控制,则 IP 代理端点可以将 DSCP 字段值从隧道流量转换为外部 IP 标头。 IP 代理端点不得将多个内部数据包合并为同一个外部数据包,除非它们具有相同的 DSCP 标记或等效的流量类别。 请注意,转换 DSCP 值的能力取决于隧道入口和出口是否属于同一差分服务域。

11. 安全注意事项

允许任意客户端建立允许发送到任意主机的隧道存在重大风险,无论隧道的范围是否限于特定主机。 不良行为者可能会滥用此功能来发送流量并将其归因于 IP 代理。 支持 IP 代理的 HTTP 服务器应该将其使用限制为经过身份验证的用户。 根据部署的不同,可能的身份验证机制包括 IP 代理端点之间的相互 TLS、通过 HTTP 授权标头 [HTTP] 进行的基于 HTTP 的身份验证,甚至不记名 Token 。 代理可以对经过身份验证的用户实施策略,以进一步限制客户端行为或处理可能的滥用行为。 例如,代理可以对通过代理发送过多流量的单个客户端进行速率限制。 另一个例子,代理可以根据某些客户端属性(例如地理位置)限制对客户端的地址(前缀)分配。

地址分配可能会对端点产生隐私影响。 例如,如果代理按经过身份验证的客户端数量划分其地址空间,然后为每个客户端分配不同的地址范围,则目标主机可以使用此信息来确定 IP 数据包何时对应于同一客户端。 避免此类跟踪向量对于某些代理部署可能很重要。 代理应该尽可能避免持久的每个客户端地址(前缀)分配。

在发送的流量中伪造 IP 源地址对于拒绝服务攻击来说很常见。 该机制的实现需要确保它们不会促进此类攻击。 特别是,在某些情况下,端点知道其对等方仅允许从给定前缀发送 IP 数据包。 例如,这可以通过带外配置信息或通过 ADDRESS_ASSIGN 胶囊共享允许的前缀时发生。 在这种情况下,端点必须遵循[BCP38]的建议以防止源地址欺骗。

限制请求范围(请参阅第 4.6 节)允许两个客户端共享代理的外部 IP 地址之一(如果它们的请求范围为不同的 Internet 协议号)。 如果代理收到发往该外部 IP 地址的 ICMP 数据包,它可以选择将其转发回客户端。 但是,其中一些 ICMP 数据包携带触发 ICMP 响应的原始 IP 数据包的一部分。 转发此类数据包可能会意外地将一个客户端的流量信息泄露给另一客户端。 为了避免这种情况,在共享外部 IP 地址上转发 ICMP 的代理必须检查 ICMP 数据包中包含的调用数据包,并且仅将 ICMP 数据包转发到范围与调用数据包匹配的客户端。

实施者将受益于阅读[TUNNEL-SECURITY]中的指南。 由于某些 IPv6 扩展标头(例如 [ROUTING-HDR])存在已知风险,因此实施者需要遵循有关处理 IPv6 扩展标头的最新指南。

将 DSCP 标记从内部数据包传输到外部数据包(请参阅第 10.3 节)向 IP 代理端点之间的路径观察者公开端到端流级别信息。 这可能会暴露单个端到端流。 因此,不建议在隐私敏感环境中使用 DSCP

HTTP/1.x 中不允许机会性发送 IP 数据包(请参阅第 7.1 节),因为服务器可能会拒绝 HTTP 升级并尝试将 IP 数据包解析为后续 HTTP 请求,从而允许请求走私攻击;请参阅[乐观] 特别是,将请求从 HTTP/2 或 3 重新编码为 HTTP/1.1 的中介不得转发任何收到的胶囊,直到它解析成功的 IP 代理响应。

12. IANA 注意事项

12.1. HTTP升级词符注册

IANA 已在 <https://www.iana.org/assignments/http-upgrade-tokens> 维护的“HTTP 升级 Token ”注册表中注册了“connect-ip” >.

价值:

连接 IP

描述:

IP 负载代理

预期版本 Token :

参考:

RFC 9484

12.2. MASQUE URI 后缀注册表创建

IANA 已创建“MASQUE URI 后缀”注册表,维护位置为 <https://www.iana.org/assignments/masque> 注册政策为专家评审;请参阅 [IANA 政策] 的第 4.5 节 这个新的注册表管理以“/.well-known/masque/”开头的路径中紧随“masque”之后的路径段;请参阅 <https://www.iana.org/assignments/well-known-uris> 了解“masque”在“众所周知的 URI”注册表中的注册.

这个新注册表包含三列:

路径段:

仅包含标记中允许的字符的 ASCII 字符串;请参阅 [HTTP] 的第 5.6.2 节 此注册表中的条目必须在此列中都有不同的条目。

描述:

条目的描述。

参考:

定义条目用途的可选参考。

注册表的初始条目如下:

Table 1: MASQUE URI Suffixes Registry
Path Segment Description Reference
udp UDP Proxying RFC 9298
ip IP Proxying RFC 9484

建议该注册机构的指定专家,只要专家认为 (1) 所请求的路径段不会与现有或预期的未来 IETF 工作相冲突,并且 (2) 用例与代理相关,他们就应该批准所有请求。

12.3. 更新 masque 知名 URI 注册

IANA 已更新“众所周知的 URI”注册表中“masque”URI 后缀的条目,该注册表维护于 <https://www.iana.org/assignments/well-known-uris>.

IANA 已更新“参考”字段以包含本文档,并将“相关信息”字段替换为“有关子后缀分配,请参阅注册管理机构 <https://www.iana.org/作业/面具>。”。

12.4. HTTP 胶囊类型注册

IANA 已将以下值添加到 <https://www.iana.org/assignments/masque> 维护的“HTTP 胶囊类型”注册表中。

Table 2: New Capsules
Value Capsule Type
0x01 ADDRESS_ASSIGN
0x02 ADDRESS_REQUEST
0x03 ROUTE_ADVERTISEMENT

所有这些新条目都对这些字段使用以下值:

地位:

永久

参考:

RFC 9484

更改控制器:

IETF

接触:

masque@ietf.org

笔记:

13. 参考文献

13.1. 规范性参考文献

[ABNF]
克罗克,D.,埃德。 P。 Overell“语法规范的增强 BNF:ABNF”STD 68RFC 5234DOI 10.17487/RFC5234 <https://www.rfc-editor.org/info/rfc5234>
[BCP38]
弗格森,P. D。 Senie“网络入口过滤:击败采用 IP 源地址欺骗的拒绝服务攻击”BCP 38RFC 2827DOI 10.17487/RFC2827<https://www.rfc-editor.org/info/rfc2827>
[动态图]
保利,T., 金尼尔,E.,和D。 Schinazi“QUIC 的不可靠数据报扩展”RFC 9221DOI 10.17487/RFC9221,<https://www.rfc-editor.org/info/rfc9221>
[DSCP]
尼科尔斯,K., 布莱克,S., 贝克,F.,和D。 Black“IPv4 和 IPv6 标头中差异化服务字段(DS 字段)的定义”RFC 2474DOI 10.17487/RFC2474<https://www.rfc-editor.org/info/rfc2474>
[电子通讯]
拉马克里希南,K., 弗洛伊德,S.,和D。 Black“向 IP 添加显式拥塞通知 (ECN)”RFC 3168DOI 10.17487/RFC3168,<https://www.rfc-editor.org/info/rfc3168>
[外部连接2]
麦克马纳斯,P.“使用 HTTP/2 引导 WebSocket”RFC 8441DOI 10.17487/RFC8441<https://www.rfc-editor.org/info/rfc8441>
[外部连接3]
汉密尔顿,R.“使用 HTTP/3 引导 WebSocket”RFC 9220DOI 10.17487/RFC9220<https://www.rfc-editor.org/info/rfc9220>
[HTTP]
菲尔丁,R.,埃德。, 诺丁汉,M.,埃德。, 和 J.雷施克,埃德。“HTTP 语义”STD 97RFC 9110DOI 10.17487/RFC9110,<https://www.rfc-editor.org/info/rfc9110>
[HTTP-DGRAM]
斯奇纳齐,D. L。 Pardue“HTTP 数据报和胶囊协议”RFC 9297DOI 10.17487/RFC9297,<https://www.rfc-editor.org/info/rfc9297>
[HTTP/1.1]
菲尔丁,R.,埃德。, 诺丁汉,M.,埃德。, 和 J.雷施克,埃德。“HTTP/1.1”STD 99RFC 9112DOI 10.17487/RFC9112,<https://www.rfc-editor.org/info/rfc9112>
[HTTP/2]
汤姆森,M.,埃德。 C.本菲尔德,埃德。“HTTP/2”RFC 9113DOI 10.17487/RFC9113< https://www.rfc-editor.org/info/rfc9113>
[HTTP/3]
主教,M.,埃德。“HTTP/3”RFC 9114DOI 10.17487/RFC9114< https://www.rfc-editor.org/info/rfc9114>
[IANA 政策]
科顿,M., 莱巴,B.,和T。 Narten“在 RFC 中编写 IANA 注意事项部分的指南”BCP 26RFC 8126DOI 10.17487 /RFC8126,,<https://www.rfc-editor.org/info/rfc8126>
[ICMP]
波斯特尔,J.“互联网控制消息协议”STD 5RFC 792DOI 10.17487/RFC0792,<https://www.rfc-editor.org/info/rfc792>
[ICMPv6]
孔塔,A., 迪林,S., 和 M.古普塔,埃德。“互联网协议版本 6 (IPv6) 规范的互联网控制消息协议 (ICMPv6)”STD 89RFC 4443DOI 10.17487/RFC4443,,<https://www.rfc-editor.org/info/rfc4443>
[IPv6]
迪林,S. R。 Hinden“互联网协议版本 6 (IPv6) 规范”STD 86RFC 8200DOI 10.17487 /RFC8200,,<https://www.rfc-editor.org/info/rfc8200>
[IPv6 区域 ID]
卡彭特,B., 柴郡,S.,和R。 Hinden“在地址文字和统一资源标识符中表示 IPv6 区域标识符”RFC 6874DOI 10.17487/RFC6874,<https://www.rfc-editor.org/info/rfc6874>
[代理状态]
诺丁汉,M. P。 Sikora“代理状态 HTTP 响应标头字段”RFC 9209DOI 10.17487/RFC9209,<https://www.rfc-editor.org/info/rfc9209>
[快速]
艾扬格,J.,埃德。 M.汤姆森,埃德。“QUIC:基于 UDP 的多路复用安全传输”RFC 9000DOI 10.17487/RFC9000
[RFC2119]
布拉德纳,S.“RFC 中用于指示需求级别的关键字”BCP 14RFC 2119DOI 10.17487/RFC2119 t3>、<https://www.rfc-editor.org/info/rfc2119>
[RFC8174]
莱巴,B.“RFC 2119 关键字中大写与小写的歧义”BCP 14RFC 8174DOI 10.17487/RFC8174<https://www.rfc-editor.org/info/rfc8174>
[TCP]
艾迪,W.,埃德。“传输控制协议 (TCP)”STD 7RFC 9293DOI 10.17487/RFC9293,<https://www.rfc-editor.org/info/rfc9293>
[模板]
格雷戈里奥,J., 菲尔丁,R., 哈德利,M., 诺丁汉,M.,和D。 Orchard“URI 模板”RFC 6570DOI 10.17487/RFC6570<https://www.rfc-editor.org/info/rfc6570>
[统一资源定位符]
伯纳斯-李,T., 菲尔丁,R.,和L。 Masinter“统一资源标识符 (URI):通用语法”STD 66RFC 3986DOI 10.17487 /RFC3986,,<https://www.rfc-editor.org/info/rfc3986>

13.2. 信息参考

[连接-UDP]
斯奇纳齐,D.“在 HTTP 中代理 UDP”RFC 9298DOI 10.17487/RFC9298 <https://www.rfc-editor.org/info/rfc9298>
[DPLPMTUD]
费尔赫斯特,G., 琼斯,T., 图克森,M., 龙格勒,I.,和T。 Völker“数据报传输的分组层路径 MTU 发现”RFC 8899DOI 10.17487/RFC8899,<https://www.rfc-editor.org/info/rfc8899>
[ECN-隧道]
布里斯科,B.“显式拥塞通知隧道”RFC 6040DOI 10.17487/RFC6040<https://www.rfc-editor.org/info/rfc6040>
[HEv2]
斯奇纳齐,D. T。 Pauly“Happy Eyeballs 版本 2:使用并发实现更好的连接”RFC 8305DOI 10.17487/RFC8305,<https://www.rfc-editor.org/info/rfc8305>
[IANA-PN]
IANA“协议号”<https://www.iana.org/assignments/protocol-numbers>
[IPSEC]
肯特,S. K。 Seo“互联网协议的安全架构”RFC 4301DOI 10.17487/RFC4301,<https://www.rfc-editor.org/info/rfc4301>
[IPv6-地址]
欣登,R. S。 Deering“IP 版本 6 寻址架构”RFC 4291DOI 10.17487/RFC4291,<https://www.rfc-editor.org/info/rfc4291>
[乐观的]
施瓦茨,B.M.“乐观使用 HTTP 升级的安全注意事项”正在进行中Internet 草案、draft-schwartz-httpbis-optimistic-upgrade-00 t2>、<https://datatracker.ietf.org/doc/html/draft-schwartz-httpbis-optimistic-upgrade-00 >
[代理请求]
切尔尼亚霍夫斯基,A., 麦考尔,D.,和D。 Schinazi“代理 IP 流量的 MASQUE 协议的要求”正在进行中互联网草案、draft-ietf-masque-ip -proxy-reqs-03,,<https://datatracker.ietf.org/doc/html/draft-ietf-masque-ip -proxy-reqs-03>
[路由-HDR]
艾布利,J., 萨沃拉,P.,和G。 Neville-Neil“IPv6 中弃用类型 0 路由标头”RFC 5095DOI 10.17487/RFC5095,<https://www.rfc-editor.org/info/rfc5095>
[隧道安全]
克里希南,S., 泰勒,D.,和J。 Hoagland“IP 隧道的安全问题”RFC 6169DOI 10.17487/RFC6169 t4>、<https://www.rfc-editor.org/info/rfc6169>
[UDP-使用]
埃格特,L., 费尔赫斯特,G.,和G。 Shepherd“UDP 使用指南”BCP 145RFC 8085DOI 10.17487/RFC8085,<https://www.rfc-editor.org/info/rfc8085>

致谢

该方法的设计灵感来自 MASQUE 工作组围绕 [PROXY-REQS] 的讨论。 作者要感谢这些讨论的参与者的反馈。 此外,Mike BishopLucas PardueAlejandro Sedeño 对该文档提供了宝贵的反馈。

客户端配置的大部分文本均基于 [CONNECT-UDP] 中的相应文本。

作者地址

汤米·保利(编辑)
苹果公司。
大卫·席纳兹
谷歌有限责任公司
1600 露天剧场大道
山景城,加利福尼亚州 94043
美国
亚历克斯·切尔尼亚霍夫斯基
谷歌有限责任公司
米娅·库勒温德
爱立信
马格努斯·韦斯特伦德
爱立信