RFC9484 HTTP中IP代理



状态: 建议标准
更多信息: 数据追踪| 知识产权| 信息页
组织: 互联网工程工作组(IETF)
RFC编号: 9484
分类: 标准追踪
出版时间: 2023年10月
国际标准期刊编号: 2070-1721
作者: T. Pauly, Ed.
Apple Inc.
D. Schinazi, A. Chernyakhovsky
Google LLC
M. Kühlewind, M. Westerlund
Ericsson

前言

本文是关于HTTP中IP代理的网络规范文档译文,尚未完成翻译,欢迎指正。

摘要

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

备忘状态

本文是互联网标准追踪文档。

本文产自互联网工程任务组(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特定代理的HTTP服务器来实现。此协议可用于多种场景,如远程接入VPN、站点到站点VPN、安全的点对点通信或通用数据包隧道化。

IP代理的操作方式与UDP代理 [CONNECT-UDP] 类似,代理本身通过一个绝对URL来标识,该URL可以包含流量的目的地。客户端使用URI模板 [TEMPLATE] 生成这些URL,详见第3节。

本协议通过使用HTTP数据报 [HTTP-DGRAM] 支持所有现有的HTTP版本。当使用HTTP/2 [HTTP/2] 或HTTP/3 [HTTP/3] 时,它使用HTTP扩展CONNECT,如 [EXT-CONNECT2] 和 [EXT-CONNECT3] 中所述。当使用HTTP/1.x [HTTP/1.1] 时,它使用HTTP Upgrade,如 [HTTP] 第7.8节所定义。

本文档更新了 [CONNECT-UDP],更改了 “masque” well-known URI;参见第12.3节。

2. 约定与定义

本文档中的关键词 “必须”, “必须 NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “应该”, “应该 NOT”, “推荐”, “NOT 推荐”, “可以”, 以及 “OPTIONAL”,当且仅当它们以全部大写字母出现时,应按照BCP 14 [RFC2119] [RFC8174] 中的描述进行解释。

在本文档中,我们使用术语"IP代理"来指代响应IP代理请求的HTTP服务器。术语"客户端"在HTTP意义上使用;客户端构造IP代理请求。如果在客户端和IP代理之间存在HTTP中间人(如 [HTTP] 第3.7节所定义),则在本文档中将其称为"中间人"。术语"IP代理端点"指代客户端和IP代理二者。

本文档使用 [QUIC] 中的术语。本文档定义协议类型时,定义格式使用 [QUIC] 第1.3节中的表示法。本规范使用 [QUIC] 第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模板 必须 为level 3模板或更低。

  • URI模板 必须 为绝对形式,且 必须 包含非空的scheme、authority和path组件。

  • URI模板的path组件 必须 以斜杠 “/” 开头。

  • 所有模板变量 必须 位于URI的path或query组件中。

  • URI模板 可以 包含 “target” 和 “ipproto” 两个变量,并 可以 包含其他变量。如果包含 “target” 或 “ipproto” 变量,其值 必须 不得为空。客户端可以使用 “*” 来表示通配符或无偏好值;参见第4.6节。

  • URI模板 必须 不得包含任何非ASCII Unicode字符,且 必须 仅包含0x21-0x7E范围内(含)的ASCII字符(注意,允许百分号编码;参见[URI] 第2.1节)。

  • 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隧道使用Capsule协议(参见[HTTP-DGRAM] 第3.2节),HTTP数据报采用第6节中定义的格式。

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

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

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

基于HTTP的IP代理 必须 通过TLS或QUIC加密,或其他等效的加密协议运行,以提供机密性、完整性和认证。

4.1. IP代理处理

收到IP代理请求后:

  • 如果接收方被配置为使用另一个HTTP服务器,它将充当中介,将请求转发到另一个HTTP服务器。注意,此类中间人可能需要重新编码请求,如果它们使用与接收请求时不同的HTTP版本进行转发,因为请求编码因版本而异(见下文)。

  • 否则,接收方将充当IP代理。IP代理可以选择拒绝IP代理请求。否则,它从从请求头重构出的URI中提取可选的 “target” 和 “ipproto” 变量,解码其百分号编码,并建立IP隧道。

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

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

成功的IP代理响应(如第4.3节和第4.5节所定义)表示IP代理已建立IP隧道并愿意代理IP载荷。除成功的IP代理响应外的任何响应都表示请求已失败;因此,客户端 必须 中止请求。

除成功的IP代理响应外,IP代理还可以发送capsules来分配地址并向客户端通告路由(第4.7节)。客户端也可以为网络到网络路由向IP代理分配地址并通告路由。

4.2. HTTP/1.1请求

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

  • 方法SHALL为 “GET”。

  • 请求SHALL包含单个Host头字段,其中包含IP代理的主机和可选端口。

  • 请求SHALL包含一个Connection头字段,值为 “Upgrade”(注意,此要求不区分大小写,依据 [HTTP] 第7.6.1节)。

  • 请求SHALL包含一个Upgrade头字段,值为 “connect-ip”。

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

例如,如果客户端配置了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状态码SHALL为101(Switching Protocols)。

  • 响应SHALL包含一个Connection头字段,值为 “Upgrade”(注意,此要求不区分大小写,依据 [HTTP] 第7.6.1节)。

  • 响应SHALL包含单个Upgrade头字段,值为 “connect-ip”。

  • 响应SHALL满足启动Capsule协议的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 Setting,如 [EXT-CONNECT2] 和 [EXT-CONNECT3] 所述,并且请求使用满足以下要求的HTTP伪头字段:

  • :method伪头字段SHALL为 “CONNECT”。

  • :protocol伪头字段SHALL为 “connect-ip”。

  • :authority伪头字段SHALL包含IP代理的authority。

  • :path和 :scheme伪头字段SHALL不得为空。它们的值SHALL包含完成URI模板扩展过程后URI模板中的scheme和path;参见第3节。URI模板中的变量可以确定请求的范围,例如请求全隧道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状态码SHALL在2xx(Successful)范围内。

  • 响应SHALL满足启动Capsule协议的HTTP响应的要求;参见[HTTP-DGRAM] 第3.2节。

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

例如,服务器可以回复如下:

HEADERS
:status = 200
capsule-protocol = ?1

图5:HTTP/2或HTTP/3响应示例

4.6. 限制请求范围

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

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

target:
变量 “target” 包含客户端希望代理数据包到达的特定主机的主机名或IP前缀。如果未指定 “target” 变量或其值为 “*",则客户端请求与任何允许的主机通信。“target” 支持使用DNS名称、IPv6前缀和IPv4前缀。注意,不支持IPv6作用域寻址区域标识符 [IPv6-ZONE-ID]。如果目标是IP前缀(IP地址可选地后跟百分号编码的斜杠,再后跟前缀长度(以位为单位)),则该请求仅支持单个IP版本。如果目标是主机名,则预期IP代理执行DNS解析以确定向客户端通告哪些路由。IP代理 应该 发送一个ROUTE_ADVERTISEMENT capsule,其中包含为所请求主机名解析到的、IP代理可访问的、且属于IP代理也发送了分配地址的地址族的所有地址的路由。
ipproto:
变量 “ipproto” 包含一个Internet协议编号;参见IANA “Assigned Internet Protocol Numbers” 注册表 [IANA-PN] 中定义的列表。如果存在,它指定客户端仅希望为此请求代理特定的IP协议。如果值为 “*",或者不包含该变量,则客户端请求使用任何IP协议。“ipproto” 变量中指示的IP协议表示在直接通过HTTP数据报发送的IP头部中携带的允许的下一个头部值(最外层IP头部)。无论此字段的值如何,ICMP流量始终被允许。

使用 [URI] 中的术语IPv6address、IPv4address和reg-name,“target” 和 “ipproto” 变量 必须 遵循图6中的格式,使用 [ABNF] 的表示法。此外:

  • 如果 “target” 包含IPv6字面量或前缀,冒号(”:")必须 进行百分号编码。例如,如果目标主机是 “2001:db8::42”,它将在URI中被编码为 “2001%3Adb8%3A%3A42”。

  • 如果存在,“target” 中的IP前缀长度SHALL以百分号编码的斜杠(”/")开头:"%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. Capsules

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

4.7.1. ADDRESS_ASSIGN Capsule

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

ADDRESS_ASSIGN Capsule {
  Type (i) = 0x01,
  Length (i),
  Assigned Address (..) ...,
}

图7:ADDRESS_ASSIGN Capsule格式

ADDRESS_ASSIGN capsule包含零个或多个已分配地址的序列。

Assigned Address {
  Request ID (i),
  IP Version (8),
  IP Address (32..128),
  IP Prefix Length (8),
}

图8:已分配地址格式

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

Request ID:
请求标识符,以可变长度整数编码。如果此地址分配是对地址请求(参见第4.7.2节)的响应,则此字段SHALL包含请求中对应字段的值。否则,此字段SHALL为零。
IP Version:
此地址分配的IP版本,以无符号8位整数编码。它 必须 为4或6。
IP Address:
已分配的IP地址。如果IP Version字段值为4,则IP Address字段SHALL的长度为32位。如果IP Version字段值为6,则IP Address字段SHALL的长度为128位。
IP Prefix Length:
IP地址中用于定义正在分配的前缀的位数,以无符号8位整数编码。这 必须 小于或等于IP Address字段的位长度。如果前缀长度等于IP地址的长度,则此capsule的接收方可以从单个源地址发送数据包。如果前缀长度小于IP地址的长度,则此capsule的接收方可以从属于该前缀的任何源地址发送数据包。如果前缀长度严格小于IP地址的位长度,则IP Address字段中未被前缀长度覆盖的低位 必须 全部设置为0。

如果接收时任何capsule字段是格式错误的,则capsule的接收方 必须 遵循 [HTTP-DGRAM] 第3.3节中定义的错误处理过程。

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

在基于HTTP的IP代理的某些部署中,端点需要由其对等方分配一个地址,然后才知道要在其自己的数据包上设置什么源地址。例如,在远程接入VPN场景(第8.1节)中,客户端在知道要使用什么地址之前无法发送IP数据包。在这些部署中,期望获得地址分配的端点 必须 发送一个ADDRESS_REQUEST capsule。如果端点不需要任何地址分配(例如,通过带外方式配置了静态地址),则这不是必需的。

虽然ADDRESS_ASSIGN capsule通常作为对ADDRESS_REQUEST capsule的响应发送,但端点 可以 在没有提示的情况下发送ADDRESS_ASSIGN capsule。

4.7.2. ADDRESS_REQUEST Capsule

ADDRESS_REQUEST capsule(capsule类型0x02)允许一个端点向其对等方请求分配IP地址。该capsule允许端点可选地指示其对将要分配到的地址的偏好。

ADDRESS_REQUEST Capsule {
  Type (i) = 0x02,
  Length (i),
  Requested Address (..) ...,
}

图9:ADDRESS_REQUEST Capsule格式

ADDRESS_REQUEST capsule包含一个或多个已请求地址的序列。

Requested Address {
  Request ID (i),
  IP Version (8),
  IP Address (32..128),
  IP Prefix Length (8),
}

图10:已请求地址格式

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

Request ID:
请求标识符,以可变长度整数编码。这是此特定地址请求的标识符。来自给定端点的每个请求携带不同的标识符。一个端点 必须 不得重用Request ID,且 必须 不得为零。
IP Version:
此地址请求的IP版本,以无符号8位整数编码。它 必须 为4或6。
IP Address:
请求的IP地址。如果IP Version字段值为4,则IP Address字段SHALL的长度为32位。如果IP Version字段值为6,则IP Address字段SHALL的长度为128位。
IP Prefix Length:
请求的IP前缀的长度,以位为单位,以无符号8位整数编码。它必须小于或等于IP Address字段的位长度。如果前缀长度严格小于IP地址的位长度,则IP Address字段中未被前缀长度覆盖的低位 必须 全部设置为0。

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

如果接收时任何capsule字段是格式错误的,则capsule的接收方必须遵循 [HTTP-DGRAM] 第3.3节中定义的错误处理过程。

收到ADDRESS_REQUEST capsule后,端点应该为其对等方分配一个或多个IP地址,然后用ADDRESS_ASSIGN capsule响应以告知对等方分配信息。对于每个已请求地址,ADDRESS_REQUEST capsule的接收方SHALL以具有匹配Request ID的已分配地址进行响应。如果请求的地址被分配了,则已分配地址响应中的IP Address和IP Prefix Length字段SHALL设置为分配的值。如果请求的地址未被分配,则IP地址SHALL为全零,且IP Prefix Length SHALL为最大长度(0.0.0.0/32或 ::/128),以表示未分配任何地址。这些地址拒绝 应该 不包括在后续的ADDRESS_ASSIGN capsule中。注意,与任何Request ID不对应的其他已分配地址条目也可以包含在同一个ADDRESS_ASSIGN响应中。

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

注意,已请求地址的排序不表示任何语义。同样,Request ID仅用作唯一标识符;它不传达任何优先级或重要性。

4.7.3. ROUTE_ADVERTISEMENT Capsule

ROUTE_ADVERTISEMENT capsule(capsule类型0x03)允许一个端点向其对等方通告它愿意将流量路由到一组IP地址范围。这表示发送方对每个地址范围都有现有路由,并通知其对等方:如果ROUTE_ADVERTISEMENT capsule的接收方在HTTP数据报中发送这些范围之一的IP数据包,则capsule的发送方将沿其现有路由转发它们。任何在这些地址范围内的地址都可以用作此capsule接收方发起的IP数据包的目的地地址。

ROUTE_ADVERTISEMENT Capsule {
  Type (i) = 0x03,
  Length (i),
  IP Address Range (..) ...,
}

图11:ROUTE_ADVERTISEMENT Capsule格式

ROUTE_ADVERTISEMENT capsule包含零个或多个IP地址范围的序列。

IP Address Range {
  IP Version (8),
  Start IP Address (32..128),
  End IP Address (32..128),
  IP Protocol (8),
}

图12:IP地址范围格式

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

IP Version:
此范围的IP版本,以无符号8位整数编码。它 必须 为4或6。
Start IP Address和End IP Address:
通告范围的包含性起始IP地址和结束IP地址。如果IP Version字段值为4,这些字段SHALL的长度为32位。如果IP Version字段值为6,这些字段SHALL的长度为128位。Start IP Address 必须 小于或等于End IP Address。
IP Protocol:
可以发送到此范围的流量的Internet协议编号,以无符号8位整数编码。如果值为0,则允许所有协议。如果值不为0,它表示在直接通过HTTP数据报发送的IP头部中携带的允许的下一个头部值(最外层IP头部)。无论此字段的值如何,ICMP流量始终被允许。

如果接收时任何capsule字段是格式错误的,则capsule的接收方 必须 遵循 [HTTP-DGRAM] 第3.3节中定义的错误处理过程。

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

每个ROUTE_ADVERTISEMENT包含完整的地址范围列表。如果在一个方向上发送多个ROUTE_ADVERTISEMENT capsule,则每个ROUTE_ADVERTISEMENT capsule都取代之前的。换言之,如果某个地址范围在之前的capsule中存在,但最近收到的ROUTE_ADVERTISEMENT capsule不包含它,则接收方将认为该范围已被撤回。

如果使用相同IP协议的多个范围发生重叠,某些路由表实现可能会拒绝它们。为防止重叠,范围是有序的;这将负担放在发送方身上,并使接收方的验证更加简单。如果IP地址范围A在同一个ROUTE_ADVERTISEMENT capsule中位于IP地址范围B之前,它们 必须 遵循以下要求:

  • A的IP Version 必须 小于或等于B的IP Version。

  • 如果A和B的IP Version相等,则A的IP Protocol 必须 小于或等于B的IP Protocol。

  • 如果A和B的IP Version和IP Protocol都相等,则A的End IP Address 必须 严格小于B的Start IP Address。

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

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

4.8. IPv6扩展头部

请求范围限定(参见第4.6节)和ROUTE_ADVERTISEMENT capsule(参见第4.7.3节)都使用Internet协议编号。这些编号既表示上层协议(如 [IPv6] 第2节所定义,示例包括TCP和UDP),也表示IPv6扩展头部(如 [IPv6] 第4节所定义,示例包括Fragment和Options头部)。IP代理 可以 拒绝将范围限定为用于扩展头部的协议编号的请求。收到数据包后,支持按Internet协议编号进行范围限定或路由的实现 必须 遍历扩展链以找到最外层的非扩展Internet协议编号,以与范围限定规则进行匹配。注意,ROUTE_ADVERTISEMENT capsule使用Internet协议编号0表示允许所有协议;它并不将路由限制为IPv6 Hop-by-Hop Options头部([IPv6] 第4.3节)。

5. 上下文标识符

本文档中定义的HTTP中IP代理机制允许未来扩展交换携带与IP载荷不同语义的HTTP数据报。其中一些扩展可以为IP载荷增加额外数据或压缩IP头部字段,而其他扩展则可以交换与IP载荷完全无关的数据。为了实现这一目标,所有与IP代理请求流关联的HTTP数据报都以一个上下文ID字段开头;见第6节

上下文ID是62位整数(0到2^62-1)。上下文ID使用变长整数编码;见[QUIC]第16节。上下文ID值0保留用于IP载荷,而非零值则是动态分配的。非零的偶数上下文ID由客户端分配,奇数上下文ID由代理分配。上下文ID命名空间与给定的HTTP请求绑定;在相同数值的上下文ID在不同请求中同时分配是可能的,并且可能具有不同的语义。上下文ID在同一HTTP请求内必须被重新分配,但可以以任何顺序分配。上下文ID分配对偶数和奇数上下文ID的限制是为了避免端点之间需要同步。然而,一旦上下文ID被分配,这些限制不再适用于该上下文ID的使用;无论最初由哪个端点分配,客户端或IP代理都可以使用它。

注册是端点通知其对等端给定上下文ID的语义和格式的动作。本文档未定义注册如何发生。未来的扩展可以使用HTTP头部字段或胶囊来注册上下文ID。根据使用的方法,有可能在接收到尚未注册的上下文ID的数据报。例如,这可能是由于在传输过程中包含数据报的数据包与包含注册消息的数据包之间发生了重排序。

6. HTTP数据报载荷格式

当与IP代理请求流关联时,HTTP数据报的HTTP数据报载荷字段(见HTTP-DGRAM)具有如图13所定义的格式。注意,当HTTP数据报使用QUIC DATAGRAM帧编码时,下文定义的上下文ID字段直接跟在QUIC DATAGRAM帧载荷开头的四分之一流ID字段之后:

IP Proxying HTTP Datagram Payload {
  Context ID (i),
  Payload (..),
}

图13:IP代理HTTP数据报格式

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

上下文ID(Context ID):

一个变长整数,包含上下文ID的值。如果接收到携带未知上下文ID的HTTP/3数据报,接收方强烈要求要么静默丢弃该数据报,要么在等待相应上下文ID注册期间临时缓冲它(大约一个往返时间)。

载荷(Payload):

数据报的载荷,其语义取决于前一个字段的值。注意,此字段可以为空。

IP数据包使用上下文ID设置为零的HTTP数据报进行编码。当上下文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跳数(Hop Count或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字节类型,20字节最大连接ID长度,4字节最大数据包编号长度,1字节DATAGRAM帧类型,8字节最大四分之一流ID,1字节零上下文ID,以及16字节AEAD认证标签,共计51字节开销,这对应于将QUIC INITIAL数据包填充到1331字节或更多。)

  • IP代理端点也可以发送带有1232字节数据的ICMPv6回显请求以确定链路MTU,如果未收到响应则拆除隧道。除非端点有带外手段保证前述技术足够,否则它们必须使用此方法。如果端点不知道其对等端的IPv6地址,它可以向链路本地所有节点多播地址(ff02::1)发送ICMPv6回显请求。

如果端点使用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流的客户端,它应该处理来自其对等端的代理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 客户端 IP 子网 C ? 代理 IP E IP ...

图14:VPN隧道设置

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

[[ 来自客户端 ]]               [[ 来自IP代理 ]]

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) // 任意

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。

[[ 来自客户端 ]]               [[ 来自IP代理 ]]

                              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) // 任意
                              (IP Version = 4
                               Start IP Address = 192.0.2.43
                               End IP Address = 192.0.2.255
                               IP Protocol = 0) // 任意

图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的协议将无法正常工作。

[[ 来自客户端 ]]               [[ 来自IP代理 ]]

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) // 任意

                              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) // 任意

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

