惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 最新话题
C
Cyber Attacks, Cyber Crime and Cyber Security
G
GRAHAM CLULEY
T
Tenable Blog
T
Threatpost
C
CXSECURITY Database RSS Feed - CXSecurity.com
I
Intezer
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
D
Darknet – Hacking Tools, Hacker News & Cyber Security
K
Kaspersky official blog
Security Latest
Security Latest
P
Privacy & Cybersecurity Law Blog
Google Online Security Blog
Google Online Security Blog
SecWiki News
SecWiki News
P
Palo Alto Networks Blog
TaoSecurity Blog
TaoSecurity Blog
Webroot Blog
Webroot Blog
Spread Privacy
Spread Privacy
O
OpenAI News
The Last Watchdog
The Last Watchdog
P
Proofpoint News Feed
C
Check Point Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
人人都是产品经理
人人都是产品经理
S
Security @ Cisco Blogs
Scott Helme
Scott Helme
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
月光博客
月光博客
S
Securelist
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
T
Troy Hunt's Blog
W
WeLiveSecurity
GbyAI
GbyAI
N
News | PayPal Newsroom
Y
Y Combinator Blog
C
Cisco Blogs
H
Help Net Security
The GitHub Blog
The GitHub Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 【当耐特】
Jina AI
Jina AI
MongoDB | Blog
MongoDB | Blog
P
Proofpoint News Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
云风的 BLOG
云风的 BLOG
小众软件
小众软件
N
News and Events Feed by Topic

Alliot's blog

Docker 代理配置机制与作用域 2025年底的安卓搞机备忘录 ArgoCD部署应用出现metadata.annotations过大问题 APC UPS更换电池校准容量 M1 Mac安装低版本Node.js Ansible使用Bitwarden存储Vault密码 Cloudflare Tunnel前置代理支持 CDN场景下配置Vaultwarden启用fail2ban 中银香港丝滑开户总结 AWS ECS使用EBS作为Volume 浅浅的调教一下国产智障电视 Nginx proxy_pass到AWS ALB的504问题 OpenV**手动指定路由规则 本地模拟CNAME解析 Nginx搭建WebDAV服务 迎来船新版本的Hexo+NexT 优雅的处理Git多帐号与代理问题 验光配镜扫盲 Prometheus relabel实现动态metrics path
从指定路径更新雷池WAF证书
Alliot · 2024-04-02 · via Alliot's blog

  雷池(SafeLine) 是长亭科技部分开源的一款 Web 防火墙,社区版本已经有较为完善的 WAF 功能,可以满足个人项目的基本 Web 防护需求。 不过目前(v5.2.0)雷池对于证书的操作,仅支持从 UI 导入或使用 Let’s Encrypt 的 HTTP-01 验证方法 来配置证书, 这对于使用 DNS 验证的短期证书用户来说非常不方便,可以看到社区有这样的需求的小伙伴还是挺多的: [建议] 证书增加使用路径导入方式 | Github issue, 因此便写了个小脚本来实现这个需求。

调研

雷池本身也是基于 Tengine 来做网关的, 证书配置也在 Tengine 来实现, 因此 Alliot 一开始准备直接操作容器中 Tengine 的证书文件来实现, 不过看样子社区中有小伙伴已经尝试过了: [Bug] 手动更新证书文件并重启容器后,【证书管理】界面的有效期时间没有同步更新, 从底下的评论可以知道目前雷池的证书还是以数据库为准,直接操作文件并不能达到更新证书的目的。
这里打算通过操作雷池 API 来达到目的。

动手

官方并没有提供 API 文档,也没有提供生成 API key 的操作,只能通过模拟登录来实现。
雷池登录流程为: 密码登录 -> 校验通过后得到中间 JWT -> 校验 OTP -> 校验通过后得到最终的 JWT, 并且前面过程中都需要携带 CSRF token, 由于逻辑并不复杂,并且也是简单的构建一下请求,这里就直接贴代码吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import requests
import time
import pyotp
import urllib3

BASE_URL = "https://www.iots.vip" # 登录地址
USERNAME = "admin"
PASSWORD = "123123123"

OTP_SECRET = "ADXXXXXXWB5S3UIWZCDX" # 动态验证码的密钥
CERT_ID = "1" # 证书ID, 一般如果仅有一个证书,ID为1, 多个证书也可以调用下面的list_all_certs来获取ID
CERT_FILE_PATH = "www.iots.vip.crt" # 证书路径
CERT_KEY_PATH = "www.iots.vip.key" # 证书路径


def get_passcode(secret):
totp = pyotp.TOTP(secret)
return totp.now()

class SafeLine:
def __init__(self, base_url):
urllib3.disable_warnings()
self.base_url = base_url
self.csrf_token = None
self.jwt = None
self.session = requests.Session()
self.session.verify = False

def get_csrf_token(self):
response = self.session.get(f"{self.base_url}/api/open/auth/csrf")
data = response.json()
self.csrf_token = data['data']['csrf_token']
return self.csrf_token

