利用 AWS Lambda 扩展和 Tailscale 建立安全的 Webhook 转发服务
关键要点
本文介绍如何使用 AWS Lambda 扩展和 Tailscale 创建一个安全的 Webhook 转发服务,以便与第三方系统集成。通过利用 WireGuard VPN 连接来确保安全性,并通过 API Gateway 管理 HTTP 请求。样例代码和架构可在 GitHub 上获取,提供自动化部署和最小维护开销的解决方案。本文由企业架构师 Duncan Parsons 和高级顾问 Simon Kok 撰写。
Webhook 使开发人员能够在构建事件驱动架构时与第三方系统或设备进行集成。然而,在某些情况下,控制目标的网络环境可能受限,或者目标的 IP 地址会发生变化。此外,一些端点缺乏足够的安全加强,需要设置反向代理和额外的安全检查以应对来自互联网的入站流量。
设置和维护高度可用的安全反向代理,以检测并将事件发送到多个后端系统是复杂的。本文展示了如何使用 AWS Lambda 扩展构建一个云原生无服务器 Webhook 转发服务,以满足这一需求,同时减少维护和运行成本。
自定义 Lambda 扩展通过一个安全的 WireGuard VPN 连接到一个位于状态防火墙和 NAT 网关 之后的私有子网目标。此示例设置一个公共 HTTPS 端点以接收事件,有选择地过滤请求并通过 WireGuard 连接进行代理。该示例采用无服务器架构,以最小化维护开销和运行成本。
示例概述
部署以下架构的示例代码可在 GitHub 上找到。这个示例使用 AWS CodePipeline 和 AWS CodeBuild 来构建代码制品,并通过 AWS CloudFormation 使用 AWS 云开发工具包 CDK进行部署。它利用 Amazon API Gateway 来管理 HTTPS 端点,并使用 Lambda 服务来执行应用程序功能。AWS Secrets Manager 存储 Tailscale 的凭据。
您可以使用 Tailscale 服务 的免费账户进行 WireGuard 连接的编排。或者,可以使用开源的 Headscale 示例设置自己的协调层。
事件生成者向 API Gateway URL 发送 HTTP 请求。API Gateway 将请求代理到 Lambda 授权器函数。该函数根据请求的源 IP 返回授权决策。API Gateway 将请求代理到运行 Tailscale 扩展的安全 Webhook 转发器 Lambda 函数。在初次调用时,Lambda 扩展从 Secrets Manager 检索 Tailscale Auth 密钥,并使用该密钥建立与适当 Tailscale 网络的连接。然后扩展将连接作为本地 SOCKS5 端口暴露给 Lambda 函数。Lambda 扩展通过 Tailscale 协调服务器维护与 Tailscale 网络的连接。通过此协调服务器,网络上所有其他设备都能了解到正在运行的 Lambda 函数,反之亦然。Lambda 函数配置为拒绝入站的 WireGuard 连接有关 shieldsup 命令的更多信息,请参见 这里。一旦与 Tailscale 网络的连接建立,安全的 Webhook 转发器 Lambda 函数便通过互联网使用 WireGuard 连接将请求转发到目标。连接通过 Tailscale 协调服务器建立,穿越 NAT 网关到达位于私有子网内的 Amazon EC2 实例。EC2 实例使用本地 Python Web 服务器响应 HTML 响应。部署后,每 60 天,Secrets Manager 将自动轮换 Tailscale Auth 密钥。它使用凭证轮换 Lambda 函数,从 Secrets Manager 检索 OAuth 凭据,利用这些凭据通过 Tailscale API 创建新的 Tailscale Auth 密钥,并将新密钥存储在 Secrets Manager 中。为了在逻辑上将网络连接层与应用程序代码层分开,Lambda 扩展封装了形成 Tailscale VPN 连接所需的代码,并通过本地 SOCK5 端口将其提供给 Lambda 函数应用程序代码。通过附加扩展,您可以在多个 Lambda 函数之间重用此连接性,以供多种用例使用。
要部署示例,请按照存储库中 README 的说明进行操作。部署可能需要 2030 分钟。
Lambda 扩展的工作原理
AWS Lambda 扩展 创建网络隧道并将其作为 SOCKS5 服务器暴露给 Lambda 函数,运行在 1055 端口。Lambda 具有三种生命周期阶段:初始化、调用和关闭。
通过 Tailscale Lambda 扩展,大部分工作在初始化阶段完成。Webhook 转发器 Lambda 函数的生命周期如下:
初始化阶段:扩展初始化 扩展连接到 Tailscale 网络,并通过本地 SOCKS5 端口暴露 WireGuard 隧道。运行时初始化 启动 Nodejs 运行时。函数初始化 导入所需的 Nodejs 模块。调用阶段:扩展故意不注册接收任何调用事件。Tailscale 网络保持在线,直到指示函数关闭。Nodejs 处理函数以 20 格式 从 API Gateway 接收请求,然后将其代理到 SOCKS5 端口,通过 WireGuard 连接将请求发送到目标。当函数收到来自目标 EC2 实例的响应后,调用阶段结束,并可选择将其返回给 API Gateway,以便转发到原始事件源。关闭阶段:扩展从 Tailscale 网络注销,并记录关闭事件的接收。函数执行环境与 Lambda 函数的执行环境一起关闭。扩展文件结构
扩展代码存在于一个 zip 文件中,其中包含发布扩展时设置的一些元数据。该 zip 文件包含三个文件夹:
/extensions 包含扩展代码,并且是 Lambda 服务在初始化 Lambda 扩展时查找运行代码的目录。/bin 包含可执行依赖项。例如,在 tsextensionsh 脚本中,运行 tailscale、tailscaled、curl、jq 和 OpenSSL 二进制文件。/ssl 存储证书颁发机构CA信任库包含受信任以进行连接的根 CA 证书。OpenSSL 使用这些证书来验证 SSL 和 TLS 证书。tsextensionsh 文件是扩展的核心。大多数代码在 Lambda 函数的初始化阶段运行。扩展代码分为三个阶段。前两个阶段与 Lambda 函数的初始化生命周期阶段相关,第三个阶段则涵盖调用和关闭生命周期阶段。
扩展阶段 1:初始化
在此阶段,扩展初始化 Tailscale 连接,并等待连接可用。
第一步从 Secrets Manager 中检索 Tailscale Auth 密钥。为了保持扩展大小小,扩展使用一系列 Bash 命令,而不是打包 AWS CLI 来制作 Sigv4 请求以访问 Secrets Manager。
Lambda 函数的临时凭据作为环境变量在 Lambda 执行环境中可用,扩展使用这些凭据来验证 Sigv4 请求。用于检索机密的 IAM 权限由 CDK 代码添加到 Lambda 执行角色。为了优化安全性,机密的策略限制了对其读取权限的访问1此 Lambda 函数和2每 60 天轮换它的 Lambda 函数。
Tailscale 代理使用 Tailscale Auth 密钥启动。tailscaled 和 tailscale 二进制文件以用户空间网络模式启动,因为每个 Lambda 函数都在其自己的容器上运行在自己的虚拟机中。有关用户空间网络模式的更多信息,请参见 Tailscale 文档。
Tailscale 进程启动后,该进程必须等待与 TailnetTailscale 网络的名称建立连接,并等待 SOCKS5 端口可用以接受连接。为此,扩展简单地等待 “tailscale status” 命令未返回带有 “stopped” 的消息,然后进入阶段 2。
扩展阶段 2:注册扩展现在向 Lambda 服务注册为已初始化。这是通过向 Lambda 服务扩展 API 发送 POST 请求,与扩展应转发的事件。
接下来运行时初始化这初始化 Lambda 函数本身的 Nodejs 运行时,然后是函数初始化事件处理程序外的代码。在 Tailscale Lambda 扩展的情况下,它只注册扩展接收 “SHUTDOWN” 事件。一旦 SOCKS5 服务已启动并可用,该扩展在之后的函数调用中没有其他操作。
飞鱼vnp官网扩展阶段 3:事件处理为了向扩展发出准备接收事件的信号,向 Lambda 运行时 API 的 “next” 端点发出 GET 请求。这会阻止扩展脚本执行,直到发送 SHUTDOWN 事件因为这是为此 Lambda 扩展注册的唯一事件。
发送该事件时,扩展从 Tailscale 服务注销,Lambda 函数关闭。如果还注册了 INVOKE 事件,扩展将处理该事件。然后它会向 Lambda 运行时 API 发回信号,表明扩展已准备好接收另一个事件,通过向 “next” 端点发送 GET 请求。
访问控制
此示例中包括一个示例 Lambda 授权器。建议使用 AWS Web 应用防火墙 服务为您的公共 API 端点增加额外保护,同时增强样本代码以满足生产使用的需求。
出于本演示的目的,实施展示了基本的源 IP CIDR 范围限制,但您可以基于请求的任何属性来做出授权决策。有关 HTTP API 的 Lambda 授权器的更多信息,请参见 这里。要使用源 IP 限制,请更新 Lambda 授权函数 AUTHDSOURCECIDR 环境变量中的 IP 接受的 CIDR 范围。
成本
您将根据此项目使用的所有资源收费。NAT 网关和 EC2 实例在最后一步手动释放管道后被销毁,以最小化成本。AWS Lambda 性能调优 工具可以帮助找到性能与成本之间的平衡,同时通过 Tailscale 网络轮询演示 EC2 实例。
以下结果显示,256 MB 的内存是最低执行成本的最佳选择。预计每月 100 万次请求的成本在 3 以下,一旦演示堆栈被销毁。
结论
使用 Lambda 扩展可以开启广泛的选项,以扩展无服务器架构的能力。本文展示了一个 Lambda 扩展,通过 WireGuard 协议和 Tailscale 服务创建一个安全的 VPN 隧道,代理事件到一个无法从互联网访问的 EC2 实例。
设置旨在最小化操作开销,并具备自动化部署管道。Lambda 授权器为端点提供安全性,允许根据请求内容和上下文实现自定义逻辑。
获取更多无服务器学习资源,请访问 无服务器地带。
标签: 贡献, 无服务器