IP A IP B IP IP C Client IP C D Proxy IP D

图19:代理流设置

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

IP代理为客户端分配一个单独的IPv6地址(2001:db8:1234::a)和一个作用域为SCTP的到单个IPv6主机(2001:db8:3456::b)的路由。客户端可以向远程主机发送和接收SCTP IP数据包。

[[ 来自客户端 ]]               [[ 来自IP代理 ]]

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数据包以控制连接建立竞速,如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。

[[ 来自客户端 ]]               [[ 来自IP代理 ]]

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

图21:代理连接竞速设置

9. 可扩展性考量

HTTP中IP代理的扩展可以定义对此机制的行为变更。此类扩展应该定义新的胶囊类型来交换配置信息(如果需要的话)。对于修改地址分配的扩展,建议(推荐)指定其扩展胶囊在ADDRESS_ASSIGN胶囊之前发送,并且在ADDRESS_ASSIGN胶囊解析完成之前不生效。这允许地址分配的修改以原子方式操作。类似地,修改路由的扩展应该在ROUTE_ADVERTISEMENT胶囊方面表现出类似的行为。

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考量

当使用HTTP/3配合QUIC数据报扩展[DGRAM]时,IP数据包在QUIC DATAGRAM帧中传输。由于这些帧不能被分片,它们只能承载不超过由QUIC连接配置和路径MTU(PMTU)决定的特定长度的数据包。如果端点正在使用QUIC DATAGRAM帧,并尝试通过隧道路由一个无法放入单个QUIC DATAGRAM帧的IP数据包,则IP代理应该在DATAGRAM胶囊中发送该IP数据包,因为这会破坏数据报分组层路径MTU发现(DPLPMTUD)所依赖的端到端不可靠性特征[DPLPMTUD]。在这种场景下,端点应该丢弃该IP数据包,并向被丢弃数据包的发送方发送ICMP"数据包过大"消息;参见[ICMPv6]第3.2节。

