树莓派4B自建网页服务器指南(6):树莓派 HTTPS 证书申请 + 公网直连验证
一、引言:为什么要引入 HTTPS 证书?
在互联网上,HTTPS 已成为网站的基本门槛。它不仅能加密数据传输,防止中间人窃听,还能让浏览器显示“安全锁”标识,提升用户信任度。对于个人站点而言,即使只是内网穿透或实验性质,使用受信证书也能避免浏览器反复弹出“不安全”警告,使访问体验更正规、更符合现代 Web 标准。
然而,树莓派(ARM64 架构)在申请证书时面临诸多坑:主流工具 Certbot 依赖 Python 生态,在 ARM64 下编译困难。
acme.sh 作为纯 Shell 脚本方案,成为最佳替代。本文将完整记录证书申请、Nginx 配置、网络瓶颈排查及公网验证的全过程。
本文验证域名统一使用 pi-ddns.jiejinx.cn。
二、证书申请方案选型(踩坑实录)
| 方案 | 结论 | 原因 |
|---|---|---|
| Certbot (Let's Encrypt 官方) | ❌ 树莓派 ARM64 不可用 | Python 依赖包(acme、cryptography)在 ARM64 下编译失败,snapd 安装也报错,折腾数小时无果 |
| acme.sh | ✅ 推荐 | 纯 Shell 脚本,无 Python 依赖,ARM64 原生支持,DNS-01 模式可配合阿里云 DNS API 自动签发泛域名证书 |
三、acme.sh 证书申请(完整流程)
3.1 安装 acme.sh(国内网络适配)
3.1.1 离线安装包下载
由于 官方推荐的 curl https://get.acme.sh | sh 在线安装脚本内部会去 GitHub 拉 master.tar.gz归档,国内网络常卡死,改用离线安装更稳:先用国内代理把 tar.gz 拉到 /tmp,再本地安装。
cd /tmp
wget https://gh.llkk.cc/https://github.com/acmesh-official/acme.sh/archive/master.tar.gz以上链接中,若代理超时 代理站点可进行替换,通过代理查询站查询可用节点地址替换。
例如:https://gh.llkk.cc/https://github.com/....
替换为:https://777.z321.cc.cd/https://github.com/....代理查询站:https://github.akams.cn/
3.1.2 本地离线安装:
tar -xzf master.tar.gz
cd acme.sh-master
./acme.sh --install -m standalone参数说明:
--install:安装到 ~/.acme.sh/,并设置 cron 自动续期
-m standalone:不自动写 ~/.bashrc(Pi OS 默认 bash,装完手动 source ~/.bashrc即可;若你换 zsh/fish 可去掉 -m,让安装脚本自动识别当前 shell 写对应 rc 文件)
可能出现的日志现象(正常现象,无需处理):
#安装末期可能出现类似日志:
Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: 28
OKerror code: 28是 libcurl 的 CURLE_OPERATION_TIMEDOUT,来源是 --install末尾顺手执行了一次 acme.sh --upgrade(自检/拉最新版),国内网络出不去 GitHub/Let's Encrypt 导致超时。这不影响安装结果——~/.acme.sh/本体、.bashrc别名、cron 任务均已装好,后面 3.2~3.4 的签发流程不受影响。
安装完刷新环境变量:
source ~/.bashrc验证安装:
acme.sh --version
# 应输出版本号(如 3.1.0)✅清理安装残留(可选):
cd /tmp
rm -f master.tar.gz
rm -rf acme.sh-master/💡 装完顺手清 /tmp残留,SD 卡 IO 和空间都金贵;不 rm 的话 systemd-tmpfiles-clean10 天后也会清,但树莓派上建议主动清。
3.2 配置阿里云 DNS API + 注册邮箱
acme.sh 需要通过阿里云 DNS API 验证域名所有权(DNS-01 模式),同时第一次签发时会向 Let's Encrypt 注册账号,需要一个有效的 contact email。
编辑配置文件:
nano ~/.acme.sh/account.conf找到这一行:
ACCOUNT_EMAIL='standalone'改为你的邮箱(例如):
ACCOUNT_EMAIL='your_email@example.com'然后在文件末尾添加两行(替换成你的真实 AK/SK):
Ali_Key='你的阿里云 AccessKey ID'
Ali_Secret='你的阿里云 AccessKey Secret'保存退出(Ctrl+O→ Enter→ Ctrl+X)。
💡 为什么不用 export而直接写文件:
新版 acme.sh v3 在 --issue内部走注册流程时,export ACCOUNT_EMAIL不一定被注册子进程读到,可能报 invalidContact;且 QQ 数字邮箱(如 123456789@qq.com)偶发被 Let's Encrypt 端点误判为非法格式。直接修改 account.conf是最稳的方式,acme.sh 签发时会自动读取完成注册,无需单独执行注册命令。
文件中原有的 UPGRADE_HASH等字段是 acme.sh 自动生成的,保留不动即可,只改 ACCOUNT_EMAIL并追加 Ali_Key/Ali_Secret是最小改动,不会破坏 acme.sh 的内部状态。
AccessKey 获取方式见第5篇 6.5 节。建议使用 RAM 子账号(仅授予 AliyunDNSFullAccess权限),不要直接使用主账号密钥。
3.3 签发证书(主域名 + 泛域名)
acme.sh --issue --server letsencrypt --dns dns_ali -d jiejinx.cn -d *.jiejinx.cn💡 为什么显式 --server letsencrypt:
acme.sh v3+ 默认 CA 已改为 ZeroSSL,ZeroSSL 需 EAB 凭证,个人树莓派场景用不上。
命令不加 --server新版 acme.sh 会报 No EAB credentials。显式指定最稳,也兼容老版 acme.sh。
这条命令会:
- 调用阿里云 DNS API,为 jiejinx.cn和 *.jiejinx.cn添加 TXT 验证记录
- 等待 DNS 生效(约 10-60 秒)
- 验证通过后,向 Let's Encrypt 申请证书
- 签发成功后,自动删除 TXT 记录
💡** 日志中的 error code 说明:** 签发过程中可能出现以下两行错误日志:
Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: 35 Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: 28
error 35 (CURLE_SSL_CONNECT_ERROR):SSL/TLS 握手失败,通常因网络抖动导致公共 DNS 查询超时
error 28 (CURLE_OPERATION_TIMEDOUT):连接超时,acme.sh 在通过公共 DNS 检查 TXT 记录是否生效时,因国内网络环境偶发超时
两者均不影响证书签发结果——acme.sh 内置重试机制,上述错误发生后会自动切换到备选检查点,最终 Success即为验证通过。日志末尾的 Your cert is in:和 fullchain.cer出现即代表证书签发成功。
签发成功后,证书文件位于:
~/.acme.sh/jiejinx.cn_ecc/
├── fullchain.cer # 完整证书链(Nginx 使用)
├── jiejinx.cn.key # 私钥(Nginx 使用)
├── ca.cer # CA 中间证书
└── jiejinx.cn.cer # 域名证书3.4 验证证书信息
# 查看证书详情
openssl x509 -in ~/.acme.sh/jiejinx.cn_ecc/fullchain.cer -text -noout | grep -E "Subject:|Not Before|Not After|DNS"
# 查看 SAN(Subject Alternative Names),应包含 jiejinx.cn 和 *.jiejinx.cn
openssl x509 -in ~/.acme.sh/jiejinx.cn_ecc/fullchain.cer -text -noout | grep -A1 "Subject Alternative Name"输出示例:
Subject: CN = jiejinx.cn
Not Before: Apr 1 00:00:00 2026 GMT
Not After: Jun 30 00:00:00 2026 GMT
DNS:jiejinx.cn, DNS:*.jiejinx.cn3.5 自动续期
acme.sh 安装时已自动添加 cron 任务,无需手动干预。验证 cron 任务是否存在:
crontab -l | grep acme应输出类似:
56 0 * * * "/home/pi/.acme.sh"/acme.sh --cron --home "/home/pi/.acme.sh" > /dev/null💡 泛域名证书的优势:*.jiejinx.cn可覆盖所有二级子域名(pi.jiejinx.cn、pi-ddns.jiejinx.cn、pi-cf.jiejinx.cn、www.jiejinx.cn等)。
后续新增子域名时,无需重新申请证书,直接使用现有证书即可。
这是 DNS-01 模式相比 HTTP-01 模式的核心优势——不依赖 80 端口,且支持泛域名。
四、Nginx 配置要点(含完整命令行)
4.1 创建 SSL 证书存放目录
sudo mkdir -p /etc/nginx/ssl/jiejinx.cn4.2 复制证书文件
sudo cp ~/.acme.sh/jiejinx.cn_ecc/fullchain.cer /etc/nginx/ssl/jiejinx.cn/fullchain.pem
sudo cp ~/.acme.sh/jiejinx.cn_ecc/jiejinx.cn.key /etc/nginx/ssl/jiejinx.cn/privkey.pem
sudo chmod 600 /etc/nginx/ssl/jiejinx.cn/privkey.pem4.3 编写 Nginx 站点配置
sudo nano /etc/nginx/sites-available/pi粘贴以下内容:
server {
listen 9133 ssl;
listen [::]:9133 ssl;
http2 on;
server_name pi-ddns.jiejinx.cn;
ssl_certificate /etc/nginx/ssl/jiejinx.cn/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/jiejinx.cn/privkey.pem;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}💡 server_name包含所有需要 HTTPS 访问的子域名。
泛域名证书 *.jiejinx.cn天然覆盖 pi-ddns、pi-cf等子域,无需为每个子域单独申请证书。
4.4 启用站点并重载 Nginx
# 创建软链接启用站点
sudo ln -s /etc/nginx/sites-available/pi /etc/nginx/sites-enabled/
# 测试配置是否正确
sudo nginx -t
# 重载 Nginx 使配置生效
sudo systemctl reload nginx4.5 验证监听状态
ss -tlnp | grep 9133应看到类似输出:
LISTEN 0 511 0.0.0.0:9133 0.0.0.0:* users:(("nginx",pid=xxx,fd=xx))
LISTEN 0 511 [::]:9133 [::]:* users:(("nginx",pid=xxx,fd=xx))[::]:9133表示 Nginx 已在 IPv6 端口上监听 ✅
五、网络与端口问题(宽带限制与光猫防火墙)
5.1 家宽 80/443 端口封锁(现实约束)
三大运营商(电信/联通/移动)家庭宽带线路均封锁 80(HTTP)和 443(HTTPS)入站端口,这是公知事实,非配置错误。
应对策略:
- 树莓派 Nginx 监听非标高位端口(如 9133)
- 公网访问时必须显式携带端口号:https://pi-ddns.jiejinx.cn:9133
- 如需隐藏端口号,需借助反向代理(如阿里云 ECS Nginx 反代)或 Cloudflare Tunnel(备选)
5.2 光猫 IPv6 防火墙防护选项(最大暗坑)
现象:树莓派 IPv6 地址公网可达(ping6 通),Nginx 监听 9133 端口正常,但同地域不同网段的手机/电脑访问 https://[IPv6]:9133始终超时。
根因:光猫(华为、中兴等)默认开启 IPv6 SPI 防火墙 或 IPv6 防护 选项,会拦截所有入站 TCP/UDP 连接(无论端口),仅放行 ICMPv6(ping 通是假象)。
六、防火墙设置(测试用途,附带安全建议)
6.1 关闭光猫与路由器的 IPv6 防火墙(测试用)
6.1.1光猫端
登录光猫管理后台(一般为 192.168.1.1,登陆信息见背面标签),找到 安全 → 防火墙 → IPv6 SPI 防火墙 或 IPv6 防护 选项,关闭该选项(部分光猫需在“高级安全”或“攻击防护”子菜单)。保存生效,无需重启光猫。
6.1.2路由器端
光猫防火墙关闭后,若仍无法公网访问,路由器自身的 IPv6 防火墙往往是第二道关卡。家用路由器(华硕、TP-Link、小米、中兴等)默认会拦截所有来自公网的 IPv6 入站连接。
以本文实测的中兴 E2633 为例:
- 登录路由器管理后台(一般为 192.168.10.1 登陆信息见路由器背面标签)
- 进入 安全 → 防火墙(或 高级安全)
- 找到 防火墙级别,将其从“高(推荐)”改为 “低”
- 取消勾选 “防攻击保护”(如有)
- 点击 提交 保存
💡 其他品牌参考位置:
华硕:防火墙 → IPv6 防火墙 → 启用 IPv6 防火墙(取消勾选)
TP-Link:安全 → 高级安全 → 忽略来自 WAN 的 Ping(关闭) + 开启 SPI 防火墙(关闭)
小米:常用设置 → 安全中心 → 防火墙 → IPv6 防火墙(关闭)
验证:关闭后,用手机 4G/5G 访问 https://pi-ddns.jiejinx.cn:9133,应能正常显示页面。若仍不通,可能是运营商上行 ACL 拦截,此时纯 IPv6 直连方案已达上限,需进入第7篇 ECS 反代方案。
6.2 ⚠️ 重要免责声明
上述关闭光猫 IPv6 防火墙的操作仅为测试验证链路连通性,不应作为长期安全策略。光猫自带的防火墙虽然简陋,但仍能阻挡一部分扫描攻击。强烈建议在生产环境中,在树莓派或路由器上启用专业的防火墙规则(如 iptables 或 ufw),仅放行必要的端口(如 9133),并限制来源 IP 范围。切勿直接关闭防护裸奔,以免设备暴露于公网风险之下。
6.3 推荐的安全加固方案
- 在树莓派上启用 ufw(见 6.4 节)
- 或者使用带有防火墙功能的路由器(如 OpenWrt、爱快等),在路由器上控制入站流量
- 配合 Fail2ban 防止暴力扫描
6.4 树莓派防火墙配置(ufw)
光猫防火墙品牌繁杂、配置各异,但树莓派上的防火墙是统一的。无论光猫侧怎么设,树莓派自身必须做好端口管控。
6.4.1 安装 ufw
sudo apt install ufw -y6.4.2 设置默认策略
sudo ufw default deny incoming # 默认阻止所有入站
sudo ufw default allow outgoing # 允许所有出站6.4.3 放行必要端口
# SSH(22端口,必须放行否则连不上)
sudo ufw allow 22/tcp comment 'SSH'
# Nginx HTTPS 非标端口(本文用 9133)
sudo ufw allow 9133/tcp comment 'Nginx HTTPS non-standard port'6.4.4 启用防火墙
sudo ufw enable启用后查看状态:
sudo ufw status verbose应输出类似:
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
9133/tcp ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
9133/tcp (v6) ALLOW Anywhere (v6)6.4.5 未来新增端口的放行方法
如果需要开放更多端口(例如 frp 的 7000、Docker 的 9443 等),使用相同语法:
sudo ufw allow <端口号>/tcp comment '描述'例如:
sudo ufw allow 8443/tcp comment 'frp dashboard'
sudo ufw allow 9090/tcp comment 'Cockpit'⚠️ 不要一次性放行过多端口。遵循最小权限原则:只放行业务必需的端口,其余一律拒绝。ufw 的日志位于 /var/log/ufw.log,可用于排查被拦截的连接。
6.4.6 删除误开放的端口
sudo ufw delete allow <端口号>/tcp七、公网访问验证(ddns-go + acme.sh 证书)
前提条件:
✅ ddns-go 已成功将树莓派公网 IPv6 更新到阿里云 DNS AAAA 记录(pi-ddns.jiejinx.cn)
✅ 光猫 IPv6 防火墙已关闭(测试用,见 6.1)
✅ 树莓派 ufw 已放行 9133 端口(见 6.4)
✅ 树莓派 Nginx 监听 9133 ssl,acme.sh 证书 SAN 覆盖 pi-ddns.jiejinx.cn
验证步骤:
# 1. 验证 DNS 解析
nslookup pi-ddns.jiejinx.cn 8.8.8.8
# 应返回公网 IPv6 地址(2409:xxxx)
# 2. 验证 Nginx 响应(本机)
curl -v https://pi-ddns.jiejinx.cn:9133
# 应返回 Nginx 页面,无证书错误
# 3. 外网验证(手机 4G/5G,关闭 WiFi)
# 浏览器访问 https://pi-ddns.jiejinx.cn:9133
# 应显示安全锁(证书受信),页面正常加载至此,树莓派已实现纯 IPv6 公网直连 HTTPS 访问。
八、本章目标完成清单
| 项目 | 状态 |
|---|---|
| acme.sh 安装并签发泛域名证书 | ✅ |
| Nginx 配置 SSL(9133 端口) | ✅ |
| 树莓派 ufw 防火墙安装与端口放行 | ✅ |
| 光猫 IPv6 防火墙关闭(测试用) | ✅ |
| 公网 HTTPS 直连验证通过 | ✅ |
| 理解家宽 80/443 端口封锁限制 | ✅ |