FreeBSD 中文社区 2025 第二季度问卷调查
FreeBSD 中文社区(CFC)
VitePress 镜像站QQ 群 787969044视频教程Ⅰ视频教程Ⅱ
  • FreeBSD 从入门到追忆
  • 中文期刊
  • 状态报告
  • 发行说明
  • 手册
  • 网络文章集锦
  • 笔记本支持报告
  • Port 开发者手册
  • 架构手册
  • 开发者手册
  • 中文 man 手册
  • 文章
  • 书籍
  • FreeBSD 中文期刊
  • 编辑日志
  • 2025-123 下游项目
    • FreeBSD 发布工程:新主管上任
    • GhostBSD:从易用到挣扎与重生
    • BSD Now 与将来
    • 字符设备驱动教程(第三部分)
    • 学会走路——连接 GPIO 系统
    • FreeBSD 中对 SYN 段的处理
    • FreeBSD 2024 年秋季峰会
  • 2024-1112 虚拟化
    • 字符设备驱动程序教程(第二部分)
    • 面向 Linux 和 Windows 用户的 bhyve
    • Xen 与 FreeBSD
    • Wifibox:一种嵌入式虚拟化无线路由器
    • 嵌入式 FreeBSD:Fabric——起步阶段
    • DGP:一种新的数据包控制方法
    • 会议报告:我在都柏林的 EuroBSDCon 体验
  • 2024-0910 内核开发
    • 字符设备驱动程序教程
    • VPP 移植到了 FreeBSD:基础用法
    • 利用 Kyua 的 Jail 功能提升 FreeBSD 测试套件的并行效率
    • FreeBSD 上的 Valgrind
    • 嵌入式 FreeBSD:探索 bhyve
    • TCP/IP 历险记:FreeBSD TCP 协议栈中的 Pacing
    • 实用软件:实现无纸化(Paperless)
  • 2024-0708 存储与文件系统
    • FreeBSD 中的 NVMe-oF
    • FreeBSD iSCSI 入门
    • 使用 ZFS 原生加密保护数据
    • 嵌入式 FreeBSD:打造自己的镜像
    • TCP LRO 简介
    • 基于 Samba 的时间机器备份
  • 2024-0506 配置管理对决
    • 基本系统中的 mfsBSD
    • rdist
    • Hashicorp Vault
    • 在 GitHub 上向 FreeBSD 提交 PR
    • 悼念 Mike Karels
    • 2024 年 5-6 月来信
    • 嵌入式 FreeBSD 面包板
    • TCP/IP 历险记:TCP BBLog
    • 实用软件:开发定制 Ansible 模块
  • 2024-0304 开发工作流与集成
    • FreeBSD 内核开发工作流程
    • FreeBSD 与 KDE 持续集成(CI)
    • 更现代的内核调试工具
    • 从零开始的 ZFS 镜像及 makefs -t zfs
    • 提升 Git 使用体验
  • 2024-0102 网络(十周年)
    • FreeBSD 中的 RACK 栈和替代 TCP 栈
    • FreeBSD 14 中有关 TCP 的更新
    • if_ovpn 还是 OpenVPN
    • SR-IOV 已成为 FreeBSD 的重要功能
    • FreeBSD 接口 API(IfAPI)
    • BATMAN:更优的可移动热点网络方式
    • 配置自己的 VPN——基于 FreeBSD、Wireguard、IPv6 和广告拦截
    • 实用软件:使用 Zabbix 监控主机
  • 2023-1112 FreeBSD 14.0
    • LinuxBoot:从 Linux 启动 FreeBSD
    • FreeBSD 容器镜像
    • 现在用 Webhook 触发我
    • 新的 Ports 提交者:oel Bodenmann (jbo@freebsd.org)
  • 2023-0910 Port 与软件包
    • 回忆录:与 Warner Losh(@imp)的访谈
    • 在你自己的仓库中定制 Poudriere 源
    • Wazuh 和 MITRE Caldera 在 FreeBSD Jail 中的使用
    • PEP 517
    • CCCamp 2023 旅行报告
  • 2023-0708 容器与云
    • 在 Firecracker 上的 FreeBSD
    • 使用 pot 和 nomad 管理 Jail
    • 会议报告:C 与 BSD 正如拉丁语与我们——一位神学家的旅程
    • 抒怀之旅:与 Doug Rabson 的访谈
    • 基于 Jail 的广告拦截教程
    • 我们收到的来信
  • 2023-0506 FreeBSD 三十周年纪念特刊
    • CheriBSD 近十多年的历程
    • AArch64:成为 FreeBSD 新的一级架构
    • 岁月如梭:我个人的时间线
    • 安装 FreeBSD 1.0:回顾 30 年前
    • ZFS 是如何进入 FreeBSD 的呢?
    • 我不是来自约克郡的,我保证!
    • 回忆录:采访 David Greenman Lawrence
    • FreeBSD 和早期的 Unix 社区
    • 早期的 FreeBSD 移植
    • FreeBSD 30 周年:成功的秘诀
    • FreeBSD 在日本:回忆之旅与今日之实
  • 2023-0304 嵌入式
    • CheriBSD port 和软件包
    • 让我们来试试 ChatGPT
    • GPU 直通
  • 2023-0102 构建 FreEBSD Web 服务器
    • ZFS 的原子 I/O 与 PostgreSQL
    • 虚拟实验室——BSD 编程研讨会
    • ZFS 简介
    • 会议报告:落基山庆祝女性计算机科学家
    • 进行中的工作/征求反馈:数据包批处理
    • 基金会与 FreeBSD 桌面
  • 2022-1112 可观测性和衡量标准
    • 在 FreeBSD 的 DDB 内核调试器中编写自定义命令
    • DTrace:老式跟踪系统的新扩展
    • 基于证书的 Icinga 监控
    • 活动监控脚本(activitymonitor.sh)
    • 实用 IPv6(第四部分)
    • EuroBSDCon 会议报道
    • 实用 Port:Prometheus 的安装与配置
    • 书评:《用火解决问题:管理老化的计算机系统(并为现代系统保驾护航)》Kill It with Fire: Manage Aging Computer Systems (and Future Proof Modern Ones)
  • 2022-0910 安全性
    • CARP 简介
    • 重构内核加密服务框架
    • PAM 小窍门
    • SSH 小窍门
    • 实用 IPv6(第三部分)
    • 书评:Understanding Software Dynamics(深入理解软件性能——一种动态视角)—— Richard L. Sites 著
    • 访谈:保障 FreeBSD 安全性
    • MCH 2022 会议报告
  • 2022-0708 科研、系统与 FreeBSD
    • 在 FreeBSD 上构建 Loom 框架
    • 教授本科生 Unix 课程
    • FreeBSD 入门研讨会
    • 实用 IPv6(第二部分)
    • 在 2022 年及以后推广 FreeBSD
    • 进行中的工作/征求反馈:Socket 缓冲区
    • FreeBSD 开发者峰会报告
    • 支持 Electromagnetic Field 2022
  • 2022-0506 灾难恢复
    • 使用 FreeBSD 构建高弹性的私有云
    • LLDB 14 —— FreeBSD 新调试器
    • 实用 IPv6(第一部分)
    • 利用 netdump(4) 进行事后内核调试
    • 进行中的工作/征求反馈:FreeBSD 启动性能
    • 实用 Port:在 OpenZFS 上设置 NFSv4 文件服务器
  • 2022-0304 ARM64 是一级架构
    • FreeBSD/ARM64 上的数据科学
    • Pinebook Pro 上的 FreeBSD
    • 嵌入式控制器的 ACPI 支持
    • 进行中的工作/征求反馈:Lumina 桌面征集开发人员
    • 实用 Port:如何设置 Apple 时间机器
  • 2022-0102 软件与系统管理
    • 为 FreeBSD Ports 做贡献
    • 使用 Git 贡献到 FreeBSD Ports
    • CBSD:第一部分——生产环境
    • 将 OpenBSD 的 pf syncookie 代码移植到 FreeBSD 的 pf
    • 进行中的工作/征求反馈:mkjail
    • 《编程智慧:编程鬼才的经验和思考》(The Kollected Kode Vicious)书评
    • 会议报告:EuroBSDCon 2021 我的第一次 EuroBSDCon:一位新组织者的视角
  • 2021-1112 存储
    • 开放通道 SSD
    • 构建 FreeBSD 社区
    • 与完美操作系统同行 27 年
    • 进行中的工作/征求反馈:OccamBSD
    • 通过 iSCSI 导入 ZFS ZIL——不要在工作中这样做——就像我做的那样
  • 2021-0910 FreeBSD 开发
    • FreeBSD 代码审查与 git-arc
    • 如何为 FreeBSD 实现简单的 USB 驱动程序
    • 内核开发技巧
    • 程序员编程杂谈
  • 2021-0708 桌面/无线网
    • 通往 FreeBSD 桌面的直线路径
    • FreeBSD 13 中的人机接口设备 (HID) 支持
    • Panfrost 驱动程序
    • 用 Git 更新 FreeBSD
    • FreeBSD 的新面孔
    • 想给你的桌面加点佐料?
  • 2021-0506 安全
    • 七种提升新安装 FreeBSD 安全性的方法
    • copyinout 框架
    • 使用 TLS 改善 NFS 安全性
    • Capsicum 案例研究:Got
    • 对 Jail 进行安全扫描
  • 2021-0304 FreeBSD 13.0
    • 展望未来
    • FreeBSD 13.0 工具链
    • FreeBSD 13.0 中有新加载器吗?
    • TCP Cubic 准备起飞
    • OpenZFS 中的 Zstandard 压缩
    • 会议报告:FreeBSD 供应商峰会
    • Git 不够吗?
  • 2021-0102 案例研究
    • Tarsnap 的 FreeBSD 集群
    • BALLY WULFF
    • Netflix Open Connect
    • FreeBSD 的新面孔
    • 写作学者的 FreeBSD
    • 在世界之巅
  • 2020-1112 工作流/持续集成(CI)
    • FreeBSD Git 快速入门
    • 使用 syzkaller 进行内核 Fuzzing
    • Mastering Vim Quickly 书评
    • 线上会议实用技巧
    • 在控制台上进行网络监控
  • 2020-0910 贡献与入门
    • 采访:Warner Losh,第 2 部分
    • 代码审查
    • 撰写良好的提交消息
    • 如何在不是程序员的情况下做出贡献——成为 FreeBSD 译者
    • 如何成为文档提交者
    • 谷歌编程之夏
    • 为 FreeBSD 期刊撰写文章
    • 你为什么使用 FreeBSD
    • FreeBSD 的新面孔
  • 2020-0708 基准测试/调优
    • FreeBSD Friday
    • 采访:Warner Losh,第 1 部分
    • 构建和运行开源社区
    • 在 FreeBSD 上轻松搭建我的世界(Minecraft)服务器
    • FreeBSD 的新面孔
  • 2020-0506 网络性能
    • 内核中的 TLS 卸载
    • 访谈:Michael W Lucas
    • FreeBSD 桌面发行版
    • 使用 Poudriere 进行 Port 批量管理
    • FreeBSD 的新面孔