10.2. ECN考量

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

相反,如果外部拥塞控制未被禁用,则[ECN-TUNNEL]中关于在内外部IP头之间传递ECN标记的指导不适用,因为如果外部连接使用ECN,它将正确地对拥塞通知做出响应。内部流量也可以使用ECN,独立于外部连接是否使用ECN。

10.3. 差异化服务考量

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

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

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

11. 安全性考量

允许任意客户端建立允许向任意主机发送流量的隧道存在显著风险,无论隧道是否限定到特定主机。恶意行为者可能滥用此功能来发送流量,并将其归因于IP代理。支持IP代理的HTTP服务器应该限制其仅供经过身份验证的用户使用。根据部署情况,可能的身份验证机制包括IP代理端点之间的双向TLS、通过HTTP Authorization头的基于HTTP的身份验证[HTTP],甚至是持有者令牌。代理可以为经过身份验证的用户执行策略,以进一步约束客户端行为或应对可能的滥用。例如,代理可以对通过代理发送过量流量的个别客户端进行速率限制。又如,代理可以基于某些客户端属性(如地理位置)限制分配给客户端的地址(前缀)。

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

伪造已发送流量中的IP源地址在拒绝服务攻击中很常见。此机制的实现需要确保其不会助长此类攻击。特别地,存在这样的场景:端点知道其对端只允许从给定前缀发送IP数据包。例如,可以通过带外配置信息,或当允许的前缀通过ADDRESS_ASSIGN胶囊共享时发生这种情况。在这些场景中,端点必须遵循[BCP38]的建议以防止源地址欺骗。