def login(self, username, password):
self.get_csrf_token()
payload = {
"username": username,
"password": password,
"csrf_token": self.csrf_token
}
response = self.session.post(f"{self.base_url}/api/open/auth/login", json=payload)
data = response.json()
self.jwt = data['data']['jwt']
return self.jwt

def validate_mfa(self, code):
self.get_csrf_token()
headers = {'authorization': 'Bearer ' + self.jwt}
payload = {
"code": code,
"timestamp": int(time.time() * 1000),
"csrf_token": self.csrf_token
}
response = self.session.post(f"{self.base_url}/api/open/auth/tfa", headers=headers, json=payload)
data = response.json()
if data['err'] is None:
self.jwt = data['data']['jwt']
print("login success")
else:
self.jwt = None
return data['data']['jwt']

def list_all_certs(self):
headers = {'authorization': 'Bearer ' + self.jwt}
response = self.session.get(f"{self.base_url}/api/open/cert", headers=headers)
data = response.json()
return data['data']['nodes']

def update_cert(self, cert_id, crt, key):
headers = {'authorization': 'Bearer ' + self.jwt}
payload = {
"manual": {
"crt": crt,
"key": key
},
"type": 2
}
response = self.session.put(f"{self.base_url}/api/open/cert/{cert_id}", headers=headers, json=payload)
data = response.json()
if data['err'] is None:
print("update success")


if __name__ == '__main__':
safeline = SafeLine(base_url=BASE_URL)
safeline.login(USERNAME, PASSWORD)
safeline.validate_mfa(get_passcode(OTP_SECRET))

with open(CERT_FILE_PATH, 'r') as cert_file:
cert_str = cert_file.read()
with open(CERT_KEY_PATH, 'r') as key_file:
cert_key = key_file.read()
safeline.update_cert(CERT_ID, cert_str, cert_key)

安装依赖:

1
pip install requests pyotp

填好参数后 python main.py 运行,去到控制台便可以看到完成了证书更新。

部署到Certbot

Alliot 是使用 Certbot 自动申请的泛域名证书,配合对应 DNS 提供商的插件,可以实现自动颁发、续签证书。 这里使用 certbot-dns-aliyun 来实现阿里云托管域名的 Let’s Encrypt 证书自动申请。

安装部署Certbot && 阿里云DNS插件

已经有自己的证书的可以跳到下一小节。

1
2
# 确保已经安装Python3运行环境后执行 
pip install certbot certbot-nginx certbot-dns-aliyun

创建配置文件,填入阿里云 AccessKey(申请方式: 获取AccessKey|Aliyun):

1
2
3
4
mkdir /etc/certbot

touch ali_credentials.ini
chmod 600 ali_credentials.ini

ali_credentials.ini 格式如下:

1
2
dns_aliyun_access_key = xxxx
dns_aliyun_access_key_secret = xxxx

之后我们尝试申请一下证书:

1
2
3
4
certbot certonly \
--authenticator=dns-aliyun \
--dns-aliyun-credentials='/etc/certbot/ali_credentials.ini' \
-d "*.example.com,example.com"

添加一个定时任务到 crontab

1
(crontab -l 2>/dev/null; echo "0 0 * * * certbot renew -q") | crontab -

配置自动更新雷池里的证书

现在 Certbot 已经可以为我们自动申请 SSL 证书了,我们可以利用 Certbot 的 renewal-hooks 来达到证书续期后自动更新到雷池:

1
2
3
4
5
6
7
8
9
10
# 复制上面的代码,填入自己的配置
vim /etc/certbot/renew_safeline_cert.py

# 创建一个hook
cd /etc/letsencrypt/renewal-hooks/deploy

cat > update_safeline_ssl.sh << EOF
#!/bin/bash
python /etc/certbot/safeline_renew_cert/main.py
EOF

现在来测试一下 renewal-hooks:

1
2
3
4
5
6
7
8
9
10
11
certbot renew 
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/www.iots.vip.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Simulating renewal of an existing certificate for www.iots.vip
Waiting 30 seconds for DNS changes to propagate
Hook 'deploy-hook' ran with output:
login success
update success

可以看到 deploy-hook 成功执行,大工告成! 之后每次 Certbot 在更新完证书后都会同步更新雷池里托管的 SSL 证书。

更新

date: 2024-12
为了更方便大家调用,Alliot 封装了一个 Safeline 雷池的 Pypi 包,你可以直接通过如下方式来调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from safeline import SafeLine
CERT_ID = 1
CERT_FILE_PATH = "mycert.pem"
CERT_KEY_PATH = "mykey.pem"

if __name__ == '__main__':
BASE_URL = "https://xxxx"
USERNAME = "admin"
PASSWORD = "xxxxxx"

OTP_SECRET = "x"

waf = SafeLine(BASE_URL,
USERNAME,
PASSWORD,
OTP_SECRET
)


with open(CERT_FILE_PATH, 'r') as cert_file:
cert_str = cert_file.read()
with open(CERT_KEY_PATH, 'r') as key_file:
cert_key = key_file.read()

waf.certification.update(CERT_ID, cert_str, cert_key)