由 GitBook 提供支持
LogoLogo

FreeBSD 中文社区(CFC) 2025

在本页
  • 什么是 Webhook,为什么我需要它?
  • 集成
  • 架构
  • 服务器端
  • 客户端
  • 消息
  • 安全性
  • 整合实现
  • 使用 HMAC 来保护 Webhook
  • 保护 Webhook 内容
  • 使用 Github 和 Webhook 更新网站
在GitHub上编辑
导出为 PDF
  1. 2023-1112 FreeBSD 14.0

现在用 Webhook 触发我

上一页FreeBSD 容器镜像下一页新的 Ports 提交者:oel Bodenmann (jbo@freebsd.org)

最后更新于5个月前

  • 原文链接:

  • 作者:Dave Cottlehuber

什么是 Webhook,为什么我需要它?

Webhook 是一种基于 HTTP 事件驱动的远程回调协议,几乎可通过所有编程语言和工具轻松调用脚本和任务。Webhook 的优点在于其普遍应用和简单性。仅一个简单的 HTTP 链接,你就可以请求远程服务器执行任务,如调暗灯光、部署代码和代表你运行任意命令。

最简单的 Webhook 可能只是智能手机浏览器中的书签链接;更为复杂的版本,则可能需要强认证和授权。

尽管有像 Ansible 和 Puppet 这样较大型的自动化工具集,但有时,简单的方案足以满足需求。Webhook 就是这种方案,它能让你在远程计算机上安全地执行任务,仅需发出请求即可。调用 Webhook 即是“触发”操作,因此本篇文章的标题亦如此。