限制请求范围(参见第4.6节)允许两个客户端共享代理的一个外部IP地址,只要它们的请求限定到不同的互联网协议号。如果代理收到发往该外部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请求,从而允许请求走私攻击;参见[OPTIMISTIC]。特别地,将请求从HTTP/2或3重新编码为HTTP/1.1的中间设备必须转发任何接收到的胶囊,直到它已解析到成功的IP代理响应。

12. 关于IANA的考量

本节按照[IANA-POLICY]中规定的指南记录了IANA已执行的操作。

12.1. HTTP升级令牌注册

IANA已在维护于 https://www.iana.org/assignments/http-upgrade-tokens 的"HTTP Upgrade Tokens"注册表中注册了"connect-ip"。

值:connect-ip描述:IP载荷代理(Proxying of IP Payloads)期望的版本令牌:无参考文献:RFC 9484

12.2. MASQUE URI后缀注册表创建

IANA已创建维护于 https://www.iana.org/assignments/masque 的"MASQUE URI Suffixes"注册表。注册策略为专家评审;参见[IANA-POLICY]第4.5节。此新注册表管理以"/.well-known/masque/“开头的路径中紧跟在"masque"之后的路径段;关于在"Well-Known URIs"注册表中注册"masque"的信息,请参见 https://www.iana.org/assignments/well-known-uris

