拓冰建站拓冰建站
首页 / 资讯中心 / 正文

FastAPI HTTPS 部署指南:证书、SNI、TLS 终止代理与代理转发头的完整解析

FastAPI HTTPS 部署指南证书、SNI、TLS 终止代理与代理转发头的完整解析【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi本篇指南基于 FastAPI 官方文档《About HTTPS》docs/en/docs/deployment/https.md系统讲解 HTTPS 对开发者真正重要的底层机制证书生命周期、TCP 层加密与 SNI 扩展、TLS 终止代理的工作流程、Lets Encrypt 自动续期以及如何用 FastAPI CLI 的--forwarded-allow-ips选项让应用感知自身处于 HTTPS 反代之后。读完本文你将能够独立设计并配置一个带 HTTPS 的 FastAPI 生产部署架构。HTTPS 不是开关开发者视角的核心概念很多人以为 HTTPS 只是在服务器上启用或不启用的一个开关但它远比这复杂。以下是官方文档中列出的、在思考 HTTPS 时必须记住的开发者视角要点对于 HTTPS服务器需要持有由第三方机构签发的证书certificates。严格来说证书是从第三方**获取acquired**的而不是生成出来的。证书有生命周期它们会过期过期后需要续期renew即再次向第三方获取。连接的加密发生在TCP 层——这是比 HTTP 低一层。因此证书与加密的处理先于 HTTP完成。TCP 协议不认识域名它只认识 IP 地址。关于请求的是哪个具体域名的信息是放在HTTP 数据里的。HTTPS 证书认证的绑定的是一个特定域名但协议协商和加密却发生在 TCP 层此时还不知道对方访问的是哪个域名。默认情况下这意味着你每个 IP 地址只能有一张 HTTPS 证书。无论你的服务器多大、上面部署了多少个小应用。不过这个问题有解决方案。TLS 协议即处理 TCP 层加密、先于 HTTP 的那一层有一个扩展叫SNIServer Name Indication服务器名称指示SNI 允许一台单 IP 地址的服务器持有多张 HTTPS 证书从而为多个 HTTPS 域名/应用提供服务。要做到这一点必须有一个单一的组件程序运行在服务器上、监听公网 IP 地址并且持有服务器上所有的 HTTPS 证书。建立安全连接之后通信协议仍然是 HTTP内容是被加密的但承载协议依旧是 HTTP。理解这几点之后架构设计就自然得出了让一个程序/HTTP 服务器通常称为TLS 终止代理TLS Termination Proxy专门管理服务器上所有的 HTTPS 部分——接收加密的 HTTPS 请求将解密后的明文 HTTP 请求转发给真正的 HTTP 应用在本例中即运行在同一台服务器上的FastAPI应用再从应用取回HTTP 响应用合适的HTTPS 证书加密后发回给客户端。可作为 TLS 终止代理的常见选项包括Traefik还能自动处理证书续期Caddy也能自动处理证书续期NginxHAProxyLets Encrypt让免费且永久的安全 HTTPS成为可能在 Lets Encrypt 出现之前这些HTTPS 证书由受信任的第三方机构出售获取流程繁琐、需要不少文书工作而且证书价格相当昂贵。Lets Encrypt是 Linux 基金会旗下的项目它以自动化方式免费提供 HTTPS 证书。这些证书使用全部标准加密安全机制且有效期很短约 3 个月——正因生命周期短其安全性实际上更好。Lets Encrypt 会对域名进行安全验证并自动生成证书这也使得证书续期可以被完全自动化。其核心理念就是自动完成证书的获取与续期让你拥有免费的、永久的、安全的 HTTPS。逐步拆解一个 HTTPS API 请求的完整生命周期下面以开发者最关心的思路为主线一步步看一个 HTTPS API 是如何运转的。域名Domain Name一切通常从购买一个域名开始。随后在 DNS 服务器通常是你的云服务商提供的上配置它。你可能会租一台云服务器虚拟机它会拥有一个固定fixed即不随时间变化、非动态的公网 IP 地址。在 DNS 服务器上你会配置一条记录A 记录把你的域名指向服务器的公网 IP 地址。这一步通常只在第一次搭建环境时做一次。提示域名部分发生在 HTTPS 之前但由于一切都依赖于域名与 IP 地址值得在此先交代。DNS 解析浏览器先向DNS 服务器查询该域名对应的 IP以someapp.example.com为例。DNS 服务器会告诉浏览器使用某个具体的IP 地址——即你之前配置到 DNS 服务器上的、你服务器使用的公网 IP。TLS 握手开始TLS Handshake Start随后浏览器通过443 端口HTTPS 端口与该 IP 地址通信。通信的第一部分是建立客户端与服务端之间的连接并确定双方将使用的加密密钥等。这段客户端与服务端之间建立 TLS 连接的交互过程就是TLS 握手TLS handshake。带 SNI 扩展的 TLS 协商一个特定IP 地址的特定端口上只能有一个进程在监听。同一 IP 上可以有其他进程监听其他端口但每个IP 端口组合只能有一个进程。TLSHTTPS默认使用443端口所以我们需要这个端口。由于只有一个进程可以监听该端口执行监听的就是TLS 终止代理。TLS 终止代理持有一张或多张TLS 证书HTTPS 证书。借助前文提到的SNI 扩展TLS 终止代理会检查当前可用证书中哪一张应该用于这条连接——选择与客户端期望的域名匹配的那一张。在本例中它会使用someapp.example.com的证书。客户端已经信任签发该 TLS 证书的实体本例中是 Lets Encrypt因此可以验证该证书有效。接着客户端与 TLS 终止代理使用该证书商定如何加密后续所有的TCP 通信至此TLS 握手部分完成。此后客户端与服务器之间拥有了一条加密的 TCP 连接——这正是 TLS 提供的能力。然后双方在这条连接之上开始真正的HTTP 通信。这就是HTTPS的本质它就是普通的 HTTP只是跑在一条安全的 TLS 连接内而不是跑在一条纯未加密的 TCP 连接上。提示注意通信的加密发生在TCP 层而不是 HTTP 层。HTTPS 请求现在客户端浏览器与服务器具体说是 TLS 终止代理之间已有一条加密 TCP 连接可以开始HTTP 通信了。客户端发出的HTTPS 请求本质上就是一条通过加密 TLS 连接传输的 HTTP 请求。解密请求Decrypt the RequestTLS 终止代理使用商定好的加密方式解密请求并把明文解密后的HTTP 请求转发给运行应用的进程——例如运行着 FastAPI 应用的Uvicorn进程。HTTP 响应应用处理完请求后向 TLS 终止代理发送一条明文未加密的 HTTP 响应。HTTPS 响应TLS 终止代理随后用之前商定好的加密方式起始于someapp.example.com的证书加密响应并将其发回浏览器。浏览器验证响应有效、且用正确的密钥加密之后解密响应并处理它。客户端浏览器能够确定响应确实来自正确的服务器因为它使用的正是双方之前通过HTTPS 证书商定好的加密体系。多台应用共享一台服务器在同一台服务器或几台服务器上可以部署多个应用——例如其他 API 程序或数据库。只有一个进程可以占用那个特定的 IP 与端口组合本例中是 TLS 终止代理但其他应用/进程同样可以运行在这些服务器上只要它们不试图使用相同的公网 IP 端口组合。这样TLS 终止代理就能为多个域名、多个应用处理 HTTPS 与证书再把请求转发给对应的应用。证书续期Certificate Renewal在未来的某个时间点每张证书都会过期获取后约 3 个月。届时会有另一个程序有时是另一个独立程序有时也可以是同一个 TLS 终止代理去联系 Lets Encrypt续期证书。TLS 证书是绑定域名的而不是绑定 IP 地址。因此续期程序需要向证书机构Lets Encrypt证明它确实**拥有并控制该域名**。为适应不同应用的部署形态有多种证明方式比较流行的有修改某些 DNS 记录。续期程序需要支持相应 DNS 服务商的 API因此这取决于你使用的 DNS 服务商可能可选也可能不可选。运行一个服务至少在证书获取过程中运行在该域名对应的公网 IP 地址上。如前所述只有一个进程可以监听特定的 IP 与端口。这正是同一个 TLS 终止代理同时负责证书续期非常有用的原因之一。否则你可能不得不临时停止TLS 终止代理、启动续期程序获取证书、把新证书配置进 TLS 终止代理、再重启TLS 终止代理。这样做并不理想因为代理停止期间应用将不可用。在应用持续服务的同时完成整个续期流程正是你希望用TLS 终止代理作为独立的 HTTPS 处理系统、而不是直接把 TLS 证书交给应用服务器例如 Uvicorn使用的最主要原因。代理转发头Proxy Forwarded Headers与--forwarded-allow-ips使用代理处理 HTTPS 时你的应用服务器例如通过 FastAPI CLI 运行的 Uvicorn完全不知道 HTTPS 过程的存在——它只是与TLS 终止代理之间用明文 HTTP通信。这个代理通常会在把请求传给应用服务器之前临时加上一些 HTTP 头告诉应用服务器请求是由代理**转发forwarded**过来的。技术细节代理头包括X-Forwarded-For原始客户端 IPX-Forwarded-Proto原始协议如httpsX-Forwarded-Host原始主机名不过由于应用服务器并不知道它背后有一个受信任的代理所以默认情况下它不会信任这些头。但你可以把应用服务器配置为信任由代理发来的forwarded头。如果使用 FastAPI CLI可以用CLI Option--forwarded-allow-ips指定应该信任哪些 IP 发来的forwarded头。例如如果应用服务器只与受信任的代理通信可以设置为--forwarded-allow-ips*来信任所有入站 IP——因为它实际只会收到来自代理所用 IP 的请求$ uv run fastapi run --forwarded-allow-ips*这样应用就能知道自己对外的公开 URL 是什么、是否使用 HTTPS、域名是什么等这对正确生成重定向redirects之类的场景非常有用。关于这一点可以从当前仓库的源码结构得到印证fastapi/cli.py 中的main()只是把fastapi命令委托给fastapi_cli.cli.main即独立分发的 fastapi-cli 包需安装pip install fastapi[standard]并明确提示缺少该包时的安装方式。因此--forwarded-allow-ips这类启动参数由 CLI 层实现最终由 ASGI 服务器Uvicorn解析代理头并传递给应用。完整用法含重定向示例、root_path配置与本地 Traefik 联调参见官方进阶文档 Behind a Proxy其中 Enable Proxy Forwarded Headers 小节专门讲解--forwarded-allow-ips与 HTTPS 重定向的关系。一个典型的场景是你的 API 部署在https://mysuperapp.com而 Uvicorn 本地监听http://127.0.0.1:8000。定义路由/items/时客户端访问/items会触发 307 重定向如果应用服务器不信任代理头重定向目标会被生成为http://localhost:8000/items/这样的内网地址配置--forwarded-allow-ips后重定向就会正确地指向https://mysuperapp.com/items/。验证当前请求上下文中的代理信息可以参考仓库中的示例代码 docs_src/behind_a_proxy/tutorial001_py310.pyfrom fastapi import FastAPI, Request app FastAPI() app.get(/app) def read_main(request: Request): return {message: Hello World, root_path: request.scope.get(root_path)}request.scopeASGI 规范的一部分中携带了服务器解析后的root_path等代理相关信息配合--root-path见 docs_src/behind_a_proxy/tutorial002_py310.py 中直接在FastAPI()构造函数传入root_path的写法应用就能正确地为集成文档 UI 生成 OpenAPI 的servers条目。小结Recap拥有HTTPS非常重要在大多数场景中甚至是关键性的。但作为开发者你在 HTTPS 上需要投入的大部分精力其实只是理解这些概念以及它们是如何运作的。一旦你掌握了上面面向开发者的 HTTPS基础知识就可以轻松地把不同工具Traefik、Caddy、Nginx、HAProxy 等 TLS 终止代理 Lets Encrypt 自动续期 FastAPI CLI 的代理头配置组合起来以简单的方式管理整个 HTTPS 生命周期。在 FastAPI 部署系列文档的后续章节中参见 deployment 目录 下的 manually、docker 等还会给出为FastAPI应用配置HTTPS的多个具体实操示例可以继续跟进阅读。【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门