集成

目前尚无官方标准,但通常情况下,Webhook 是通过 POST 请求发送,并使用 JSON 对象作为消息体,通常会启用 TLS 加密,并通过签名确保防止篡改、网络伪造和重放攻击。

常见的集成,有聊天服务如 Mattermost、Slack 和 IRC;软件仓库如 Github 和 Gitlab;通用托管服务如 Zapier 或 IFTT;以及许多家居自动化系统如 Home Assistant 等。几乎在所有地方,Webhook 都能收发,因此 Webhook 的应用范围几乎是无限的。

虽然你可以在一个小时内就编写一个最简单的 Webhook 客户端或服务器,但如今,几乎每种编程语言中都有不少现成的选择。聊天软件通常提供了内置的 Webhook 触发器,用户可以通过类似 /command 的语法来调用。IRC 服务器也未被遗忘,一般由守护进程和插件实现。

Webhook 另一个不太明显的优势是它能够明确划分安全性和权限。一个低权限用户可以调用远程系统上的 Webhook。可以以低权限运行远程 Webhook 服务,先进行验证和基本语法检查。然后,在验证通过后,再调用高权限任务。也许最终的任务有权限访问某个特权令牌,来重启服务、部署新代码,或者让孩子们再享受一个小时的电子娱乐时间。