此新注册表包含三列:

路径段(Path Segment):仅包含token中允许字符的ASCII字符串;参见[HTTP]第5.6.2节。此注册表中的条目必须在此列中均具有不同的条目。描述(Description):对条目的描述。参考文献(Reference):定义该条目用途的可选参考文献。

注册表的初始条目如下:

路径段 描述 参考文献
udp UDP代理(UDP Proxying) RFC 9298
ip IP代理(IP Proxying) RFC 9484

表1:MASQUE URI后缀注册表

此注册表的指定专家应知晓,只要专家认为(1)请求的路径段不会与现有或预期的未来IETF工作冲突,且(2)用例与代理相关,就应当批准所有请求。

12.3. 对masque Well-Known URI注册的更新

IANA已更新维护于 https://www.iana.org/assignments/well-known-uris 的"Well-Known URIs"注册表中"masque" URI后缀条目的信息。

IANA已将"Reference"字段更新为包含本文档,并将"Related Information"字段替换为"For sub-suffix allocations, see the registry at https://www.iana.org/assignments/masque."。

12.4. HTTP Capsule类型注册

IANA已向维护于 https://www.iana.org/assignments/masque 的"HTTP Capsule Types"注册表添加以下值。

Capsule类型
0x01 ADDRESS_ASSIGN
0x02 ADDRESS_REQUEST
0x03 ROUTE_ADVERTISEMENT

