跳到主要内容

RFC 9308 - QUIC 传输协议的适用性 (Applicability of the QUIC Transport Protocol)

  • 状态: Informational
  • 发布日期: September 2022
  • Stream: IETF
  • 勘误: 无勘误

摘要 (Abstract)​

本文档讨论 QUIC 传输协议的适用性, 重点关注影响在 QUIC 之上开发与部署应用协议的注意事项. 目标读者是将应用协议映射到 QUIC 的设计者以及这些应用协议的实现者.

本备忘录状态 (Status of This Memo)​

本文档不是 Internet Standards Track 规范; 它以资料性目的发布.

本文档是互联网工程任务组 (Internet Engineering Task Force, IETF) 的产物. 它代表 IETF 社区的共识. 它已接受公开审阅, 并已获互联网工程指导组 (Internet Engineering Steering Group, IESG) 批准发布. 并非所有经 IESG 批准的文档都是任何级别 Internet Standard 的候选; 见 RFC 7841 第 2 节.

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

Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved.

本文档受 BCP 78 以及 IETF Trust 关于 IETF 文档的法律条款 (https://trustee.ietf.org/license-info) 约束 (以本文档发布之日有效者为准). 请仔细审阅这些文件. 从本文档提取的代码组件必须包含 Trust Legal Provisions 第 4.e 节所述的 Revised BSD License 文本, 并按该许可证所述不提供保证.

目录 (Table of Contents)​

  1. 引言
  2. 回退的必要性
  3. 0-RTT
  4. 流的使用
  5. 分组化与时延
  6. 错误处理
  7. 确认效率
  8. 端口选择与应用端点发现
  9. 连接迁移
  10. 连接终止
  11. 信息暴露与连接 ID
  12. QoS 与 DSCP
  13. 版本与密码握手的使用
  14. 支持新版本部署
  15. QUIC 上的不可靠数据报服务
  16. IANA 考虑
  17. 安全考虑
  18. 参考文献

1. 引言 (Introduction)​

QUIC [QUIC] 是一种提供多项高级特性的新传输协议. 它最初为 HTTP 用例设计, 但其能力可用于更广泛的应用. QUIC 封装在 UDP 中. QUIC 版本 1 集成 TLS 1.3 [TLS13] 以加密所有载荷数据与大部分控制信息. 使用 QUIC 的 HTTP 版本称为 HTTP/3 [QUIC-HTTP].

本文档为希望使用 QUIC 协议、而不自行实现传输栈的应用开发者提供指导. 这包括在 HTTP/3 之上运行或直接在 QUIC 之上运行的应用的一般指导.

后续各节讨论 QUIC 适用性的具体注意事项, 以及应用开发者在将 QUIC 用作其应用传输时必须考虑的问题.

2. 回退的必要性 (The Necessity of Fallback)​

QUIC 以 UDP 为基底. 这支持用户态实现, 并允许穿越网络中间盒 (包括 NAT), 而无需更新现有网络基础设施.

测量研究表明, 约 3% [Trammell16] 到 5% [Swett16] 的网络会阻断所有 UDP 流量, 尽管几乎没有证据表明 UDP 相对 TCP 存在其他系统性劣势 [Edeline16]. 这种阻断意味着所有运行在 QUIC 之上的应用必须要么准备好在此类网络上接受连通失败, 要么被设计为回退到其他传输协议. 对 HTTP 而言, 该回退是 TLS over TCP.

IETF 传输服务 (TAPS) 规范 [TAPS-ARCH] 描述了面向多协议的通用 API 系统. 这对 QUIC 特别相关, 因为它处理多协议之间回退的影响.

具体而言, 需要避免回退到不安全协议或更弱版本的安全协议. 一般地, 实现回退的应用需要考虑安全后果. 回退到 TCP 与 TLS 会使控制信息暴露于网络中的修改与操纵. 此外, 降级到比 QUIC 版本 1 所用 TLS 1.3 更旧的 TLS 版本可能导致显著更弱的密码保护. 例如, 协议协商 [RFC7301] 的结果仅在使用 TLS 1.3 时具有机密性保护.

这些应用必须在缺少回退协议所不具备的 QUIC 特性时仍能运行 (可能功能受损). 对回退到 TLS over TCP, 最明显的差异是 TCP 不提供流多路复用, 因此若需要流多路复用则必须在应用层实现. 此外, TCP 实现与网络路径常常不支持 TCP Fast Open (TFO) 选项 [RFC7413], 而 TFO 可在新连接的第一个控制报文中一并发送载荷数据, 类似 QUIC 中的 0-RTT 会话恢复. 注意有证据表明, 即使成功协商 TFO, 中间盒仍可能阻断 SYN 数据 (见 [PaaschNanog]). 即便 Fast Open 端到端成功, 它也通常限于单个报文的 TLS 握手与应用数据, 不同于 QUIC 0-RTT.

此外, 尽管加密 (此处为 TLS) 与 QUIC 不可分割地集成, 但 TCP 上的 TLS 协商可能被阻断. 若无法支持 TLS over TCP, 应中止连接, 应用宜向用户提示安全通信不可用.

总之, 任何回退机制都可能带来性能下降并可削弱安全; 然而, 回退不得静默违反应用对其载荷数据机密性或完整性的期望.

3. 0-RTT​

QUIC 提供 0-RTT 连接建立. 尽管 TLS 1.3 over TCP 也存在类似能力, 0-RTT 对使用 QUIC 的应用既带来机会也带来挑战.

从应用视角看, 提供 0-RTT 连接建立的传输协议与不提供 0-RTT 的协议有质的不同. 关闭并重新打开连接与尝试保持连接打开之间的相对权衡不同; 见第 3.2 节.

应用需要有意选择使用 0-RTT, 因为 0-RTT 带有重放攻击风险. 使用 0-RTT 的应用协议需要一份描述可安全发送信息类型的配置文件. 对 HTTP, 该配置文件见 [HTTP-REPLAY].

3.1. 重放攻击 (Replay Attacks)​

0-RTT 报文中数据的重传或恶意重放可能导致服务器侧多次收到相同数据.

客户端在 0-RTT 报文中发送的应用数据若被重放, 可能被处理多次. 应用需要清楚什么可安全地放在 0-RTT 中发送. 希望启用 0-RTT 的应用协议需要仔细分析并描述可在 0-RTT 中发送的内容; 见 [QUIC-TLS] 第 5.6 节.

在某些情况下, 将 0-RTT 中的应用数据限制为不会在服务器上造成持久副作用的数据可能足够. 发起数据检索或建立配置是可能安全的动作示例. 幂等操作——重复与单次执行净效果相同的操作——可能安全. 然而, 也可能将各自幂等的操作组合成非幂等序列.

一旦服务器接受 0-RTT 数据, 就没有办法选择性地丢弃已接收的数据. 不过, 协议可以定义拒绝在重放时可能不安全的个别动作的方法.

某些 TLS 实现与部署可能提供部分甚至完整的重放保护, 可用于管理重放风险.

3.2. 会话恢复与保活 (Session Resumption versus Keep-Alive)​

由于 QUIC 封装在 UDP 中, 使用 QUIC 的应用必须处理较短的网络空闲超时. 已部署的有状态中间盒通常在发送第一个分组时为 UDP 流建立状态, 并保持比 TCP 短得多的空闲期. [RFC5382] 建议 TCP 空闲期至少 124 分钟, 但文献中几乎没有该指南被广泛实现的证据. 然而 UDP 的短网络超时有充分记录. 根据 2010 年研究 ([Hatonen10]), UDP 应用可假定任何 NAT 绑定或其他状态条目在仅三十秒不活动后即可过期. [RFC8085] 第 3.5 节进一步讨论 UDP 保活间隔: 它要求最小值 15 秒, 但推荐更大值, 或完全省略保活.

通过使用连接 ID, QUIC 被设计为在超时后对 NAT 重绑定具有鲁棒性. 然而, 这仅在一端点在其对等方使用的地址上保持可用、且由对等方在超时后发送时才有帮助.

某些 QUIC 连接可能对 NAT 重绑定不鲁棒, 因为路由基础设施 (特别是负载均衡器) 使用地址/端口四元组引导流量. 此外, 具有地址转换以外功能的中间盒仍可能影响路径. 特别是, 某些防火墙对没有对应客户端最近状态的服务器流量不予放行.

QUIC 应用可调整空闲期以管理超时风险. 空闲期与网络空闲超时不同于连接空闲超时, 后者定义为两端点 idle timeout 参数的最小值; 见 [QUIC] 第 10.1 节. 有三种选项:

  • 若应用层协议仅由无或很短空闲期的交互组成, 或协议对 NAT 重绑定的抵抗足够, 则可忽略该问题.
  • 确保不存在长空闲期.
  • 在长空闲期后恢复会话, 并在适当时使用 0-RTT 恢复.

第一种策略最容易, 但仅适用于某些应用.

QUIC 应用中的服务器或客户端可发送 PING 帧作为保活, 以防止连接与任何路径上状态超时. 保活使用建议因应用而异, 主要取决于时延要求与消息频率. 在此情况下, 应用映射必须指明由客户端还是服务器负责保持应用存活. 虽然 [Hatonen10] 建议在公网存在 NAT 时 30 秒可能合适, 但若部署能持续在 NAT 重绑定后存活, 或处于受控环境 (例如数据中心), 则更大值更可取, 以降低网络与计算负载.

在长空闲期中比每 30 秒更频繁地发送 PING 帧, 在某些情况下可能导致过多无效流量, 并对功耗受限 (移动) 设备造成不可接受的功耗. 此外, 短于 30 秒的超时会使处理短暂网络中断更难, 例如虚拟机 (VM) 迁移或移动中的覆盖丢失. 见 [RFC8085], 尤其是第 3.5 节.

或者, 客户端 (而非服务器) 可使用会话恢复而非发送保活流量. 在此情况下, 想要在已空闲超过服务器 idle timeout (可从 idle_timeout 传输参数获知) 的连接上向服务器发送数据的客户端可简单重连. 在可能时, 该重连可使用 0-RTT 会话恢复, 降低重启连接的时延. 当然, 这种方法仅在可以安全使用 0-RTT 且由客户端作为重启方时才有效.

恢复与保活之间的权衡需要按应用逐一评估. 一般地, 应用应当只在持续通信极有可能发生的情形下使用保活; 例如 [QUIC-HTTP] 建议仅在某请求尚未完成时才使用保活.

4. 流的使用 (Use of Streams)​

QUIC 的流多路复用特性允许应用在单一连接上运行多个流, 且各流之间不存在队头阻塞. 流数据承载在帧中, 线路上的一个 QUIC 分组可以携带一个或多个流帧.

流可以是单向的或双向的, 且流可由客户端或服务器发起. 只有单向流的发起方才能在该流上发送数据.

由于流偏移与连接流控制上限的编码限制, 流和连接在每个方向上最多各可承载 2^62-1 字节. 在目前而言不太可能发生的应用达到该上限的情况下, 将需要建立一条新连接.

流可以独立地打开和关闭, 既可以优雅地也可以突然地关闭. 应用可以通过指示 QUIC 在 STREAM 帧中发送 FIN 位来优雅地关闭一个流的出口方向. 在没有对端生成的 FIN 的情况下, 它无法优雅地关闭入口方向, 这与 TCP 很相似. 不过, 端点可以突然关闭出口方向, 或者请求其对端突然关闭入口方向; 这两个动作彼此完全独立.

QUIC 不为任何流提供异常处理接口. 若对应用至关重要的某个流被关闭, 应用可以在应用层生成错误消息, 通知另一端和/或更高层, 后者最终可以终止 QUIC 连接.

应用数据到流的映射是应用相关的, HTTP/3 的映射在 [QUIC-HTTP] 中描述. 在设计应用对流的使用时, 有几条通用原则可以遵循:

  • 单个流提供有序性. 若应用要求某些数据按序接收, 这些数据应当在同一条流上发送. 跨流不保证传输、接收或交付顺序.

  • 多个流提供并发性. 可以独立处理的数据——若强制按序接收则会遭受队头阻塞——应当在不同的流上传输.

  • 流可以提供面向消息的语义, 并允许取消消息. 若一条消息映射到单个流, 则可以通过重置该流使未确认的消息失效, 以此为该消息模拟部分可靠性.

若 QUIC 接收方已打开最大允许的并发流数, 而发送方表示需要更多流, 这并不会自动导致接收方增加最大流数. 因此, 应用在决定如何将数据映射到流时, 应当考虑允许的最大流数、当前打开的流数以及当前正在使用的流数.

QUIC 为每个流分配一个称为流 ID (stream ID) 的数字标识符. 虽然这些标识符与流类型之间的关系在 QUIC 版本 1 中有明确定义, 但未来版本可能出于各种原因改变这种关系. QUIC 实现应当暴露每个流的属性 (由哪个端点发起该流、该流是单向还是双向、该流所用的流 ID); 应用应当查询这些属性, 而不是试图从流 ID 推断它们.

为应用打开的流分配流标识符的方法可能因传输实现而异. 因此, 应用不应假定某个尚未分配的流会获得特定的流 ID. 例如, HTTP/3 使用流 ID 来引用已经打开的流, 但不对未来的流 ID 或其分配方式做任何假设 (见 [QUIC-HTTP] 第 6 节).

4.1. 流与流多路复用 (Stream versus Flow Multiplexing)​

流只对应用有意义; 由于流信息承载在 QUIC 的加密边界之内, 一个给定的分组不会暴露其中携带了哪些流. 因此, 流多路复用并不打算用于让不同的流获得不同的网络处理. 需要不同网络处理的应用流量应当经由不同的 5 元组承载 (即多个 QUIC 连接). 考虑到 QUIC 能够在连接的第一个 RTT 内发送应用数据 (前提是此前已与同一主机成功建立过连接并提供必要的凭据), 建立另一条连接的代价极低.

4.2. 优先级 (Prioritization)​

流优先级既不暴露给网络, 也不暴露给接收方. 优先级由发送方管理, QUIC 传输层应当为应用提供对流进行优先级排序的接口 [QUIC]. 应用可以在 QUIC 之上实现自己的优先级方案: 运行在 QUIC 之上的应用协议可以定义用于通告优先级的显式消息, 例如 [RFC9218] 为 HTTP 定义的那些消息. 应用协议可以定义规则, 允许端点根据上下文确定优先级, 也可以提供更高层的接口, 把决定留给其上的应用.

重传的优先级处理可以由发送方在传输层实现. [QUIC] 建议先重传丢失的数据再发送新数据, 除非应用另有指示. 当 QUIC 端点使用完全可靠的流进行传输时, 对重传排定优先级在大多数情况下是有益的, 它能填补空隙并释放流控制窗口. 对于部分可靠或不可靠的流, 让重传优先于更高优先级流的数据进行调度可能并不可取. 对这类流, QUIC 要么提供控制优先级的显式接口, 要么根据流的可靠性级别推导优先级决策.

4.3. 有序与可靠交付 (Ordered and Reliable Delivery)​

QUIC 流实现有序且可靠的交付. 尽管实现可以提供将流用于部分可靠性或乱序交付的选项, 但大多数实现会假定数据按序可靠交付.

在这一假设下, 接收流数据的端点在流起始处连续的数据可用之前可能无法取得进展. 特别是, 接收方可能扣留流控制信用, 直到连续数据交付给应用; 见 [QUIC] 第 2.2 节. 为支持这种接收逻辑, 端点会持续发送流数据直至其被确认, 确保流起始处的数据最先被发送并被确认.

采用不同发送行为且未与对端协商该改变的端点, 可能遇到性能问题或死锁.

4.4. 流控制死锁 (Flow Control Deadlocks)​

QUIC 流控制 ([QUIC] 第 4 节) 提供了一种管理端点用于接收数据的有限缓冲区之访问的手段. 该机制限制了可存在于端点缓冲区中或网络传输中的数据量. 然而, 存在若干种由限制引发状况的情形, 它们会导致连接的性能欠佳甚至陷入死锁.

对任何使用 QUIC 的协议而言, 流控制中的死锁都有可能发生, 尽管它是否成为问题取决于实现如何消费数据以及如何提供流控制信用. 理解死锁的成因可能有助于实现避免死锁.

流控制信用的更新大小与更新频率会影响性能. 使用 QUIC 的应用通常拥有一个从传输缓冲区读取数据的数据消费者. 某些实现可能在传输层与应用层分别拥有独立的接收缓冲区. 消费数据并不总是意味着数据被立即处理. 不过, 一种常见的实现技术是在数据被消费时通过发出 MAX_DATA 和/或 MAX_STREAM_DATA 帧来向发送方扩展流控制信用. 这些帧的交付受接收方到数据发送方的反向信道时延的影响. 若信用未及时扩展, 发送方的应用可能被阻塞, 实际上扼住了发送方.

若接收方不从传输层增量地读取数据, 大的应用消息可能导致死锁. 若消息大于可用的流控制信用, 且接收方在整条消息接收并交付完毕之前不释放额外的流控制信用, 死锁就可能发生. 即使未达到流的流控制上限, 这种情况也可能发生, 因为连接级流控制上限可能已被其他流消耗.

带长度前缀的消息格式便于数据消费者把数据留在传输缓冲区中不读, 从而扣留流控制信用. 若流控制上限阻止消息剩余部分的发送, 就会导致死锁. 长度前缀还可能有助于检测这类死锁. 当应用协议的消息可能作为单个单元处理时, 为整条消息原子地预留流控制信用可以降低这类死锁发生的可能性.

数据消费者可以在数据变为可用时立即读取所有数据, 以促使接收方扩展流控制信用并降低死锁几率. 然而, 这样的数据消费者可能需要其他手段, 来让对端对其为部分处理的消息所保存的额外状态负责.

若不同流上的数据相互依赖, 也可能发生死锁. 假设某条流上的数据先于其依赖的第二条流上的数据到达. 若第一条流保持不被读取, 阻止接收方为第二条流扩展流控制信用, 死锁就会发生. 为降低相互依赖数据的死锁可能性, 发送方应当确保在其依赖的数据已在流级和连接级流控制信用中都得到核算之前, 不发送该依赖数据.

某些死锁场景可以通过用 STOP_SENDING 或 RESET_STREAM 取消受影响的流来解决. 在某些协议中, 取消一些流会导致连接被终止.

4.5. 流限制承诺 (Stream Limit Commitments)​

QUIC 端点负责通告其允许对端打开的流的累计上限. 初始上限通过 initial_max_streams_bidi 与 initial_max_streams_uni 传输参数通告. 随着流被打开和关闭, 它们被消耗, 累计总数随之递增. 上限可以用 MAX_STREAMS 帧增加, 但没有降低上限的机制. 一旦达到流上限, 就不能再打开更多流, 这会阻止使用 QUIC 的应用继续取得进展. 在这一阶段, 连接可以通过空闲超时或显式关闭来终止; 见第 10 节.

使用 QUIC 并通告累计流上限的应用可能需要在达到上限之前关闭连接, 例如为了停掉服务器以进行计划内维护. 立即关闭连接会导致正在使用的流突然关闭. 视应用如何使用 QUIC 流而定, 这可能是不希望的, 或对行为与性能有害.

一种更优雅的关闭技术是停止增加流上限, 让连接在剩余流被消耗后自然终止. 然而, 这所需的时间取决于对端, 不可预测的关闭期可能不符合应用或运营需求. 使用 QUIC 的应用可以对打开流的上限保持保守, 以减少承诺与不确定性. 然而, 对流上限过于保守会影响流并发性. 在这些方面取得平衡可能因应用及其部署而异.

作为依靠流上限来避免突然关闭的替代, 可以使用应用层的优雅关闭机制来传达将在未来某个时刻显式关闭连接的意图. HTTP/3 使用 GOAWAY 帧提供了这样一种机制. 在 HTTP/3 中, 当客户端收到 GOAWAY 帧后, 即使累计流上限允许, 它也停止打开新流. 客户端会转而创建一条新连接, 在其上打开后续的流. 一旦旧连接上的所有流都关闭, 就可以通过连接关闭或在空闲超时到期后安全地终止该连接 (见第 10 节).

5. 分组化与时延 (Packetization and Latency)​

QUIC 向应用暴露一个提供多个流的接口; 然而, 应用通常无法控制经由这些流传输的数据如何映射为帧, 也无法控制这些帧如何捆绑成分组.

默认情况下, 许多实现会尽量把来自一个或多个流的 STREAM 帧打包进每个 QUIC 分组, 以最小化带宽消耗与计算成本 (见 [QUIC] 第 13 节). 若可用数据不足以填满一个分组, 实现可能等待一小段时间, 以优化带宽效率而非时延. 这段时延可以是预先配置的, 也可以根据观察到的应用发送模式动态调整.

若应用要求低时延且每次只发送少量数据块, 向 QUIC 指示所有数据应立即发出可能是有价值的. 或者, 若应用预期使用特定的发送模式, 它也可以向 QUIC 提供一个建议的时延, 指明在把帧捆绑成分组之前应等待多久.

类似地, 应用通常无法控制 QUIC 分组在线路上的长度. QUIC 提供添加 PADDING 帧以任意增大分组大小的能力. QUIC 使用填充来确保路径在握手期间能够传输至少一定大小的数据报 (见 [QUIC] 第 8.1 节和第 14.1 节), 用于连接迁移后的路径验证 (见 [QUIC] 第 8.2 节), 以及用于数据报分组化层 PMTU 发现 (DPLPMTUD) (见 [QUIC] 第 14.3 节).

应用也可以使用填充来减少所发送数据相关信息的泄露. QUIC 实现可以暴露一个接口, 允许应用层指定如何施加填充.

6. 错误处理 (Error Handling)​

QUIC 建议端点将检测到的任何错误告知对端. 错误可能发生在传输层和应用层. 传输层错误 (例如协议违规) 会影响整个连接. 使用 QUIC 的应用可以定义自己的错误检测与信号机制 (例如 [QUIC-HTTP] 第 8 节). 应用层错误既可以影响整个连接, 也可以只影响单条流.

QUIC 定义了一个用于传输层错误处理的错误码空间. QUIC 鼓励端点使用最具针对性的错误码, 但也允许使用任何适用的错误码, 包括通用的错误码.

使用 QUIC 的应用定义的错误码空间独立于 QUIC 或其他应用 (例如 [QUIC-HTTP] 第 8.1 节). 应用错误码空间中的值可以在连接级错误与流级错误之间复用.

连接错误会导致连接终止. 连接错误使用 CONNECTION_CLOSE 帧来传递信号, 该帧包含一个错误码和一个可以为零长度的原因字段. 不同类型的 CONNECTION_CLOSE 帧分别用于传递传输层错误和应用层错误的信号.

流错误会导致流终止. 流错误使用 STOP_SENDING 或 RESET_STREAM 帧传递信号, 这些帧只包含一个错误码.

7. 确认效率 (Acknowledgment Efficiency)​

未使用扩展的 QUIC 版本 1 采用了一种继承自 TCP 的确认策略 (见 [QUIC] 第 13.2 节). 也就是说, 它建议每两个分组确认一个. 然而, 生成和处理 QUIC 确认会消耗发送端和接收端的资源. 确认还会产生转发开销并占用链路带宽, 这可能影响某些类型网络上的性能. 应用可以通过采用降低确认速率的替代策略来提升整体性能. [QUIC-ACK-FREQUENCY] 描述了用于表明期望确认延迟的扩展, 并讨论了其用例以及对拥塞控制和恢复的影响.

8. 端口选择与应用端点发现 (Port Selection and Application Endpoint Discovery)​

通常, 端口号有两个用途: "首先, 它们提供一个解复用标识符, 用于区分同一对端点之间的不同传输会话; 其次, 它们也可以标识进程所连接的应用协议及相关服务" ([RFC6335] 第 3 节). 如 [RFC6335] 所述, 由于封装机制和动态端口分配机制的存在, 如今基于端口号在网络中识别应用的假设已不太成立.

由于 QUIC 是一种通用传输协议, 并没有要求服务器为 QUIC 使用某个特定的 UDP 端口. 对于具有 TCP 回退且尚未有 UDP 替代映射的应用, 通常恰当的做法是 (在必要时) 注册并使用与该应用已注册的 TCP 端口相对应的 UDP 端口号. 例如, HTTP/3 [QUIC-HTTP] 的默认端口是 UDP 端口 443, 类比于 TCP 上 TLS 之上的 HTTP/1.1 或 HTTP/2.

鉴于网络管理实践中普遍存在端口号与应用一一对应的假设, 使用那些难以映射到已注册服务名的端口, 可能会导致使用端口号进行应用识别的防火墙等网络设备对流量加以阻止或改变其转发行为.

应用可以定义替代的端点发现机制, 以允许使用默认端口之外的端口. 例如, HTTP/3 ([QUIC-HTTP] 第 3.2 节和第 3.3 节) 规定 HTTP 源 (origin) 可以使用 HTTP 替代服务 (Alternative Services) [RFC7838], 以 "h3" 作为应用层协议协商 (ALPN) [RFC7301] 令牌, 通告某个 UDP 端口上等效的 HTTP/3 端点的可用性.

ALPN 允许客户端和服务器协商在给定连接上使用多个协议中的哪一个. 因此, 单个 UDP 端口可以基于所提供的 ALPN 令牌支持多个应用. 使用 QUIC 的应用必须注册一个 ALPN 令牌以供 TLS 握手使用.

由于 QUIC 版本 1 推迟定义完整的版本协商机制, HTTP/3 要求使用 QUIC 版本 1, 并将其定义的 ALPN 令牌 ("h3") 限定为仅适用于该版本. 迄今为止, 无论是在 HTTP/3 中还是在更一般的场景中, 都尚未选定管理不同 QUIC 版本使用的统一方法. 使用 QUIC 的应用协议需要考虑其协议将如何管理不同的 QUIC 版本. 这些协议的决策可以参考其他协议 (如 HTTP/3) 所做的选择.

8.1. 源端口选择 (Source Port Selection)​

一些 UDP 协议容易受到反射攻击, 攻击者借此能够把流量引向第三方, 形成拒绝服务. 例如, 以下源端口就与已知易受反射攻击的应用相关联, 其原因往往是服务器配置不当:

  • 端口 53 - DNS [RFC1034]

  • 端口 123 - NTP [RFC5905]

  • 端口 1900 - SSDP [SSDP]

  • 端口 5353 - mDNS [RFC6762]

  • 端口 11211 - memcache

服务方可能会封锁与已知易受反射攻击的协议相关联的源端口, 以避免处理大量数据包的开销. 然而, 这种做法会给客户端带来负面影响 -- 客户端不仅需要建立新的连接, 而且在某些情况下还可能导致客户端在一段时间内避免对该服务使用 QUIC, 并降级到非 UDP 协议 (见第 2 节).

因此, 鼓励客户端实现避免使用与已知易受反射攻击的协议相关联的源端口. 注意, 遵循 [RFC6335] 中针对客户端实现给出的一般性指导, 即使用 49152-65535 范围内的临时端口, 其效果就是避开了这些端口. 还要注意, 其他源端口也可能成为反射攻击的载体.

9. 连接迁移 (Connection Migration)​

QUIC 支持客户端发起的连接迁移. 当客户端的 IP 地址发生变化时, QUIC 端点仍然可以借助 QUIC 头部中的目的连接 ID 字段 (见第 11 节) 把数据包与现有的传输连接关联起来. 这支持了地址信息发生变化的多种情形, 例如 NAT 重绑定、有意更换本地接口、临时 IPv6 地址过期 [RFC8981], 或者服务器指示一个首选地址 ([QUIC] 第 9.6 节).

如果任何客户端处于 NAT 之后或可能处于 NAT 之后, 强烈建议服务器使用非零长度的连接 ID. 在支持主动迁移时, 同样强烈建议使用非零长度的连接 ID. 若连接被有意迁移到新路径, 则会使用新的连接 ID, 以尽量降低网络观察者进行链接的可能性. 只要提供了非零长度的连接 ID, 另一端 QUIC 端点就可以使用该连接 ID 把不同地址关联到同一连接和同一实体上.

QUIC 版本 1 的基础规范在同一时刻只支持使用单一网络路径, 这足以支撑故障切换类用例. 需要进行路径验证, 让端点在使用路径之前先对其加以验证, 以防范地址伪造攻击. 路径验证至少需要一个 RTT, 而且路径迁移之后拥塞控制也会被重置. 因此, 迁移通常会对性能产生影响.

QUIC 探测包可以同时在多条路径上发送, 用于执行地址验证以及测量路径特性. 探测包不能携带应用数据, 但很可能包含填充帧. 端点可以把关于其接收情况的信息作为该路径拥塞控制的输入. 应用可以利用从探测中学到的信息, 为切换路径的决策提供依据.

在 QUIC 版本 1 中, 只有客户端能够主动迁移. 不过, 服务器可以在握手期间表明自己更愿意在握手之后把连接转移到另一个地址. 例如, 这可以用于把连接从多个服务器共享的地址迁移到某个服务器实例独有的地址. 服务器可以在 TLS 握手期间通过传输参数提供一个 IPv4 地址和一个 IPv6 地址, 若两者都提供, 客户端可以在二者之间进行选择. 见 [QUIC] 第 9.6 节.

10. 连接终止 (Connection Termination)​

QUIC 连接以三种方式之一终止: 隐式空闲超时、显式立即关闭, 或显式无状态重置.

QUIC 没有提供任何优雅连接终止机制; 使用 QUIC 的应用可以定义自己的优雅终止流程 (例如 [QUIC-HTTP] 第 5.2 节).

QUIC 空闲超时通过传输参数启用. 客户端和服务器各自通告一个超时时长, 连接的实际生效值是两者中的较小值. 超时时长经过之后, 连接会被静默关闭. 因此, 应用应当能够配置自己的最大值, 并能够获取为该连接计算出的最小值. 应用可以根据已打开或预期打开的连接数量, 为新连接调整最大空闲超时, 因为较短的超时值可以更快地释放资源.

在流上或数据报中交换的应用数据会推迟 QUIC 空闲超时. 因此, 提供自身保活机制的应用会让 QUIC 连接保持存活. 未提供自身保活机制的应用可以使用传输层机制 (见 [QUIC] 第 10.1.2 节和第 3.2 节). 然而, QUIC 实现中控制这类传输行为的接口可能各不相同, 从而影响这类方法的稳健性.

立即关闭通过 CONNECTION_CLOSE 帧 (见第 6 节) 传递信号. 立即关闭会使所有流立刻变为关闭状态, 这可能对应用产生影响; 见第 4.5 节.

无状态重置是端点在无法访问连接状态时的最后手段. 收到无状态重置表明发生了不可恢复的错误, 它与连接错误的不同之处在于不提供任何应用层信息.

11. 信息暴露与连接 ID (Information Exposure and the Connection ID)​

QUIC 会在头部未加密的部分向网络暴露一些信息, 或是在加密上下文建立之前, 或是因为这些信息本就打算供网络使用. 关于 QUIC 可管理性的更多信息, 见 [QUIC-MANAGEABILITY]. QUIC 有一种长头部, 会暴露一些额外的信息 (版本和源连接 ID); 而短头部只暴露目的连接 ID. 在 QUIC 版本 1 中, 长头部用于连接建立期间, 短头部用于已建立连接的数据传输.

连接 ID 可以是零长度的. 每个端点都可以独立选择零长度连接 ID, 并且除客户端在连接建立期间发送的首批数据包之外, 在任何数据包上都可以使用.

选择零长度连接 ID 的端点将收到目的连接 ID 为零长度的数据包. 这样的端点需要借助其他信息, 例如源和目的 IP 地址及端口号, 来识别所指的是哪条连接. 这可能意味着, 如果这些值发生变化, 端点将无法成功把数据报匹配到连接上, 从而使连接实际上无法在 NAT 重绑定后存活, 也无法迁移到新路径.

11.1. 服务器生成的连接 ID​

QUIC 支持由服务器生成连接 ID, 并在连接建立期间发送给客户端 (见 [QUIC] 第 7.2 节). 位于负载均衡器之后的服务器可能需要在握手期间更换连接 ID, 把服务器身份或其负载均衡池的相关信息编码进去, 以支持无状态负载均衡.

带有负载均衡器和其他路由基础设施的服务器部署, 需要确保这些基础设施始终把数据包路由到持有连接状态的那台服务器实例, 即使地址、端口或连接 ID 发生变化也是如此. 这可能需要在服务器与基础设施之间进行协调. 实现这一点的一种方法是把路由信息编码到连接 ID 中. 关于这一技术的示例, 见 [QUIC-LB].

11.2. 用连接 ID 迁移缓解时序可链接性​

如果 QUIC 端点不签发新的连接 ID, 客户端就无法利用连接 ID 来降低地址迁移带来的可链接性. 选择对外部观察者而言不可链接的取值, 可以确保不同路径上的活动无法通过连接 ID 被轻易关联起来.

虽然足够健壮的连接 ID 生成方案能够缓解可链接性问题, 但它们并不能提供完整的保护. 对 6 元组 (源和目的地址以及迁移后的连接 ID) 生命周期的分析, 仍可能暴露这些关联.

在服务器池中连接迁移很少发生的情形下, 观察者将两个连接 ID 关联起来是轻而易举的事. 反过来, 当每台服务器同时处理多个迁移时, 即便服务器映射关系已经暴露, 这些信息也可能并不足够.

应对这些攻击最有效的缓解手段来自网络设计和/或运营实践, 例如: 使用把更多流量汇聚到同一服务器端地址的负载均衡架构, 通过协调迁移的时机来设法增加同一时刻同时发生的迁移数量, 或者采用其他方式.

11.3. 使用服务器 Retry 进行重定向​

QUIC 提供了 Retry 包, 服务器可以在收到客户端 Initial 包之后发送 Retry 包作为响应. 服务器可以在该包中选择一个新的连接 ID, 客户端随后会使用服务器选定的连接 ID 重新发送一个客户端 Initial 包进行重试. 这一机制可用于把连接重定向到另一台服务器, 例如出于性能方面的原因, 或者当服务器池中的服务器在逐步升级、因而可能支持不同 QUIC 版本时.

在这种情况下, 假定属于某个池的所有服务器都是在负载均衡器的配合下提供服务的, 负载均衡器基于连接 ID 转发流量. 服务器可以在 Retry 包中选择连接 ID, 使负载均衡器把下一个 Initial 包重定向到该池中的另一台服务器. 或者, 负载均衡器也可以直接提供 Retry 卸载 (offload), 更多描述见 [QUIC-RETRY].

[RFC5077] 第 4 节中描述的构造 TLS 会话恢复票据的方法, 提供了一个同样可以应用于验证令牌的示例. 不过, 强烈建议使用更现代的密码算法.

12. QoS 与 DSCP (Quality of Service and Diffserv Code Point)​

正如 [QUIC] 中定义的那样, QUIC 只有一个拥塞控制器和一个恢复处理器. 这一设计假定: 同一条 QUIC 连接的所有数据包 (或至少是具有相同 5 元组 {目的地址, 源地址, 协议, 目的端口, 源端口} 的数据包), 只要带有相同的区分服务码点 (DSCP) [RFC2475], 就会得到相似的网络处理, 因为关于每个数据包丢失或延迟的反馈都会作为拥塞控制器的输入. 因此, 属于同一连接的数据包应当使用单一的 DSCP. [RFC7657] 第 5.1 节讨论了 Diffserv 与数据报传输协议的交互 ([RFC7657]); 在这方面, 与 QUIC 的交互类似于与流控制传输协议 (SCTP) 的交互.

当在单一 QUIC 连接上复用多条流时, 所选择的 DSCP 值应当是所有被复用流中请求的最高优先级所对应的那个值.

如果希望得到有差别的网络处理, 例如使用不同的 DSCP, 可以使用指向同一服务器的多条 QUIC 连接. 一般而言, 建议尽量减少指向同一服务器的 QUIC 连接数量, 以避免增加开销, 更重要的是避免拥塞控制之间的相互竞争.

与 Diffserv 的其他使用场景一样, 当数据包进入一个不支持该 DSCP 值的网段时, 可能导致连接得不到它所期望的网络处理. 随着数据包沿网络路径传送, 其中的 DSCP 值也可能被重新标记, 从而改变所请求的处理方式.

13. 版本与密码握手的使用 (Use of Versions and Cryptographic Handshake)​

QUIC 的版本化可能彻底改变协议的行为, 只有少数被声明为不变量 (invariant) 的头部字段的含义保持不变 [QUIC-INVARIANTS]. 版本号较高的 QUIC 版本不一定提供更好的服务, 而可能只是提供一组不同的特性. 因此, 应用需要能够选择自己想要使用哪些版本的 QUIC.

新版本可以使用 TLS 1.3 或更高版本以外的加密方案. [QUIC] 规定了密码握手所需满足的要求, 该握手目前由 TLS 1.3 实现, 并在单独的规范 [QUIC-TLS] 中描述. 之所以进行这种拆分, 是为了实现带有不同密码握手的轻量级版本化.

[QUIC] 中建立的 "QUIC Versions" 注册表允许为实验目的进行临时注册. 进行注册 (包括实验性版本的注册) 对于避免冲突非常重要. 实验性版本不应长期使用, 也不应注册为永久版本, 以尽量降低基于版本号进行指纹识别的风险.

14. 支持新版本部署 (Enabling Deployment of New Versions)​

QUIC 版本 1 在其基础规范中并未规定版本协商机制, 但 [QUIC-VERSION-NEGOTIATION] 提出了一种可提供兼容版本协商 (compatible version negotiation) 的扩展.

该方法使用三阶段的部署机制, 支持在大型服务器部署中对多个版本进行渐进式推出和实验. 在该方法中, 部署中的所有服务器必须先全部接受使用新版本的连接 (阶段 1), 之后任何服务器才能通告该版本 (阶段 2), 而新版本的认证 (阶段 3) 只有在该版本的通告完全部署完毕之后才会进行.

详情参见 [QUIC-VERSION-NEGOTIATION] 第 5 节.

15. QUIC 上的不可靠数据报服务 (Unreliable Datagram Service over QUIC)​

[RFC9221] 规定了一个 QUIC 扩展, 用于在 QUIC 上发送和接收不可靠数据报 (unreliable datagram). 与直接运行在 UDP 之上不同, 使用 QUIC 数据报服务的应用无需按照 [RFC8085] 自行实现拥塞控制, 因为 QUIC 数据报本身受拥塞控制.

QUIC 数据报不受流量控制, 因此当接收方过载时, 数据块可能会被丢弃. QUIC 的可靠传输服务提供基于流的接口, 可以在多条 QUIC 流上按序发送和接收数据; 而数据报服务提供的则是无序的、基于消息的接口. 如有需要, 可以在其上再使用应用层分帧, 以便将多个相互独立的不可靠数据报流复用在同一条 QUIC 连接上.

16. IANA 考虑 (IANA Considerations)​

本文档没有需要 IANA 执行的动作; 但请注意, 第 8 节建议: 已经注册了 TCP 端口但希望指定 QUIC 作为传输方式的应用, 应当参照其现有的 TCP 注册方式, 注册一个对应的 UDP 端口.

17. 安全考虑 (Security Considerations)​

参见 [QUIC] 和 [QUIC-TLS] 中的安全考虑章节; 底层传输协议的安全考虑对使用 QUIC 的应用同样相关. 在部署和使用 QUIC 时, 应当考虑 [QUIC-TLS] 中讨论的可链接性 (linkability)、重放攻击和随机性等问题.

此外, 迁移到新地址会在客户端地址之间向服务器暴露关联, 并可能在连接 ID 无法更改或流可被关联时向路径暴露该关联. 在支持迁移时, 需要从用户隐私角度考虑.

应用开发者应注意: 当因网络阻断 UDP 而无法使用 QUIC 时, 其使用的任何回退应保证与 QUIC 相同的安全属性. 若不可能, 连接应失败, 以允许应用显式处理回退到安全性较弱的替代方案. 见第 2 节.

此外, [QUIC-HTTP] 提供特定于 HTTP 的安全考虑. 然而, 关于跨协议攻击、流量分析与填充或迁移的讨论也可能与其他使用 QUIC 的应用相关.

18. 参考文献 (References)​

18.1. 规范性引用 (Normative References)​

[QUIC] 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.

[QUIC-INVARIANTS] Thomson, M., "Version-Independent Properties of QUIC", RFC 8999, DOI 10.17487/RFC8999, May 2021, https://www.rfc-editor.org/info/rfc8999.

[QUIC-TLS] Thomson, M., Ed. and S. Turner, Ed., "Using TLS to Secure QUIC", RFC 9001, DOI 10.17487/RFC9001, May 2021, https://www.rfc-editor.org/info/rfc9001.

18.2. 资料性引用 (Informative References)​

[Edeline16] Edeline, K., Kühlewind, M., Trammell, B., Aben, E., and B. Donnet, "Using UDP for Internet Transport Evolution", DOI 10.48550/arXiv.1612.07816, 22 December 2016, https://arxiv.org/abs/1612.07816.

[Hatonen10] Hätönen, S., Nyrhinen, A., Eggert, L., Strowes, S., Sarolahti, P., and M. Kojo, "An Experimental Study of Home Gateway Characteristics", Proc. ACM IMC 2010, November 2010, https://conferences.sigcomm.org/imc/2010/papers/p260.pdf.

[HTTP-REPLAY] Thomson, M., Nottingham, M., and W. Tarreau, "Using Early Data in HTTP", RFC 8470, DOI 10.17487/RFC8470, September 2018, https://www.rfc-editor.org/info/rfc8470.

[PaaschNanog] Paasch, C., "Network support for TCP Fast Open", NANOG 67 Presentation, 13 June 2016, https://www.nanog.org/sites/default/files/Paasch_Network_Support.pdf.

[QUIC-ACK-FREQUENCY] Iyengar, J. and I. Swett, "QUIC Acknowledgement Frequency", Work in Progress, Internet-Draft, draft-ietf-quic-ack-frequency-02, 11 July 2022, https://datatracker.ietf.org/doc/html/draft-ietf-quic-ack-frequency-02.

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

[QUIC-LB] Duke, M., Banks, N., and C. Huitema, "QUIC-LB: Generating Routable QUIC Connection IDs", Work in Progress, Internet-Draft, draft-ietf-quic-load-balancers-14, 11 July 2022, https://datatracker.ietf.org/doc/html/draft-ietf-quic-load-balancers-14.

[QUIC-MANAGEABILITY] Kühlewind, M. and B. Trammell, "Manageability of the QUIC Transport Protocol", RFC 9312, DOI 10.17487/RFC9312, September 2022, https://www.rfc-editor.org/info/rfc9312.

[QUIC-RETRY] Duke, M. and N. Banks, "QUIC Retry Offload", Work in Progress, Internet-Draft, draft-ietf-quic-retry-offload-00, 25 May 2022, https://datatracker.ietf.org/doc/html/draft-ietf-quic-retry-offload-00.

[QUIC-VERSION-NEGOTIATION] Schinazi, D. and E. Rescorla, "Compatible Version Negotiation for QUIC", Work in Progress, Internet-Draft, draft-ietf-quic-version-negotiation-10, 27 September 2022, https://datatracker.ietf.org/doc/html/draft-ietf-quic-version-negotiation-10.

[RFC1034] Mockapetris, P., "Domain names - concepts and facilities", STD 13, RFC 1034, DOI 10.17487/RFC1034, November 1987, https://www.rfc-editor.org/info/rfc1034.

[RFC2475] Blake, S., Black, D., Carlson, M., Davies, E., Wang, Z., and W. Weiss, "An Architecture for Differentiated Services", RFC 2475, DOI 10.17487/RFC2475, December 1998, https://www.rfc-editor.org/info/rfc2475.

[RFC5077] Salowey, J., Zhou, H., Eronen, P., and H. Tschofenig, "Transport Layer Security (TLS) Session Resumption without Server-Side State", RFC 5077, DOI 10.17487/RFC5077, January 2008, https://www.rfc-editor.org/info/rfc5077.

[RFC5382] Guha, S., Ed., Biswas, K., Ford, B., Sivakumar, S., and P. Srisuresh, "NAT Behavioral Requirements for TCP", BCP 142, RFC 5382, DOI 10.17487/RFC5382, October 2008, https://www.rfc-editor.org/info/rfc5382.

[RFC5905] Mills, D., Martin, J., Ed., Burbank, J., and W. Kasch, "Network Time Protocol Version 4: Protocol and Algorithms Specification", RFC 5905, DOI 10.17487/RFC5905, June 2010, https://www.rfc-editor.org/info/rfc5905.

[RFC6335] Cotton, M., Eggert, L., Touch, J., Westerlund, M., and S. Cheshire, "Internet Assigned Numbers Authority (IANA) Procedures for the Management of the Service Name and Transport Protocol Port Number Registry", BCP 165, RFC 6335, DOI 10.17487/RFC6335, August 2011, https://www.rfc-editor.org/info/rfc6335.

[RFC6762] Cheshire, S. and M. Krochmal, "Multicast DNS", RFC 6762, DOI 10.17487/RFC6762, February 2013, https://www.rfc-editor.org/info/rfc6762.

[RFC7301] Friedl, S., Popov, A., Langley, A., and E. Stephan, "Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension", RFC 7301, DOI 10.17487/RFC7301, July 2014, https://www.rfc-editor.org/info/rfc7301.

[RFC7413] Cheng, Y., Chu, J., Radhakrishnan, S., and A. Jain, "TCP Fast Open", RFC 7413, DOI 10.17487/RFC7413, December 2014, https://www.rfc-editor.org/info/rfc7413.

[RFC7657] Black, D., Ed. and P. Jones, "Differentiated Services (Diffserv) and Real-Time Communication", RFC 7657, DOI 10.17487/RFC7657, November 2015, https://www.rfc-editor.org/info/rfc7657.

[RFC7838] Nottingham, M., McManus, P., and J. Reschke, "HTTP Alternative Services", RFC 7838, DOI 10.17487/RFC7838, April 2016, https://www.rfc-editor.org/info/rfc7838.

[RFC8085] 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.

[RFC8981] Gont, F., Krishnan, S., Narten, T., and R. Draves, "Temporary Address Extensions for Stateless Address Autoconfiguration in IPv6", RFC 8981, DOI 10.17487/RFC8981, February 2021, https://www.rfc-editor.org/info/rfc8981.

[RFC9218] Oku, K. and L. Pardue, "Extensible Prioritization Scheme for HTTP", RFC 9218, DOI 10.17487/RFC9218, June 2022, https://www.rfc-editor.org/info/rfc9218.

[RFC9221] 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.

[SSDP] Donoho, A., Roe, B., Bodlaender, M., Gildred, J., Messer, A., Kim, Y., Fairman, B., and J. Tourzan, "UPnP Device Architecture 2.0", 17 April 2020, https://openconnectivity.org/upnp-specs/UPnP-arch-DeviceArchitecture-v2.0-20200417.pdf.

[Swett16] Swett, I., "QUIC Deployment Experience @Google", IETF96 QUIC BoF Presentation, 20 July 2016, https://www.ietf.org/proceedings/96/slides/slides-96-quic-3.pdf.

[TAPS-ARCH] Pauly, T., Trammell, B., Brunstrom, A., Fairhurst, G., and C. Perkins, "An Architecture for Transport Services", Work in Progress, Internet-Draft, draft-ietf-taps-arch-14, 27 September 2022, https://datatracker.ietf.org/doc/html/draft-ietf-taps-arch-14.

[TLS13] Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, https://www.rfc-editor.org/info/rfc8446.

[Trammell16] Trammell, B. and M. Kühlewind, "Internet Path Transparency Measurements using RIPE Atlas", RIPE 72 MAT Presentation, 25 May 2016, https://ripe72.ripe.net/wp-content/uploads/presentations/86-atlas-udpdiff.pdf.

致谢 (Acknowledgments)​

特别感谢 Last Call 审阅者 Chris Lonvick 与 Ines Robles.

本工作部分得到欧洲委员会 Horizon 2020 资助协议 no. 688421 (MAMI) 以及瑞士国家教育、研究与创新秘书处合同 no. 15.0268 的支持. 该支持不意味着背书.

贡献者 (Contributors)​

Gorry Fairhurst, Ian Swett, Igor Lubashev, Lucas Pardue, Mike Bishop, Mark Nottingham, Martin Duke, Martin Thomson, Sean Turner, Tommy Pauly 等对本文件贡献了重要文本或反馈.

作者地址 (Authors' Addresses)​

Mirja Kühlewind Ericsson Email: [email protected]

Brian Trammell Google Switzerland GmbH Gustav-Gull-Platz 1 CH-8004 Zurich Switzerland Email: [email protected]