像 GitHub、GitLab 和自托管选项等常见的软件仓库也提供这类功能,触发时可以包括分支名、提交记录以及做出更改的用户。

这使得构建可以更新网站、重启系统和根据需要触发更复杂工具链的工具变得相对简单。

架构

典型的 Webhook 架构由一台监听传入请求的服务器和一部提交请求的客户端组成,客户端可能还会带上一些参数,包括认证和授权信息。

服务器端

首先,我们来讨论服务器端。服务器端一般会是一个守护进程,来监听 HTTP 请求,并根据特定条件处理请求。如果请求不符合这些条件,服务器会拒绝该请求,并返回适当的 HTTP 状态码。如果请求成功提交,服务器可以从批准的请求中提取参数,然后根据需要执行自定义操作。

客户端

消息

消息通常是个 JSON 对象。对于那些关注重放/时间攻击的用户,你应该在消息体中包含时间戳,并在进一步处理前验证该时间戳。如果你的 Webhook 工具包能够对特定的头部进行签名和验证,那也是一个可选方案,但大多数工具包不支持该功能。

安全性

可以使用共享的密钥对 HTTP 请求的主体进行签名,生成的签名作为消息头部提供。这既提供了身份验证的手段,又证明了请求在传输过程中未被篡改。它依赖于共享密钥,使两端可以独立验证消息签名,通过附加的 HTTP 头部和消信息体来完成验证。

最常见的签名方法是 HMAC-SHA256。这是两种加密算法的组合——我们熟悉的 SHA256 哈希算法可以对较大信息进行安全摘要,在这里是指 HTTP 的主体,另外 HMAC 方法使用一个密钥与信息结合生成一个唯一的代码,也即数字签名。

这两种功能结合起来,用于检测信息是否被篡改。它就像是对内容的数字印章,确认信息必定是由知道共享密钥的一方发送的。

请注意,使用 TLS 加密和签名能够提供信息的机密性和完整性,但不能保证可用性。精心策划的攻击者可能会中断或淹没网络,从而导致信息丢失而没有任何通知。

一般做法是,在 Webhook 的主体中包含时间戳,且由于 HMAC 签名的保护,可以有效抵御时间攻击和重放攻击。