表2:新增Capsule类型

所有新增条目在以下字段使用相同的值:

状态(Status):permanent(永久)参考文献(Reference):RFC 9484变更控制者(Change Controller):IETF联系方式(Contact):masque@ietf.org备注(Notes):无

13. 参考文献

13.1. 规范性参考文献

[ABNF] 用于语法规范的增强型BNF:ABNF

Crocker, D., Ed. and P. Overell, “Augmented BNF for Syntax Specifications: ABNF”, STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, https://www.rfc-editor.org/info/rfc5234.

[BCP38] 网络入口过滤:挫败利用IP源地址欺骗的拒绝服务攻击

Ferguson, P. and D. Senie, “Network Ingress Filtering: Defeating Denial of Service Attacks which employ IP Source Address Spoofing”, BCP 38, RFC 2827, DOI 10.17487/RFC2827, May 2000, https://www.rfc-editor.org/info/rfc2827.

[DGRAM] QUIC不可靠数据报扩展

Pauly, T., Kinnear, E., and D. Schinazi, “An Unreliable Datagram Extension to QUIC”, RFC 9221, DOI 10.17487/RFC9221, March 2022, https://www.rfc-editor.org/info/rfc9221.

[DSCP] IPv4和IPv6头中差异化服务字段(DS字段)的定义

Nichols, K., Blake, S., Baker, F., and D. Black, “Definition of the Differentiated Services Field (DS Field) in the IPv4 and IPv6 Headers”, RFC 2474, DOI 10.17487/RFC2474, December 1998, https://www.rfc-editor.org/info/rfc2474.

