添加了路由状态检查,跳过禁用路由

This commit is contained in:
jingrow 2026-01-01 18:43:06 +00:00
parent 5bd9e95e15
commit 2421089e68
8 changed files with 11 additions and 1235 deletions

7
.gitignore vendored
View File

@ -3,3 +3,10 @@
/etcd_data/* /etcd_data/*
!/etcd_data/.keep !/etcd_data/.keep
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python

View File

@ -1,121 +0,0 @@
# 配置说明
## 配置方式
配置已直接定义在 Python 文件中,**不需要** `config.json` 文件。
### 方式一:直接修改 Python 文件(推荐)
编辑 Python 文件中的 `DEFAULT_CONFIG` 字典:
#### ssl_manager.py
```python
DEFAULT_CONFIG = {
'apisix_admin_url': 'http://localhost:9180',
'apisix_admin_key': '8206e6e42b6b53243c52a767cc633137',
'certbot_path': '/usr/bin/certbot',
'cert_dir': '/etc/letsencrypt/live',
'letsencrypt_email': 'admin@jingrowtools.cn', # 修改为你的邮箱
'letsencrypt_staging': True, # 生产环境改为 False
'webroot_path': '/var/www/certbot'
}
```
#### test_ssl_auto.py
```python
DEFAULT_TEST_CONFIG = {
'apisix_admin_url': 'http://localhost:9180',
'apisix_admin_key': '8206e6e42b6b53243c52a767cc633137',
'webroot_path': '/var/www/certbot',
'letsencrypt_staging': True
}
```
### 方式二:使用环境变量(推荐用于生产环境)
通过环境变量覆盖默认配置:
```bash
export APISIX_ADMIN_URL="http://localhost:9180"
export APISIX_ADMIN_KEY="your-admin-key"
export LETSENCRYPT_EMAIL="your-email@example.com"
export LETSENCRYPT_STAGING="false"
export WEBROOT_PATH="/var/www/certbot"
```
### 方式三:使用配置文件(可选,向后兼容)
如果仍想使用 `config.json`,可以创建它,配置会覆盖默认值:
```json
{
"apisix_admin_url": "http://localhost:9180",
"apisix_admin_key": "your-admin-key",
"certbot_path": "/usr/bin/certbot",
"cert_dir": "/etc/letsencrypt/live",
"letsencrypt_email": "your-email@example.com",
"letsencrypt_staging": false,
"webroot_path": "/var/www/certbot"
}
```
然后使用 `--config` 参数:
```bash
python3 ssl_manager.py request --domain example.com --config config.json
```
## 配置优先级
1. **环境变量**(最高优先级)
2. **配置文件**(如果使用 `--config` 参数)
3. **Python 文件中的 DEFAULT_CONFIG**(默认值)
## 配置项说明
| 配置项 | 说明 | 默认值 |
|--------|------|--------|
| `apisix_admin_url` | APISIX Admin API 地址 | `http://localhost:9180` |
| `apisix_admin_key` | APISIX Admin API 密钥 | `8206e6e42b6b53243c52a767cc633137` |
| `certbot_path` | Certbot 可执行文件路径 | `/usr/bin/certbot` |
| `cert_dir` | 证书存储目录 | `/etc/letsencrypt/live` |
| `letsencrypt_email` | Let's Encrypt 邮箱 | `admin@jingrowtools.cn` |
| `letsencrypt_staging` | 是否使用 staging 模式 | `True`(测试环境) |
| `webroot_path` | Webroot 验证文件路径 | `/var/www/certbot` |
## 快速配置
### 修改邮箱和切换到生产环境
编辑 `ssl_manager.py`
```python
DEFAULT_CONFIG = {
# ... 其他配置 ...
'letsencrypt_email': 'your-email@example.com', # 修改这里
'letsencrypt_staging': False, # 改为 False 使用生产环境
# ... 其他配置 ...
}
```
### 修改 APISIX Admin Key
编辑 `ssl_manager.py`
```python
DEFAULT_CONFIG = {
'apisix_admin_key': 'your-new-admin-key', # 修改这里
# ... 其他配置 ...
}
```
## 注意事项
1. **Staging 模式**:默认使用 staging 模式(测试环境),不会消耗生产环境配额
2. **生产环境**:切换到生产环境前,确保:
- 域名 DNS 已正确解析
- 80 端口可访问
- 验证路径可访问
3. **安全性**:不要将包含敏感信息的配置文件提交到版本控制系统

View File

@ -1,231 +0,0 @@
# Dashboard 看不到路由和证书的排查指南
## 问题现象
测试脚本成功创建了路由和证书,但在 Dashboard 面板中看不到。
## 验证数据确实存在
### 通过 Admin API 验证
```bash
# 检查路由
curl -s http://localhost:9180/apisix/admin/routes/test.jingrowtools.cn \
-H 'X-API-KEY: 8206e6e42b6b53243c52a767cc633137'
# 检查 SSL
curl -s http://localhost:9180/apisix/admin/ssls/00000000000000000023 \
-H 'X-API-KEY: 8206e6e42b6b53243c52a767cc633137'
```
### 通过 etcd 验证
```bash
# 检查路由
docker exec apisix-etcd-1 etcdctl get /apisix/routes/test.jingrowtools.cn
# 检查 SSL
docker exec apisix-etcd-1 etcdctl get /apisix/ssls/00000000000000000023
```
## 可能的原因和解决方案
### 1. Dashboard 缓存问题 ⚠️ **最常见**
**原因:** Dashboard 可能缓存了数据,没有实时刷新。
**解决方案:**
- **刷新浏览器页面**F5 或 Ctrl+R
- **清除浏览器缓存**Ctrl+Shift+Delete
- **硬刷新**Ctrl+Shift+R 或 Ctrl+F5
- **等待几秒钟**后再次查看Dashboard 可能有轮询间隔)
### 2. Dashboard 过滤条件
**原因:** Dashboard 可能设置了过滤条件,隐藏了某些路由。
**解决方案:**
- 检查 Dashboard 的搜索/过滤框,确保没有输入过滤条件
- 检查路由列表的显示选项(如:显示所有、只显示启用的等)
- 尝试搜索 `test.jingrowtools.cn` 看是否能找到
### 3. Dashboard 连接问题
**原因:** Dashboard 可能连接到了不同的 etcd 实例。
**检查方法:**
```bash
# 检查 Dashboard 日志
docker logs apisix-dashboard --tail 50 | grep -i etcd
# 检查 Dashboard 配置
cat /home/jingrow/apisix/dashboard_conf/conf.yaml
```
**解决方案:**
- 确保 Dashboard 配置的 etcd 地址正确
- 重启 Dashboard`docker restart apisix-dashboard`
### 4. 路由/证书状态问题
**原因:** Dashboard 可能只显示特定状态的路由/证书。
**检查方法:**
```bash
# 检查路由状态
curl -s http://localhost:9180/apisix/admin/routes/test.jingrowtools.cn \
-H 'X-API-KEY: 8206e6e42b6b53243c52a767cc633137' | \
python3 -c "import sys, json; print(json.load(sys.stdin)['value']['status'])"
# 检查 SSL 状态
curl -s http://localhost:9180/apisix/admin/ssls/00000000000000000023 \
-H 'X-API-KEY: 8206e6e42b6b53243c52a767cc633137' | \
python3 -c "import sys, json; print(json.load(sys.stdin)['value']['status'])"
```
**解决方案:**
- 确保 `status: 1`(启用状态)
- 如果状态为 0需要启用
### 5. Dashboard 版本兼容性问题
**原因:** Dashboard 版本可能与 APISIX 版本不兼容。
**检查方法:**
```bash
# 检查 Dashboard 版本
docker exec apisix-dashboard cat /usr/local/apisix-dashboard/version 2>/dev/null || \
docker exec apisix-dashboard ls /usr/local/apisix-dashboard/
# 检查 APISIX 版本
docker exec apisix-apisix-1 apisix version
```
### 6. 权限问题
**原因:** Dashboard 用户可能没有查看权限。
**解决方案:**
- 检查 Dashboard 登录用户权限
- 尝试使用管理员账户登录
## 快速排查步骤
### 步骤 1: 验证数据存在
```bash
# 检查路由是否存在
curl -s http://localhost:9180/apisix/admin/routes \
-H 'X-API-KEY: 8206e6e42b6b53243c52a767cc633137' | \
python3 -c "import sys, json; routes=json.load(sys.stdin)['list']; \
test=[r for r in routes if 'test.jingrowtools.cn' in str(r.get('value', {}).get('name', ''))]; \
print(f'找到测试路由: {len(test)} 个')"
# 检查 SSL 是否存在
curl -s http://localhost:9180/apisix/admin/ssls \
-H 'X-API-KEY: 8206e6e42b6b53243c52a767cc633137' | \
python3 -c "import sys, json; ssls=json.load(sys.stdin)['list']; \
test=[s for s in ssls if 'test.jingrowtools.cn' in str(s.get('value', {}).get('snis', []))]; \
print(f'找到测试 SSL: {len(test)} 个')"
```
### 步骤 2: 刷新 Dashboard
1. 在浏览器中按 `Ctrl+Shift+R` 硬刷新
2. 等待 5-10 秒
3. 再次查看路由和 SSL 列表
### 步骤 3: 检查 Dashboard 连接
```bash
# 重启 Dashboard
docker restart apisix-dashboard
# 等待启动
sleep 5
# 检查日志
docker logs apisix-dashboard --tail 20
```
### 步骤 4: 直接通过 Dashboard API 查询
```bash
# 访问 Dashboard API需要登录 token
# 在浏览器中打开开发者工具F12查看 Network 请求
# 找到 Dashboard API 的请求,查看返回的数据
```
## 常见解决方案
### 方案 1: 强制刷新(最简单)
1. 打开 Dashboard
2. 按 `Ctrl+Shift+R` 硬刷新
3. 等待几秒钟
4. 再次查看
### 方案 2: 重启 Dashboard
```bash
docker restart apisix-dashboard
```
等待 10 秒后刷新浏览器。
### 方案 3: 检查路由状态
如果路由状态为 0禁用需要启用
```bash
# 启用路由
curl -X PUT http://localhost:9180/apisix/admin/routes/test.jingrowtools.cn \
-H 'X-API-KEY: 8206e6e42b6b53243c52a767cc633137' \
-H 'Content-Type: application/json' \
-d '{
"uri": "/*",
"name": "test.jingrowtools.cn",
"host": "test.jingrowtools.cn",
"status": 1,
...
}'
```
## 验证脚本
创建一个验证脚本检查 Dashboard 是否能访问数据:
```bash
#!/bin/bash
# 验证 Dashboard 数据访问
echo "检查路由..."
curl -s http://localhost:9180/apisix/admin/routes \
-H 'X-API-KEY: 8206e6e42b6b53243c52a767cc633137' | \
python3 -c "import sys, json; data=json.load(sys.stdin); \
print(f'总路由数: {len(data[\"list\"])}'); \
test=[r for r in data['list'] if 'test' in str(r.get('value', {}).get('name', ''))]; \
print(f'测试路由数: {len(test)}')"
echo ""
echo "检查 SSL..."
curl -s http://localhost:9180/apisix/admin/ssls \
-H 'X-API-KEY: 8206e6e42b6b53243c52a767cc633137' | \
python3 -c "import sys, json; data=json.load(sys.stdin); \
print(f'总 SSL 数: {len(data[\"list\"])}'); \
test=[s for s in data['list'] if 'test' in str(s.get('value', {}).get('snis', []))]; \
print(f'测试 SSL 数: {len(test)}')"
```
## 总结
**最可能的原因:**
1. ✅ Dashboard 缓存 - 需要刷新浏览器
2. ✅ Dashboard 过滤条件 - 检查搜索框
3. ✅ 数据状态 - 确保 status=1
**快速解决:**
1. 硬刷新浏览器Ctrl+Shift+R
2. 等待 5-10 秒
3. 检查搜索/过滤条件
4. 如果还不行,重启 Dashboard

View File

@ -1,133 +0,0 @@
# 完整测试流程说明
## 是的,测试脚本执行的是完整的创建路由并自动申请 SSL 证书的流程
### 测试流程步骤
当使用 `python3 test_ssl_auto.py --domain test.jingrowtools.cn` 时,脚本会依次执行:
#### 1. 检查系统依赖 ✅
- 检查 Certbot 是否安装
- 检查 Python 模块是否可用
- 检查 OpenSSL 是否安装
#### 2. 检查 APISIX 服务 ✅
- 验证 APISIX Admin API 是否可访问
- 检查连接和认证
#### 3. 检查 Webroot 目录 ✅
- 检查 `/var/www/certbot` 目录是否存在
- 创建 `.well-known/acme-challenge` 子目录
#### 4. 检查/创建 Webroot 路由 ✅ **自动创建验证路由**
- 检查是否存在该域名的 webroot 路由
- **如果不存在,自动创建**
- 路由 ID: `certbot-webroot-{domain}`
- Host: 指定的域名
- URI: `/.well-known/acme-challenge/*`
- Priority: 10000最高优先级
- 功能: 自动读取验证文件并返回
#### 5. 测试验证路径 ⚠️ **测试验证路由是否工作**
- 创建测试文件
- 通过 APISIX 访问验证路径
- 验证路由是否正确返回文件内容
#### 6. 创建测试路由 ✅ **创建用户指定的域名路由**
- **自动创建域名路由**
- 路由 ID: 域名本身
- Host: 指定的域名
- URI: `/*`
- Upstream: 配置的后端服务
- 这是实际业务路由
#### 7. 申请 SSL 证书 ✅ **自动申请证书**
- 使用 Certbot 申请 Let's Encrypt 证书
- 自动处理验证流程
- 证书保存到 `/etc/letsencrypt/live/{domain}/`
#### 8. 同步证书到 APISIX ✅ **自动上传证书**
- 读取证书文件
- 通过 APISIX Admin API 创建/更新 SSL 配置
- 关联到域名
#### 9. 验证证书信息 ✅
- 使用 OpenSSL 验证证书
- 显示证书详细信息
## 完整流程示例
```bash
# 执行测试
python3 test_ssl_auto.py --domain test.jingrowtools.cn --no-cleanup
# 流程输出:
[步骤 1/9] 检查系统依赖 ✅
[步骤 2/9] 检查 APISIX 服务 ✅
[步骤 3/9] 检查 Webroot 目录 ✅
[步骤 4/9] 检查/创建 Webroot 路由 ✅
→ 自动创建: certbot-webroot-test-jingrowtools-cn
[步骤 5/9] 测试验证路径 ✅
[步骤 6/9] 创建测试路由 ✅
→ 自动创建: test.jingrowtools.cn (业务路由)
[步骤 7/9] 申请 SSL 证书 ✅
→ Certbot 自动申请证书
[步骤 8/9] 同步证书到 APISIX ✅
→ 证书自动上传到 APISIX
[步骤 9/9] 验证证书信息 ✅
```
## 自动化的部分
### ✅ 自动创建验证路由
- 无需手动配置 webroot 路由
- 脚本自动检测并创建
- 确保验证路径可访问
### ✅ 自动创建业务路由
- 根据指定域名自动创建路由
- 配置默认的 upstream
- 路由立即可用
### ✅ 自动申请证书
- 调用 Certbot 自动申请
- 处理所有验证流程
- 无需手动干预
### ✅ 自动同步证书
- 读取证书文件
- 自动上传到 APISIX
- 自动关联域名
## 权限问题处理
如果遇到权限问题(如测试输出中的错误),脚本已优化:
1. **自动尝试使用 sudo**:如果直接写入失败,会尝试使用 sudo
2. **容错处理**即使验证路径测试失败也会继续执行证书申请Certbot 会自动处理文件创建)
3. **提示信息**:提供清晰的权限修复建议
### 修复权限(推荐)
```bash
# 一次性修复权限
sudo mkdir -p /var/www/certbot/.well-known/acme-challenge
sudo chown -R $USER:$USER /var/www/certbot
sudo chmod -R 755 /var/www/certbot
```
## 总结
**是的,测试脚本执行的是完整的自动化流程:**
1. ✅ **自动创建验证路由**webroot 路由)
2. ✅ **自动创建业务路由**(用户指定的域名)
3. ✅ **自动申请 SSL 证书**Let's Encrypt
4. ✅ **自动同步证书到 APISIX**(上传并配置)
整个过程完全自动化,只需要:
- 提供域名
- 确保 DNS 已解析
- 运行测试脚本
测试完成后,域名路由和 SSL 证书都已配置完成,可以直接使用 HTTPS 访问。

View File

@ -1,228 +0,0 @@
# HTTP-01 验证失败根源分析
## 问题现象
Let's Encrypt 在申请证书时返回:
```
Domain: jingrowtools.cn
Type: unauthorized
Detail: 125.89.136.224: Invalid response from http://jingrowtools.cn/.well-known/acme-challenge/xxx: 404
```
## 根本原因分析
### 1. **路由匹配优先级问题** ⚠️ **核心问题**
**问题描述:**
- APISIX 路由匹配规则:`host` 匹配 > `uri` 匹配 > `priority` 优先级
- 当前配置:
- `jingrowtools.cn` 路由:`host: "jingrowtools.cn"`, `uri: "/*"`, `priority: 0`
- `certbot-webroot` 路由:`uri: "/.well-known/acme-challenge/*"`, `priority: 9999`, **没有 host 限制**
**匹配流程:**
1. 请求 `http://jingrowtools.cn/.well-known/acme-challenge/xxx`
2. APISIX 先匹配 `host: "jingrowtools.cn"` → 找到 `jingrowtools.cn` 路由
3. 在该路由内匹配 `uri: "/*"`**匹配成功**
4. 请求被转发到 upstream `192.168.10.2:8201`
5. **webroot 路由永远不会被匹配到**
**根本原因:**
- `host` 匹配优先级高于 `uri` 匹配
- 即使 webroot 路由的 `priority` 更高,但 `host` 匹配会先命中 `jingrowtools.cn` 路由
- webroot 路由没有设置 `host`,导致无法优先匹配
### 2. **容器文件系统隔离问题**
**问题描述:**
- APISIX 运行在 Docker 容器中
- Certbot 在宿主机上运行
- 验证文件写入到 `/var/www/certbot`(宿主机)
- 但 APISIX 容器内无法访问宿主机文件系统
**解决方案:**
- 需要在 `docker-compose.yml` 中挂载卷:
```yaml
volumes:
- /var/www/certbot:/var/www/certbot:ro
```
### 3. **Serverless 函数执行问题**
**问题描述:**
- 使用 `serverless-pre-function` 插件读取文件
- Lua 函数需要访问容器内的文件系统
- 如果文件路径不正确或权限不足,会返回 404
**当前函数:**
```lua
local path = "/var/www/certbot/.well-known/acme-challenge/" .. string.match(ctx.var.uri, "/.well-known/acme-challenge/(.+)")
local file = io.open(path, "r")
```
**潜在问题:**
- 路径拼接可能不正确
- 文件权限问题
- 容器内文件不存在
## 解决方案
### 方案一:修复路由匹配(推荐)✅
**修改 webroot 路由,添加 host 匹配并提高优先级:**
```bash
curl -X PUT 'http://localhost:9180/apisix/admin/routes/certbot-webroot' \
-H 'X-API-KEY: 8206e6e42b6b53243c52a767cc633137' \
-H 'Content-Type: application/json' \
-d '{
"uri": "/.well-known/acme-challenge/*",
"name": "certbot-webroot",
"priority": 10000,
"host": "jingrowtools.cn",
"plugins": {
"serverless-pre-function": {
"phase": "rewrite",
"functions": [
"return function(conf, ctx) local token = string.match(ctx.var.uri, \"/.well-known/acme-challenge/(.+)\"); local path = \"/var/www/certbot/.well-known/acme-challenge/\" .. token; local file = io.open(path, \"r\"); if file then local content = file:read(\"*all\"); file:close(); ngx.header.content_type = \"text/plain\"; ngx.say(content); else ngx.status = 404; ngx.say(\"File not found: \" .. path); end end"
]
}
},
"status": 1
}'
```
**关键修改:**
1. ✅ 添加 `"host": "jingrowtools.cn"` - 确保只匹配该域名
2. ✅ 提高 `priority` 到 10000 - 确保优先匹配
3. ✅ 修复 Lua 函数路径处理
### 方案二:修改主路由,排除验证路径
**在 `jingrowtools.cn` 路由中添加条件,排除验证路径:**
```json
{
"uri": "/*",
"name": "jingrowtools.cn",
"host": "jingrowtools.cn",
"vars": [
["uri", "!~", "^/.well-known/acme-challenge/"]
],
...
}
```
这样验证路径就不会被主路由匹配。
### 方案三:使用 DNS-01 验证(最可靠)✅✅
**优点:**
- 不依赖 HTTP 服务
- 不需要配置 webroot 路由
- 适合容器化环境
- 支持通配符证书
**缺点:**
- 需要 DNS API 访问权限
- 配置稍复杂
**实现:**
需要修改 `ssl_manager.py`,支持 DNS-01 验证。
### 方案四:使用独立的验证服务
**创建一个简单的 HTTP 服务专门处理验证:**
```python
# 简单的验证服务
from http.server import HTTPServer, BaseHTTPRequestHandler
import os
class ACMEHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path.startswith('/.well-known/acme-challenge/'):
token = self.path.split('/')[-1]
file_path = f'/var/www/certbot/.well-known/acme-challenge/{token}'
if os.path.exists(file_path):
with open(file_path, 'r') as f:
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
self.wfile.write(f.read().encode())
else:
self.send_response(404)
self.end_headers()
else:
self.send_response(404)
self.end_headers()
if __name__ == '__main__':
server = HTTPServer(('0.0.0.0', 8080), ACMEHandler)
server.serve_forever()
```
然后在 APISIX 中创建一个路由指向这个服务。
## 推荐解决步骤
### 立即修复(方案一)
1. **确保容器挂载了 webroot 目录:**
```yaml
# docker-compose.yml
volumes:
- /var/www/certbot:/var/www/certbot:ro
```
2. **更新 webroot 路由配置(添加 host 和更高优先级):**
```bash
# 使用上面的方案一配置
```
3. **测试验证路径:**
```bash
echo "test-token" | sudo tee /var/www/certbot/.well-known/acme-challenge/test-token
curl http://jingrowtools.cn/.well-known/acme-challenge/test-token
# 应该返回: test-token
```
4. **重新申请证书:**
```bash
cd /home/jingrow/apisix/ssl_manager
python3 ssl_manager.py request --domain jingrowtools.cn
```
## 验证流程说明
Let's Encrypt HTTP-01 验证流程:
1. **Certbot 生成随机 token**
- 例如:`yUXNhDPsvsjEwYjxishk_XZ6kGZFRqn22FSUYcfuZQY`
2. **写入验证文件**
- 路径:`/var/www/certbot/.well-known/acme-challenge/{token}`
- 内容:`{token}.{account_key_thumbprint}`
3. **Let's Encrypt 服务器访问**
- URL: `http://jingrowtools.cn/.well-known/acme-challenge/{token}`
- 期望:返回文件内容
4. **APISIX 路由匹配**
- ❌ **当前问题**:匹配到 `jingrowtools.cn` 路由,转发到 upstream
- ✅ **应该**:匹配到 `certbot-webroot` 路由,返回文件内容
5. **验证结果**
- 成功Let's Encrypt 收到正确内容 → 颁发证书
- 失败:收到 404 或其他错误 → 拒绝申请
## 总结
**HTTP 验证失败的根本原因:**
1. **主要问题**:路由匹配优先级 - `host` 匹配优先于 `uri` 匹配,导致验证请求被错误路由
2. **次要问题**:容器文件系统隔离 - 需要正确挂载卷
3. **潜在问题**Serverless 函数路径处理 - 需要确保路径正确
**最佳解决方案:**
- 方案一(修复路由匹配)+ 容器卷挂载 = 最简单有效
- 方案三DNS-01 验证)= 最可靠,适合生产环境

View File

@ -1,349 +0,0 @@
# APISIX SSL 证书自动管理
基于 Certbot + APISIX Admin API 的 SSL 证书自动申请和续期方案。
## 功能特性
- ✅ 自动申请 Let's Encrypt 免费 SSL 证书
- ✅ 自动将证书同步到 APISIX
- ✅ 自动续期证书90 天有效期)
- ✅ 监听路由创建,自动为新域名申请证书
- ✅ 支持多域名证书
- ✅ 支持测试环境staging
## 目录结构
```
ssl_manager/
├── ssl_manager.py # SSL 证书管理主脚本
├── route_watcher.py # 路由监听服务
├── certbot_deploy_hook.sh # Certbot 部署钩子
├── config.json # 配置文件
├── requirements.txt # Python 依赖
└── README.md # 说明文档
```
## 安装步骤
### 1. 安装 Certbot
```bash
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install certbot
# CentOS/RHEL
sudo yum install certbot
```
### 2. 安装 Python 依赖
```bash
cd /home/jingrow/apisix/ssl_manager
# 方法一:使用 uv推荐更快
uv pip install --system -r requirements.txt
# 方法二:使用 pip3
pip3 install -r requirements.txt
```
### 3. 配置
配置已直接定义在 Python 文件中,**不需要** `config.json`
**方式一:直接修改 Python 文件(推荐)**
编辑 `ssl_manager.py` 中的 `DEFAULT_CONFIG`
```python
DEFAULT_CONFIG = {
'apisix_admin_url': 'http://localhost:9180',
'apisix_admin_key': '你的APISIX管理密钥', # 修改这里
'letsencrypt_email': 'your-email@example.com', # 修改这里
'letsencrypt_staging': False, # 生产环境改为 False
# ... 其他配置 ...
}
```
**方式二:使用环境变量**
```bash
export APISIX_ADMIN_KEY="your-admin-key"
export LETSENCRYPT_EMAIL="your-email@example.com"
export LETSENCRYPT_STAGING="false"
```
详细配置说明请查看 `CONFIG.md`
### 4. 创建 Webroot 目录
Certbot 需要 webroot 目录用于验证:
```bash
sudo mkdir -p /var/www/certbot
sudo chown -R www-data:www-data /var/www/certbot
```
### 5. 配置 APISIX 支持 Webroot 验证
需要在 APISIX 中配置一个路由,将 `/.well-known/acme-challenge/` 请求转发到 webroot 目录。
## 使用方法
### 手动申请证书
```bash
# 申请单个域名证书
python3 ssl_manager.py request --domain example.com
# 申请多域名证书
python3 ssl_manager.py request --domain example.com --additional-domains www.example.com api.example.com
```
### 手动续期证书
```bash
# 续期单个域名
python3 ssl_manager.py renew --domain example.com
# 续期所有证书
python3 ssl_manager.py renew-all
```
### 同步现有证书到 APISIX
```bash
python3 ssl_manager.py sync --domain example.com
```
### 检查证书过期时间
```bash
python3 ssl_manager.py check --domain example.com
```
### 启动路由监听服务
```bash
# 持续监听(每 60 秒检查一次)
python3 route_watcher.py
# 只执行一次
python3 route_watcher.py --once
# 自定义检查间隔
python3 route_watcher.py --interval 30
```
## 自动续期配置
### 方法一:使用 Certbot 自动续期 + 部署钩子
1. 配置 Certbot 自动续期:
```bash
# 编辑 Certbot 续期配置
sudo nano /etc/letsencrypt/renewal/example.com.conf
```
在配置文件中添加部署钩子:
```ini
[renewalparams]
deploy_hook = /home/jingrow/apisix/ssl_manager/certbot_deploy_hook.sh
```
2. 测试续期:
```bash
sudo certbot renew --dry-run
```
3. 设置 systemd timer推荐
创建 `/etc/systemd/system/certbot-renew.timer`
```ini
[Unit]
Description=Certbot Renewal Timer
[Timer]
OnCalendar=daily
RandomizedDelaySec=3600
Persistent=true
[Install]
WantedBy=timers.target
```
创建 `/etc/systemd/system/certbot-renew.service`
```ini
[Unit]
Description=Certbot Renewal Service
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --deploy-hook /home/jingrow/apisix/ssl_manager/certbot_deploy_hook.sh
```
启用定时器:
```bash
sudo systemctl enable certbot-renew.timer
sudo systemctl start certbot-renew.timer
```
### 方法二:使用自定义脚本 + systemd timer
创建 `/etc/systemd/system/apisix-ssl-renew.service`
```ini
[Unit]
Description=APISIX SSL Certificate Renewal
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/bin/python3 /home/jingrow/apisix/ssl_manager/ssl_manager.py renew-all
User=root
```
创建 `/etc/systemd/system/apisix-ssl-renew.timer`
```ini
[Unit]
Description=APISIX SSL Certificate Renewal Timer
[Timer]
OnCalendar=weekly
RandomizedDelaySec=3600
Persistent=true
[Install]
WantedBy=timers.target
```
启用:
```bash
sudo systemctl enable apisix-ssl-renew.timer
sudo systemctl start apisix-ssl-renew.timer
```
## 路由监听服务
路由监听服务会自动检测新创建的路由,并为其中的域名申请证书。
### 启动服务
```bash
# 使用 systemd推荐
sudo systemctl start apisix-route-watcher.service
# 或使用 screen/tmux
screen -S route-watcher
python3 route_watcher.py
```
### 创建 systemd 服务
创建 `/etc/systemd/system/apisix-route-watcher.service`
```ini
[Unit]
Description=APISIX Route Watcher Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/jingrow/apisix/ssl_manager/route_watcher.py
Restart=always
RestartSec=10
User=root
[Install]
WantedBy=multi-user.target
```
启用服务:
```bash
sudo systemctl enable apisix-route-watcher.service
sudo systemctl start apisix-route-watcher.service
```
## 环境变量配置
也可以通过环境变量配置:
```bash
export APISIX_ADMIN_URL="http://localhost:9180"
export APISIX_ADMIN_KEY="your-admin-key"
export LETSENCRYPT_EMAIL="your-email@example.com"
export LETSENCRYPT_STAGING="false"
export WEBROOT_PATH="/var/www/certbot"
```
## 注意事项
1. **首次使用建议使用 staging 模式测试**
```json
"letsencrypt_staging": true
```
2. **确保 80 端口可访问**Let's Encrypt 需要验证域名所有权,通常使用 HTTP-01 验证方式。
3. **DNS 验证**:如果无法使用 HTTP-01 验证,可以配置 DNS-01 验证(需要修改脚本)。
4. **证书存储**:证书存储在 `/etc/letsencrypt/live/` 目录,请确保有备份。
5. **日志位置**
- SSL 管理器日志:`/var/log/apisix-ssl-manager.log`
- 路由监听日志:`/var/log/apisix-route-watcher.log`
- Certbot 部署钩子日志:`/var/log/apisix-certbot-deploy.log`
## 故障排查
### 证书申请失败
1. 检查域名 DNS 解析是否正确
2. 检查 80 端口是否可访问
3. 检查 webroot 目录权限
4. 查看 Certbot 日志:`/var/log/letsencrypt/letsencrypt.log`
### 证书无法同步到 APISIX
1. 检查 APISIX Admin API 是否可访问
2. 检查 Admin Key 是否正确
3. 查看 SSL 管理器日志
### 自动续期不工作
1. 检查 systemd timer 状态:`systemctl status certbot-renew.timer`
2. 手动测试续期:`certbot renew --dry-run`
3. 检查部署钩子脚本权限:`chmod +x certbot_deploy_hook.sh`
## 测试
### 测试环境staging
```json
"letsencrypt_staging": true
```
Staging 环境有更高的申请频率限制,适合测试。
### 生产环境
测试通过后,设置:
```json
"letsencrypt_staging": false
```
## 许可证
Apache License 2.0

View File

@ -1,173 +0,0 @@
# SSL 证书自动申请测试脚本使用说明
## 功能
`test_ssl_auto.py` 是一个完整的测试脚本,用于测试从路由创建到 SSL 证书申请的整个流程。
## 测试步骤
脚本会依次执行以下步骤,每个步骤都会显示成功或失败:
1. **检查系统依赖** - 检查 certbot、Python 模块等
2. **检查 APISIX 服务** - 验证 APISIX Admin API 是否可访问
3. **检查 Webroot 目录** - 检查验证文件目录是否存在
4. **检查/创建 Webroot 路由** - 检查或创建验证路由
5. **测试验证路径** - 测试验证路径是否可访问
6. **创建测试路由** - 创建测试域名路由
7. **申请 SSL 证书** - 使用 Let's Encrypt 申请证书
8. **同步证书到 APISIX** - 将证书上传到 APISIX
9. **验证证书信息** - 验证证书是否有效
## 使用方法
### 基本用法
```bash
# 使用自动生成的测试域名(测试完成后自动清理)
python3 test_ssl_auto.py
# 指定测试域名
python3 test_ssl_auto.py --domain test.example.com
# 指定配置文件
python3 test_ssl_auto.py --config config.json --domain test.example.com
```
### 选项说明
- `--domain, -d`: 指定测试域名(不指定则自动生成)
- `--config, -c`: 指定配置文件路径(默认使用环境变量或默认配置)
- `--cleanup`: 测试完成后清理测试数据(路由和 SSL 配置)
- `--no-cleanup`: 测试完成后不清理测试数据
### 示例
```bash
# 示例1: 快速测试(自动生成域名,自动清理)
python3 test_ssl_auto.py
# 示例2: 测试指定域名(保留测试数据)
python3 test_ssl_auto.py --domain test.jingrowtools.cn --no-cleanup
# 示例3: 使用配置文件,测试完成后清理
python3 test_ssl_auto.py --config config.json --domain test.jingrowtools.cn --cleanup
```
## 输出说明
### 成功输出示例
```
✅ 检查系统依赖 - 成功
✅ 检查 APISIX 服务 - 成功
✅ 检查 Webroot 目录 - 成功
...
```
### 失败输出示例
```
❌ 检查系统依赖 - 失败
❌ 检查 APISIX 服务 - 异常: Connection refused
...
```
## 注意事项
1. **域名解析**: 测试域名必须 DNS 解析到当前服务器,否则证书申请会失败
2. **Staging 模式**: 默认使用 staging 模式(测试环境),不会消耗生产环境配额
3. **权限要求**: 某些操作需要 root 权限(如创建证书文件)
4. **清理数据**: 使用自动生成的域名时,默认会清理测试数据;指定域名时,默认保留数据
## 测试流程
```
开始测试
检查依赖 → 失败 → 结束
↓ 成功
检查 APISIX → 失败 → 结束
↓ 成功
检查 Webroot → 失败 → 结束
↓ 成功
检查/创建路由 → 失败 → 结束
↓ 成功
测试验证路径 → 失败 → 结束
↓ 成功
创建测试路由 → 失败 → 结束
↓ 成功
申请证书 → 失败 → 结束
↓ 成功
同步证书 → 失败 → 结束
↓ 成功
验证证书 → 完成
清理数据(可选)
显示测试总结
```
## 故障排查
### 1. Certbot 未安装
```bash
sudo apt-get install certbot
```
### 2. APISIX 服务不可访问
```bash
# 检查 APISIX 是否运行
docker ps | grep apisix
# 检查端口
netstat -tlnp | grep 9180
```
### 3. Webroot 目录不存在
```bash
sudo mkdir -p /var/www/certbot/.well-known/acme-challenge
sudo chown -R www-data:www-data /var/www/certbot
```
### 4. 验证路径不可访问
- 检查 webroot 路由是否正确配置
- 检查路由 priority 是否足够高
- 检查路由 host 是否匹配
## 完整测试示例
```bash
# 1. 准备测试域名(确保 DNS 已解析)
export TEST_DOMAIN="test-$(date +%s).jingrowtools.cn"
# 2. 运行测试
python3 test_ssl_auto.py --domain $TEST_DOMAIN --no-cleanup
# 3. 检查结果
curl -v https://$TEST_DOMAIN
# 4. 清理(如果需要)
python3 ssl_manager.py sync --domain $TEST_DOMAIN # 先同步证书
# 然后手动删除路由和 SSL 配置
```
## 与生产环境集成
测试通过后,可以:
1. 修改 `config.json` 设置 `letsencrypt_staging: false`
2. 使用 `ssl_manager.py` 申请生产证书
3. 配置自动续期
```bash
# 申请生产证书
python3 ssl_manager.py request --domain your-domain.com
# 启用自动续期
sudo systemctl enable apisix-ssl-renew.timer
sudo systemctl start apisix-ssl-renew.timer
```

View File

@ -188,6 +188,10 @@ class RouteWatcher:
# 从路由中提取所有域名 # 从路由中提取所有域名
for route in routes: for route in routes:
route_value = route.get('value', {})
# 跳过禁用的路由status=0 表示禁用)
if route_value.get('status') == 0:
continue
domains = self.extract_domains_from_route(route) domains = self.extract_domains_from_route(route)
new_domains.update(domains) new_domains.update(domains)