请注意,未经时间戳的主体总是会有相同的签名。这在某些情况下是有用的。例如,可以预先计算 HMAC 签名,并使用一个不变的 HTTP 请求来触发远程操作,而无需在发起 Webhook 请求的系统上公开 HMAC 密钥。

整合实现

$ sudo pkg install -r FreeBSD www/webhook ftp/curl www/gurl

让我们启动服务器,运行个简单的例子,将其保存为 webhooks.yaml。

它将使用命令 logger(1),在 /var/log/messages 中写入一个短条目,记录成功调用 Webhook 的 HTTP User-Agent 头。

注意,这里有一个 trigger-rule 键,请确保 HTTP 查询参数 secret 的值与字符串 squirrel 匹配。

目前我们没有 TLS 安全性,也没有 HMAC 签名,因此系统的安全性还不高。

---
- id: logger
  execute-command: /usr/bin/logger
  pass-arguments-to-command:
  - source: string
    name: '-t'
  - source: string
    name: 'webhook'
  - source: string
    name: 'invoked with HTTP User Agent:'
  - source: header
    name: 'user-agent'
  response-message: |
    webhook executed
  trigger-rule-mismatch-http-response-code: 400
&nbs;&nbs;trigger-rule:
    match:
      type: value
      value: squirrel
    &nbs; parameter:
       source: url
       name: secret

然后在终端运行 webhook -debug -hotreload -hooks webhook.yaml。上述参数浅显易懂。

在其他终端里,运行 tail -qF /var/log/messages | grep webhook,这样我们就可以实时查看结果。

最后,我们使用 curl 来触发 Webhook,首先不带查询参数,然后再带上查询参数:

$ curl -4v ‘http://localhost:9000/hooks/logger’
* Trying 127.0.0.1:9000…
* Connected to localhost (127.0.0.1) port 9000
› GET /hooks/logger HTTP/1.1
› Host: localhost:9000
› User-Agent: curl/8.3.0
› Accept: */*
›
‹ HTTP/1.1 400 Bad Request
‹ Date: Fri, 20 Oct 2023 12:50:35 GMT|
‹ Content-Length: 30
‹ Content-Type: text/plain; charset=utf-8
‹
* Connection #0 to host localhost left intact
Hook rules were not satisfied.

可以看到,失败的请求被拒绝,并且使用 webhooks.yaml 配置文件中指定的 HTTP 状态码返回,HTTP 响应体解释了失败的原因。

提供所需的查询和 secret 参数:

$ curl -4v 'http://localhost:9000/hooks/logger?secret=squirrel'
* Trying 127.0.0.1:9000...
* Connected to localhost (127.0.0.1) port 9000
› GET /hooks/logger?secret=squirrel HTTP/1.1
› Host: localhost:9000
› User-Agent: curl/8.3.0
› Accept: */*
›
‹ HTTP/1.1 200 OK
‹ Date: Fri, 20 Oct 2023 12:50:39 GMT
‹ Content-Length: 17
‹ Content-Type: text/plain; charset=utf-8
‹
webhook executed
* Connection #0 to host localhost left intact

Webhook 被成功执行后,我们可以在 syslog 输出中看到结果:

Oct 20 12:50:39 akai webhook[67758]: invoked with HTTP User Agent: curl/8.3.0

使用 HMAC 来保护 Webhook

前面提到的 HMAC 签名,当应用于 HTTP 正文并作为签名发送时,可以防止篡改,提供认证和完整性保护,但只针对正文,而不包括头部。让我们来实现这一点。我们的第一步是生成一个简短的密钥,并修改 webhook.yaml 以要求进行验证。

$ export HMAC_SECRET=$(head /dev/random | sha256)

为方便记忆,在本文章中我们使用 n0decaf 作为密钥,但你应使用一个强密码。

替换 webhook.yml 文件为以下内容,这将从负载中提取两个 JSON 值(负载是经签名的,因此可信),并将它们传给我们的命令以执行。

---
- id: echo
  execute-command: /bin/echo
  include-command-output-in-response: true
  trigger-rule-mismatch-http-response-code: 400
  trigger-rule:
    and:
    # ensures payload is secure -- headers are not trusted
    - match:
        type: payload-hmac-sha256
        secret: n0decaf
        parameter:
          source: header
          name: x-hmac-sig
  pass-arguments-to-command:
  - source: ‘payload’
    name: ‘os’
  - source: ‘payload’
    name: ‘town’