[ECN] 向IP添加显式拥塞通知(ECN)

Ramakrishnan, K., Floyd, S., and D. Black, “The Addition of Explicit Congestion Notification (ECN) to IP”, RFC 3168, DOI 10.17487/RFC3168, September 2001, https://www.rfc-editor.org/info/rfc3168.

[EXT-CONNECT2] 使用HTTP/2引导WebSocket

McManus, P., “Bootstrapping WebSockets with HTTP/2”, RFC 8441, DOI 10.17487/RFC8441, September 2018, https://www.rfc-editor.org/info/rfc8441.

[EXT-CONNECT3] 使用HTTP/3引导WebSocket

Hamilton, R., “Bootstrapping WebSockets with HTTP/3”, RFC 9220, DOI 10.17487/RFC9220, June 2022, https://www.rfc-editor.org/info/rfc9220.

[HTTP] HTTP语义

Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., “HTTP Semantics”, STD 97, RFC 9110, DOI 10.17487/RFC9110, June 2022, https://www.rfc-editor.org/info/rfc9110.

[HTTP-DGRAM] HTTP数据报与胶囊协议

Schinazi, D. and L. Pardue, “HTTP Datagrams and the Capsule Protocol”, RFC 9297, DOI 10.17487/RFC9297, August 2022, https://www.rfc-editor.org/info/rfc9297.

[HTTP/1.1] HTTP/1.1

Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., “HTTP/1.1”, STD 99, RFC 9112, DOI 10.17487/RFC9112, June 2022, https://www.rfc-editor.org/info/rfc9112.

[HTTP/2] HTTP/2

Thomson, M., Ed. and C. Benfield, Ed., “HTTP/2”, RFC 9113, DOI 10.17487/RFC9113, June 2022, https://www.rfc-editor.org/info/rfc9113.

[HTTP/3] HTTP/3

Bishop, M., Ed., “HTTP/3”, RFC 9114, DOI 10.17487/RFC9114, June 2022, https://www.rfc-editor.org/info/rfc9114.

[IANA-POLICY] RFC中IANA考量章节编写指南

Cotton, M., Leiba, B., and T. Narten, “Guidelines for Writing an IANA Considerations Section in RFCs”, BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, https://www.rfc-editor.org/info/rfc8126.

[ICMP] 互联网控制消息协议

Postel, J., “Internet Control Message Protocol”, STD 5, RFC 792, DOI 10.17487/RFC0792, September 1981, https://www.rfc-editor.org/info/rfc792.

[ICMPv6] 互联网协议版本6(IPv6)规范的互联网控制消息协议(ICMPv6)

Conta, A., Deering, S., and M. Gupta, Ed., “Internet Control Message Protocol (ICMPv6) for the Internet Protocol Version 6 (IPv6) Specification”, STD 89, RFC 4443, DOI 10.17487/RFC4443, March 2006, https://www.rfc-editor.org/info/rfc4443.

[IPv6] 互联网协议版本6(IPv6)规范

Deering, S. and R. Hinden, “Internet Protocol, Version 6 (IPv6) Specification”, STD 86, RFC 8200, DOI 10.17487/RFC8200, July 2017, https://www.rfc-editor.org/info/rfc8200.

[IPv6-ZONE-ID] 在地址字面量和统一资源标识符中表示IPv6区域标识符

Carpenter, B., Cheshire, S., and R. Hinden, “Representing IPv6 Zone Identifiers in Address Literals and Uniform Resource Identifiers”, RFC 6874, DOI 10.17487/RFC6874, February 2013, https://www.rfc-editor.org/info/rfc6874.

[PROXY-STATUS] Proxy-Status HTTP响应头字段

Nottingham, M. and P. Sikora, “The Proxy-Status HTTP Response Header Field”, RFC 9209, DOI 10.17487/RFC9209, June 2022, https://www.rfc-editor.org/info/rfc9209.

[QUIC] QUIC:一种基于UDP的安全多路复用传输协议

Iyengar, J., Ed. and M. Thomson, Ed., “QUIC: A UDP-Based Multiplexed and Secure Transport”, RFC 9000, DOI 10.17487/RFC9000, May 2021, https://www.rfc-editor.org/info/rfc9000.

[RFC2119] 用于RFC中指示需求等级的关键词

Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels”, BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, https://www.rfc-editor.org/info/rfc2119.

[RFC8174] RFC 2119关键词中大写与小写的歧义性

Leiba, B., “Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words”, BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, https://www.rfc-editor.org/info/rfc8174.

[TCP] 传输控制协议(TCP)

Eddy, W., Ed., “Transmission Control Protocol (TCP)”, STD 7, RFC 9293, DOI 10.17487/RFC9293, August 2022, https://www.rfc-editor.org/info/rfc9293.

[TEMPLATE] URI模板