使用 openssl dgst 计算正文的签名:

$ echo -n ‘{“os”:”freebsd”,”town”:”vienna”}’ \
    | openssl dgst -sha256 -hmac n0decaf
SHA2-256(stdin)= f8cb13e906bcb2592a13f5d4b80d521a894e0f422a9e697bc68bc34554394032

现在,带上正文和签名,让我们发出第一个签名请求:

$ curl -v http://localhost:9000/hooks/echo \
    --json {“os”:”freebsd”,”town”:”vienna”} \
    -Hx-hmac-sig:sha256=f8cb13e906bcb2592a13f5d4b80d521a894e0f422a9e697bc68bc34554394032

*  Trying [::1]:9000...
* Connected to localhost (::1) port 9000
› POST /hooks/echo HTTP/1.1
› Host: localhost:9000
› User-Agent: curl/8.3.0
› x-hmac-sig:sha256=f8cb13e906bcb2592a13f5d4b80d521a894e0f422a9e697bc68bc34554394032
› Content-Type: application/json
› Accept: application/json
› Content-Length: 32
›
‹ HTTP/1.1 200 OK
‹ Date: Sat, 21 Oct 2023 00:41:57 GMT
‹ Content-Length: 15
‹ Content-Type: text/plain; charset=utf-8
‹
freebsd vienna
* Connection #0 to host localhost left intact

在服务器端,运行 -debug 模式时,输出如下:

[webhook] 2023/10/21 00:41:57 [9d5040] incoming HTTP POST request from [::1]:11747
[webhook] 2023/10/21 00:41:57 [9d5040] echo got matched
[webhook] 2023/10/21 00:41:57 [9d5040] echo hook triggered successfully
[webhook] 2023/10/21 00:41:57 [9d5040] executing /bin/echo (/bin/echo) with arguments [“/bin/echo” “freebsd” “vienna”] and environment [] using as cwd
[webhook] 2023/10/21 00:41:57 [9d5040] command output: freebsd vienna

[webhook] 2023/10/21 00:41:57 [9d5040] finished handling echo
‹ [9d5040] 0
‹ [9d5040]
‹ [9d5040] freebsd vienna
[webhook] 2023/10/21 00:41:57 [9d5040] 200 | 15 B | 1.277959ms | localhost:9000 | POST /hooks/echo

每次单独计算签名是容易出错的。gurl 是一个早期项目的分支,它自动生成 HMAC 签名,并且简化了 JSON 处理。

签名类型和签名头部名称被加到密钥前面,并用 : 连接。它作为环境变量导出,这样它就不会直接显示在 shell 历史中。

$ export HMAC_SECRET=sha256:x-hmac-sig:n0decaf
$ gurl -json=true -hmac HMAC_SECRET \
  POST http://localhost:9000/hooks/echo \
  os=freebsd town=otutahi

POST /hooks/echo HTTP/1.1
Host: localhost:9000
Accept: application/json
Accept-Encoding: gzip, deflate
Content-Type: application/json
User-Agent: gurl/0.2.3
X-Hmac-Sig: sha256=f634363faff03deed8fbcef8b10952592d43c8abbb6b4a540ef16af0acaff172

{“os”:”freebsd”,”town”:”otutahi”}

如上所示,签名会为我们生成,并且添加 JSON 键=值对时无需引用和转义。

返回的响应也为我们进行了美化的格式化:HMAC 已被服务器验证,两个键的值已提取并作为参数传递给我们的 echo 命令,结果被捕获并返回在 HTTP 响应体中。

HTTP/1.1 200 OK
Date : Sat, 21 Oct 2023 00:50:25 GMT
Content-Length : 16
Content-Type : text/plain; charset=utf-8

freebsd otutahi

保护 Webhook 内容

虽然使用 HMAC 可以防止篡改信息正文,但它仍然是明文显示的,黑客依然可以看到内容。