Gregorio, J., Fielding, R., Hadley, M., Nottingham, M., and D. Orchard, “URI Template”, RFC 6570, DOI 10.17487/RFC6570, March 2012, https://www.rfc-editor.org/info/rfc6570.

[URI] 统一资源标识符(URI):通用语法

Berners-Lee, T., Fielding, R., and L. Masinter, “Uniform Resource Identifier (URI): Generic Syntax”, STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, https://www.rfc-editor.org/info/rfc3986.

13.2. 资料性参考文献

[CONNECT-UDP] HTTP中的UDP代理

Schinazi, D., “Proxying UDP in HTTP”, RFC 9298, DOI 10.17487/RFC9298, August 2022, https://www.rfc-editor.org/info/rfc9298.

[DPLPMTUD] 数据报传输的分组层路径MTU发现

Fairhurst, G., Jones, T., Tüxen, M., Rüngeler, I., and T. Völker, “Packetization Layer Path MTU Discovery for Datagram Transports”, RFC 8899, DOI 10.17487/RFC8899, September 2020, https://www.rfc-editor.org/info/rfc8899.

[ECN-TUNNEL] 显式拥塞通知的隧道传输

Briscoe, B., “Tunnelling of Explicit Congestion Notification”, RFC 6040, DOI 10.17487/RFC6040, November 2010, https://www.rfc-editor.org/info/rfc6040.

[HEv2] Happy Eyeballs版本2:利用并发性实现更好的连接性

Schinazi, D. and T. Pauly, “Happy Eyeballs Version 2: Better Connectivity Using Concurrency”, RFC 8305, DOI 10.17487/RFC8305, December 2017, https://www.rfc-editor.org/info/rfc8305.

[IANA-PN] 协议号

IANA, “Protocol Numbers”, https://www.iana.org/assignments/protocol-numbers.

[IPSEC] 互联网协议安全架构

Kent, S. and K. Seo, “Security Architecture for the Internet Protocol”, RFC 4301, DOI 10.17487/RFC4301, December 2005, https://www.rfc-editor.org/info/rfc4301.

[IPv6-ADDR] IP版本6寻址架构

Hinden, R. and S. Deering, “IP Version 6 Addressing Architecture”, RFC 4291, DOI 10.17487/RFC4291, February 2006, https://www.rfc-editor.org/info/rfc4291.

[OPTIMISTIC] 乐观使用HTTP升级的安全性考量

Schwartz, B. M., “Security Considerations for Optimistic Use of HTTP Upgrade”, Work in Progress, Internet-Draft, draft-schwartz-httpbis-optimistic-upgrade-00, 21 August 2023, https://datatracker.ietf.org/doc/html/draft-schwartz-httpbis-optimistic-upgrade-00.

[PROXY-REQS] MASQUE协议代理IP流量的需求

Chernyakhovsky, A., McCall, D., and D. Schinazi, “Requirements for a MASQUE Protocol to Proxy IP Traffic”, Work in Progress, Internet-Draft, draft-ietf-masque-ip-proxy-reqs-03, 27 August 2021, https://datatracker.ietf.org/doc/html/draft-ietf-masque-ip-proxy-reqs-03.

[ROUTING-HDR] 废弃IPv6中的类型0路由头

Abley, J., Savola, P., and G. Neville-Neil, “Deprecation of Type 0 Routing Headers in IPv6”, RFC 5095, DOI 10.17487/RFC5095, December 2007, https://www.rfc-editor.org/info/rfc5095.

[TUNNEL-SECURITY] IP隧道的安全性问题

Krishnan, S., Thaler, D., and J. Hoagland, “Security Concerns with IP Tunneling”, RFC 6169, DOI 10.17487/RFC6169, April 2011, https://www.rfc-editor.org/info/rfc6169.

[UDP-USAGE] UDP使用指南

Eggert, L., Fairhurst, G., and G. Shepherd, “UDP Usage Guidelines”, BCP 145, RFC 8085, DOI 10.17487/RFC8085, March 2017, https://www.rfc-editor.org/info/rfc8085.

致谢

本方法的设计受到MASQUE工作组围绕[PROXY-REQS]的讨论的启发。作者要感谢参与这些讨论的参与者提供的反馈。此外,Mike Bishop、Lucas Pardue和Alejandro Sedeño对本文档提供了宝贵的反馈。

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

作者地址

Tommy Pauly(编辑)

Apple Inc.

Email: tpauly@apple.com

David Schinazi

Google LLC

1600 Amphitheatre Parkway

Mountain View, CA 94043

United States of America

Email: dschinazi.ietf@gmail.com

Alex Chernyakhovsky

Google LLC

Email: achernya@google.com

Mirja Kühlewind

Ericsson

Email: mirja.kuehlewind@ericsson.com

Magnus Westerlund

Ericsson

Email: magnus.westerlund@ericsson.com