我们可以通过添加传输层安全性(TLS)来进一步保护,使用自签名的 TLS 密钥和证书,为本地的 webhook 服务器提升安全性,并重启 webhook 服务器:

$ openssl req -newkey rsa:2048 -keyout hooks.key \
  -x509 -days 365 -nodes -subj ‘/CN=localhost’ -out hooks.crt

$ webhook -debug -hotreload \
  -secure -cert hooks.crt -key hooks.key \
  -hooks webhook.yaml

由于我们使用的是自签名证书,curl 命令需要额外加上参数 -k 来忽略证书验证,其他步骤与之前相同:

curl -4vk https://localhost:9000/hooks/logger?secret=squirrel
'
* Trying 127.0.0.1:9000...
* Connected to localhost (127.0.0.1) port 9000
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN: server accepted http/1.1
* Server certificate:
* subject: CN=localhost
* start date: Oct 20 13:05:09 2023 GMT
* expire date: Oct 19 13:05:09 2024 GMT
* issuer: CN=localhost
* SSL certificate verify result: self-signed certificate (18), continuing anyway.
* using HTTP/1.1
› GET /hooks/logger?secret=squirrel HTTP/1.1
› Host: localhost:9000
› User-Agent: curl/8.3.0
› Accept: */*
›
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
› HTTP/1.1 200 OK
› Date: Fri, 20 Oct 2023 13:12:07 GMT
› Content-Length: 17
› Content-Type: text/plain; charset=utf-8
›
webhook executed
* Connection #0 to host localhost left intact

使用 Github 和 Webhook 更新网站

要成功完成此操作,你需要有一个自己的域名和一台小型服务器或虚拟机来托管 daemon。虽然本文无法覆盖所有细节,如设置自己的网站、TLS 加密证书和 DNS 配置,但以下步骤大致适用于任何软件平台。

你需要设置一台代理服务器,例如 Caddy、nginx、haproxy 或类似的,确保启用有效的 TLS。一个好选择是通过 Let's Encrypt 使用 ACME 协议自动管理证书。

调整你的代理服务器,使其将适当的请求路由到 webhook daemon。你可以限制可以访问的 IP 地址,以及限制 HTTP 方法。GitHub 的 API 提供了 /meta 端点用于检索其 IP 地址,但需要保持更新。

启用 webhook 服务,再使用之前相同的参数启动你的 daemon:

# /etc/rc.conf.d/webhook
webhook_enable=YES
webhook_facility=daemon
webhook_user=www
webhook_conf=/usr/local/etc/webhook/webhooks.yml
webhook_options=” \
  -verbose \
  -hotreload \
  -nopanic \
  -ip 127.0.0.1 \
  -http-methods POST \
  -port 1999 \
  -logfile /var/log/webhooks.log \
  “

从外部验证该 URL 和 webhook daemon 是否可访问。

在你的代码托管平台(如 GitHub)创建一个新的 JSON 格式 webhook,并使用共享的 HMAC 密钥,在每次推送到仓库时触发它。

例如,在 GitHub 中,你需要提供:

  • Payload URL,指向你的代理 webhook daemon 的外部链接

  • Content-Type 设置为 application/json

  • 共享密钥(如示例中的 n0decaf)

在 GitHub 上创建 webhook 后,你应该能够确认接收到了成功的事件。在你下次推送代码时,可以查看 GitHub 网站,查看 GitHub 发送的请求和 daemon 返回的响应。

由于服务器使用 HTTP,几乎所有客户端都能用来发送请求。 是一种非常普遍的选择,但我们会使用一个更加友好的工具——,它内置了对 HMAC 签名的支持。

我们将安装一些实用工具,包括 、常用工具 ,以及 gurl——使 Webhook 签名变得轻松的工具。

可以在 Port 的 和中找到更复杂的示例。

不提供类似的参数,并且要求你正确地配置。对于生产环境,建议使用反向代理服务器,如 和 ,提供稳健的 TLS 终止,并通过 Let's Encrypt 等服务使用公共 TLS 证书。

Kick Me Now with Webhooks
cURL
gurl
Webhook 服务器
curl
sample webhook.yaml
详细文档
gurl
nginx
haproxy