├── .dockerignore
├── .github
├── ISSUE_TEMPLATE
│ ├── 1feature-request.yaml
│ ├── 2bug-report.yaml
│ ├── 3other.yaml
│ └── config.yml
└── workflows
│ └── release-charts.yml
├── .gitignore
├── .gitmodules
├── CHANGELOG.md
├── Dockerfile
├── FAQ.md
├── LICENSE.md
├── README.md
├── README_EN.md
├── blockpage
├── index.html
├── limited.html
├── maintaining.html
└── not_found.html
├── charts
└── safeline
│ ├── .helmignore
│ ├── Chart.yaml
│ ├── README.md
│ ├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── cache
│ │ └── cache-pvc.yaml
│ ├── chaos
│ │ ├── chaos-dpl.yaml
│ │ ├── chaos-pvc.yaml
│ │ └── chaos-svc.yaml
│ ├── database
│ │ ├── database-secret.yaml
│ │ ├── database-ss.yaml
│ │ └── database-svc.yaml
│ ├── detector
│ │ ├── detector-dpl.yaml
│ │ ├── detector-pvc.yaml
│ │ └── detector-svc.yaml
│ ├── fvm
│ │ ├── fvm-dpl.yaml
│ │ └── fvm-svc.yaml
│ ├── logs
│ │ └── logs-pvc.yaml
│ ├── luigi
│ │ ├── luigi-dpl.yaml
│ │ ├── luigi-pvc.yaml
│ │ └── luigi-svc.yaml
│ ├── mgt
│ │ ├── mgt-dpl.yaml
│ │ ├── mgt-pvc.yaml
│ │ └── mgt-svc.yaml
│ ├── nginx
│ │ └── nginx-pvc.yaml
│ ├── run
│ │ └── run-pvc.yaml
│ ├── sock
│ │ └── sock-pvc.yaml
│ └── tengine
│ │ ├── tengine-dpl.yaml
│ │ └── tengine-svc.yaml
│ └── values.yaml
├── release
├── ipgroup
│ ├── README.md
│ ├── crawler
│ │ ├── 360.txt
│ │ └── cloudflare.txt
│ └── geo
│ │ └── cn.txt
└── latest
│ ├── compose.yaml
│ ├── seccomp.json
│ ├── setup.sh
│ ├── upgrade.sh
│ └── version.json
├── website
├── .gitignore
├── .npmrc
├── README.md
├── babel.config.js
├── blog
│ └── 2023-08-04-website.md
├── compose.yml
├── docs
│ ├── 01-introduction.md
│ ├── 02-guide
│ │ ├── 01-install.md
│ │ ├── 02-login.md
│ │ ├── 03-config.md
│ │ ├── 04-test.md
│ │ ├── 05-upgrade.md
│ │ └── _category_.json
│ ├── 03-faq
│ │ ├── 01-install.md
│ │ ├── 02-login.md
│ │ ├── 03-other.md
│ │ └── _category_.json
│ ├── 04-practice
│ │ ├── 00-monitor.md
│ │ └── _category_.json
│ └── 05-about
│ │ ├── 00-changelog.md
│ │ ├── 01-syntaxanalysis.md
│ │ ├── 02-challenge.md
│ │ ├── 03-framework.md
│ │ ├── 04-chaitin.md
│ │ └── _category_.json
├── docusaurus.config.js
├── package-lock.json
├── package.json
├── sidebars.js
├── src
│ ├── api
│ │ └── index.ts
│ ├── components
│ │ ├── Features.tsx
│ │ ├── Icon.tsx
│ │ ├── Message
│ │ │ ├── Alert.tsx
│ │ │ ├── Message.tsx
│ │ │ └── index.tsx
│ │ ├── Modal
│ │ │ ├── ConfirmDialog.tsx
│ │ │ ├── Modal.tsx
│ │ │ ├── confrim.tsx
│ │ │ └── index.tsx
│ │ ├── Theme.tsx
│ │ ├── Title.tsx
│ │ ├── Version
│ │ │ ├── Consultation.tsx
│ │ │ ├── FunctionTable.tsx
│ │ │ └── index.tsx
│ │ ├── detection
│ │ │ ├── Result.tsx
│ │ │ ├── SampleCount.tsx
│ │ │ ├── SampleList.tsx
│ │ │ ├── SampleSteps.tsx
│ │ │ ├── SamplesForm.tsx
│ │ │ └── types.ts
│ │ └── utils.ts
│ ├── css
│ │ └── custom.css
│ ├── pages
│ │ ├── detection.tsx
│ │ └── index.tsx
│ └── theme
│ │ └── Footer
│ │ └── Copyright
│ │ └── index.js
├── static
│ ├── .nojekyll
│ ├── fonts
│ │ └── iconfont.js
│ └── images
│ │ ├── 403.svg
│ │ ├── album
│ │ ├── 0.png
│ │ ├── 1.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ ├── 4.png
│ │ ├── 5.png
│ │ └── block.png
│ │ ├── class.png
│ │ ├── docs
│ │ ├── DNS.png
│ │ ├── LoadBlance.png
│ │ ├── Untitled10.png
│ │ ├── Untitled11.png
│ │ ├── Untitled12.png
│ │ ├── Untitled13.png
│ │ ├── about_changelog
│ │ │ ├── acl_page.png
│ │ │ ├── api_assets.png
│ │ │ ├── api_assets_collect1.png
│ │ │ ├── api_assets_collect2.png
│ │ │ ├── cert_create.png
│ │ │ ├── cs_statistics.png
│ │ │ ├── forbidden_page_ext.png
│ │ │ ├── log_detail.png
│ │ │ ├── map.png
│ │ │ ├── mgt_cert.png
│ │ │ ├── mgt_cert_config.png
│ │ │ ├── site_config.png
│ │ │ ├── website_1.png
│ │ │ └── website_2.png
│ │ ├── add_challenge.png
│ │ ├── challenge.png
│ │ ├── config_access_log.png
│ │ ├── fake_host.jpg
│ │ ├── flow.png
│ │ ├── framework.png
│ │ ├── get_source_ip.png
│ │ ├── guide_config
│ │ │ ├── deploy_on_separate_server.png
│ │ │ ├── deploy_on_web_server.png
│ │ │ ├── deploy_origin.png
│ │ │ ├── deploy_with_other_server.png
│ │ │ └── tengine_502.png
│ │ ├── guide_install
│ │ │ └── collie_apps.png
│ │ ├── guide_introduction
│ │ │ ├── website_with_safeline.png
│ │ │ └── website_without_safeline.png
│ │ ├── manual.png
│ │ ├── practice_monitor
│ │ │ ├── gift.png
│ │ │ ├── machineid.png
│ │ │ └── website.png
│ │ ├── safeline_https_website.gif
│ │ ├── server_index01.png
│ │ └── server_index02.png
│ │ ├── favicon.ico
│ │ ├── feature.svg
│ │ ├── gif
│ │ ├── config_site.gif
│ │ ├── detect_log.gif
│ │ └── login.gif
│ │ ├── github.png
│ │ ├── logo.png
│ │ ├── logo.svg
│ │ ├── qq.png
│ │ ├── safeline.png
│ │ ├── wechat-230717.png
│ │ ├── wechat-230825.png
│ │ ├── wechat-light.png
│ │ ├── wechat-logo.png
│ │ └── wechat.png
└── tsconfig.json
└── yanshi
├── .gitignore
├── Makefile
├── README.md
├── contrib
├── vim
│ ├── compiler
│ │ └── yanshi.vim
│ ├── ftdetect
│ │ └── yanshi.vim
│ ├── ftplugin
│ │ └── yanshi.vim
│ ├── syntax
│ │ └── yanshi.vim
│ └── syntax_checkers
│ │ └── yanshi
│ │ └── yanshi.vim
└── zsh
│ └── _yanshi
├── src
├── common.cc
├── common.hh
├── compiler.cc
├── compiler.hh
├── fsa.cc
├── fsa.hh
├── fsa_anno.cc
├── fsa_anno.hh
├── lexer.l
├── lexer_helper.cc
├── lexer_helper.hh
├── loader.cc
├── loader.hh
├── location.cc
├── location.hh
├── main.cc
├── option.cc
├── option.hh
├── parser.y
├── repl.cc
├── repl.hh
├── syntax.cc
└── syntax.hh
└── unittest
├── determinize_test.cc
├── difference_test.cc
├── intersection_test.cc
├── minimize_test.cc
├── union_test.cc
└── unittest_helper.hh
/.dockerignore:
--------------------------------------------------------------------------------
1 | website/node_modules
2 | website/build
3 | website/.docusaurus
4 |
5 | blazehttp/.github
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/1feature-request.yaml:
--------------------------------------------------------------------------------
1 | name: 功能建议
2 | # Feature request
3 | description: 新功能或现有能力的优化建议
4 | title: "[建议] "
5 |
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | 提示:创建前请搜索一下是否有重复问题。一个 issue 尽量只描述一个问题。简洁、准确的描述有助于集中大家的意见,推进问题尽快解决
11 | # Please check for duplicate issue first.
12 | # 尽量描述需求的背景、原始问题,避免出现 X-Y 问题,参考: https://coolshell.cn/articles/10804.html
13 | - type: textarea
14 | id: problem
15 | attributes:
16 | label: 背景与遇到的问题
17 | # Background and the problem that frustrates you
18 | placeholder: |
19 | 例如:我的业务有xxx特性,当我在使用xxx功能的时候,会遇到xxx情况...
20 | validations:
21 | required: false
22 | - type: textarea
23 | id: solution
24 | attributes:
25 | label: 建议的解决方案
26 | # Describe the solution you'd like
27 | placeholder: |
28 | 例如:建议增加xxx功能;将xxx改为xxx...
29 | validations:
30 | required: false
31 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/2bug-report.yaml:
--------------------------------------------------------------------------------
1 | name: Bug
2 | description: 明确的软件故障或缺陷
3 | # Create a report to help us improve
4 | title: "[Bug] "
5 |
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | 提示:提问前请先搜索一下是否存在重复问题
11 | # Please check for duplicate issue first.
12 | - type: textarea
13 | id: Description
14 | attributes:
15 | label: 问题描述
16 | # Describe the bug
17 | validations:
18 | required: false
19 | - type: input
20 | id: version
21 | attributes:
22 | label: 版本号
23 | placeholder: 3.0.0
24 | validations:
25 | required: true
26 | - type: textarea
27 | id: Reproduce
28 | attributes:
29 | label: 复现方法
30 | # To Reproduce
31 | placeholder: |
32 | 1. ...
33 | 2. ...
34 | validations:
35 | required: true
36 | - type: textarea
37 | id: Expected
38 | attributes:
39 | label: 期望的结果
40 | # Expected behavior. Descript what you expected to happen.
41 | validations:
42 | required: true
43 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/3other.yaml:
--------------------------------------------------------------------------------
1 | name: 其他问题与反馈
2 | description: 文档、部署失败等其他问题。
3 | body:
4 | - type: markdown
5 | attributes:
6 | value: |
7 | 提示:创建前请先搜索一下是否存在重复问题
8 | # Please check for duplicate issue first.
9 | # 尽量描述需求的背景、原始问题,避免出现 X-Y 问题,参考: https://coolshell.cn/articles/10804.html
10 | # 提問的智慧: https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md
11 | - type: textarea
12 | id: content
13 | attributes:
14 | label: 反馈内容
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: Ture
2 | contact_links:
3 | - name: 绕过反馈
4 | url: https://stack.chaitin.com/security-challenge/safeline/index
5 | about: Waf 绕过可在 CT Stack 安全挑战赛提交细节
6 |
--------------------------------------------------------------------------------
/.github/workflows/release-charts.yml:
--------------------------------------------------------------------------------
1 | name: Release Charts
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | release:
10 | permissions:
11 | contents: write
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checkout
15 | uses: actions/checkout@v3
16 | with:
17 | fetch-depth: 0
18 |
19 | - name: Configure Git
20 | run: |
21 | git config user.name "$GITHUB_ACTOR"
22 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
23 |
24 | - name: Install Helm
25 | uses: azure/setup-helm@v3
26 |
27 | - name: Run chart-releaser
28 | uses: helm/chart-releaser-action@v1.6.0
29 | env:
30 | CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.Zone.Identifier
2 | .DS_Store
3 | *.zip
4 | *.tar
5 | *.tgz
6 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "blazehttp"]
2 | path = blazehttp
3 | url = https://github.com/chaitin/blazehttp
4 | [submodule "lua-resty-t1k"]
5 | path = lua-resty-t1k
6 | url = https://github.com/chaitin/lua-resty-t1k
7 | [submodule "plugins"]
8 | path = plugins
9 | url = https://github.com/chaitin/safeline-open-platform
10 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:20.5-alpine
2 |
3 | RUN apk update
4 | RUN apk add nginx tini
5 |
6 | RUN echo -e " \n\
7 | server { \n\
8 | listen 80; \n\
9 | \n\
10 | location /api/count { \n\
11 | proxy_pass https://rivers-telemetry.chaitin.cn:10086; \n\
12 | } \n\
13 | location /api/exist { \n\
14 | proxy_pass https://rivers-telemetry.chaitin.cn:10086; \n\
15 | } \n\
16 | location /blazehttp { \n\
17 | root /app/; \n\
18 | try_files \$uri =404; \n\
19 | } \n\
20 | location /release { \n\
21 | root /app/; \n\
22 | try_files \$uri =404; \n\
23 | } \n\
24 | location / { \n\
25 | rewrite /posts/guide_introduction /docs/ permanent; \n\
26 | rewrite /posts/guide_install /docs/guide/install permanent; \n\
27 | rewrite /docs/上手指南/guide_install /docs/guide/install permanent; \n\
28 | rewrite /posts/guide_login /docs/guide/login permanent; \n\
29 | rewrite /docs/上手指南/guide_login /docs/guide/login permanent; \n\
30 | rewrite /posts/guide_config /docs/guide/config permanent; \n\
31 | rewrite /docs/上手指南/guide_config /docs/guide/config permanent; \n\
32 | rewrite /posts/guide_test /docs/guide/test permanent; \n\
33 | rewrite /docs/上手指南/guide_test /docs/guide/test permanent; \n\
34 | rewrite /posts/guide_upgrade /docs/guide/upgrade permanent; \n\
35 | rewrite /docs/上手指南/guide_upgrade /docs/guide/upgrade permanent; \n\
36 | rewrite /posts/faq_install /docs/faq/install permanent; \n\
37 | rewrite /docs/常见问题排查/faq_install /docs/faq/install permanent; \n\
38 | rewrite /posts/faq_login /docs/faq/login permanent; \n\
39 | rewrite /docs/常见问题排查/faq_login /docs/faq/login permanent; \n\
40 | rewrite /posts/faq_access /docs/guide/config permanent; \n\
41 | rewrite /docs/常见问题排查/faq_access /docs/guide/config permanent; \n\
42 | rewrite /posts/faq_config /docs/faq/config permanent; \n\
43 | rewrite /docs/常见问题排查/faq_config /docs/faq/config permanent; \n\
44 | rewrite /posts/faq_other /docs/faq/other permanent; \n\
45 | rewrite /docs/常见问题排查/faq_other /docs/faq/other permanent; \n\
46 | rewrite /posts/about_syntaxanalysis /docs/about/syntaxanalysis permanent; \n\
47 | rewrite /docs/关于雷池/about_syntaxanalysis /docs/about/syntaxanalysis permanent; \n\
48 | rewrite /posts/about_challenge /docs/about/challenge permanent; \n\
49 | rewrite /docs/关于雷池/about_challenge /docs/about/challenge permanent; \n\
50 | rewrite /posts/about_changelog /docs/about/changelog permanent; \n\
51 | rewrite /docs/关于雷池/about_changelog /docs/about/changelog permanent; \n\
52 | rewrite /posts/about_chaitin /docs/about/chaitin permanent; \n\
53 | rewrite /docs/关于雷池/about_chaitin /docs/about/chaitin permanent; \n\
54 | rewrite /docs/faq/access /docs/guide/config permanent; \n\
55 | rewrite /docs/faq/config /docs/guide/config permanent; \n\
56 | proxy_pass http://127.0.0.1:3000; \n\
57 | } \n\
58 | } \n\
59 | " > /etc/nginx/http.d/default.conf
60 | RUN sed -i 's/access_log/access_log off; #/' /etc/nginx/nginx.conf
61 | RUN nginx -t
62 |
63 | COPY release /app/release
64 | # 需要提前编译 blaze
65 | # cd blaze; ./build.sh
66 | COPY blazehttp/build /app/blazehttp
67 |
68 | COPY website /app
69 | WORKDIR /app
70 | RUN npm ci
71 | RUN npm run build
72 |
73 | CMD nginx; tini -- npm run serve
74 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | ## 软件许可证
2 |
3 | 本许可证(以下简称“许可证”)适用于您所获取的软件(以下简称“软件”),请您在使用本软件前仔细阅读以下条款。使用本软件表示您同意并接受本许可证的条款。
4 |
5 | 1. **版权声明**
6 | 本产品的所有代码、镜像、文件其版权均属于北京长亭科技有限公司。
7 |
8 | 2. **使用许可**
9 | 在遵守本许可证条款的前提下,您有权在单一设备上安装、运行本软件,仅用于个人非商业目的。
10 |
11 | 3. **禁止事项**
12 | 您不得对本软件进行以下行为:
13 | a) 破解、逆向工程、反编译、反汇编等行为;
14 | b) 二次包装、修改、改编、复制、翻译、再许可或制作衍生作品;
15 | c) 用于商业用途或任何盈利活动;
16 | d) 未经授权的传播、分发、出售、出租本软件;
17 | e) 将本软件与侵犯他人知识产权或违反法律法规的内容、行为结合。
18 |
19 | 4. **保留权利**
20 | 本软件的版权归原作者所有,除本许可证明确授权外,所有其他权利均由原作者保留。未经原作者明确授权,您不得行使本许可证未明确授权的其他权利。如超出授权使用,原作者保留追究法律责任的权利。
21 |
22 | 5. **免责声明**
23 | 本软件按“现状”提供,不提供任何形式的保证,包括但不限于对适销性、适用于特定用途、无侵权等方面的保证。原作者对于因使用本软件而造成的任何损失、损害、诉讼等不承担责任。
24 |
25 | 6. **终止条款**
26 | 本许可证自您接受之日起生效,直至终止。如您未遵守本许可证的任何条款,原作者有权随时终止本许可证。一旦许可证终止,您必须停止使用本软件,并销毁您拥有或控制的所有副本。
27 |
28 | 7. **适用法律与争议解决**
29 | 本许可证受原作者所在国家或司法管辖区法律的约束并依据其解释。任何因本许可证引起的或与其相关的争议应通过协商解决。如协商无果,任何一方均可将争议提交原作者所在国家或司法管辖区的有管辖权的法院解决。
30 |
31 | ## License
32 |
33 | This License (hereinafter referred to as "License") applies to the software you have obtained (hereinafter referred to as "Software"). Please read the following terms carefully before using the Software. Using the Software indicates your agreement and acceptance of the terms of this License.
34 |
35 | 1. **Copyright Notice**
36 | All codes, images, and files of this product are copyrighted by Beijing Chaitin Future Technology Co.,Ltd
37 |
38 | 2. **Usage Permission**
39 | Subject to compliance with the terms of this License, you are granted the right to install and run the Software on a single device for personal non-commercial purposes only.
40 |
41 | 3. **Prohibitions**
42 | You shall not engage in the following activities in relation to the Software:
43 | a) Cracking, reverse engineering, decompiling, disassembling, or other similar actions;
44 | b) Repackaging, modifying, adapting, copying, translating, sublicensing, or creating derivative works;
45 | c) Using for commercial purposes or any profit-making activities;
46 | d) Unauthorized dissemination, distribution, sale, or rental of the Software;
47 | e) Combining the Software with content or actions that infringe upon the intellectual property rights of others or violate laws and regulations.
48 |
49 | 4. **Reservation of Rights**
50 | The copyright of the Software belongs to the original author. All other rights not expressly granted in this License are reserved by the original author. You may not exercise any other rights not expressly granted in this License without the explicit authorization of the original author.If used beyond the scope of the authorization, the original author reserves the right to pursue legal liability.
51 |
52 | 5. **Disclaimers**
53 | The Software is provided "as is" without any warranties of any kind, including but not limited to warranties of merchantability, fitness for a particular purpose, or non-infringement. The original author shall not be liable for any loss, damage, litigation, or any other consequences resulting from the use of the Software.
54 |
55 | 6. **Termination**
56 | This License shall be effective upon your acceptance and shall continue in effect until terminated. The original author reserves the right to terminate this License at any time if you fail to comply with any of the terms and conditions of this License. Upon termination, you must cease all use of the Software and destroy all copies in your possession or control.
57 |
58 | 7. **Applicable Law and Dispute Resolution**
59 | This License shall be governed by and construed in accordance with the laws of the country or jurisdiction where the original author is located. Any disputes arising from or in connection with this License shall be resolved through negotiation. In case no settlement can be reached through negotiation, either party may submit the dispute to the competent court of the country or jurisdiction where the original author is located.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 雷池 - 广受好评的社区 WAF
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | 官方网站 |
16 | 在线 Demo |
17 | 技术文档 |
18 | For English
19 |
20 |
21 | 一款足够简单、足够好用、足够强的免费 WAF。基于业界领先的语义引擎检测技术,作为反向代理接入,保护你的网站不受黑客攻击。
22 |
23 | 核心检测能力由智能语义分析算法驱动,专为社区而生,不让黑客越雷池半步。
24 |
25 |
26 |
27 | 相关源码仓库
28 |
29 | 语义分析自动机引擎 |
30 | 流量分析插件 |
31 | T1K 协议 |
32 | 测试工具
33 |
34 |
35 | ## 相关特性
36 |
37 | #### 便捷性
38 |
39 | 采用容器化部署,一条命令即可完成安装,0 成本上手。安全配置开箱即用,无需人工维护,可实现安全躺平式管理。
40 |
41 | #### 安全性
42 |
43 | 首创业内领先的智能语义分析算法,精准检测、低误报、难绕过。语义分析算法无规则,面对未知特征的 0day 攻击不再手足无措。
44 |
45 | #### 高性能
46 |
47 | 无规则引擎,线性安全检测算法,平均请求检测延迟在 1 毫秒级别。并发能力强,单核轻松检测 2000+ TPS,只要硬件足够强,可支撑的流量规模无上限。
48 |
49 | #### 高可用
50 |
51 | 流量处理引擎基于 Nginx 开发,性能与稳定性均可得到保障。内置完善的健康检查机制,服务可用性高达 99.99%。
52 |
53 | ## 🚀 安装
54 |
55 | ### 配置需求
56 |
57 | - 操作系统:Linux
58 | - 指令架构:x86_64
59 | - 软件依赖:Docker 20.10.6 版本以上
60 | - 软件依赖:Docker Compose 2.0.0 版本以上
61 | - 最小化环境:1 核 CPU / 1 GB 内存 / 10 GB 磁盘
62 |
63 |
64 | ### 一键安装
65 |
66 | ```
67 | bash -c "$(curl -fsSLk https://waf-ce.chaitin.cn/release/latest/setup.sh)"
68 | ```
69 |
70 | > 更多安装方式请参考 安装雷池
71 |
72 | ## 🕹️ 快速使用
73 |
74 | ### 登录
75 |
76 | 浏览器打开后台管理页面 `https://:9443`。根据界面提示,使用 **支持 TOTP 的认证软件** 扫描二维码,然后输入动态口令登录:
77 |
78 | 
79 |
80 | ### 配置防护站点
81 |
82 | 雷池以反向代理方式接入,优先于网站服务器接收流量,对流量中的攻击行为进行检测和清洗,将清洗过后的流量转发给网站服务器。
83 |
84 | 
85 |
86 | 💡 TIPS: 添加后,执行 `curl -H "Host: <域名>" http://:<端口>` 应能获取到业务网站的响应。
87 |
88 | ### 测试效果
89 |
90 | 使用以下方式尝试模拟黑客攻击,看看雷池的防护效果如何
91 |
92 | - 浏览器访问 `http://:<端口>/?id=1%20AND%201=1`
93 | - 浏览器访问 `http://:<端口>/?a=`
94 |
95 | 
96 |
97 | > 如果你需要进行深度测试,请参考 测试防护效果
98 |
99 | ### FAQ
100 |
101 | - [安装问题](https://waf-ce.chaitin.cn/posts/faq_install)
102 | - [登录问题](https://waf-ce.chaitin.cn/posts/faq_login)
103 | - [网站无法访问](https://waf-ce.chaitin.cn/posts/faq_access)
104 | - [配置问题](https://waf-ce.chaitin.cn/posts/faq_config)
105 | - [其他问题](https://waf-ce.chaitin.cn/posts/faq_other)
106 |
107 | ## 🏘️ 联系我们
108 |
109 | 1. 可以通过 GitHub Issue 直接进行 Bug 反馈和功能建议
110 | 2. 可以扫描下方二维码加入雷池社区版用户讨论群
111 |
112 |
113 |
114 | ## Star History
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/README_EN.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SafeLine Community Edition
5 | Keep hackers at bay
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Official Website
16 | English | 中文文档
17 |
18 | 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.
19 |
20 | ## ✨ Demo
21 |
22 | ### 🔥🔥🔥 Online Demo: https://demo.waf-ce.chaitin.cn:9443/
23 |
24 | There is a simple http server, listened on `http://127.0.0.1:8889`, can be used as for testing.
25 |
26 | 
27 |
28 | 
29 |
30 | ## 🚀 Installation
31 |
32 | ### 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
33 | ```shell
34 | docker info # >= 20.10.6
35 | docker compose version # >= 2.0.0
36 | ```
37 |
38 | ### 2. Setup and deploy
39 |
40 | ```shell
41 | mkdir -p safeline && cd safeline
42 | # setup
43 | curl -kfLsS https://waf-ce.chaitin.cn/release/latest/setup.sh | bash
44 |
45 | # launch
46 | sudo docker compose up -d
47 | ```
48 |
49 | #### Upgrade
50 |
51 | **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.**
52 |
53 | ```shell
54 | curl -kfLsS https://waf-ce.chaitin.cn/release/latest/upgrade.sh | bash
55 |
56 | # delete the old used image layers if necessary.
57 | docker rmi $(docker images | grep "safeline" | grep "none" | awk '{print $3}')
58 | ```
59 |
60 | ## 🕹️ Quick Start
61 |
62 | ### 1. Login
63 |
64 | Open admin page `https://:9443` and scan qrcode with any authenticator Apps that support TOTP, enter the code to login.
65 |
66 | 
67 |
68 | ### 2. Create website
69 |
70 | 
71 |
72 | 💡 TIPS: After creating website,execute `curl -H "Host: " http://:` to check if you can get correct response from web server.
73 |
74 | ### 3. Deploy your website to SafeLine
75 |
76 | - If your website is hosted by DNS, just modify your DNS record to WAF
77 | - If your website is behind any reverse-proxy like nginx, you can modify your nginx conf and set upstream to WAF
78 |
79 | ### 4. Protected!👌
80 |
81 | Try these:
82 |
83 | - `http://:/webshell.php`
84 | - `http://:/?id=1%20AND%201=1`
85 | - `http://:/?a=`
86 |
87 | ## 📖 FAQ
88 |
89 | Please refer to our [FAQ](FAQ.md) first if you have any questions.
90 |
91 | For examples:
92 | - [docker compose or docker-compose?](FAQ.md#docker-compose-or-docker-compose)
93 | - [website configurations](FAQ.md#站点配置问题)
94 | - [website not working / not correctly response](FAQ.md#配置完成之后还是没有成功访问到上游服务器)
95 |
96 | ## 🏘️ Contact Us
97 |
98 | 1. You can make bug feedback and feature suggestions directly through GitHub Issues.
99 | 2. By scanning the QR code below (use wechat or qq), you can join the discussion group of SafeLine users for detailed discussions.
100 |
101 |
102 |
103 | ## ✨ CTStack
104 |
105 |
106 | SafeLine has already joined [CTStack](https://stack.chaitin.com/tool/detail?id=717) community.
107 |
108 | ## Star History
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/charts/safeline/.helmignore:
--------------------------------------------------------------------------------
1 | # Patterns to ignore when building packages.
2 | # This supports shell glob matching, relative path matching, and
3 | # negation (prefixed with !). Only one pattern per line.
4 | .DS_Store
5 | # Common VCS dirs
6 | .git/
7 | .gitignore
8 | .bzr/
9 | .bzrignore
10 | .hg/
11 | .hgignore
12 | .svn/
13 | # Common backup files
14 | *.swp
15 | *.bak
16 | *.tmp
17 | *.orig
18 | *~
19 | # Various IDEs
20 | .project
21 | .idea/
22 | *.tmproj
23 | .vscode/
24 |
--------------------------------------------------------------------------------
/charts/safeline/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | appVersion: 7.1.0
3 | description: A free WAF that is simple enough, easy to use, and strong enough. Based on the industry's leading semantic engine detection technology, it acts as a reverse proxy access to protect your website from hackers.
4 | home: https://waf-ce.chaitin.cn/
5 | icon: https://waf-ce.chaitin.cn/images/403.svg
6 | keywords:
7 | - waf
8 | - chaitin
9 | - safeline
10 | maintainers:
11 | - email: admin@jangrui.com
12 | name: Jangrui
13 | name: safeline
14 | sources:
15 | - https://github.com/chaitin/safeline
16 | - https://github.com/jangrui/safeline-helm
17 | version: 7.1.0
18 |
--------------------------------------------------------------------------------
/charts/safeline/README.md:
--------------------------------------------------------------------------------
1 | # Helm Chart for SafeLine
2 |
3 | ## Prerequisites
4 |
5 | - Kubernetes cluster storage support RWX.
6 |
7 | ## Installation
8 |
9 | Install the SafeLine helm chart with a release name `safeline`:
10 | ```bash
11 | helm repo add jangrui https://github.com/jangrui/SafeLine --force-update
12 | helm -n safeline upgrade -i safeline jangrui/safeline --create-namespace
13 | ```
14 |
15 | ## Uninstallation
16 |
17 | To uninstall/delete the `safeline` deployment:
18 | ```bash
19 | helm -n safeline uninstall safeline
20 | ```
21 |
--------------------------------------------------------------------------------
/charts/safeline/templates/NOTES.txt:
--------------------------------------------------------------------------------
1 | Please wait for several minutes for Safeline deployment to complete.
2 | Then you should be able to visit the Safeline managenment at {{ template "safeline.mgt.api" . }}
3 | For more details, please visit https://github.com/chaitin/SafeLine
--------------------------------------------------------------------------------
/charts/safeline/templates/cache/cache-pvc.yaml:
--------------------------------------------------------------------------------
1 | {{- $cache := .Values.persistence.persistentVolumeClaim.cache -}}
2 | {{- if and .Values.persistence.enabled (not $cache.existingClaim) }}
3 | kind: PersistentVolumeClaim
4 | apiVersion: v1
5 | metadata:
6 | name: {{ template "safeline.cache" . }}
7 | annotations:
8 | {{- range $key, $value := $cache.annotations }}
9 | {{ $key }}: {{ $value | quote }}
10 | {{- end }}
11 | {{- if eq .Values.persistence.resourcePolicy "keep" }}
12 | helm.sh/resource-policy: keep
13 | {{- end }}
14 | labels:
15 | {{ include "safeline.labels" . | indent 4 }}
16 | component: cache
17 | spec:
18 | accessModes:
19 | - {{ $cache.accessMode }}
20 | resources:
21 | requests:
22 | storage: {{ $cache.size }}
23 | {{- if .Values.global.persistence.storageClass }}
24 | storageClassName: {{ .Values.global.persistence.storageClass }}
25 | {{- else if $cache.storageClass }}
26 | {{- if eq "-" $cache.storageClass }}
27 | storageClassName: ""
28 | {{- else }}
29 | storageClassName: {{ $cache.storageClass }}
30 | {{- end }}
31 | {{- end }}
32 | {{- end }}
33 |
--------------------------------------------------------------------------------
/charts/safeline/templates/chaos/chaos-dpl.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: {{ template "safeline.chaos" . }}
5 | labels:
6 | {{ include "safeline.labels" . | indent 4 }}
7 | component: chaos
8 | spec:
9 | replicas: {{ .Values.chaos.replicas }}
10 | revisionHistoryLimit: {{ .Values.chaos.revisionHistoryLimit }}
11 | strategy:
12 | {{- if .Values.strategy }}
13 | {{ toYaml .Values.strategy | indent 4 }}
14 | {{- end }}
15 | selector:
16 | matchLabels:
17 | {{ include "safeline.matchLabels" . | indent 6 }}
18 | component: chaos
19 | template:
20 | metadata:
21 | labels:
22 | {{ include "safeline.matchLabels" . | indent 8 }}
23 | component: chaos
24 | annotations:
25 | {{- if .Values.chaos.podAnnotations }}
26 | {{ toYaml .Values.chaos.podAnnotations | indent 8 }}
27 | {{- end }}
28 | spec:
29 | {{- if .Values.chaos.serviceAccountName }}
30 | serviceAccountName: {{ .Values.chaos.serviceAccountName }}
31 | {{- end -}}
32 | {{- with .Values.imagePullSecrets }}
33 | imagePullSecrets:
34 | {{- toYaml . | nindent 8 }}
35 | {{- end }}
36 | automountServiceAccountToken: {{ .Values.chaos.automountServiceAccountToken | default false }}
37 | terminationGracePeriodSeconds: 120
38 | containers:
39 | - name: chaos
40 | image: {{ default .Values.global.image.registry .Values.chaos.image.registry }}/{{ include "safeline.chaos.image.repository" . }}:{{ default .Chart.AppVersion .Values.chaos.image.tag }}
41 | imagePullPolicy: {{ .Values.imagePullPolicy }}
42 | {{- if .Values.chaos.resources }}
43 | resources:
44 | {{ toYaml .Values.chaos.resources | indent 10 }}
45 | {{- end }}
46 | ports:
47 | - name: chaos
48 | containerPort: {{ template "safeline.chaos.port" . }}
49 | volumeMounts:
50 | - name: localtime
51 | mountPath: /etc/localtime
52 | readOnly: true
53 | - mountPath: /app/chaos
54 | name: chaos
55 | volumes:
56 | - name: localtime
57 | hostPath:
58 | path: /etc/localtime
59 |
60 | {{- if .Values.persistence.enabled }}
61 | - name: chaos
62 | persistentVolumeClaim:
63 | claimName: {{ .Values.persistence.persistentVolumeClaim.chaos.existingClaim | default (include "safeline.chaos" .) }}
64 | {{- else -}}
65 | - name: chaos
66 | emptyDir: {}
67 | {{- end -}}
68 |
69 | {{- with .Values.chaos.nodeSelector }}
70 | nodeSelector:
71 | {{ toYaml . | indent 8 }}
72 | {{- end }}
73 | {{- with .Values.chaos.affinity }}
74 | affinity:
75 | {{ toYaml . | indent 8 }}
76 | {{- end }}
77 | {{- with .Values.chaos.tolerations }}
78 | tolerations:
79 | {{ toYaml . | indent 8 }}
80 | {{- end }}
81 |
--------------------------------------------------------------------------------
/charts/safeline/templates/chaos/chaos-pvc.yaml:
--------------------------------------------------------------------------------
1 | {{- $chaos := .Values.persistence.persistentVolumeClaim.chaos -}}
2 | {{- if and .Values.persistence.enabled (not $chaos.existingClaim) }}
3 | kind: PersistentVolumeClaim
4 | apiVersion: v1
5 | metadata:
6 | name: {{ template "safeline.chaos" . }}
7 | annotations:
8 | {{- range $key, $value := $chaos.annotations }}
9 | {{ $key }}: {{ $value | quote }}
10 | {{- end }}
11 | {{- if eq .Values.persistence.resourcePolicy "keep" }}
12 | helm.sh/resource-policy: keep
13 | {{- end }}
14 | labels:
15 | {{ include "safeline.labels" . | indent 4 }}
16 | component: chaos
17 | spec:
18 | accessModes:
19 | - {{ $chaos.accessMode }}
20 | resources:
21 | requests:
22 | storage: {{ $chaos.size }}
23 | {{- if .Values.global.persistence.storageClass }}
24 | storageClassName: {{ .Values.global.persistence.storageClass }}
25 | {{- else if $chaos.storageClass }}
26 | {{- if eq "-" $chaos.storageClass }}
27 | storageClassName: ""
28 | {{- else }}
29 | storageClassName: {{ $chaos.storageClass }}
30 | {{- end }}
31 | {{- end }}
32 | {{- end }}
33 |
--------------------------------------------------------------------------------
/charts/safeline/templates/chaos/chaos-svc.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: "{{ template "safeline.chaos" . }}"
5 | labels:
6 | {{ include "safeline.labels" . | indent 4 }}
7 | spec:
8 | {{- if or (eq .Values.chaos.service.type "NodePort") (eq .Values.chaos.service.type "LoadBalancer") }}
9 | type: NodePort
10 | {{- end }}
11 | ports:
12 | - name: chaos
13 | protocol: TCP
14 | port: {{ template "safeline.chaos.port" . }}
15 | selector:
16 | {{ include "safeline.matchLabels" . | indent 4 }}
17 | component: chaos
18 |
--------------------------------------------------------------------------------
/charts/safeline/templates/database/database-secret.yaml:
--------------------------------------------------------------------------------
1 | {{- if eq .Values.database.type "internal" -}}
2 | apiVersion: v1
3 | kind: Secret
4 | metadata:
5 | name: "{{ template "safeline.database" . }}"
6 | labels:
7 | {{ include "safeline.labels" . | indent 4 }}
8 | type: Opaque
9 | data:
10 | POSTGRES_PASSWORD: {{ template "safeline.database.encryptedPassword" . }}
11 | {{- end -}}
12 |
--------------------------------------------------------------------------------
/charts/safeline/templates/database/database-ss.yaml:
--------------------------------------------------------------------------------
1 | {{- if eq .Values.database.type "internal" -}}
2 | {{- $database := .Values.persistence.persistentVolumeClaim.database -}}
3 | apiVersion: apps/v1
4 | kind: StatefulSet
5 | metadata:
6 | name: "{{ template "safeline.database" . }}"
7 | labels:
8 | {{ include "safeline.labels" . | indent 4 }}
9 | component: database
10 | spec:
11 | replicas: 1
12 | serviceName: "{{ template "safeline.database" . }}"
13 | selector:
14 | matchLabels:
15 | {{ include "safeline.matchLabels" . | indent 6 }}
16 | component: database
17 | template:
18 | metadata:
19 | labels:
20 | {{ include "safeline.labels" . | indent 8 }}
21 | component: database
22 | annotations:
23 | checksum/secret: {{ include (print $.Template.BasePath "/database/database-secret.yaml") . | sha256sum }}
24 | {{- if .Values.database.podAnnotations }}
25 | {{ toYaml .Values.database.podAnnotations | indent 8 }}
26 | {{- end }}
27 | spec:
28 | {{- if .Values.database.internal.serviceAccountName }}
29 | serviceAccountName: {{ .Values.database.internal.serviceAccountName }}
30 | {{- end -}}
31 | {{- with .Values.imagePullSecrets }}
32 | imagePullSecrets:
33 | {{- toYaml . | nindent 8 }}
34 | {{- end }}
35 | automountServiceAccountToken: {{ .Values.database.internal.automountServiceAccountToken | default false }}
36 | terminationGracePeriodSeconds: 120
37 | containers:
38 | - name: database
39 | image: {{ default .Values.global.image.registry .Values.database.internal.image.registry }}/{{ .Values.database.internal.image.repository }}:{{ .Values.database.internal.image.tag }}
40 | imagePullPolicy: {{ .Values.imagePullPolicy }}
41 | {{- if .Values.database.internal.resources }}
42 | resources:
43 | {{ toYaml .Values.database.internal.resources | indent 10 }}
44 | {{- end }}
45 | envFrom:
46 | - secretRef:
47 | name: "{{ template "safeline.database" . }}"
48 | env:
49 | # - name: PGDATA
50 | # value: "/var/lib/postgresql/data/pgdata"
51 | - name: POSTGRES_USER
52 | value: {{ template "safeline.database.username" . }}
53 | volumeMounts:
54 | - name: database-data
55 | mountPath: /var/lib/postgresql/data
56 | - name: shm-volume
57 | mountPath: /dev/shm
58 | - name: localtime
59 | mountPath: /etc/localtime
60 | readOnly: true
61 | livenessProbe:
62 | exec:
63 | command:
64 | - /bin/sh
65 | - -c
66 | - pg_isready -U safeline-ce -d safeline-ce
67 | initialDelaySeconds: 30
68 | periodSeconds: 10
69 | timeoutSeconds: 5
70 | failureThreshold: 3
71 | readinessProbe:
72 | exec:
73 | command:
74 | - /bin/sh
75 | - -c
76 | - pg_isready -U safeline-ce -d safeline-ce
77 | initialDelaySeconds: 30
78 | periodSeconds: 10
79 | timeoutSeconds: 5
80 | failureThreshold: 3
81 | volumes:
82 | - name: localtime
83 | hostPath:
84 | path: /etc/localtime
85 | - name: shm-volume
86 | emptyDir:
87 | medium: Memory
88 | sizeLimit: {{ .Values.database.internal.shmSizeLimit }}
89 | {{- if not .Values.persistence.enabled }}
90 | - name: "database-data"
91 | emptyDir: {}
92 | {{- else if $database.existingClaim }}
93 | - name: "database-data"
94 | persistentVolumeClaim:
95 | claimName: {{ $database.existingClaim }}
96 | {{- end -}}
97 |
98 | {{- with .Values.database.internal.nodeSelector }}
99 | nodeSelector:
100 | {{ toYaml . | indent 8 }}
101 | {{- end }}
102 | {{- with .Values.database.internal.affinity }}
103 | affinity:
104 | {{ toYaml . | indent 8 }}
105 | {{- end }}
106 | {{- with .Values.database.internal.tolerations }}
107 | tolerations:
108 | {{ toYaml . | indent 8 }}
109 | {{- end }}
110 | {{- if .Values.database.internal.priorityClassName }}
111 | priorityClassName: {{ .Values.database.internal.priorityClassName }}
112 | {{- end }}
113 | {{- if and .Values.persistence.enabled (not $database.existingClaim) }}
114 | volumeClaimTemplates:
115 | - metadata:
116 | name: "database-data"
117 | labels:
118 | {{ include "safeline.labels" . | indent 8 }}
119 | annotations:
120 | {{- range $key, $value := $database.annotations }}
121 | {{ $key }}: {{ $value | quote }}
122 | {{- end }}
123 | spec:
124 | accessModes: [{{ $database.accessMode | quote }}]
125 | {{- if .Values.global.persistence.storageClass }}
126 | storageClassName: "{{ .Values.global.persistence.storageClass }}"
127 | {{- else if $database.storageClass }}
128 | {{- if (eq "-" $database.storageClass) }}
129 | storageClassName: ""
130 | {{- else }}
131 | storageClassName: "{{ $database.storageClass }}"
132 | {{- end }}
133 | {{- end }}
134 | resources:
135 | requests:
136 | storage: {{ $database.size | quote }}
137 | {{- end -}}
138 | {{- end -}}
139 |
--------------------------------------------------------------------------------
/charts/safeline/templates/database/database-svc.yaml:
--------------------------------------------------------------------------------
1 | {{- if eq .Values.database.type "internal" -}}
2 | apiVersion: v1
3 | kind: Service
4 | metadata:
5 | name: {{ template "safeline.database.host" . }}
6 | labels:
7 | {{ include "safeline.labels" . | indent 4 }}
8 | spec:
9 | ports:
10 | - port: 5432
11 | selector:
12 | {{ include "safeline.matchLabels" . | indent 4 }}
13 | component: database
14 | {{- end -}}
--------------------------------------------------------------------------------
/charts/safeline/templates/detector/detector-dpl.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: {{ template "safeline.detector" . }}
5 | labels:
6 | {{ include "safeline.labels" . | indent 4 }}
7 | component: detector
8 | spec:
9 | replicas: {{ .Values.detector.replicas }}
10 | revisionHistoryLimit: {{ .Values.detector.revisionHistoryLimit }}
11 | strategy:
12 | {{- if .Values.strategy }}
13 | {{ toYaml .Values.strategy | indent 4 }}
14 | {{- end }}
15 | selector:
16 | matchLabels:
17 | {{ include "safeline.matchLabels" . | indent 6 }}
18 | component: detector
19 | template:
20 | metadata:
21 | labels:
22 | {{ include "safeline.matchLabels" . | indent 8 }}
23 | component: detector
24 | annotations:
25 | {{- if .Values.detector.podAnnotations }}
26 | {{ toYaml .Values.detector.podAnnotations | indent 8 }}
27 | {{- end }}
28 | spec:
29 | {{- if .Values.detector.serviceAccountName }}
30 | serviceAccountName: {{ .Values.detector.serviceAccountName }}
31 | {{- end -}}
32 | {{- with .Values.imagePullSecrets }}
33 | imagePullSecrets:
34 | {{- toYaml . | nindent 8 }}
35 | {{- end }}
36 | automountServiceAccountToken: {{ .Values.detector.automountServiceAccountToken | default false }}
37 | terminationGracePeriodSeconds: 120
38 | containers:
39 | - name: detector
40 | image: {{ default .Values.global.image.registry .Values.detector.image.registry }}/{{ include "safeline.detector.image.repository" . }}:{{ default .Chart.AppVersion .Values.detector.image.tag }}
41 | imagePullPolicy: {{ .Values.imagePullPolicy }}
42 | ports:
43 | - name: tcd
44 | containerPort: {{ template "safeline.detector.tcd.port" . }}
45 | - name: sns
46 | containerPort: {{ template "safeline.detector.sns.port" . }}
47 | - name: koopa
48 | containerPort: {{ template "safeline.detector.koopa.port" . }}
49 | env:
50 | - name: LOG_DIR
51 | value: /logs/detector
52 | volumeMounts:
53 | - mountPath: /resources/detector
54 | name: detector
55 | - mountPath: /logs
56 | name: logs
57 | - name: localtime
58 | mountPath: /etc/localtime
59 | readOnly: true
60 | volumes:
61 | - name: localtime
62 | hostPath:
63 | path: /etc/localtime
64 |
65 | {{- if .Values.persistence.enabled }}
66 | - name: detector
67 | persistentVolumeClaim:
68 | claimName: {{ .Values.persistence.persistentVolumeClaim.detector.existingClaim | default (include "safeline.detector" .) }}
69 | - name: logs
70 | persistentVolumeClaim:
71 | claimName: {{ .Values.persistence.persistentVolumeClaim.logs.existingClaim | default (include "safeline.logs" .) }}
72 | {{- else -}}
73 | - name: detector
74 | emptyDir: {}
75 | - name: logs
76 | emptyDir: {}
77 | {{- end -}}
78 |
79 | {{- if .Values.detector.resources }}
80 | resources:
81 | {{ toYaml .Values.detector.resources | indent 10 }}
82 | {{- end }}
83 |
84 | {{- with .Values.detector.nodeSelector }}
85 | nodeSelector:
86 | {{ toYaml . | indent 8 }}
87 | {{- end }}
88 | {{- with .Values.detector.affinity }}
89 | affinity:
90 | {{ toYaml . | indent 8 }}
91 | {{- end }}
92 | {{- with .Values.detector.tolerations }}
93 | tolerations:
94 | {{ toYaml . | indent 8 }}
95 | {{- end }}
96 | {{- if .Values.detector.priorityClassName }}
97 | priorityClassName: {{ .Values.detector.priorityClassName }}
98 | {{- end }}
99 |
--------------------------------------------------------------------------------
/charts/safeline/templates/detector/detector-pvc.yaml:
--------------------------------------------------------------------------------
1 | {{- $detector := .Values.persistence.persistentVolumeClaim.detector -}}
2 | {{- if and .Values.persistence.enabled (not $detector.existingClaim) }}
3 | kind: PersistentVolumeClaim
4 | apiVersion: v1
5 | metadata:
6 | name: {{ template "safeline.detector" . }}
7 | annotations:
8 | {{- range $key, $value := $detector.annotations }}
9 | {{ $key }}: {{ $value | quote }}
10 | {{- end }}
11 | {{- if eq .Values.persistence.resourcePolicy "keep" }}
12 | helm.sh/resource-policy: keep
13 | {{- end }}
14 | labels:
15 | {{ include "safeline.labels" . | indent 4 }}
16 | component: detector
17 | spec:
18 | accessModes:
19 | - {{ $detector.accessMode }}
20 | resources:
21 | requests:
22 | storage: {{ $detector.size }}
23 | {{- if .Values.global.persistence.storageClass }}
24 | storageClassName: {{ .Values.global.persistence.storageClass }}
25 | {{- else if $detector.storageClass }}
26 | {{- if eq "-" $detector.storageClass }}
27 | storageClassName: ""
28 | {{- else }}
29 | storageClassName: {{ $detector.storageClass }}
30 | {{- end }}
31 | {{- end }}
32 | {{- end }}
33 |
--------------------------------------------------------------------------------
/charts/safeline/templates/detector/detector-svc.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: {{ template "safeline.detector" . }}
5 | labels:
6 | {{ include "safeline.labels" . | indent 4 }}
7 | spec:
8 | ports:
9 | - name: tcd
10 | port: {{ template "safeline.detector.tcd.port" . }}
11 | - name: sns
12 | port: {{ template "safeline.detector.sns.port" . }}
13 | selector:
14 | {{ include "safeline.matchLabels" . | indent 4 }}
15 | component: detector
16 |
--------------------------------------------------------------------------------
/charts/safeline/templates/fvm/fvm-dpl.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: {{ template "safeline.fvm" . }}
5 | labels:
6 | {{ include "safeline.labels" . | indent 4 }}
7 | component: fvm
8 | spec:
9 | replicas: {{ .Values.fvm.replicas }}
10 | revisionHistoryLimit: {{ .Values.fvm.revisionHistoryLimit }}
11 | strategy:
12 | {{- if .Values.strategy }}
13 | {{ toYaml .Values.strategy | indent 4 }}
14 | {{- end }}
15 | selector:
16 | matchLabels:
17 | {{ include "safeline.matchLabels" . | indent 6 }}
18 | component: fvm
19 | template:
20 | metadata:
21 | labels:
22 | {{ include "safeline.matchLabels" . | indent 8 }}
23 | component: fvm
24 | annotations:
25 | {{- if .Values.fvm.podAnnotations }}
26 | {{ toYaml .Values.fvm.podAnnotations | indent 8 }}
27 | {{- end }}
28 | spec:
29 | {{- if .Values.fvm.serviceAccountName }}
30 | serviceAccountName: {{ .Values.fvm.serviceAccountName }}
31 | {{- end -}}
32 | {{- with .Values.imagePullSecrets }}
33 | imagePullSecrets:
34 | {{- toYaml . | nindent 8 }}
35 | {{- end }}
36 | automountServiceAccountToken: {{ .Values.fvm.automountServiceAccountToken | default false }}
37 | terminationGracePeriodSeconds: 120
38 | containers:
39 | - name: fvm
40 | image: {{ default .Values.global.image.registry .Values.fvm.image.registry }}/{{ include "safeline.fvm.image.repository" . }}:{{ default .Chart.AppVersion .Values.fvm.image.tag }}
41 | imagePullPolicy: {{ .Values.imagePullPolicy }}
42 | ports:
43 | - name: api
44 | containerPort: {{ template "safeline.fvm.api.port" . }}
45 | - name: web
46 | containerPort: {{ template "safeline.fvm.web.port" . }}
47 | volumeMounts:
48 | - name: localtime
49 | mountPath: /etc/localtime
50 | readOnly: true
51 | {{- if .Values.fvm.resources }}
52 | resources:
53 | {{ toYaml .Values.fvm.resources | indent 10 }}
54 | {{- end }}
55 | volumes:
56 | - name: localtime
57 | hostPath:
58 | path: /etc/localtime
59 |
60 | {{- with .Values.fvm.nodeSelector }}
61 | nodeSelector:
62 | {{ toYaml . | indent 8 }}
63 | {{- end }}
64 | {{- with .Values.fvm.affinity }}
65 | affinity:
66 | {{ toYaml . | indent 8 }}
67 | {{- end }}
68 | {{- with .Values.fvm.tolerations }}
69 | tolerations:
70 | {{ toYaml . | indent 8 }}
71 | {{- end }}
72 | {{- if .Values.fvm.priorityClassName }}
73 | priorityClassName: {{ .Values.fvm.priorityClassName }}
74 | {{- end }}
75 |
--------------------------------------------------------------------------------
/charts/safeline/templates/fvm/fvm-svc.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: "{{ template "safeline.fvm" . }}"
5 | labels:
6 | {{ include "safeline.labels" . | indent 4 }}
7 | spec:
8 | {{- if or (eq .Values.fvm.service.type "NodePort") (eq .Values.fvm.service.type "LoadBalancer") }}
9 | type: NodePort
10 | {{- end }}
11 | ports:
12 | - name: api
13 | protocol: TCP
14 | port: {{ template "safeline.fvm.api.port" . }}
15 | - name: web
16 | protocol: TCP
17 | port: {{ template "safeline.fvm.web.port" . }}
18 | selector:
19 | {{ include "safeline.matchLabels" . | indent 4 }}
20 | component: fvm
21 |
--------------------------------------------------------------------------------
/charts/safeline/templates/logs/logs-pvc.yaml:
--------------------------------------------------------------------------------
1 | {{- $logs := .Values.persistence.persistentVolumeClaim.logs -}}
2 | {{- if and .Values.persistence.enabled (not $logs.existingClaim) }}
3 | kind: PersistentVolumeClaim
4 | apiVersion: v1
5 | metadata:
6 | name: {{ template "safeline.logs" . }}
7 | annotations:
8 | {{- range $key, $value := $logs.annotations }}
9 | {{ $key }}: {{ $value | quote }}
10 | {{- end }}
11 | {{- if eq .Values.persistence.resourcePolicy "keep" }}
12 | helm.sh/resource-policy: keep
13 | {{- end }}
14 | labels:
15 | {{ include "safeline.labels" . | indent 4 }}
16 | component: logs
17 | spec:
18 | accessModes:
19 | - {{ $logs.accessMode }}
20 | resources:
21 | requests:
22 | storage: {{ $logs.size }}
23 | {{- if .Values.global.persistence.storageClass }}
24 | storageClassName: {{ .Values.global.persistence.storageClass }}
25 | {{- else if $logs.storageClass }}
26 | {{- if eq "-" $logs.storageClass }}
27 | storageClassName: ""
28 | {{- else }}
29 | storageClassName: {{ $logs.storageClass }}
30 | {{- end }}
31 | {{- end }}
32 | {{- end }}
33 |
--------------------------------------------------------------------------------
/charts/safeline/templates/luigi/luigi-dpl.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: {{ template "safeline.luigi" . }}
5 | labels:
6 | {{ include "safeline.labels" . | indent 4 }}
7 | component: luigi
8 | spec:
9 | replicas: {{ .Values.luigi.replicas }}
10 | revisionHistoryLimit: {{ .Values.luigi.revisionHistoryLimit }}
11 | strategy:
12 | {{- if .Values.strategy }}
13 | {{ toYaml .Values.strategy | indent 4 }}
14 | {{- end }}
15 | selector:
16 | matchLabels:
17 | {{ include "safeline.matchLabels" . | indent 6 }}
18 | component: luigi
19 | template:
20 | metadata:
21 | labels:
22 | {{ include "safeline.matchLabels" . | indent 8 }}
23 | component: luigi
24 | annotations:
25 | {{- if .Values.luigi.podAnnotations }}
26 | {{ toYaml .Values.luigi.podAnnotations | indent 8 }}
27 | {{- end }}
28 | spec:
29 | {{- if .Values.luigi.serviceAccountName }}
30 | serviceAccountName: {{ .Values.luigi.serviceAccountName }}
31 | {{- end -}}
32 | {{- with .Values.imagePullSecrets }}
33 | imagePullSecrets:
34 | {{- toYaml . | nindent 8 }}
35 | {{- end }}
36 | automountServiceAccountToken: {{ .Values.luigi.automountServiceAccountToken | default false }}
37 | terminationGracePeriodSeconds: 120
38 | containers:
39 | - name: luigi
40 | image: {{ default .Values.global.image.registry .Values.luigi.image.registry }}/{{ include "safeline.luigi.image.repository" . }}:{{ default .Chart.AppVersion .Values.luigi.image.tag }}
41 | imagePullPolicy: {{ .Values.imagePullPolicy }}
42 | ports:
43 | - name: luigi
44 | containerPort: {{ template "safeline.luigi.port" . }}
45 | env:
46 | - name: MGT_IP
47 | value: {{ template "safeline.mgt" . }}
48 | - name: LUIGI_PG
49 | value: {{ template "safeline.database.url" . }}
50 | volumeMounts:
51 | - name: localtime
52 | mountPath: /etc/localtime
53 | readOnly: true
54 | - name: luigi
55 | mountPath: /app/data
56 | {{- if .Values.luigi.resources }}
57 | resources:
58 | {{ toYaml .Values.luigi.resources | indent 10 }}
59 | {{- end }}
60 | volumes:
61 | - name: localtime
62 | hostPath:
63 | path: /etc/localtime
64 | {{- if .Values.persistence.enabled }}
65 | - name: luigi
66 | persistentVolumeClaim:
67 | claimName: {{ .Values.persistence.persistentVolumeClaim.luigi.existingClaim | default (include "safeline.luigi" .) }}
68 | {{- else -}}
69 | - name: luigi
70 | emptyDir: {}
71 | {{- end -}}
72 |
73 | {{- with .Values.luigi.nodeSelector }}
74 | nodeSelector:
75 | {{ toYaml . | indent 8 }}
76 | {{- end }}
77 | {{- with .Values.luigi.affinity }}
78 | affinity:
79 | {{ toYaml . | indent 8 }}
80 | {{- end }}
81 | {{- with .Values.luigi.tolerations }}
82 | tolerations:
83 | {{ toYaml . | indent 8 }}
84 | {{- end }}
85 | {{- if .Values.luigi.priorityClassName }}
86 | priorityClassName: {{ .Values.luigi.priorityClassName }}
87 | {{- end }}
88 |
--------------------------------------------------------------------------------
/charts/safeline/templates/luigi/luigi-pvc.yaml:
--------------------------------------------------------------------------------
1 | {{- $luigi := .Values.persistence.persistentVolumeClaim.luigi -}}
2 | {{- if and .Values.persistence.enabled (not $luigi.existingClaim) }}
3 | kind: PersistentVolumeClaim
4 | apiVersion: v1
5 | metadata:
6 | name: {{ template "safeline.luigi" . }}
7 | annotations:
8 | {{- range $key, $value := $luigi.annotations }}
9 | {{ $key }}: {{ $value | quote }}
10 | {{- end }}
11 | {{- if eq .Values.persistence.resourcePolicy "keep" }}
12 | helm.sh/resource-policy: keep
13 | {{- end }}
14 | labels:
15 | {{ include "safeline.labels" . | indent 4 }}
16 | component: luigi
17 | spec:
18 | accessModes:
19 | - {{ $luigi.accessMode }}
20 | resources:
21 | requests:
22 | storage: {{ $luigi.size }}
23 | {{- if .Values.global.persistence.storageClass }}
24 | storageClassName: {{ .Values.global.persistence.storageClass }}
25 | {{- else if $luigi.storageClass }}
26 | {{- if eq "-" $luigi.storageClass }}
27 | storageClassName: ""
28 | {{- else }}
29 | storageClassName: {{ $luigi.storageClass }}
30 | {{- end }}
31 | {{- end }}
32 | {{- end }}
33 |
--------------------------------------------------------------------------------
/charts/safeline/templates/luigi/luigi-svc.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: "{{ template "safeline.luigi" . }}"
5 | labels:
6 | {{ include "safeline.labels" . | indent 4 }}
7 | spec:
8 | {{- if or (eq .Values.luigi.service.type "NodePort") (eq .Values.luigi.service.type "LoadBalancer") }}
9 | type: NodePort
10 | {{- end }}
11 | ports:
12 | - name: luigi
13 | protocol: TCP
14 | port: {{ template "safeline.luigi.port" . }}
15 | selector:
16 | {{ include "safeline.matchLabels" . | indent 4 }}
17 | component: luigi
18 |
--------------------------------------------------------------------------------
/charts/safeline/templates/mgt/mgt-dpl.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: {{ template "safeline.mgt" . }}
5 | labels:
6 | {{ include "safeline.labels" . | indent 4 }}
7 | component: mgt
8 | spec:
9 | replicas: {{ .Values.mgt.replicas }}
10 | revisionHistoryLimit: {{ .Values.mgt.revisionHistoryLimit }}
11 | strategy:
12 | {{- if .Values.strategy }}
13 | {{ toYaml .Values.strategy | indent 4 }}
14 | {{- end }}
15 | selector:
16 | matchLabels:
17 | {{ include "safeline.matchLabels" . | indent 6 }}
18 | component: mgt
19 | template:
20 | metadata:
21 | labels:
22 | {{ include "safeline.matchLabels" . | indent 8 }}
23 | component: mgt
24 | annotations:
25 | {{- if .Values.mgt.podAnnotations }}
26 | {{ toYaml .Values.mgt.podAnnotations | indent 8 }}
27 | {{- end }}
28 | spec:
29 | {{- if .Values.mgt.serviceAccountName }}
30 | serviceAccountName: {{ .Values.mgt.serviceAccountName }}
31 | {{- end -}}
32 | {{- with .Values.imagePullSecrets }}
33 | imagePullSecrets:
34 | {{- toYaml . | nindent 8 }}
35 | {{- end }}
36 | automountServiceAccountToken: {{ .Values.mgt.automountServiceAccountToken | default false }}
37 | terminationGracePeriodSeconds: 120
38 | containers:
39 | - name: mgt
40 | image: {{ default .Values.global.image.registry .Values.mgt.image.registry }}/{{ include "safeline.mgt.image.repository" . }}:{{ default .Chart.AppVersion .Values.mgt.image.tag }}
41 | imagePullPolicy: {{ .Values.imagePullPolicy }}
42 | ports:
43 | - name: web
44 | containerPort: {{ template "safeline.mgt.web.port" . }}
45 | - name: api
46 | containerPort: {{ template "safeline.mgt.api.port" . }}
47 | - name: tcd
48 | containerPort: {{ template "safeline.mgt.tcd.port" . }}
49 | env:
50 | - name: MGT_PG
51 | value: {{ template "safeline.database.url" . }}
52 | - name: TCD_TASK_ADDRESS
53 | value: {{ template "safeline.tengine" . }}:{{ template "safeline.tengine.tcd.port" . }}
54 | volumeMounts:
55 | - name: localtime
56 | mountPath: /etc/localtime
57 | readOnly: true
58 | - mountPath: /app/data
59 | name: mgt
60 | - mountPath: /app/sock
61 | name: sock
62 | - mountPath: /app/log
63 | name: logs
64 | livenessProbe:
65 | httpGet:
66 | scheme: HTTPS
67 | port: 1443
68 | path: /api/open/health
69 | initialDelaySeconds: 30
70 | periodSeconds: 10
71 | timeoutSeconds: 5
72 | successThreshold: 1
73 | failureThreshold: 3
74 | readinessProbe:
75 | httpGet:
76 | scheme: HTTPS
77 | port: 1443
78 | path: /api/open/health
79 | initialDelaySeconds: 5
80 | periodSeconds: 5
81 | timeoutSeconds: 1
82 | successThreshold: 1
83 | failureThreshold: 3
84 | {{- if .Values.mgt.resources }}
85 | resources:
86 | {{ toYaml .Values.mgt.resources | indent 10 }}
87 | {{- end }}
88 | volumes:
89 | - name: localtime
90 | hostPath:
91 | path: /etc/localtime
92 | {{- if .Values.persistence.enabled }}
93 | - name: mgt
94 | persistentVolumeClaim:
95 | claimName: {{ .Values.persistence.persistentVolumeClaim.mgt.existingClaim | default (include "safeline.mgt" .) }}
96 | - name: sock
97 | persistentVolumeClaim:
98 | claimName: {{ .Values.persistence.persistentVolumeClaim.sock.existingClaim | default (include "safeline.sock" .) }}
99 | - name: logs
100 | persistentVolumeClaim:
101 | claimName: {{ .Values.persistence.persistentVolumeClaim.logs.existingClaim | default (include "safeline.logs" .) }}
102 | {{- else -}}
103 | - name: mgt
104 | emptyDir: {}
105 | - name: sock
106 | emptyDir: {}
107 | - name: logs
108 | emptyDir: {}
109 | {{- end -}}
110 |
111 | {{- with .Values.mgt.nodeSelector }}
112 | nodeSelector:
113 | {{ toYaml . | indent 8 }}
114 | {{- end }}
115 | {{- with .Values.mgt.affinity }}
116 | affinity:
117 | {{ toYaml . | indent 8 }}
118 | {{- end }}
119 | {{- with .Values.mgt.tolerations }}
120 | tolerations:
121 | {{ toYaml . | indent 8 }}
122 | {{- end }}
123 | {{- if .Values.mgt.priorityClassName }}
124 | priorityClassName: {{ .Values.mgt.priorityClassName }}
125 | {{- end }}
126 |
--------------------------------------------------------------------------------
/charts/safeline/templates/mgt/mgt-pvc.yaml:
--------------------------------------------------------------------------------
1 | {{- $mgt := .Values.persistence.persistentVolumeClaim.mgt -}}
2 | {{- if and .Values.persistence.enabled (not $mgt.existingClaim) }}
3 | kind: PersistentVolumeClaim
4 | apiVersion: v1
5 | metadata:
6 | name: {{ template "safeline.mgt" . }}
7 | annotations:
8 | {{- range $key, $value := $mgt.annotations }}
9 | {{ $key }}: {{ $value | quote }}
10 | {{- end }}
11 | {{- if eq .Values.persistence.resourcePolicy "keep" }}
12 | helm.sh/resource-policy: keep
13 | {{- end }}
14 | labels:
15 | {{ include "safeline.labels" . | indent 4 }}
16 | component: mgt
17 | spec:
18 | accessModes:
19 | - {{ $mgt.accessMode }}
20 | resources:
21 | requests:
22 | storage: {{ $mgt.size }}
23 | {{- if .Values.global.persistence.storageClass }}
24 | storageClassName: {{ .Values.global.persistence.storageClass }}
25 | {{- else if $mgt.storageClass }}
26 | {{- if eq "-" $mgt.storageClass }}
27 | storageClassName: ""
28 | {{- else }}
29 | storageClassName: {{ $mgt.storageClass }}
30 | {{- end }}
31 | {{- end }}
32 | {{- end }}
33 |
--------------------------------------------------------------------------------
/charts/safeline/templates/mgt/mgt-svc.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: "{{ template "safeline.mgt" . }}"
5 | labels:
6 | {{ include "safeline.labels" . | indent 4 }}
7 | spec:
8 | {{- if or (eq .Values.mgt.service.type "NodePort") (eq .Values.mgt.service.type "LoadBalancer") }}
9 | type: NodePort
10 | {{- end }}
11 | ports:
12 | - name: web
13 | port: {{ template "safeline.mgt.web.port" . }}
14 | {{- if or (eq .Values.mgt.service.type "NodePort") (eq .Values.mgt.service.type "LoadBalancer") }}
15 | nodePort: {{ .Values.mgt.service.web.nodePort }}
16 | {{- end }}
17 | - name: api
18 | protocol: TCP
19 | port: {{ template "safeline.mgt.api.port" .}}
20 | - name: tcd
21 | protocol: TCP
22 | port: {{ template "safeline.mgt.tcd.port" .}}
23 | selector:
24 | {{ include "safeline.matchLabels" . | indent 4 }}
25 | component: mgt
26 |
--------------------------------------------------------------------------------
/charts/safeline/templates/nginx/nginx-pvc.yaml:
--------------------------------------------------------------------------------
1 | {{- $nginx := .Values.persistence.persistentVolumeClaim.nginx -}}
2 | {{- if and .Values.persistence.enabled (not $nginx.existingClaim) }}
3 | kind: PersistentVolumeClaim
4 | apiVersion: v1
5 | metadata:
6 | name: {{ template "safeline.nginx" . }}
7 | annotations:
8 | {{- range $key, $value := $nginx.annotations }}
9 | {{ $key }}: {{ $value | quote }}
10 | {{- end }}
11 | {{- if eq .Values.persistence.resourcePolicy "keep" }}
12 | helm.sh/resource-policy: keep
13 | {{- end }}
14 | labels:
15 | {{ include "safeline.labels" . | indent 4 }}
16 | component: nginx
17 | spec:
18 | accessModes:
19 | - {{ $nginx.accessMode }}
20 | resources:
21 | requests:
22 | storage: {{ $nginx.size }}
23 | {{- if .Values.global.persistence.storageClass }}
24 | storageClassName: {{ .Values.global.persistence.storageClass }}
25 | {{- else if $nginx.storageClass }}
26 | {{- if eq "-" $nginx.storageClass }}
27 | storageClassName: ""
28 | {{- else }}
29 | storageClassName: {{ $nginx.storageClass }}
30 | {{- end }}
31 | {{- end }}
32 | {{- end }}
33 |
--------------------------------------------------------------------------------
/charts/safeline/templates/run/run-pvc.yaml:
--------------------------------------------------------------------------------
1 | {{- $run := .Values.persistence.persistentVolumeClaim.run -}}
2 | {{- if and .Values.persistence.enabled (not $run.existingClaim) }}
3 | kind: PersistentVolumeClaim
4 | apiVersion: v1
5 | metadata:
6 | name: {{ template "safeline.run" . }}
7 | annotations:
8 | {{- range $key, $value := $run.annotations }}
9 | {{ $key }}: {{ $value | quote }}
10 | {{- end }}
11 | {{- if eq .Values.persistence.resourcePolicy "keep" }}
12 | helm.sh/resource-policy: keep
13 | {{- end }}
14 | labels:
15 | {{ include "safeline.labels" . | indent 4 }}
16 | component: run
17 | spec:
18 | accessModes:
19 | - {{ $run.accessMode }}
20 | resources:
21 | requests:
22 | storage: {{ $run.size }}
23 | {{- if .Values.global.persistence.storageClass }}
24 | storageClassName: {{ .Values.global.persistence.storageClass }}
25 | {{- else if $run.storageClass }}
26 | {{- if eq "-" $run.storageClass }}
27 | storageClassName: ""
28 | {{- else }}
29 | storageClassName: {{ $run.storageClass }}
30 | {{- end }}
31 | {{- end }}
32 | {{- end }}
33 |
--------------------------------------------------------------------------------
/charts/safeline/templates/sock/sock-pvc.yaml:
--------------------------------------------------------------------------------
1 | {{- $sock := .Values.persistence.persistentVolumeClaim.sock -}}
2 | {{- if and .Values.persistence.enabled (not $sock.existingClaim) }}
3 | kind: PersistentVolumeClaim
4 | apiVersion: v1
5 | metadata:
6 | name: {{ template "safeline.sock" . }}
7 | annotations:
8 | {{- range $key, $value := $sock.annotations }}
9 | {{ $key }}: {{ $value | quote }}
10 | {{- end }}
11 | {{- if eq .Values.persistence.resourcePolicy "keep" }}
12 | helm.sh/resource-policy: keep
13 | {{- end }}
14 | labels:
15 | {{ include "safeline.labels" . | indent 4 }}
16 | component: sock
17 | spec:
18 | accessModes:
19 | - {{ $sock.accessMode }}
20 | resources:
21 | requests:
22 | storage: {{ $sock.size }}
23 | {{- if .Values.global.persistence.storageClass }}
24 | storageClassName: {{ .Values.global.persistence.storageClass }}
25 | {{- else if $sock.storageClass }}
26 | {{- if eq "-" $sock.storageClass }}
27 | storageClassName: ""
28 | {{- else }}
29 | storageClassName: {{ $sock.storageClass }}
30 | {{- end }}
31 | {{- end }}
32 | {{- end }}
33 |
--------------------------------------------------------------------------------
/charts/safeline/templates/tengine/tengine-dpl.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: {{ template "safeline.tengine" . }}
5 | labels:
6 | {{ include "safeline.labels" . | indent 4 }}
7 | component: tengine
8 | spec:
9 | replicas: {{ .Values.tengine.replicas }}
10 | revisionHistoryLimit: {{ .Values.tengine.revisionHistoryLimit }}
11 | strategy:
12 | {{- if .Values.strategy }}
13 | {{ toYaml .Values.strategy | indent 4 }}
14 | {{- end }}
15 | selector:
16 | matchLabels:
17 | {{ include "safeline.matchLabels" . | indent 6 }}
18 | component: tengine
19 | template:
20 | metadata:
21 | labels:
22 | {{ include "safeline.matchLabels" . | indent 8 }}
23 | component: tengine
24 | annotations:
25 | {{- if .Values.tengine.podAnnotations }}
26 | {{ toYaml .Values.tengine.podAnnotations | indent 8 }}
27 | {{- end }}
28 | spec:
29 | {{- if .Values.tengine.serviceAccountName }}
30 | serviceAccountName: {{ .Values.tengine.serviceAccountName }}
31 | {{- end -}}
32 | {{- with .Values.imagePullSecrets }}
33 | imagePullSecrets:
34 | {{- toYaml . | nindent 8 }}
35 | {{- end }}
36 | automountServiceAccountToken: {{ .Values.tengine.automountServiceAccountToken | default false }}
37 | terminationGracePeriodSeconds: 120
38 | initContainers:
39 | - name: mkdir-nginx-logs-dir
40 | image: {{ default .Values.global.image.registry .Values.tengine.image.registry }}/{{ include "safeline.tengine.image.repository" . }}:{{ default .Chart.AppVersion .Values.tengine.image.tag }}
41 | imagePullPolicy: {{ .Values.imagePullPolicy }}
42 | command:
43 | - sh
44 | - -c
45 | - |-
46 | mkdir -p /var/log/nginx
47 | volumeMounts:
48 | - mountPath: /var/log
49 | name: logs
50 | containers:
51 | - name: tengine
52 | image: {{ default .Values.global.image.registry .Values.tengine.image.registry }}/{{ include "safeline.tengine.image.repository" . }}:{{ default .Chart.AppVersion .Values.tengine.image.tag }}
53 | imagePullPolicy: {{ .Values.imagePullPolicy }}
54 | ports:
55 | - name: health
56 | containerPort: {{ template "safeline.tengine.health.port" . }}
57 | - name: tcd
58 | containerPort: {{ template "safeline.tengine.tcd.port" . }}
59 | - name: http
60 | containerPort: {{ template "safeline.tengine.http.port" . }}
61 | env:
62 | - name: TCD_MGT_API
63 | value: {{ template "safeline.mgt.api" . }}
64 | - name: TCD_SNSERVER
65 | value: {{ template "safeline.detector.tcd" . }}
66 | - name: SNSERVER_ADDR
67 | value: {{ template "safeline.detector.tcd" . }}
68 | - name: TCD_TASK_ADDRESS
69 | value: 0.0.0.0:{{ template "safeline.tengine.tcd.port" . }}
70 | volumeMounts:
71 | - name: localtime
72 | mountPath: /etc/localtime
73 | readOnly: true
74 | - mountPath: /etc/nginx
75 | name: nginx
76 | - mountPath: /resources/detector
77 | name: detector
78 | - mountPath: /resources/chaos
79 | name: chaos
80 | - mountPath: /var/log
81 | name: logs
82 | - mountPath: /usr/local/nginx/cache
83 | name: cache
84 | - mountPath: /app/sock
85 | name: sock
86 | - mountPath: /app/run
87 | name: run
88 | volumes:
89 | - name: localtime
90 | hostPath:
91 | path: /etc/localtime
92 | {{- if .Values.persistence.enabled }}
93 | - name: nginx
94 | persistentVolumeClaim:
95 | claimName: {{ .Values.persistence.persistentVolumeClaim.nginx.existingClaim | default (include "safeline.nginx" .) }}
96 | - name: detector
97 | persistentVolumeClaim:
98 | claimName: {{ .Values.persistence.persistentVolumeClaim.detector.existingClaim | default (include "safeline.detector" .) }}
99 | - name: chaos
100 | persistentVolumeClaim:
101 | claimName: {{ .Values.persistence.persistentVolumeClaim.chaos.existingClaim | default (include "safeline.chaos" .) }}
102 | - name: logs
103 | persistentVolumeClaim:
104 | claimName: {{ .Values.persistence.persistentVolumeClaim.logs.existingClaim | default (include "safeline.logs" .) }}
105 | - name: cache
106 | persistentVolumeClaim:
107 | claimName: {{ .Values.persistence.persistentVolumeClaim.cache.existingClaim | default (include "safeline.cache" .) }}
108 | - name: sock
109 | persistentVolumeClaim:
110 | claimName: {{ .Values.persistence.persistentVolumeClaim.sock.existingClaim | default (include "safeline.sock" .) }}
111 | - name: run
112 | persistentVolumeClaim:
113 | claimName: {{ .Values.persistence.persistentVolumeClaim.run.existingClaim | default (include "safeline.run" .) }}
114 | {{- else -}}
115 | - name: nginx
116 | emptyDir: {}
117 | - name: detector
118 | emptyDir: {}
119 | - name: chaos
120 | emptyDir: {}
121 | - name: logs
122 | emptyDir: {}
123 | - name: cache
124 | emptyDir: {}
125 | - name: sock
126 | emptyDir: {}
127 | - name: run
128 | emptyDir: {}
129 | {{- end -}}
130 |
131 | {{- if .Values.tengine.resources }}
132 | resources:
133 | {{ toYaml .Values.tengine.resources | indent 10 }}
134 | {{- end }}
135 |
136 | {{- with .Values.tengine.nodeSelector }}
137 | nodeSelector:
138 | {{ toYaml . | indent 8 }}
139 | {{- end }}
140 | {{- with .Values.tengine.affinity }}
141 | affinity:
142 | {{ toYaml . | indent 8 }}
143 | {{- end }}
144 | {{- with .Values.tengine.tolerations }}
145 | tolerations:
146 | {{ toYaml . | indent 8 }}
147 | {{- end }}
148 | {{- if .Values.tengine.priorityClassName }}
149 | priorityClassName: {{ .Values.tengine.priorityClassName }}
150 | {{- end }}
151 |
--------------------------------------------------------------------------------
/charts/safeline/templates/tengine/tengine-svc.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: "{{ template "safeline.tengine" . }}"
5 | labels:
6 | {{ include "safeline.labels" . | indent 4 }}
7 | spec:
8 | ports:
9 | - name: health
10 | protocol: TCP
11 | port: {{ template "safeline.tengine.health.port" . }}
12 | - name: http
13 | protocol: TCP
14 | port: {{ template "safeline.tengine.http.port" . }}
15 | - name: tcd
16 | protocol: TCP
17 | port: {{ template "safeline.tengine.tcd.port" . }}
18 | selector:
19 | {{ include "safeline.matchLabels" . | indent 4 }}
20 | component: tengine
21 |
--------------------------------------------------------------------------------
/release/ipgroup/README.md:
--------------------------------------------------------------------------------
1 | # 雷池内置 IP 组
2 |
3 | ### 国家 IP 库
4 |
5 | 定期手动更新,数据来源 https://ipv4.fetus.jp/tw
6 |
7 | ### 爬虫 IP 库
8 |
9 | ##### cloudflare
10 |
11 | 官方 https://www.cloudflare.com/ips-v4
12 |
13 | ##### 360
14 |
15 | http://www.so.com/help/spider_ip.html
16 |
17 | ##### 百度
18 |
19 | 没有爬虫 IP 池,官方推荐的判断方法 https://ziyuan.baidu.com/college/articleinfo?id=1198
20 |
--------------------------------------------------------------------------------
/release/ipgroup/crawler/360.txt:
--------------------------------------------------------------------------------
1 | # http://www.so.com/help/spider_ip.html
2 |
3 | 180.153.232.0/24
4 | 180.153.234.0/24
5 | 180.153.236.0/24
6 | 180.163.220.0/24
7 | 42.236.101.0/24
8 | 42.236.102.0/24
9 | 42.236.103.0/24
10 | 42.236.10.0/24
11 | 42.236.12.0/24
12 | 42.236.13.0/24
13 | 42.236.14.0/24
14 | 42.236.15.0/24
15 | 42.236.16.0/24
16 | 42.236.17.0/24
17 | 42.236.46.0/24
18 | 42.236.48.0/24
19 | 42.236.49.0/24
20 | 42.236.50.0/24
21 | 42.236.51.0/24
22 | 42.236.52.0/24
23 | 42.236.53.0/24
24 | 42.236.54.0/24
25 | 42.236.55.0/24
26 | 42.236.99.0/24
--------------------------------------------------------------------------------
/release/ipgroup/crawler/cloudflare.txt:
--------------------------------------------------------------------------------
1 | # sync from https://www.cloudflare.com/ips-v4
2 |
3 | 173.245.48.0/20
4 | 103.21.244.0/22
5 | 103.22.200.0/22
6 | 103.31.4.0/22
7 | 141.101.64.0/18
8 | 108.162.192.0/18
9 | 190.93.240.0/20
10 | 188.114.96.0/20
11 | 197.234.240.0/22
12 | 198.41.128.0/17
13 | 162.158.0.0/15
14 | 104.16.0.0/13
15 | 104.24.0.0/14
16 | 172.64.0.0/13
17 | 131.0.72.0/22
--------------------------------------------------------------------------------
/release/latest/compose.yaml:
--------------------------------------------------------------------------------
1 | networks:
2 | safeline-ce:
3 | name: safeline-ce
4 | driver: bridge
5 | ipam:
6 | driver: default
7 | config:
8 | - gateway: ${SUBNET_PREFIX:?SUBNET_PREFIX required}.1
9 | subnet: ${SUBNET_PREFIX}.0/24
10 | driver_opts:
11 | com.docker.network.bridge.name: safeline-ce
12 |
13 | services:
14 | postgres:
15 | container_name: safeline-postgres
16 | restart: always
17 | image: postgres:15.2
18 | volumes:
19 | - ${SAFELINE_DIR}/resources/postgres/data:/var/lib/postgresql/data
20 | - /etc/localtime:/etc/localtime:ro
21 | environment:
22 | - POSTGRES_USER=safeline-ce
23 | - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?postgres password required}
24 | networks:
25 | safeline-ce:
26 | ipv4_address: ${SUBNET_PREFIX}.2
27 | cap_drop:
28 | - net_raw
29 | command: [postgres, -c, max_connections=200]
30 | redis:
31 | container_name: safeline-redis
32 | restart: always
33 | image: redis:7.0.10
34 | volumes:
35 | - ${SAFELINE_DIR}/resources/redis/data:/data
36 | - /etc/localtime:/etc/localtime:ro
37 | command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
38 | networks:
39 | safeline-ce:
40 | ipv4_address: ${SUBNET_PREFIX}.3
41 | cap_drop:
42 | - net_raw
43 | sysctls:
44 | net.core.somaxconn: "511"
45 | management:
46 | container_name: safeline-mgt-api
47 | restart: always
48 | image: chaitin/safeline-mgt-api:${IMAGE_TAG:?image tag required}
49 | volumes:
50 | - ${SAFELINE_DIR?safeline dir required}/resources/management:/resources/management
51 | - ${SAFELINE_DIR}/resources/nginx:/resources/nginx
52 | - ${SAFELINE_DIR}/logs:/logs
53 | - /etc/localtime:/etc/localtime:ro
54 | ports:
55 | - ${MGT_PORT:-9443}:1443
56 | environment:
57 | - MANAGEMENT_RESOURCES_DIR=/resources/management
58 | - NGINX_RESOURCES_DIR=/resources/nginx
59 | - DATABASE_URL=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-postgres/safeline-ce
60 | - MARIO_URL=http://safeline-mario:3335
61 | - DETECTOR_URL=http://safeline-detector:8001
62 | - REDIS_URL=redis://:${REDIS_PASSWORD}@safeline-redis:6379/0
63 | - MANAGEMENT_LOGS_DIR=/logs/management
64 | dns:
65 | - 119.29.29.29
66 | - 223.5.5.5
67 | - 180.76.76.76
68 | - 1.2.4.8
69 | - 114.114.114.114
70 | - 8.8.8.8
71 | networks:
72 | safeline-ce:
73 | ipv4_address: ${SUBNET_PREFIX}.4
74 | cap_drop:
75 | - net_raw
76 | detector:
77 | container_name: safeline-detector
78 | restart: always
79 | image: chaitin/safeline-detector:${IMAGE_TAG}
80 | volumes:
81 | - ${SAFELINE_DIR}/resources/detector:/resources/detector
82 | - ${SAFELINE_DIR}/logs/detector:/logs/detector
83 | - /etc/localtime:/etc/localtime:ro
84 | environment:
85 | - LOG_DIR=/logs/detector
86 | networks:
87 | safeline-ce:
88 | ipv4_address: ${SUBNET_PREFIX}.5
89 | cap_drop:
90 | - net_raw
91 | mario:
92 | container_name: safeline-mario
93 | restart: always
94 | image: chaitin/safeline-mario:${IMAGE_TAG}
95 | volumes:
96 | - ${SAFELINE_DIR}/resources/mario:/resources/mario
97 | - ${SAFELINE_DIR}/logs/mario:/logs/mario
98 | - /etc/localtime:/etc/localtime:ro
99 | environment:
100 | - LOG_DIR=/logs/mario
101 | - GOGC=100
102 | - DATABASE_URL=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-postgres/safeline-ce
103 | - REDIS_URL=redis://:${REDIS_PASSWORD}@safeline-redis:6379/0
104 | networks:
105 | safeline-ce:
106 | ipv4_address: ${SUBNET_PREFIX}.6
107 | cap_drop:
108 | - net_raw
109 | tengine:
110 | container_name: safeline-tengine
111 | restart: always
112 | image: chaitin/safeline-tengine:${IMAGE_TAG}
113 | volumes:
114 | - ${SAFELINE_DIR}/resources/nginx:/etc/nginx
115 | - ${SAFELINE_DIR}/resources/management:/resources/management
116 | - ${SAFELINE_DIR}/resources/detector:/resources/detector
117 | - ${SAFELINE_DIR}/logs/nginx:/var/log/nginx
118 | - /etc/localtime:/etc/localtime:ro
119 | - ${SAFELINE_DIR}/resources/cache:/usr/local/nginx/cache
120 | - /etc/resolv.conf:/etc/resolv.conf
121 | environment:
122 | - REDIS_URL=redis://:${REDIS_PASSWORD}@${SUBNET_PREFIX}.3:6379/0
123 | - MGT_ADDR=${SUBNET_PREFIX}.4:9002
124 | ulimits:
125 | nofile: 131072
126 | network_mode: host
127 |
--------------------------------------------------------------------------------
/release/latest/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "latest_version": "v3.11.0",
3 | "rec_version": "v3.8.2"
4 | }
--------------------------------------------------------------------------------
/website/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | /node_modules
3 |
4 | # Production
5 | /build
6 |
7 | # Generated files
8 | .docusaurus
9 | .cache-loader
10 |
11 | # Misc
12 | .DS_Store
13 | .env.local
14 | .env.development.local
15 | .env.test.local
16 | .env.production.local
17 |
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
--------------------------------------------------------------------------------
/website/.npmrc:
--------------------------------------------------------------------------------
1 | strict-ssl=false
2 | save-prefix=""
3 | engine-strict=true
4 | registry="https://registry.npmmirror.com"
--------------------------------------------------------------------------------
/website/README.md:
--------------------------------------------------------------------------------
1 | # Website
2 |
3 | 使用 [Docusaurus 2](https://docusaurus.io/), 作为基础框架。
4 |
5 | ### 开发
6 |
7 | ```sh
8 | # 代码变动后可以自动更新,但是不能
9 | npm start
10 | # 支持搜索功能,但是无法自动更新
11 | npm run preview
12 | ```
13 |
14 | ### 部署
15 |
16 | 手动本地构建 docker 镜像,然后运行
17 |
18 | ```sh
19 | docker build -t website:latest .
20 | docker run --name site -p 3000:80 -d website:latest
21 | ```
22 |
23 | ### 链接替换
24 |
25 | 使用 nginx rewrite 把更改地址的链接记录下,运行旧链接访问到新地址
26 |
27 | ```nginx
28 |
29 | location / {
30 |
31 | rewrite /posts/guide_introduction /docs/ permanent;
32 | rewrite /posts/guide_install /docs/guide/install permanent;
33 | rewrite /docs/上手指南/guide_install /docs/guide/install permanent;
34 |
35 | rewrite /posts/guide_login /docs/guide/login permanent;
36 | rewrite /docs/上手指南/guide_login /docs/guide/login permanent;
37 |
38 | rewrite /posts/guide_config /docs/guide/config permanent;
39 | rewrite /docs/上手指南/guide_config /docs/guide/config permanent;
40 |
41 | rewrite /posts/guide_test /docs/guide/test permanent;
42 | rewrite /docs/上手指南/guide_test /docs/guide/test permanent;
43 |
44 | rewrite /posts/guide_upgrade /docs/guide/upgrade permanent;
45 | rewrite /docs/上手指南/guide_upgrade /docs/guide/upgrade permanent;
46 |
47 | rewrite /posts/faq_install /docs/faq/install permanent;
48 | rewrite /docs/常见问题排查/faq_install /docs/faq/install permanent;
49 |
50 | rewrite /posts/faq_login /docs/faq/login permanent;
51 | rewrite /docs/常见问题排查/faq_login /docs/faq/login permanent;
52 |
53 | rewrite /posts/faq_access /docs/guide/config permanent;
54 | rewrite /docs/常见问题排查/faq_access /docs/guide/config permanent;
55 |
56 | rewrite /posts/faq_config /docs/faq/config permanent;
57 | rewrite /docs/常见问题排查/faq_config /docs/faq/config permanent;
58 |
59 | rewrite /posts/faq_other /docs/faq/other permanent;
60 | rewrite /docs/常见问题排查/faq_other /docs/faq/other permanent;
61 |
62 | rewrite /posts/about_syntaxanalysis /docs/about/syntaxanalysis permanent;
63 | rewrite /docs/关于雷池/about_syntaxanalysis /docs/about/syntaxanalysis permanent;
64 |
65 | rewrite /posts/about_challenge /docs/about/challenge permanent;
66 | rewrite /docs/关于雷池/about_challenge /docs/about/challenge permanent;
67 |
68 | rewrite /posts/about_changelog /docs/about/changelog permanent;
69 | rewrite /docs/关于雷池/about_changelog /docs/about/changelog permanent;
70 |
71 | rewrite /posts/about_chaitin /docs/about/chaitin permanent;
72 | rewrite /docs/关于雷池/about_chaitin /docs/about/chaitin permanent;
73 |
74 | rewrite /docs/faq/access /docs/guide/config permanent;
75 | rewrite /docs/faq/config /docs/guide/config permanent;
76 |
77 | proxy_pass http://upstream;
78 | }
79 | ```
--------------------------------------------------------------------------------
/website/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
3 | };
4 |
--------------------------------------------------------------------------------
/website/blog/2023-08-04-website.md:
--------------------------------------------------------------------------------
1 | # Website
2 |
3 | 为了支持文档检索,采用 https://docusaurus.io/ 作为新的网站框架。
--------------------------------------------------------------------------------
/website/compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | web:
3 | image: safeline-official:2
4 | ports:
5 | - 80:80
6 |
--------------------------------------------------------------------------------
/website/docs/01-introduction.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "雷池简介"
3 | slug: /
4 | ---
5 |
6 | # 雷池简介
7 |
8 | ## 什么是 WAF
9 |
10 | WAF 是 Web Application Firewall 的缩写,也被称为 Web 应用防火墙。区别于传统防火墙,WAF 工作在应用层,对基于 HTTP/HTTPS 协议的 Web 系统有着更好的防护效果,使其免于受到黑客的攻击。
11 |
12 | ## 什么是雷池
13 |
14 | 雷池是长亭科技耗时近 10 年倾情打造的 WAF,核心检测能力由智能语义分析算法驱动。
15 |
16 | Slogan: 不让黑客越雷池半步。
17 |
18 | ## 为什么是雷池
19 |
20 | #### 便捷性
21 |
22 | 采用容器化部署,一条命令即可完成安装,0 成本上手
23 |
24 | 安全配置开箱即用,无需人工维护,可实现安全躺平式管理
25 |
26 | #### 安全性
27 |
28 | 首创业内领先的智能语义分析算法,精准检测、低误报、难绕过
29 |
30 | 语义分析算法无规则,面对未知特征的 0day 攻击不再手足无措
31 |
32 | #### 高性能
33 |
34 | 无规则引擎,线性安全检测算法,平均请求检测延迟在 1 毫秒级别
35 |
36 | 并发能力强,单核轻松检测 2000+ TPS,只要硬件足够强,可支撑的流量规模无上限
37 |
38 | #### 高可用
39 |
40 | 流量处理引擎基于 Nginx 开发,性能与稳定性均可得到保障
41 |
42 | 内置完善的健康检查机制,服务可用性高达 99.99%
43 |
44 | ## WAF 部署架构
45 |
46 | 下图是一个简单的网站流量拓扑,外部用户发出请求,经过网络最终传递到网站服务器。
47 |
48 | 此时,若外部用户中存在恶意用户,那么由恶意用户发出的攻击请求也会经过网络最终传递到网站服务器。
49 |
50 | 
51 |
52 | 社区版雷池以反向代理方式接入,优先于网站服务器接收流量,对流量中的攻击行为进行检测和清洗,将清洗过后的流量转发给网站服务器。
53 |
54 | 通过以上行为,最终确保外部攻击流量无法触达网站服务器。
55 |
56 | 
57 |
--------------------------------------------------------------------------------
/website/docs/02-guide/01-install.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "安装雷池"
3 | ---
4 |
5 | # 安装雷池
6 |
7 | ## 配置需求
8 |
9 | - 操作系统:Linux
10 | - 指令架构:x86_64
11 | - 软件依赖:Docker 20.10.14 版本以上
12 | - 软件依赖:Docker Compose 2.0.0 版本以上
13 | - 最小化环境:1 核 CPU / 1 GB 内存 / 5 GB 磁盘
14 |
15 | 可以逐行执行以下命令来确认服务器配置
16 |
17 | ```shell
18 | uname -m # 查看指令架构
19 | docker version # 查看 Docker 版本
20 | docker compose version # 查看 Docker Compose 版本
21 | docker-compose version # 同上(兼容老版本 Docker Compose)
22 | cat /proc/cpuinfo # 查看 CPU 信息
23 | cat /proc/meminfo # 查看内存信息
24 | df -h # 查看磁盘信息
25 |
26 | lscpu | grep ssse3 # 确认 CPU 是否支持 ssse3 指令集
27 | ```
28 |
29 | 有三种安装方式供选择
30 |
31 | - [在线安装](#在线安装) : 推荐安装方式
32 | - [离线安装](#离线安装) : 服务器无法连接 Docker Hub 时选择
33 | - [一键安装](#使用牧云助手安装) : 最简单的安装方式
34 |
35 | ## 在线安装
36 |
37 | **_如果服务器可以访问互联网环境,推荐使用该方式_**
38 |
39 | 执行以下命令,即可开始安装
40 |
41 | ```
42 | bash -c "$(curl -fsSLk https://waf-ce.chaitin.cn/release/latest/setup.sh)"
43 | ```
44 |
45 | > 如果连接 Docker Hub 网络不稳,导致镜像下载失败,可以采用 [离线安装](#离线安装) 方式
46 |
47 | 经过以上步骤,你的雷池已经安装好了,下一步请参考 [登录雷池](/docs/guide/login)
48 |
49 | ## 离线安装
50 |
51 | 如果你的服务器无法连接互联网环境,或连接 Docker Hub 网络不稳,可以使用镜像包安装方式
52 |
53 | > 这里忽略 Docker 安装的过程
54 |
55 | 首先,下载 [雷池社区版镜像包](https://demo.waf-ce.chaitin.cn/image.tar.gz) 并传输到需要安装雷池的服务器上,执行以下命令加载镜像
56 |
57 | ```
58 | cat image.tar.gz | gzip -d | docker load
59 | ```
60 |
61 | 执行以下命令创建并进入雷池安装目录
62 |
63 | ```
64 | mkdir -p safeline # 创建 safeline 目录
65 | cd safeline # 进入 safeline 目录
66 | ```
67 |
68 | 下载 [编排脚本](https://waf-ce.chaitin.cn/release/latest/compose.yaml) 并传输到 safeline 目录中
69 |
70 | 执行以下命令,生成雷池运行所需的相关环境变量
71 |
72 | ```
73 | echo "SAFELINE_DIR=$(pwd)" >> .env
74 | echo "IMAGE_TAG=latest" >> .env
75 | echo "MGT_PORT=9443" >> .env
76 | echo "POSTGRES_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 > .env
77 | echo "REDIS_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 > .env
78 | echo "SUBNET_PREFIX=172.22.222" >> .env
79 | ```
80 |
81 | 执行以下命令启动雷池
82 |
83 | ```
84 | docker compose up -d
85 | ```
86 |
87 | 经过以上步骤,你的雷池已经安装好了,下一步请参考 [登录雷池](/docs/guide/login)
88 |
89 | ## 使用牧云助手安装
90 |
91 | 也可以使用 [牧云主机管理助手](https://collie.chaitin.cn/) 进行一键安装
92 |
93 | 
94 |
95 | 参考视频教程 [用 “白嫖的云主机” 一键安装 “开源的 Web 防火墙”](https://www.bilibili.com/video/BV1sh4y1t7Pk/)
96 |
97 | ## 常见安装问题
98 |
99 | 请参考 [安装问题](/docs/faq/install)
100 |
--------------------------------------------------------------------------------
/website/docs/02-guide/02-login.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "登录雷池"
3 | ---
4 |
5 | # 登录雷池
6 |
7 | 浏览器打开后台管理页面 `https://:9443`。根据界面提示,使用 **支持 TOTP 的认证软件或者小程序** 扫描二维码,然后输入动态口令登录:
8 |
9 | 
10 |
--------------------------------------------------------------------------------
/website/docs/02-guide/03-config.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "配置防护站点"
3 | ---
4 |
5 | # 配置防护站点
6 |
7 | ## 界面操作
8 | 
9 |
10 | 添加后,在客户端执行 `curl -H "Host: <域名>" http://<雷池 IP>:<雷池监听端口>` ,若能获取到业务网站的响应,并且站点上 “今日访问量” 增加,则代表配置成功。
11 |
12 | ## 如何配置域名、端口、上游服务器
13 | ### 工作原理
14 |
15 | 雷池社区版主要以 **反向代理** 的方式工作,类似于一台 nginx 服务。部署时,需要让网站流量先抵达雷池,经过雷池检测和过滤后,再转给原来的网站业务。
16 |
17 | 如果你不了解反向代理的工作原理,可以通过以下几种雷池常见的工作场景,来了解如何配置站点。
18 |
19 | 假设你的网站域名为 `example.com`,如图:
20 |
21 | 
22 |
23 | ### 在单独设备上部署雷池(推荐)
24 |
25 | 如果你可以提供一台独立设备部署雷池,那么你需要:
26 | 1. **将网站流量指向雷池**。例如将域名解析到雷池
27 | 2. 禁止网站服务器上,所有除了雷池之外的访问。例如配置防火墙,或者直接把网站服务器放到内网
28 |
29 | 效果大致如下:
30 |
31 | 
32 |
33 | 雷池上相应的站点配置为:
34 | * 域名:公网域名 `example.com`
35 | * 端口:80 或 443/ssl
36 | * 上游服务器:网站服务器的地址 `http://192.168.10.10`
37 |
38 | ### 直接在网站服务器上部署雷池
39 |
40 | 提示:不建议这样部署,因为这样单机的负载更高、设备宕机的概率更大。非纯净的环境还会提高安装失败的概率,故障排查也会比较困难。
41 |
42 | 如果能接受这些风险,雷池也可以直接部署在网站服务器上。你需要:
43 | 1. 将原本监听 80 或 443/ssl 端口的网站服务改到其他端口,**让雷池监听设备的 80 或 443/ssl 端口**
44 | 2. 使网站服务仅允许本机访问。例如配置系统防火墙、Iptables
45 |
46 | 效果大致如图:
47 |
48 | 
49 |
50 | 此时雷池上的站点配置为:
51 | * 域名:公网域名 `example.com`
52 | * 端口:80 或 443/ssl
53 | * 上游服务器:`http://127.0.0.1:<网站服务改后的端口>`
54 |
55 | ### 和其他反代设备一起部署的情况
56 |
57 | 雷池作为反代设备,可以在任意位置接入主链路。只要将接入位置的流量指向雷池,并在雷池的 “上游服务器” 处填写请求的下一跳服务器地址即可。例如:
58 |
59 | 
60 |
61 | ## 配置后网站无法访问,如何排查
62 |
63 | 如果按照上文指引部署雷池、配置了站点,但网站仍无法访问,建议按照以下步骤排查:
64 |
65 | 1. 明确 “网站无法访问” 的具体表现:
66 | * 如果 `502 Bad Gateway tengine`:
67 |
68 | 
69 |
70 | 大概率是是雷池的上游服务器配置不正确,或者雷池无法访问到上游服务器。请继续按下面步骤排查,重点排查步骤 6、7
71 | * 如果请求能够返回但是十分缓慢
72 | * 首先确认服务器负载是否正常
73 | * 在客户端执行命令,检查雷池服务器与上游服务器的网络:`curl -H "Host: " -vv -o /dev/null -s -w 'time_namelookup: %{time_namelookup}\ntime_connect: %{time_connect}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n' http://<上游服务器地址>`
74 | * 如果 time_namelookup 时间过大,请检查 dns server 配置
75 | * 如果 time_connect 时间过大,请检查雷池与上游服务器之间的网络状态
76 | * 如果 time_starttransfer 时间过大,请检查上游服务器状态,是否出现资源过载情况
77 | * 如果不是以上情况,继续下一步
78 | 2. 在客户端执行 `curl -H "Host: <域名>" http://<雷池 IP>:<雷池监听端口>` 。正常情况下,应能获取到业务网站的响应,并且站点的 “今日访问量” +1
79 | * 如果浏览器无法访问,但这一步正常获取到响应,大概率是因为:
80 | * 测试过程中,网站域名还没有切到雷池,浏览器测试时访问的是 `http(s)://<雷池 IP>`,恰好业务服务上有 Host 验证,所以拒绝了该请求。这种情况需要修改本机 host,把域名解析到雷池 IP,再访问 `http(s)://<域名>`,才能准确测试
81 | * 网站业务做了其他一些特殊处理。例如访问后 301 跳转到了其他地址,需要具体排查网站业务的响应内容
82 | * 如果不能获取到响应,继续下一步
83 | 3. 在雷池设备上执行 `curl -H "Host: <域名>" http://<雷池 IP>:<雷池监听端口>`。正常情况下,应能获取到业务网站的响应,并且站点上 “今日访问量” +1
84 | * 如果步骤 2 失败而这里成功,说明客户端到雷池之间的网络存在问题。请排查网络,保证客户端可访问到雷池
85 | * 如果不能获取到响应,继续下一步
86 | 4. 在雷池设备上执行 `curl -H "Host: <域名>" http://127.0.0.1:<雷池监听端口>`。正常情况下,应能获取到业务网站的响应,并且站点的 “今日访问量” +1
87 | * 如果步骤 3 失败而这里成功,且 `telnet <雷池 IP> <雷池监听端口>` 返回 `Unable to connect to remote host: Connection refused`,大概率是被雷池设备上的防火墙拦截了。可能是操作系统本身的防火墙,还有可能是云服务商的防火墙。请根据实际情况逐项排查,开放雷池监听端口的访问
88 | * 如果不能获取到响应,继续下一步
89 | 5. 在雷池设备上执行 `netstat -anp | grep <雷池监听端口>` 确认端口监听情况。正常情况下,应该有一个 nginx 进程监听在 `0.0.0.0:<雷池监听端口>`。没有的话请通过社群或者 Github issue 提交反馈,附上排查过程。有的话继续下一步
90 | 6. 在雷池设备上 `curl -H "Host: <域名>" <上游服务器地址>`。正常情况下,应能获取到业务网站的响应
91 | * 如果步骤 4 失败而这里成功,请通过社群或者 Github issue 提交反馈,附上排查过程
92 | * 如果这步失败,说明雷池和上游服务器之间的网络存在问题。请排查网络,确保雷池可以访问到上游服务器
93 |
94 | 如果排查后问题还是没有解决,请通过社群或者 Github issue 提交反馈,并附上排查的过程和截图。
--------------------------------------------------------------------------------
/website/docs/02-guide/04-test.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "测试防护效果"
3 | ---
4 |
5 | # 测试防护效果
6 |
7 | ## 确认网站可以正常访问
8 |
9 | 根据雷池 WAF 配置的网站参数访问你的网站。
10 |
11 | 打开浏览器访问 `http://:<端口>/`。
12 |
13 | > 网站协议默认是 http,勾选 ssl 则为 https
14 | > 主机名可以是雷池的 IP,也可以是网站的域名(确保域名已经解析到雷池)
15 | > 端口是你在雷池页面中配置的网站端口
16 |
17 | 若网站访问不正常,请参考 [网站无法访问](/docs/02-guide/03-config.md)。
18 |
19 | ## 尝试手动模拟攻击
20 |
21 | 打开浏览器,访问以下地址即可模拟出对应的攻击:
22 |
23 | - 模拟 SQL 注入,请访问 `http://:<端口>/?id=1%20AND%201=1`
24 | - 模拟 XSS,请访问 `http://:<端口>/?html=`
25 |
26 | 通过浏览器,你将会看到雷池已经发现并阻断了攻击请求。
27 |
28 | 若请求没有被阻断,请参考 [防护不生效](/docs/03-faq/03-other.md)
29 |
30 | ## 自动化测试防护效果
31 |
32 | 两条请求当然无法完整的测试雷池的防护效果,可以使用 blazehttp 自动化工具进行批量测试
33 |
34 | #### 下载测试工具
35 |
36 | - [Windows 版本](https://waf-ce.chaitin.cn/blazehttp/blazehttp_windows.exe)
37 | - [Mac 版本(x64)](https://waf-ce.chaitin.cn/blazehttp/blazehttp_mac_x64)
38 | - [Mac 版本(M1)](https://waf-ce.chaitin.cn/blazehttp/blazehttp_mac_m1)
39 | - [Linux 版本(x64)](https://waf-ce.chaitin.cn/blazehttp/blazehttp_linux_x64)
40 | - [Linux 版本(ARM)](https://waf-ce.chaitin.cn/blazehttp/blazehttp_linux_arm64)
41 | - [源码仓库](https://github.com/chaitin/blazehttp)
42 |
43 | #### 准备测试样本
44 |
45 | - [测试样本](https://waf-ce.chaitin.cn/blazehttp/testcases.zip)
46 |
47 | 下载请求样本后解压到 `testcases` 目录
48 |
49 | #### 开始测试
50 |
51 | 1. 将测试工具 `blazehttp` 和测试样本 `testcases` 放在同一个目录下
52 | 2. 进入对应的目录
53 | 3. 使用以下请求开始测试
54 |
55 | ```
56 | ./blazehttp -t http://:<端口> -g './testcases/**/*.http'
57 | ```
58 |
59 | #### 测试效果展示
60 |
61 | ```
62 | # 测试请求
63 | ./blazehttp -t http://192.168.0.1:8080 -g './testcases/**/*.http'
64 |
65 | sending 100% |██████████████████████████████████████████| (18/18, 86 it/s)
66 | Total http file: 18, success: 18 failed: 0
67 | Stat http response code
68 |
69 | Status code: 403 hit: 16
70 | Status code: 200 hit: 2
71 |
72 | Stat http request tag
73 |
74 | tag: sqli hit: 1
75 | tag: black hit: 16
76 | tag: file_include hit: 1
77 | tag: file_upload hit: 1
78 | tag: java_unserialize hit: 1
79 | tag: php_unserialize hit: 1
80 | tag: cmdi hit: 1
81 | tag: ssrf hit: 1
82 | tag: xslti hit: 1
83 | tag: xss hit: 1
84 | tag: xxe hit: 1
85 | tag: asp_code hit: 1
86 | tag: white hit: 2
87 | tag: ognl hit: 1
88 | tag: shellshock hit: 1
89 | tag: ssti hit: 1
90 | tag: directory_traversal hit: 1
91 | tag: php_code hit: 1
92 | ```
93 |
--------------------------------------------------------------------------------
/website/docs/02-guide/05-upgrade.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "升级雷池"
3 | ---
4 |
5 | # 升级雷池
6 |
7 | **注意**: 升级雷池时服务会重启,流量会中断一小段时间,根据业务情况选择合适的时间来执行升级操作。
8 |
9 | ## 在线升级
10 |
11 | 执行以下命令即可进行升级。
12 |
13 | ```
14 | bash -c "$(curl -fsSLk https://waf-ce.chaitin.cn/release/latest/upgrade.sh)"
15 | ```
16 |
17 | [可选] 升级成功后,可以执行以下命令删除旧版本 Docke 镜像,以释放磁盘空间。
18 |
19 | ```
20 | docker rmi $(docker images | grep "safeline" | grep "none" | awk '{print $3}')
21 | ```
22 |
23 | > 有部分环境的默认 SafeLine 安装路径是在 `/data/safeline-ce`,安装之后可能会发现需要重新绑定 OTP、配置丢失等情况,可以修改 .env 的 `SAFELINE_DIR` 变量,指向 `/data/safeline-ce`
24 |
25 | ## 离线镜像
26 |
27 | 适用于 docker hub 拉取镜像失败的场景,手动更新镜像。
28 |
29 | ```
30 | # cd /path/to/safeline
31 |
32 | mv compose.yaml compose.yaml.old
33 | wget "https://waf-ce.chaitin.cn/release/latest/compose.yaml" --no-check-certificate -O compose.yaml
34 |
35 | wget "https://waf-ce.chaitin.cn/release/latest/seccomp.json" --no-check-certificate -O seccomp.json
36 |
37 | sed -i "s/IMAGE_TAG=.*/IMAGE_TAG=latest/g" ".env"
38 |
39 | grep "SAFELINE_DIR" ".env" > /dev/null || echo "SAFELINE_DIR=$(pwd)" >> ".env"
40 | grep "IMAGE_TAG" ".env" > /dev/null || echo "IMAGE_TAG=latest" >> ".env"
41 | grep "MGT_PORT" ".env" > /dev/null || echo "MGT_PORT=9443" >> ".env"
42 | grep "POSTGRES_PASSWORD" ".env" > /dev/null || echo "POSTGRES_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 > ".env"
43 | grep "REDIS_PASSWORD" ".env" > /dev/null || echo "REDIS_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 > ".env"
44 | grep "SUBNET_PREFIX" ".env" > /dev/null || echo "SUBNET_PREFIX=172.22.222" >> ".env"
45 | ```
46 |
47 | 下载 [雷池社区版镜像包](https://demo.waf-ce.chaitin.cn/image.tar.gz) 并传输到需要安装雷池的服务器上,执行以下命令加载镜像
48 |
49 | ```
50 | docker load -i image.tar.gz
51 | ```
52 |
53 | 执行以下命令替换 Docker 容器
54 |
55 | ```
56 | docker compose down
57 | docker compose up -d
58 | ```
59 |
60 | OK,你已经完成了升级
61 |
--------------------------------------------------------------------------------
/website/docs/02-guide/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "上手指南",
3 | "collapsed": false,
4 | "link": {
5 | "type": "generated-index"
6 | }
7 | }
--------------------------------------------------------------------------------
/website/docs/03-faq/01-install.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "安装问题"
3 | ---
4 |
5 | # 安装问题
6 |
7 | ## 支不支持 MacOS/Windows
8 |
9 | 不支持,由于雷池所依赖的部分 docker 特性在 MacOS/Windows 上并不生效,所以雷池在 MacOS/Windows 并不能正常工作。
10 |
11 | ## 我能把雷池和业务服务部署到同一台机器中吗?
12 |
13 | 不建议,如放在一起,在流量不变的情况下,机器负载将高于分开部署,增大了资源耗尽的可能性。
14 |
15 | ## docker compose 还是 docker-compose?
16 |
17 | `docker compose`(带空格)是 V2 版本,Go 写的。`docker-compose` 是 V1 版本,Python 写的,已经不维护了。
18 |
19 | 我们推荐使用 V2 版本的 `docker compose`,V1 可能会有兼容性等问题。
20 |
21 | [docker/compose](https://github.com/docker/compose/) 中提到:
22 |
23 | > For a smooth transition from legacy docker-compose 1.xx, please consider installing [compose-switch](https://github.com/docker/compose-switch) to translate `docker-compose ...` commands into Compose V2's `docker compose ....` . Also check V2's `--compatibility` flag.
24 |
25 | 其他参考:[https://stackoverflow.com/questions/66514436/difference-between-docker-compose-and-docker-compose](https://stackoverflow.com/a/66516826)
26 |
27 | ## 镜像下载缓慢甚至连接超时
28 |
29 | 这个是因为 docker hub 默认使用位于美西节点拉取镜像,可以自行配置国内镜像加速源。
30 |
31 | ## ERROR: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
32 |
33 | 如描述,你需要启动 docker daemon 才能执行相关的命令。尝试 `systemctl start docker`。
34 |
35 | ## docker not found, unable to deploy
36 |
37 | 如描述,你需要安装 `docker`。尝试 `curl -fLsS https://get.docker.com/ | sh` 或者 [Install Docker Engine](https://docs.docker.com/engine/install/)。
38 |
39 | ## docker compose v2 not found, unable to deploy
40 |
41 | 如描述,你需要安装 `docker compose v2`。尝试 `[Install Docker Compose](https://docs.docker.com/compose/install/)`。
42 |
43 | ## `failed to create network safeline-ce`
44 |
45 | safeline-ce 是雷池部署时候创建的 network,出现类似报错,先重启下 dockerd 之后重试。
46 |
47 | ## safeline-tengine 出现 Address already in use
48 |
49 | `docker logs -f safeline-tengine` 容器日志中看到 `Address already in use` 信息。
50 |
51 | 端口冲突,根据报错信息中的端口号,排查是哪个服务占用了,手动处理冲突。
52 |
53 | ## safelint-mgt-api 出现 Operation not permitted
54 | `docker logs -f safelint-mgt-api` 容器日志中看到 `runtime/cgo: pthread_create failed: Operation not permitted` 报错,这个错误一般会在 docker 20.10.9 及以下发生。
55 |
56 | - 最推荐的方式是升级 docker 到最新版本尝试解决这个问题。
57 | - 或您的系统支持配置 seccomp (执行 `grep CONFIG_SECCOMP= /boot/config-$(uname -r)` 输出 `CONFIG_SECCOMP=y` 则为支持),
58 | 则可以在雷池工作目录下载 [seccomp](https://waf-ce.chaitin.cn/release/latest/seccomp.json) 并且编辑 compose.yaml 文件,
59 | 在 management 下加入如下配置项,然后执行 `docker compose down && docker compose up -d` 来尝试解决这个问题:
60 | ```yaml
61 | security_opt:
62 | - seccomp=./seccomp.json
63 | ```
64 |
65 | ## safeline-postgres 出现 Operation not permitted
66 |
67 | `docker logs -f safeline-postgres` 容器日志中看到 `Operation not permitted` 报错。
68 |
69 | 可能是您的 docker 版本过低,升级 docker 到最新版本尝试一下。
70 |
71 | ## 如何自定义 SafeLine 安装路径?
72 |
73 | 基于最新的 `compose.yaml`,你可以手动修改 `.env` 文件的 `SAFELINE_DIR` 变量。
74 |
75 | ## 如何修改 SafeLine 后台管理的默认端口?本机 `:9443` 已经被别的服务占用了
76 |
77 | 基于最新的 `compose.yaml`,你可以手动添加 `MGT_PORT` 变量到 `.env` 文件。
78 |
--------------------------------------------------------------------------------
/website/docs/03-faq/02-login.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "登录问题"
3 | ---
4 |
5 | # 登录问题
6 |
7 | > TOTP (Time-based One-Time Password algorithm) 将密钥与当前时间进行组合,通过哈希算法产生一次性密码,已被采纳为 RFC 6238,被用于许多双因素身份验证系统。
8 |
9 | ## 动态口令错误
10 |
11 | #### 时间不准
12 |
13 | 雷池社区版动态口令认证采用了 TOTP 算法,TOTP 与时间强相关,如果相关设备的时间不准,可能会导致动态口令计算错误。
14 |
15 | 1. 检查手机时间是否准确(或其他 TOTP 扫码设备)
16 | 2. 检查雷池服务器时间是否准确
17 |
18 | #### 动态口令可能已失效
19 |
20 | TOTP 动态口令只有 30 秒的有效期,如果认证失败,请在动态口令刷新后重新尝试。
21 |
22 | ## 重新绑定动态口令
23 |
24 | 登录服务器,打开终端,执行以下命令即可重置动态口令
25 |
26 | ```
27 | docker exec safeline-mgt-api resetadmin
28 | ```
29 |
30 | 命令执行完成后打开雷池页面重新绑定即可。
31 |
32 | **注意:重置动态口令后要尽快完成绑定,别被其他人捷足先登了。**
33 |
34 | ## 多人使用
35 |
36 | 如果想多人使用雷池社区版,只需要以下 3 步:
37 |
38 | 1. 重置动态口令(参考 [重置认证](#重置认证))
39 | 2. 进入登录页面,这时会自动跳转到 TOTP 绑定页面,保存 “绑定二维码”(注意,非 “认证二维码”)
40 | 3. 将 “绑定二维码” 分享给其他人进行绑定,绑定后即可登录(注:“绑定二维码” 无绑定次数限制,无时效限制)
41 |
42 | **注意:保存的 “绑定二维码” 千万别泄漏,任何人得到以后都可以绑定并登录。**
43 |
--------------------------------------------------------------------------------
/website/docs/03-faq/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "常见问题排查",
3 | "collapsed": false,
4 | "link": {
5 | "type": "generated-index"
6 | }
7 | }
--------------------------------------------------------------------------------
/website/docs/04-practice/00-monitor.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "可用性监控"
3 | ---
4 |
5 | # 网站可用性监控
6 |
7 | 除了对网站的安全防护以外,不少站长还对网站的可用性、稳定性健康监测和敏感内容监测也有强烈需求,有此类需求的站长可以搭配使用 [长亭百川网站监测](https://rivers.chaitin.cn/landing/radar) 产品。
8 |
9 | ### 关于长亭百川网站监测
10 |
11 | [长亭百川网站监测](https://rivers.chaitin.cn/landing/radar) 是一款专门为网站管理员打造的网站监测工具,能够有效监测站点可用性、SSL证书合法性、网站敏感内容等信息。
12 |
13 | 交互界面简洁直观、操作上手轻松、注重用户体验,实时监测每个页面的状态和详细信息,让你对网站运行状态了如指掌。
14 |
15 | 
16 |
17 | ### 雷池用户福利
18 |
19 | 凡是安装了雷池社区版的用户,可凭借雷池设备码领取长亭网站监控产品 100 元体验金一份
20 |
21 | 
22 |
23 | 
24 |
25 |
--------------------------------------------------------------------------------
/website/docs/04-practice/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "最佳实践",
3 | "collapsed": false,
4 | "link": {
5 | "type": "generated-index"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/website/docs/05-about/01-syntaxanalysis.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "语义分析检测算法"
3 | ---
4 |
5 | # 语义分析检测算法
6 |
7 | ## 传统规则防护,在当下为什么失灵?
8 |
9 | 当下,Web 应用防火墙大多采用规则匹配方式来识别和阻断攻击流量,但由于 Web 攻击成本低、方式复杂多样、高危漏洞不定期爆发等原因,管理者们在安全运维工作中不得不持续调整防护规则,以保障业务的可用性和安全性。尽管如此,每天依然面临着不少的误报和漏报,影响正常业务运转甚至导致 Web 服务失陷。
10 |
11 | 究其原因,是由于基于规则匹配的攻击识别方法存在先天不足导致的。在乔姆斯基文法体系中,编写匹配规则的正则文法属于 3 型文法,而用于构造攻击 Payload 的程序语言属于 2 型文法,如下图所示:
12 |
13 | 
14 |
15 | 从文法表达能力比较,3 型文法包含在 2 型文法之内,基于正则的规则描述无法完全覆盖基于程序语言的攻击 Payload,这也是基于规则匹配识别攻击的 WAF 防护效果低于预期的根本原因。
16 |
17 | ## 雷池的解决之道:算法的革新重构 WAF
18 |
19 | 长亭科技自成立起便深入探索 Web 安全防护的新思路,创新性提出以 “智能语义分析算法” 解决 Web 攻击识别问题,给 WAF 内置 “智能大脑”,使其具备自主识别攻击行为的能力,同时结合机器学习建模,不断增强和完善 “大脑” 的分析能力,不依赖传统的规则库即可满足 Web 应用日常安全防护需求。
20 |
21 | 雷池通过对 Web 请求和返回内容进行智能分析,使 WAF 具备智能判断攻击威胁的能力。智能语义分析算法由词法分析、语法分析、语义分析和威胁模型匹配 4 个步骤组成。
22 |
23 | 
24 |
25 | 雷池内置涵盖常用编程语言的编译器,通过对 HTTP 的载荷内容进行深度解码后,按照其语言类型匹配相应语法编译器,进而匹配威胁模型得到威胁评级,阻断或允许访问请求。
26 |
27 | 与规则匹配型威胁检测方式相比,智能语义分析技术具有准确率高、误报率低的特点。以 SQL 注入检测为例:
28 |
29 | 
30 |
31 | 
32 |
33 | 作为全球范围内第一款以智能语义分析算法为核心引擎能力打造的下一代 WAF,雷池展现出了更多让安全产品 “更聪明” 的可能。除了形成了质变的检测引擎的精准程度,它可以通过插件形式灵活扩展、实现瑞士军刀般的功能增加,可以变形适配、安装部署进各种网络环境,可以跟机器学习等前沿技术更好的融合、增强流量分析的能力等。
34 |
--------------------------------------------------------------------------------
/website/docs/05-about/02-challenge.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "人机验证"
3 | ---
4 |
5 | # 人机验证
6 |
7 | 自从雷池社区版发布以来,我们一直密切关注用户对于爬虫和扫描器的反馈和防护需求。 因此,在 2.0 版本中,我们致力于探索与此相关的功能,以满足用户的期望和保护网站的安全。
8 |
9 | 
10 |
11 | ### 加入人机验证之后的请求处理流程
12 |
13 | 
14 |
15 | ### 人机验证如何配置
16 |
17 | 首先,点击位于左边栏的人机验证。之后,点击 **添加人机验证**。
18 | 
19 | 在这里我们可以配置是否开启交互式校验以及规则的名称以及规则的触发条件。
20 |
21 | ### 人机验证触发规则
22 |
23 | 1. 规则内的条件之间是并且的关系,即需要全部命中,才会触发
24 | 2. 规则与规则之间是或的关系,则有一个命中,便会触发
25 |
26 | ### 交互与非交互的区别
27 |
28 | 如果选择开启交互,那么用户需要点击页面中间的勾选框开始验证,如果选择非交互,那么将自动开始验证。
29 | 
30 |
--------------------------------------------------------------------------------
/website/docs/05-about/04-chaitin.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "关于我们"
3 | ---
4 |
5 | # 关于我们
6 |
7 | ## 关于长亭
8 |
9 | 雷池是长亭科技耗时近 10 年倾情打造的 Web 应用防护产品,核心检测能力由智能语义分析算法驱动。
10 |
11 | 北京长亭未来科技有限公司是国际顶尖的网络信息安全公司之一,创始人团队 5 人均为清华博士,并引入阿里云安全核心人才团队。全球首发基于智能语义分析的下一代 Web 应用防火墙产品,目前,公司已形成以攻(安全评估系统)、防(下一代 Web 应用防火墙)、知(安全分析与管理平台)、查(主机安全管理平台)、抓(伪装欺骗系统)为核心的新一代安全防护体系,并提供优质的安全测试及咨询服务,为企业级客户带来智能的全新安全防护思路。
12 |
13 | 长亭专注为企业级用户提供专业的网络信息安全解决方案。2016 年即发布基于人工智能语义分析的下一代 Web 应用防火墙,颠覆了传统依赖规则防护的工作原理,为企业用户带来智能、简单、省心的安全产品及服务。
14 |
15 | 长亭雷池坚持以技术为导向,产品与服务所涉及到的算法与核心技术均领先国际行业前沿标准,不仅颠覆了繁琐耗时的传统工作原理,更将产品性能提升至领先水准,为企业用户带来更快、更精准、更智能的安全防护。
16 |
17 | ## 荣誉 & 资质
18 |
19 | ### 2021 年
20 |
21 | - 入选 IDC《中国硬件 Web 应用防火墙(WAF)市场份额》前四
22 | - 重磅发布《实战攻防-企业红蓝对抗实践指南》
23 | - 荣获 2021 网信自主创新优秀产品 “补天奖”
24 | - 荣膺 CNNVD 2020 年度优秀技术支撑单位
25 | - 10 项虚拟机漏洞获 Oracle 官方致谢
26 | - 入选安全牛第八版中国网络安全行业全景图
27 | - 入选 CCSIP 2021 中国网络安全产业全景图
28 | - 入选嘶吼 2021 网络安全产业链图谱
29 |
30 | ### 2020 年
31 |
32 | - 2020 年金融科技产品创新突出贡献奖
33 | - 2020 年网络安全创新能力 100 强
34 | - 入选数世咨询《蜜罐诱捕能力指南》
35 | - 入选数说安全中国网络安全市场全景图
36 | - Network Products Guide IT World Award
37 | - 2020 年中国人工智能商业落地价值潜力 100 强
38 | - 2020 Application Security and Testing 铜奖
39 | - 入选安全牛《2020 中国网络安全企业 100 强报告》
40 | - 发现并命名幽灵猫(Ghostcat)漏洞
41 | - 联合发布《国家区块链漏洞库-区块链漏洞定级细则》
42 |
43 | ### 2019 年
44 |
45 | - 入选 Forrester《Now Tech:Web Application Firewalls, Q4 2019》报告
46 | - 2019 年关键信息基础设施“盘古奖”
47 | - 荣获《金融电子化》“2019 年度金融科技产品创新突出贡献奖”
48 | - 中国网络安全与信息产业 “金智奖” 2019 年度优秀单位
49 |
50 | ### 2018 年
51 |
52 | - 通过国家保密局涉密信息系统产品认证
53 | - 通信网络安全服务能力一级资质认证
54 | - 中国 IT 思想力奖-金融科技产品创新奖
55 | - TSRC 2017 最佳客户端洞主 & 年度最佳合作伙伴
56 | - 获 Info Security Products Guide 全球卓越奖
57 | - 入选《CIO Advisor》亚太地区 25 家最热门人工智能公司
58 | - 入围 Gartner 2018《Web 应用防火墙魔力象限报告亚太版》
59 | - 2018 年度金融科技优秀产品创新奖
60 | - “2018 年度金牌服务机构” 安全服务奖
61 |
62 | ### 2017 年
63 |
64 | - OWASP 认证雷池(SafeLine)下一代 Web 应用防火墙
65 | - 通过国家测评中心/信息安全服务资质测评单位
66 | - Gartner 魔力象限报告提名
67 | - 再次登上 Black Hat USA 演讲
68 | - 《财富》杂志评选中国创新百强 “人工智能和机器人” 领域全国第一
69 | - 受邀出席世界互联网大会网络安全闭门会
70 | - 阿里巴巴年度优秀生态合作伙伴
71 | - 入选 Cyber Defense Magazine 全球网络安全领导者 Top 25
72 |
73 | ### 2016 年
74 |
75 | - ISO9001 国际质量体系认证
76 | - ISO27001 国际质量体系认证
77 | - 长亭雷池 Web 应用防火墙(增强级)销售许可证
78 | - 国家信息安全漏洞库(CNNVD)二级技术支撑单位资质
79 | - 中国年度最佳产品奖、IT 行业最具影响力企业奖
80 | - 年度特殊贡献奖
81 | - GeekPwn 三周年特别贡献奖
82 |
83 | ### 2015 年
84 |
85 | - 中国国家高新技术企业称号
86 | - 中关村高新技术企业称号
87 | - “最具价值安全问题” 荣誉认证
88 | - 首次登上 Black Hat USA 演讲
89 |
--------------------------------------------------------------------------------
/website/docs/05-about/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "关于雷池",
3 | "collapsed": false,
4 | "link": {
5 | "type": "generated-index"
6 | }
7 | }
--------------------------------------------------------------------------------
/website/docusaurus.config.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // Note: type annotations allow type checking and IDEs autocompletion
3 |
4 | const lightCodeTheme = require("prism-react-renderer/themes/github");
5 | const darkCodeTheme = require("prism-react-renderer/themes/dracula");
6 |
7 | /** @type {import('@docusaurus/types').Config} */
8 | const config = {
9 | title: "长亭雷池 WAF 社区版",
10 | tagline: "",
11 | favicon: "images/favicon.ico",
12 |
13 | // Set the production url of your site here
14 | url: "https://waf-ce.chaitin.cn/",
15 | // Set the // pathname under which your site is served
16 | // For GitHub pages deployment, it is often '//'
17 | baseUrl: "/",
18 |
19 | // GitHub pages deployment config.
20 | // If you aren't using GitHub pages, you don't need these.
21 | organizationName: "chaitin", // Usually your GitHub org/user name.
22 | projectName: "safeline-ce-site", // Usually your repo name.
23 |
24 | onBrokenLinks: "throw",
25 | onBrokenMarkdownLinks: "warn",
26 |
27 | // Even if you don't use internalization, you can use this field to set useful
28 | // metadata like html lang. For example, if your site is Chinese, you may want
29 | // to replace "en" with "zh-Hans".
30 | i18n: {
31 | defaultLocale: "zh-Hans",
32 | locales: ["zh-Hans"],
33 | },
34 |
35 | themes: [
36 | [
37 | // @ts-ignore
38 | require.resolve("@easyops-cn/docusaurus-search-local"),
39 | /** @type {import("@easyops-cn/docusaurus-search-local").PluginOptions} */
40 | // @ts-ignore
41 | ({
42 | // ... Your options.
43 | // `hashed` is recommended as long-term-cache of index file is possible.
44 | hashed: true,
45 | // For Docs using Chinese, The `language` is recommended to set to:
46 | // ```
47 | language: ["en", "zh"],
48 | // ```
49 | }),
50 | ],
51 | ],
52 |
53 | presets: [
54 | [
55 | "classic",
56 | /** @type {import('@docusaurus/preset-classic').Options} */
57 | ({
58 | docs: {
59 | sidebarPath: require.resolve("./sidebars.js"),
60 | // Remove this to remove the "edit this page" links.
61 | // editUrl: "https://github.com/chaitin/safeline/tree/main/website",
62 | },
63 | blog: {
64 | showReadingTime: true,
65 | // Remove this to remove the "edit this page" links.
66 | // editUrl: "https://github.com/chaitin/safeline/tree/main/website",
67 | },
68 | theme: {
69 | customCss: require.resolve("./src/css/custom.css"),
70 | },
71 | }),
72 | ],
73 | ],
74 |
75 | themeConfig:
76 | /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
77 | ({
78 | // Replace with your project's social card
79 | image: "images/safeline.png",
80 | navbar: {
81 | title: "",
82 | logo: { alt: "Logo", src: "images/logo.png" },
83 | items: [
84 | { to: "/docs", label: "技术文档", position: "right" },
85 | { to: "/detection", label: "效果对比", position: "right" },
86 | {
87 | to: "https://www.bilibili.com/medialist/detail/ml2342694989",
88 | label: "教学视频",
89 | position: "right",
90 | },
91 | {
92 | to: "https://demo.waf-ce.chaitin.cn:9443/dashboard",
93 | label: "演示环境",
94 | position: "right",
95 | },
96 | ],
97 | },
98 |
99 | footer: {
100 | style: "dark",
101 | links: [
102 | {
103 | title: " ",
104 | items: [
105 | {
106 | label: "北京长亭科技有限公司",
107 | to: "https://www.chaitin.cn/zh/",
108 | },
109 | {
110 | label: "长亭 B 站主页",
111 | href: "https://space.bilibili.com/521870525",
112 | },
113 | ],
114 | },
115 | {
116 | title: " ",
117 | items: [
118 | {
119 | label: "CT Stack 安全社区",
120 | href: "https://stack.chaitin.cn/",
121 | },
122 | {
123 | label: "长亭合作伙伴论坛",
124 | href: "https://bbs.chaitin.cn/",
125 | },
126 | ],
127 | },
128 | {
129 | title: " ",
130 | items: [
131 | {
132 | label: "长亭百川云平台",
133 | href: "https://rivers.chaitin.cn/",
134 | },
135 | {
136 | label: "关于我们",
137 | to: "/docs/about/chaitin",
138 | },
139 | ],
140 | },
141 | {
142 | title: " ",
143 | items: [
144 | {
145 | label: "长亭 GitHub 主页",
146 | href: "https://github.com/chaitin",
147 | },
148 | ],
149 | },
150 | ],
151 | copyright: `Copyright © ${new Date().getFullYear()}
152 | 北京长亭未来科技有限公司京 ICP 备 19035216 号京公网安备 11010802020947 号`,
153 | },
154 | prism: {
155 | theme: lightCodeTheme,
156 | darkTheme: darkCodeTheme,
157 | },
158 | }),
159 | };
160 |
161 | module.exports = config;
162 |
--------------------------------------------------------------------------------
/website/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "website",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "docusaurus": "docusaurus",
7 | "start": "docusaurus start",
8 | "build": "docusaurus build",
9 | "swizzle": "docusaurus swizzle",
10 | "deploy": "docusaurus deploy",
11 | "clear": "docusaurus clear",
12 | "serve": "docusaurus serve",
13 | "preview": "docusaurus clear; docusaurus build; docusaurus serve",
14 | "write-translations": "docusaurus write-translations",
15 | "write-heading-ids": "docusaurus write-heading-ids",
16 | "typecheck": "tsc"
17 | },
18 | "dependencies": {
19 | "@docusaurus/core": "2.4.1",
20 | "@docusaurus/preset-classic": "2.4.1",
21 | "@easyops-cn/docusaurus-search-local": "^0.35.0",
22 | "@emotion/react": "11.11.1",
23 | "@emotion/styled": "11.11.0",
24 | "@mdx-js/react": "^1.6.22",
25 | "@mui/icons-material": "5.14.3",
26 | "@mui/lab": "5.0.0-alpha.138",
27 | "@mui/material": "5.14.3",
28 | "clsx": "^1.2.1",
29 | "countup.js": "2.7.0",
30 | "prism-react-renderer": "^1.3.5",
31 | "react": "^17.0.2",
32 | "react-dom": "^17.0.2",
33 | "react-responsive-carousel": "3.2.23"
34 | },
35 | "devDependencies": {
36 | "@docusaurus/module-type-aliases": "2.4.1",
37 | "@tsconfig/docusaurus": "^1.0.5",
38 | "typescript": "^4.7.4"
39 | },
40 | "browserslist": {
41 | "production": [
42 | ">0.5%",
43 | "not dead",
44 | "not op_mini all"
45 | ],
46 | "development": [
47 | "last 1 chrome version",
48 | "last 1 firefox version",
49 | "last 1 safari version"
50 | ]
51 | },
52 | "engines": {
53 | "node": ">=16.14"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/website/sidebars.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Creating a sidebar enables you to:
3 | - create an ordered group of docs
4 | - render a sidebar for each doc of that group
5 | - provide next/previous navigation
6 |
7 | The sidebars can be generated from the filesystem, or explicitly defined here.
8 |
9 | Create as many sidebars as you want.
10 | */
11 |
12 | // @ts-check
13 |
14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
15 | const sidebars = {
16 | // By default, Docusaurus generates a sidebar from the docs folder structure
17 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
18 |
19 | // But you can create a sidebar manually
20 | /*
21 | tutorialSidebar: [
22 | 'intro',
23 | 'hello',
24 | {
25 | type: 'category',
26 | label: 'Tutorial',
27 | items: ['tutorial-basics/create-a-document'],
28 | },
29 | ],
30 | */
31 | };
32 |
33 | module.exports = sidebars;
34 |
--------------------------------------------------------------------------------
/website/src/api/index.ts:
--------------------------------------------------------------------------------
1 | export {
2 | submitSampleSet,
3 | getSampleSet,
4 | getSampleSetResult,
5 | getSampleDetail,
6 | getSetupCount,
7 | };
8 |
9 | // http://localhost:2023
10 | const BASE_API = "/api";
11 |
12 | function submitSampleSet(data: {
13 | pocs: Array<{ content: string; tag: string }>;
14 | record_it: boolean;
15 | }) {
16 | return fetch(BASE_API + "/poc/list", {
17 | method: "POST",
18 | headers: { "Content-Type": "application/json" },
19 | mode: "cors",
20 | // credentials: "include",
21 | body: JSON.stringify(data),
22 | }).then((res) => res.json());
23 | }
24 |
25 | function getSampleSet(id: string) {
26 | return fetch(BASE_API + "/poc/list?id=" + id).then((res) => res.json());
27 | }
28 |
29 | function getSampleDetail(id: string) {
30 | return fetch(BASE_API + "/poc/detail?id=" + id).then((res) => res.json());
31 | }
32 |
33 | async function getSampleSetResult(id: string, timeout: number = 60) {
34 | const startAt = new Date().getTime();
35 | const isTimeout = () => new Date().getTime() - startAt > timeout * 1000;
36 | const maxRetry = 20;
37 |
38 | for (let i = 0; i < maxRetry; i++) {
39 | const res = await fetch(BASE_API + "/poc/results?id=" + id).then((res) =>
40 | res.json()
41 | );
42 | if (res.code == 0 && res.data.data) {
43 | return { data: res.data.data, timeout: false };
44 | }
45 | if (isTimeout()) break;
46 | await new Promise((r) => setTimeout(r, 2000));
47 | }
48 | return { data: [], timeout: true };
49 | }
50 |
51 | function getSetupCount() {
52 | return fetch(BASE_API + "/count").then((res) => res.json());
53 | }
54 |
--------------------------------------------------------------------------------
/website/src/components/Features.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Grid, Box, Typography } from "@mui/material";
3 |
4 | const FEATURE_LIST = [
5 | {
6 | title: "便捷",
7 | content: (
8 | <>
9 |
10 | 采用容器化部署,一条命令即可完成安装,0 成本上手
11 |
12 |
13 | 安全配置开箱即用,无需人工维护,可实现安全躺平式管理
14 |
15 | >
16 | ),
17 | },
18 | {
19 | title: "安全",
20 | content: (
21 | <>
22 |
23 | 首创业内领先的智能语义分析算法,精准检测、低误报、难绕过
24 |
25 |
26 | 语义分析算法无规则,面对未知特征的 0day 攻击不再手足无措
27 |
28 | >
29 | ),
30 | },
31 | {
32 | title: "高性能",
33 | content: (
34 | <>
35 |
36 | 无规则引擎,线性安全检测算法,平均请求检测延迟在 1 毫秒级别
37 |
38 |
39 | 并发能力强,单核轻松检测 2000+
40 | TPS,只要硬件足够强,可支撑的流量规模无上限
41 |
42 | >
43 | ),
44 | },
45 | {
46 | title: "高可用",
47 | content: (
48 | <>
49 |
50 | 流量处理引擎基于 Nginx 开发,性能与稳定性均可得到保障
51 |
52 |
53 | 内置完善的健康检查机制,服务可用性高达 99.99%
54 |
55 | >
56 | ),
57 | },
58 | ];
59 |
60 | const Features = () => {
61 | return (
62 |
72 |
73 | {FEATURE_LIST.map((feature) => (
74 |
75 |
79 |
85 |
86 | {feature.title}
87 |
88 |
89 |
92 | {feature.content}
93 |
94 |
95 | ))}
96 |
97 |
98 | );
99 | };
100 |
101 | export default Features;
102 |
--------------------------------------------------------------------------------
/website/src/components/Icon.tsx:
--------------------------------------------------------------------------------
1 | import React, { type FC, useEffect } from "react";
2 |
3 | import { Box, type SxProps } from "@mui/material";
4 |
5 | interface IconProps {
6 | type: string;
7 | sx?: SxProps;
8 | [propName: string]: any;
9 | }
10 |
11 | const Icon: FC = ({ type, sx, ...restProps }) => {
12 | useEffect(() => {
13 | require("../../static/fonts/iconfont");
14 | }, []);
15 | return (
16 | // @ts-ignore
17 |
23 |
24 |
25 | );
26 | };
27 | export default Icon;
28 |
--------------------------------------------------------------------------------
/website/src/components/Message/Alert.tsx:
--------------------------------------------------------------------------------
1 | import React, { type FC, useRef, useEffect } from 'react'
2 |
3 | import { Alert as MAlert, type AlertColor } from '@mui/material'
4 |
5 | interface AlertProps {
6 | duration?: number
7 | onClose?(key: React.Key): void
8 | noticeKey: React.Key
9 | content?: React.ReactNode
10 | severity: AlertColor
11 | }
12 |
13 | const Alert: FC = (props) => {
14 | const { duration, severity, content, noticeKey, onClose } = props
15 | const closeTimer = useRef(null)
16 |
17 | const startCloseTimer = () => {
18 | if (duration) {
19 | closeTimer.current = window.setTimeout(() => {
20 | close()
21 | }, duration * 1000)
22 | }
23 | }
24 |
25 | const clearCloseTimer = () => {
26 | if (closeTimer.current) {
27 | clearTimeout(closeTimer.current)
28 | closeTimer.current = null
29 | }
30 | }
31 |
32 | const close = (e?: React.MouseEvent) => {
33 | if (e) {
34 | e.stopPropagation()
35 | }
36 | clearCloseTimer()
37 | if (onClose) {
38 | onClose(noticeKey)
39 | }
40 | }
41 |
42 | useEffect(() => {
43 | startCloseTimer()
44 | return () => {
45 | clearCloseTimer()
46 | }
47 | // eslint-disable-next-line react-hooks/exhaustive-deps
48 | }, [])
49 |
50 | return (
51 |
52 | {content}
53 |
54 | )
55 | }
56 |
57 | export default Alert
58 |
--------------------------------------------------------------------------------
/website/src/components/Message/Message.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, forwardRef, useImperativeHandle } from "react";
2 |
3 | import { Snackbar, Box, type AlertColor } from "@mui/material";
4 |
5 | import { render, unmount } from "@site/src/components/utils";
6 |
7 | import Alert from "./Alert";
8 |
9 | export interface Notice {
10 | key?: React.Key;
11 | content?: React.ReactNode;
12 | severity: AlertColor;
13 | onClose?: () => void;
14 | }
15 |
16 | interface MessageProps {}
17 |
18 | let seed = 0;
19 | const now = Date.now();
20 |
21 | function getUuid() {
22 | const id = seed;
23 | seed += 1;
24 | return `ctMessage_${now}_${id}`;
25 | }
26 |
27 | // eslint-disable-next-line react/display-name
28 | const Message = forwardRef((props, ref) => {
29 | const [notices, setNotices] = useState([]);
30 | const add = (notice: Notice) => {
31 | const key = notice.key ?? getUuid();
32 | setNotices((state) => {
33 | state.push({ ...notice, key });
34 | return [...state];
35 | });
36 | };
37 |
38 | const remove = (key: React.Key) => {
39 | setNotices((state) => state.filter((s) => s.key !== key));
40 | };
41 |
42 | useImperativeHandle(ref, () => ({
43 | add,
44 | remove,
45 | }));
46 |
47 | return (
48 |
49 |
50 | {notices.map((item) => {
51 | const alertProps = {
52 | ...item,
53 | noticeKey: item.key!,
54 | onClose: (noticeKey: React.Key) => {
55 | remove(noticeKey);
56 | },
57 | };
58 | return ;
59 | })}
60 |
61 |
62 | );
63 | });
64 |
65 | // @ts-ignore
66 | Message.newInstance = (properties: MessageProps, callback) => {
67 | const { ...props } = properties || {};
68 | const div = document?.createElement("div");
69 | document.body.appendChild(div);
70 | let called = false;
71 | function ref(notification: any) {
72 | if (called) {
73 | return;
74 | }
75 | called = true;
76 | callback({
77 | notice(noticeProps: MessageProps) {
78 | notification.add(noticeProps);
79 | },
80 | removeNotice(key: React.Key) {
81 | notification.remove(key);
82 | },
83 | component: notification,
84 | destroy() {
85 | unmount(div);
86 | if (div.parentNode) {
87 | div.parentNode.removeChild(div);
88 | }
89 | },
90 | });
91 | }
92 | setTimeout(() => {
93 | render(, div);
94 | });
95 | };
96 |
97 | export default Message;
98 |
--------------------------------------------------------------------------------
/website/src/components/Message/index.tsx:
--------------------------------------------------------------------------------
1 | import type React from "react";
2 |
3 | import { type AlertColor } from "@mui/material";
4 |
5 | import Notification from "./Message";
6 |
7 | type MessageStaticFunctions = Record<
8 | AlertColor,
9 | (context: React.ReactNode, duration?: number) => void
10 | >;
11 |
12 | const Message = {} as MessageStaticFunctions;
13 |
14 | let notification: any = null;
15 |
16 | if (typeof window !== "undefined") {
17 | // @ts-ignore
18 | Notification.newInstance({}, (n: any) => {
19 | notification = n;
20 | });
21 |
22 | const commonOpen =
23 | (type: AlertColor) =>
24 | (content: React.ReactNode, duration: number = 3) => {
25 | notification.notice({
26 | duration,
27 | severity: type,
28 | content,
29 | });
30 | };
31 |
32 | (["success", "warning", "info", "error"] as const).forEach((type) => {
33 | Message[type] = commonOpen(type);
34 | });
35 | }
36 |
37 | export default Message;
38 |
--------------------------------------------------------------------------------
/website/src/components/Modal/ConfirmDialog.tsx:
--------------------------------------------------------------------------------
1 | import React, { type FC } from "react";
2 |
3 | import ErrorIcon from "@mui/icons-material/Error";
4 | import { Box } from "@mui/material";
5 |
6 | import Modal, { type ModalProps } from "./Modal";
7 |
8 | export interface ConfirmDialogProps extends ModalProps {
9 | content?: React.ReactNode;
10 | width?: string;
11 | }
12 |
13 | const ConfirmDialog: FC = (props) => {
14 | const { title = "提示", content, width = "480px", ...rest } = props;
15 | return (
16 |
27 |
28 | {title}
29 |
30 | }
31 | closable={false}
32 | {...rest}
33 | sx={{ width }}
34 | >
35 | {content}
36 |
37 | );
38 | };
39 |
40 | export default ConfirmDialog;
41 |
--------------------------------------------------------------------------------
/website/src/components/Modal/Modal.tsx:
--------------------------------------------------------------------------------
1 | import React, { type FC, useState } from 'react'
2 |
3 | import CloseIcon from '@mui/icons-material/Close'
4 | import { LoadingButton } from '@mui/lab'
5 | import { Button, Dialog, DialogActions, DialogContent, DialogTitle, IconButton } from '@mui/material'
6 |
7 | export interface ModalProps {
8 | open?: boolean
9 | title?: React.ReactNode
10 | children?: React.ReactNode
11 | footer?: false | React.ReactNode
12 | okText?: React.ReactNode
13 | cancelText?: React.ReactNode
14 | showCancel?: boolean
15 | okColor?: 'primary' | 'error'
16 | cancelColor?: 'primary' | 'error'
17 | closable?: boolean
18 | onOk?(): void
19 | onClose?(): void
20 | onCancel?(): void
21 | sx?: any
22 | }
23 |
24 | const Modal: FC = (props) => {
25 | const {
26 | open = false,
27 | title,
28 | children,
29 | footer,
30 | okText = '确认',
31 | okColor = 'primary',
32 | cancelColor = 'primary',
33 | showCancel = true,
34 | cancelText = '取消',
35 | onOk,
36 | onClose,
37 | onCancel,
38 | closable = true,
39 | sx = {},
40 | } = props
41 | const [loading, setLoading] = useState(false)
42 |
43 | const onConfirm = async () => {
44 | setLoading(true)
45 | try {
46 | await onOk?.()
47 | } catch (error) {}
48 |
49 | setLoading(false)
50 | }
51 |
52 | return (
53 |
127 | )
128 | }
129 |
130 | export default Modal
131 |
--------------------------------------------------------------------------------
/website/src/components/Modal/confrim.tsx:
--------------------------------------------------------------------------------
1 | import { render as reactRender } from "@site/src/components/utils";
2 |
3 | import ConfirmDialog, { type ConfirmDialogProps } from "./ConfirmDialog";
4 |
5 | export default function confirm(config: ConfirmDialogProps) {
6 | const container = document.createDocumentFragment();
7 | const { onCancel: propCancel, onOk: propOk } = config;
8 | const onCancel = async () => {
9 | await propCancel?.();
10 | close();
11 | };
12 | const onOk = async () => {
13 | await propOk?.();
14 | close();
15 | };
16 | let currentConfig = { ...config, open: true, onCancel, onOk } as any;
17 | function render(props: ConfirmDialogProps) {
18 | setTimeout(() => {
19 | reactRender(, container);
20 | });
21 | }
22 |
23 | function close() {
24 | currentConfig = {
25 | ...currentConfig,
26 | open: false,
27 | };
28 | render(currentConfig);
29 | }
30 |
31 | render(currentConfig);
32 | }
33 |
--------------------------------------------------------------------------------
/website/src/components/Modal/index.tsx:
--------------------------------------------------------------------------------
1 | import { type ConfirmDialogProps } from './ConfirmDialog'
2 | import OriginModal from './Modal'
3 | import confirm from './confrim'
4 |
5 | type ModalStaticFunctions = Record<'confirm', (config: ConfirmDialogProps) => void>
6 | type ModalType = typeof OriginModal
7 |
8 | const Modal = OriginModal as ModalType & ModalStaticFunctions
9 |
10 | Modal.confirm = confirm
11 |
12 | export default Modal
13 |
--------------------------------------------------------------------------------
/website/src/components/Title.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Typography, SxProps } from "@mui/material";
3 |
4 | interface TitleProps {
5 | title: string;
6 | sx?: SxProps;
7 | }
8 |
9 | const Title: React.FC = ({ title, sx }) => {
10 | return (
11 |
15 |
21 | {title}
22 |
23 | );
24 | };
25 |
26 | export default Title;
27 |
--------------------------------------------------------------------------------
/website/src/components/Version/Consultation.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { useState, useEffect } from "react";
3 | import Message from "@site/src/components/Message";
4 | import Modal from "@site/src/components/Modal";
5 | import { Box, TextField, Typography, Button } from "@mui/material";
6 |
7 | function Consultation() {
8 | const [text, setText] = useState("");
9 | const [wrongPhoneNumber, setWrongPhoneNumber] = useState(false);
10 | const [consultOpen, setConsultOpen] = useState(false);
11 |
12 | const consultHandler = () => {
13 | const valid = /^1[3-9]\d{9}$/.test(text);
14 | setWrongPhoneNumber(!valid);
15 | if (!valid) {
16 | Message.error("手机号格式不正确");
17 | return;
18 | }
19 | fetch("https://leads.chaitin.net/api/trial", {
20 | // fetch('http://116.62.230.26:8999/api/trial', { // 测试用地址
21 | method: "POST",
22 | mode: "cors",
23 | headers: { "Content-Type": "application/json" },
24 | body: JSON.stringify({
25 | phone: text,
26 | platform_source: "product-official-site",
27 | product_source: "safeline-ce",
28 | source_detail: "来自雷池社区版官网",
29 | }),
30 | })
31 | .then((d) => d.json())
32 | .then((d) => {
33 | if (d.code == 0) {
34 | Message.success("提交成功");
35 | } else {
36 | Message.error("提交失败");
37 | }
38 | setConsultOpen(false);
39 | });
40 | };
41 |
42 | const textHandler = (v: string) => {
43 | setText(v);
44 | };
45 |
46 | useEffect(() => {
47 | if (!consultOpen) {
48 | setText("");
49 | }
50 | }, [consultOpen]);
51 |
52 | return (
53 | <>
54 |
69 | setConsultOpen(false)}
72 | title="咨询企业版"
73 | okText="提交"
74 | onOk={consultHandler}
75 | sx={{ width: 600 }}
76 | >
77 |
78 |
79 | textHandler(e.target.value)}
90 | />
91 |
92 |
93 | 我们将在工作时间 2 小时内联系您,您的手机号不会用于其他目的
94 |
95 |
96 |
97 | >
98 | );
99 | }
100 |
101 | export default Consultation;
102 |
--------------------------------------------------------------------------------
/website/src/components/Version/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Typography, Box, Button, alpha } from "@mui/material";
3 | import Title from "@site/src/components/Title";
4 | import FunctionTable from "./FunctionTable";
5 | import Consultation from "./Consultation";
6 |
7 | const FREE_FUNCTION = [
8 | "智能语义分析检测",
9 | "反向代理接入",
10 | "自定义黑白名单",
11 | "CC 攻击防护",
12 | "智能人机验证",
13 | "可视化安全分析",
14 | ];
15 | const ENTERPRISE_FUNCTION = [
16 | "智能语义分析检测",
17 | "串行、旁路均可接入",
18 | "集群式可扩展部署",
19 | "CC 攻击防护",
20 | "精细化引擎调节",
21 | "业务 API 智能建模",
22 | "Bot 管理,恶意 Bot 防护",
23 | "专业技术支持服务",
24 | "漏洞应急服务",
25 | ];
26 |
27 | const Version = () => {
28 | return (
29 | <>
30 |
39 |
61 |
62 | 社区版
63 |
64 |
76 |
77 | {FREE_FUNCTION.map((f) => (
78 |
96 | {f}
97 |
98 | ))}
99 |
100 |
101 |
102 | ({
104 | width: { xs: "100%", sm: 306 },
105 | flexShrink: 0,
106 | height: { xs: "auto" },
107 | px: 3,
108 | py: 2,
109 | border: "1px solid",
110 | borderColor: alpha(theme.palette.primary.main, 0.5),
111 | borderRadius: "12px",
112 | display: "flex",
113 | flexDirection: "column",
114 | alignItems: "center",
115 | "&:hover": {
116 | boxShadow:
117 | "0 36px 70px -10px rgba(61,64,76,.15), 0 18px 20px -10px rgba(61,64,76,.05)",
118 | },
119 | })}
120 | >
121 |
122 | 企业版
123 |
124 |
125 |
126 | {ENTERPRISE_FUNCTION.map((f) => (
127 |
145 | {f}
146 |
147 | ))}
148 |
149 |
150 |
151 |
152 |
153 |
154 | >
155 | );
156 | };
157 |
158 | export default Version;
159 |
--------------------------------------------------------------------------------
/website/src/components/detection/Result.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import TableContainer from "@mui/material/TableContainer";
3 | import Box from "@mui/material/Box";
4 | import Table from "@mui/material/Table";
5 | import TableRow from "@mui/material/TableRow";
6 | import TableHead from "@mui/material/TableHead";
7 | import TableCell from "@mui/material/TableCell";
8 | import TableBody from "@mui/material/TableBody";
9 | import Paper from "@mui/material/Paper";
10 | import Title from "@site/src/components/Title";
11 | import type { ResultRowsType } from "./types";
12 | import { Typography } from "@mui/material";
13 |
14 | export default Result;
15 |
16 | function Result({ rows }: { rows: ResultRowsType }) {
17 | return (
18 |
19 |
20 |
21 |
22 |
23 |
24 | WAF 类别
25 | 版本
26 | 检出率
27 | 误报率
28 | 准确率
29 | 平均检测耗时
30 |
31 |
32 |
33 | {rows.map((row, index) => (
34 |
35 |
36 | {appendLink(row.engine)}
37 |
38 |
39 | {row.version}
40 |
41 |
42 | {row.detectionRate}
43 |
44 |
45 | {row.failedRate}
46 |
47 |
48 | {row.accuracy}
49 |
50 |
51 | {row.cost}
52 |
53 |
54 | ))}
55 |
56 |
57 |
58 |
59 | );
60 | }
61 |
62 | function appendLink(engine: string) {
63 | if (engine == "ModSecurity")
64 | return (
65 |
66 | {engine}
67 |
68 | );
69 | if (engine == "TADK")
70 | return (
71 |
75 | {engine}
76 |
77 | );
78 | return engine;
79 | }
80 |
--------------------------------------------------------------------------------
/website/src/components/detection/SampleCount.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Typography from "@mui/material/Typography";
3 |
4 | function SampleCount({
5 | total,
6 | normal,
7 | attack,
8 | }: {
9 | total: number;
10 | normal: number;
11 | attack: number;
12 | }) {
13 | return (
14 |
15 | 共计 {total} 个 HTTP 请求样本,其中
16 |
17 | 普通样本 {normal} 个
18 |
19 | 、
20 | 攻击样本 {attack} 个
21 |
22 | );
23 | }
24 |
25 | export default SampleCount;
26 |
--------------------------------------------------------------------------------
/website/src/components/detection/SampleList.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useState } from "react";
3 | // import hljs from "highlight.js";
4 |
5 | import {
6 | Box,
7 | Button,
8 | Table,
9 | TableHead,
10 | TableRow,
11 | TableBody,
12 | Typography,
13 | Dialog,
14 | DialogActions,
15 | DialogContent,
16 | } from "@mui/material";
17 | import Paper from "@mui/material/Paper";
18 | import Accordion from "@mui/material/Accordion";
19 | import AccordionSummary from "@mui/material/AccordionSummary";
20 | import AccordionDetails from "@mui/material/AccordionDetails";
21 | import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
22 | import TableCell from "@mui/material/TableCell";
23 | import Title from "@site/src/components/Title";
24 | import SampleCount from "./SampleCount";
25 | import SamplesForm from "./SamplesForm";
26 | import Message from "@site/src/components/Message";
27 | import { getSampleDetail } from "@site/src/api";
28 | import { sizeLength } from "@site/src/components/utils";
29 |
30 | import type { RecordSamplesType } from "./types";
31 |
32 | export default SampleList;
33 |
34 | interface SampleListProps {
35 | value: RecordSamplesType;
36 | onSetIdChange: (id: string) => void;
37 | }
38 |
39 | function SampleList({ value, onSetIdChange }: SampleListProps) {
40 | const [open, setOpen] = useState(false);
41 | const [detail, setDetail] = useState("");
42 |
43 | const handleDetail = (id: string) => async () => {
44 | const res = await getSampleDetail(id);
45 | if (res.code != 0) {
46 | Message.error(res.msg || "获取详情失败");
47 | return;
48 | }
49 | const text = document.createElement("textarea");
50 | text.innerHTML = res.data.content;
51 | // const highlighted = hljs.highlight(text.value, {
52 | // language: "http",
53 | // });
54 | // setDetail(highlighted.value);
55 | setDetail(text.value)
56 | setOpen(true);
57 | };
58 |
59 | const handleClose = () => {
60 | setDetail("");
61 | setOpen(false);
62 | };
63 |
64 | return (
65 | <>
66 |
74 |
75 |
76 |
77 |
78 |
79 | }>
80 | !i.isAttack).length}
83 | attack={value.filter((i) => i.isAttack).length}
84 | />
85 |
86 |
87 |
88 |
89 |
90 | 样本类型
91 | 样本大小
92 | 摘要
93 |
94 |
95 |
96 |
97 | {value.map((row, index) => {
98 | const text = document.createElement("textarea");
99 | text.innerHTML = row.summary;
100 |
101 | return (
102 |
103 |
104 | {row.isAttack ? (
105 |
106 | 攻击样本
107 |
108 | ) : (
109 |
110 | 普通样本
111 |
112 | )}
113 |
114 |
115 | {sizeLength(row.size)}
116 |
117 |
118 |
126 | {text.value}
127 |
128 |
129 |
130 |
131 |
132 |
133 | );
134 | })}
135 |
136 |
137 |
138 |
139 |
140 |
152 | >
153 | );
154 | }
155 |
--------------------------------------------------------------------------------
/website/src/components/detection/SamplesForm.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useState } from "react";
3 | import Message from "@site/src/components/Message";
4 | import { submitSampleSet } from "@site/src/api";
5 | import CircularProgress from "@mui/material/CircularProgress";
6 | import CloseIcon from "@mui/icons-material/Close";
7 | import IconButton from "@mui/material/IconButton";
8 | import SampleSteps from "./SampleSteps";
9 | import Button from "@mui/material/Button";
10 | import Modal from "@mui/material/Modal";
11 | import Box from "@mui/material/Box";
12 | import Title from "@site/src/components/Title";
13 |
14 | export default SamplesForm;
15 |
16 | function SamplesForm({
17 | onSetIdChange,
18 | }: {
19 | onSetIdChange: (id: string) => void;
20 | }) {
21 | const [open, setOpen] = useState(false);
22 | const [loading, setLoading] = useState(false);
23 |
24 | const testHandler = () => {
25 | setOpen(true);
26 | };
27 | const closeHandler = () => {
28 | setOpen(false);
29 | };
30 |
31 | const getSetId = async (content: string, publish: boolean, tag: string) => {
32 | const res = await submitSampleSet({
33 | pocs: [{ content, tag }],
34 | record_it: publish,
35 | });
36 | if (res.code != 0) throw res.msg;
37 | if (res.data.total != 1) throw "样本数量错误";
38 | return res.data.id;
39 | };
40 |
41 | const submit = async ({
42 | sample,
43 | publish,
44 | isAttack,
45 | }: {
46 | sample: string;
47 | publish: boolean;
48 | isAttack: boolean;
49 | }) => {
50 | setLoading(true);
51 | try {
52 | const setId = await getSetId(
53 | sample,
54 | publish,
55 | isAttack ? "black" : "white"
56 | );
57 | onSetIdChange(setId);
58 | } catch (e) {
59 | Message.error(("解析失败: " + e) as string);
60 | }
61 | setOpen(false);
62 | setLoading(false);
63 | };
64 |
65 | return (
66 | <>
67 |
70 |
71 |
84 |
91 | {loading && (
92 |
105 |
106 |
107 | )}
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | >
119 | );
120 | }
121 |
--------------------------------------------------------------------------------
/website/src/components/detection/types.ts:
--------------------------------------------------------------------------------
1 | export type RecordSamplesType = Array<{
2 | id: string;
3 | size: number;
4 | isAttack: boolean;
5 | summary: string;
6 | }>;
7 |
8 | export type SampleDetailType = {
9 | id: string;
10 | size: number;
11 | isAttack: boolean;
12 | raw: string;
13 | summary: string;
14 | };
15 |
16 | export type ResultRowsType = Array<{
17 | engine: string;
18 | version: string;
19 | detectionRate: number;
20 | failedRate: number;
21 | accuracy: number;
22 | cost: string;
23 | }>;
24 |
--------------------------------------------------------------------------------
/website/src/components/utils.ts:
--------------------------------------------------------------------------------
1 | import ReactDOM, { type Root } from "react-dom";
2 |
3 | const MARK = "__ct_react_root__";
4 |
5 | type ContainerType = (Element | DocumentFragment) & {
6 | [MARK]?: Root;
7 | };
8 |
9 | export function render(node: React.ReactElement, container: ContainerType) {
10 | const root = container[MARK] || container;
11 |
12 | ReactDOM.render(node, root);
13 |
14 | container[MARK] = root;
15 | }
16 |
17 | export async function unmount(container: ContainerType) {
18 | return Promise.resolve().then(() => {
19 | container[MARK]?.unmount();
20 | delete container[MARK];
21 | });
22 | }
23 |
24 | export function sizeLength(l: number) {
25 | return l > 1024 * 2 ? Math.round(l / 1024) + "KB" : l + "B";
26 | }
27 |
28 | export function sampleLength(s: string) {
29 | const l = new Blob([s]).size;
30 | return l > 1024 * 2 ? Math.round(l / 1024) + "KB" : l + "B";
31 | }
32 |
33 | export function sampleSummary(s: string) {
34 | return s.split("\n").slice(0, 2).join(" ").slice(0, 60);
35 | }
36 |
--------------------------------------------------------------------------------
/website/src/css/custom.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Any CSS included here will be global. The classic template
3 | * bundles Infima by default. Infima is a CSS framework designed to
4 | * work well for content-centric websites.
5 | */
6 |
7 | body {
8 | font-size: 14px;
9 | }
10 |
11 | a:hover {
12 | text-decoration: none;
13 | }
14 |
15 | /* You can override the default Infima variables here. */
16 | :root {
17 | --ifm-color-primary: #0fc6c2;
18 | --ifm-breadcrumb-color-active: #0fc6c2;
19 | --ifm-menu-color-active: #0fc6c2;
20 | --ifm-link-hover-color: #0fc6c2;
21 | --ifm-footer-link-hover-color: #0fc6c2;
22 | --ifm-navbar-link-hover-color: #0fc6c2;
23 | --ifm-navbar-background-color: #0f1935;
24 | --ifm-navbar-link-color: white;
25 | }
26 |
27 | /* Overriding root Infima variables */
28 | [data-theme="dark"] {
29 | --ifm-navbar-background-color: #0f1935;
30 | }
31 |
32 | aside.theme-doc-sidebar-container {
33 | width: 240px !important;
34 | }
35 |
36 | .navbar__toggle.clean-btn svg {
37 | color: white;
38 | }
39 |
40 | @media (max-width: 996px) {
41 | :root {
42 | --ifm-menu-color: white;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/website/src/pages/detection.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import Container from "@mui/material/Container";
3 | import Result from "@site/src/components/detection/Result";
4 | // import { useRouter } from "next/router";
5 | import { useLocation } from "@docusaurus/router";
6 | import { getSampleSet, getSampleSetResult } from "@site/src/api";
7 | import Message from "@site/src/components/Message";
8 | import type {
9 | RecordSamplesType,
10 | ResultRowsType,
11 | } from "@site/src/components/detection/types";
12 | import Grid from "@mui/material/Grid";
13 | import SampleList from "@site/src/components/detection/SampleList";
14 | import { Typography } from "@mui/material";
15 | import Layout from "@theme/Layout";
16 | import ThemeProvider from "@site/src/components/Theme";
17 |
18 | export default Detection;
19 |
20 | function Detection() {
21 | // const router = useRouter();
22 | const location = useLocation();
23 | const [samples, setSamples] = useState([]);
24 | const [result, setResult] = useState([]);
25 |
26 | useEffect(() => {
27 | // useRouter 中获取 参数会有延迟,所以先判断有没有 id 参数
28 | const realSetId =
29 | new URLSearchParams(location.search).get("id") || "default";
30 | // const setId = (router.query.id as string) || "default";
31 | const setId = "default";
32 | if (setId !== realSetId) return;
33 |
34 | // 查询样本集合
35 | getSampleSet(setId).then((res) => {
36 | if (res.code != 0) {
37 | Message.error("测试集合 " + setId + ": " + res.msg);
38 | return;
39 | }
40 | if (!res.data.data) {
41 | Message.error("测试集合 " + setId + ": 获取结果为空");
42 | return;
43 | }
44 | setSamples(
45 | res.data.data?.map((i: any) => ({
46 | id: i.id,
47 | summary: i.summary,
48 | size: i.length,
49 | isAttack: i.tag == "black",
50 | }))
51 | );
52 | });
53 |
54 | // 查询样本集合结果
55 | getSampleSetResult(setId).then(({ data, timeout }) => {
56 | if (timeout) {
57 | Message.error("获取检测集结果超时");
58 | return;
59 | }
60 | setResult(
61 | data.map((i: any) => ({
62 | engine: i.engine,
63 | version: i.version,
64 | detectionRate: percent(i.recall),
65 | failedRate: percent(i.fdr),
66 | accuracy: percent(i.accuracy),
67 | cost: i.elapsed > 0 ? i.elapsed + " 毫秒" : "小于 1 毫秒",
68 | }))
69 | );
70 | });
71 | }, []);
72 |
73 | const handleSetId = (id: string) => {
74 | // router.push({
75 | // pathname: router.pathname,
76 | // query: { id },
77 | // });
78 | };
79 |
80 | return (
81 |
82 |
83 |
84 |
85 |
86 |
91 |
92 | TP: 正确识别到攻击样本的数量
93 |
94 | 检出率 = TP / (TP + FN)
95 |
96 |
97 | TN: 正确识别到普通样本的数量
98 |
99 | 误报率 = FP / (TP + FP)
100 |
101 |
102 | FP: 将普通样本误报为攻击的数量
103 |
104 | 准确率 = (TP + TN) / (TP + TN + FP + FN)
105 |
106 |
107 | FN: 未识别到攻击样本的数量
108 |
109 |
110 |
111 |
112 |
113 | );
114 | }
115 |
116 | function percent(v: number) {
117 | return Math.round(v * 10000) / 100 + "%";
118 | }
119 |
--------------------------------------------------------------------------------
/website/src/theme/Footer/Copyright/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | export default function FooterCopyright({ copyright }) {
3 | return (
4 | <>
5 |
11 | {/* 自定义组件的目的是为了插入 cnzz 统计代码 */}
12 | {process.env.NODE_ENV == "production" && (
13 |
17 | )}
18 | >
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/website/static/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/.nojekyll
--------------------------------------------------------------------------------
/website/static/fonts/iconfont.js:
--------------------------------------------------------------------------------
1 | window._iconfont_svg_string_4031246='',function(n){var t=(t=document.getElementsByTagName("script"))[t.length-1],e=t.getAttribute("data-injectcss"),t=t.getAttribute("data-disable-injectsvg");if(!t){var o,a,i,c,d,s=function(t,e){e.parentNode.insertBefore(t,e)};if(e&&!n.__iconfont__svg__cssinject__){n.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(t){console&&console.log(t)}}o=function(){var t,e=document.createElement("div");e.innerHTML=n._iconfont_svg_string_4031246,(e=e.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",e=e,(t=document.body).firstChild?s(e,t.firstChild):t.appendChild(e))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(a=function(){document.removeEventListener("DOMContentLoaded",a,!1),o()},document.addEventListener("DOMContentLoaded",a,!1)):document.attachEvent&&(i=o,c=n.document,d=!1,r(),c.onreadystatechange=function(){"complete"==c.readyState&&(c.onreadystatechange=null,l())})}function l(){d||(d=!0,i())}function r(){try{c.documentElement.doScroll("left")}catch(t){return void setTimeout(r,50)}l()}}(window);
--------------------------------------------------------------------------------
/website/static/images/album/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/album/0.png
--------------------------------------------------------------------------------
/website/static/images/album/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/album/1.png
--------------------------------------------------------------------------------
/website/static/images/album/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/album/2.png
--------------------------------------------------------------------------------
/website/static/images/album/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/album/3.png
--------------------------------------------------------------------------------
/website/static/images/album/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/album/4.png
--------------------------------------------------------------------------------
/website/static/images/album/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/album/5.png
--------------------------------------------------------------------------------
/website/static/images/album/block.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/album/block.png
--------------------------------------------------------------------------------
/website/static/images/class.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/class.png
--------------------------------------------------------------------------------
/website/static/images/docs/DNS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/DNS.png
--------------------------------------------------------------------------------
/website/static/images/docs/LoadBlance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/LoadBlance.png
--------------------------------------------------------------------------------
/website/static/images/docs/Untitled10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/Untitled10.png
--------------------------------------------------------------------------------
/website/static/images/docs/Untitled11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/Untitled11.png
--------------------------------------------------------------------------------
/website/static/images/docs/Untitled12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/Untitled12.png
--------------------------------------------------------------------------------
/website/static/images/docs/Untitled13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/Untitled13.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/acl_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/acl_page.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/api_assets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/api_assets.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/api_assets_collect1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/api_assets_collect1.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/api_assets_collect2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/api_assets_collect2.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/cert_create.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/cert_create.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/cs_statistics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/cs_statistics.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/forbidden_page_ext.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/forbidden_page_ext.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/log_detail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/log_detail.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/map.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/mgt_cert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/mgt_cert.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/mgt_cert_config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/mgt_cert_config.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/site_config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/site_config.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/website_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/website_1.png
--------------------------------------------------------------------------------
/website/static/images/docs/about_changelog/website_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/about_changelog/website_2.png
--------------------------------------------------------------------------------
/website/static/images/docs/add_challenge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/add_challenge.png
--------------------------------------------------------------------------------
/website/static/images/docs/challenge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/challenge.png
--------------------------------------------------------------------------------
/website/static/images/docs/config_access_log.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/config_access_log.png
--------------------------------------------------------------------------------
/website/static/images/docs/fake_host.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/fake_host.jpg
--------------------------------------------------------------------------------
/website/static/images/docs/flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/flow.png
--------------------------------------------------------------------------------
/website/static/images/docs/framework.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/framework.png
--------------------------------------------------------------------------------
/website/static/images/docs/get_source_ip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/get_source_ip.png
--------------------------------------------------------------------------------
/website/static/images/docs/guide_config/deploy_on_separate_server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/guide_config/deploy_on_separate_server.png
--------------------------------------------------------------------------------
/website/static/images/docs/guide_config/deploy_on_web_server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/guide_config/deploy_on_web_server.png
--------------------------------------------------------------------------------
/website/static/images/docs/guide_config/deploy_origin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/guide_config/deploy_origin.png
--------------------------------------------------------------------------------
/website/static/images/docs/guide_config/deploy_with_other_server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/guide_config/deploy_with_other_server.png
--------------------------------------------------------------------------------
/website/static/images/docs/guide_config/tengine_502.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/guide_config/tengine_502.png
--------------------------------------------------------------------------------
/website/static/images/docs/guide_install/collie_apps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/guide_install/collie_apps.png
--------------------------------------------------------------------------------
/website/static/images/docs/guide_introduction/website_with_safeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/guide_introduction/website_with_safeline.png
--------------------------------------------------------------------------------
/website/static/images/docs/guide_introduction/website_without_safeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/guide_introduction/website_without_safeline.png
--------------------------------------------------------------------------------
/website/static/images/docs/manual.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/manual.png
--------------------------------------------------------------------------------
/website/static/images/docs/practice_monitor/gift.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/practice_monitor/gift.png
--------------------------------------------------------------------------------
/website/static/images/docs/practice_monitor/machineid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/practice_monitor/machineid.png
--------------------------------------------------------------------------------
/website/static/images/docs/practice_monitor/website.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/practice_monitor/website.png
--------------------------------------------------------------------------------
/website/static/images/docs/safeline_https_website.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/safeline_https_website.gif
--------------------------------------------------------------------------------
/website/static/images/docs/server_index01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/server_index01.png
--------------------------------------------------------------------------------
/website/static/images/docs/server_index02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/docs/server_index02.png
--------------------------------------------------------------------------------
/website/static/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/favicon.ico
--------------------------------------------------------------------------------
/website/static/images/feature.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/website/static/images/gif/config_site.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/gif/config_site.gif
--------------------------------------------------------------------------------
/website/static/images/gif/detect_log.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/gif/detect_log.gif
--------------------------------------------------------------------------------
/website/static/images/gif/login.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/gif/login.gif
--------------------------------------------------------------------------------
/website/static/images/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/github.png
--------------------------------------------------------------------------------
/website/static/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/logo.png
--------------------------------------------------------------------------------
/website/static/images/qq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/qq.png
--------------------------------------------------------------------------------
/website/static/images/safeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/safeline.png
--------------------------------------------------------------------------------
/website/static/images/wechat-230717.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/wechat-230717.png
--------------------------------------------------------------------------------
/website/static/images/wechat-230825.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/wechat-230825.png
--------------------------------------------------------------------------------
/website/static/images/wechat-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/wechat-light.png
--------------------------------------------------------------------------------
/website/static/images/wechat-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/wechat-logo.png
--------------------------------------------------------------------------------
/website/static/images/wechat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jangrui/SafeLine/7bcb09197d93c5b045dd37d58fb456cfcc631b7e/website/static/images/wechat.png
--------------------------------------------------------------------------------
/website/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | // This file is not used in compilation. It is here just for a nice editor experience.
3 | "extends": "@tsconfig/docusaurus/tsconfig.json",
4 | "compilerOptions": {
5 | "baseUrl": "."
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/yanshi/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.dot
3 | *.output
4 | /build
5 | /src/parser.cc
6 | /src/parser.hh
7 | /src/lexer.cc
8 | /src/lexer.hh
9 |
--------------------------------------------------------------------------------
/yanshi/Makefile:
--------------------------------------------------------------------------------
1 | CPPFLAGS := -g3 -std=c++1y -Isrc -I. -DHAVE_READLINE
2 |
3 | ifeq ($(build),release)
4 | BUILD := release
5 | CPPFLAGS += -Os
6 | else
7 | BUILD := build
8 | CPPFLAGS += -fsanitize=undefined,address -DDEBUG
9 | LDLIBS := -lasan -lubsan
10 | endif
11 |
12 | LDLIBS += -licuuc -lreadline
13 | SRC := $(filter-out src/lexer.cc src/parser.cc, $(wildcard src/*.cc)) src/lexer.cc src/parser.cc
14 | OBJ := $(addprefix $(BUILD)/,$(subst src/,,$(SRC:.cc=.o)))
15 | UNITTEST_SRC := $(wildcard unittest/*.cc)
16 | UNITTEST_EXE := $(subst unittest/,,$(UNITTEST_SRC:.cc=))
17 |
18 | all: $(BUILD)/yanshi # unittest
19 |
20 | unittest: $(addprefix $(BUILD)/unittest/,$(UNITTEST_EXE))
21 | $(foreach x,$(addprefix $(BUILD)/unittest/,$(UNITTEST_EXE)),$x && ) :
22 |
23 | sinclude $(OBJ:.o=.d)
24 |
25 | # FIXME
26 | $(BUILD)/repl.o: src/lexer.hh
27 |
28 | $(BUILD) $(BUILD)/unittest:
29 | mkdir -p $@
30 |
31 | $(BUILD)/yanshi: $(OBJ)
32 | $(LINK.cc) $^ $(LDLIBS) -o $@
33 |
34 | $(BUILD)/%.o: src/%.cc | $(BUILD)
35 | $(CXX) $(CPPFLAGS) -MM -MP -MT $@ -MF $(@:.o=.d) $<
36 | $(COMPILE.cc) $< -o $@
37 |
38 | $(BUILD)/unittest/%: unittest/%.cc $(wildcard unittest/*.hh) $(filter-out $(BUILD)/main.o,$(OBJ)) | $(BUILD)/unittest
39 | $(CXX) $(CPPFLAGS) -MM -MP -MT $@ -MF $(@:.o=.d) $<
40 | $(LINK.cc) $(filter-out %.hh,$^) $(LDLIBS) -o $@
41 |
42 | src/lexer.cc src/lexer.hh: src/lexer.l
43 | flex --header-file=src/lexer.hh -o src/lexer.cc $<
44 |
45 | src/parser.cc src/parser.hh: src/parser.y src/common.hh src/location.hh src/option.hh src/syntax.hh
46 | bison --defines=src/parser.hh -o src/parser.cc $<
47 |
48 | $(BUILD)/loader.o: src/parser.hh
49 | $(BUILD)/parser.o: src/lexer.hh
50 | $(BUILD)/lexer.o: src/parser.hh
51 |
52 | clean:
53 | $(RM) -r build release
54 |
55 | distclean: clean
56 | $(RM) src/{lexer,parser}.{cc,hh}
57 |
58 | .PHONY: all clean distclean
59 |
--------------------------------------------------------------------------------
/yanshi/contrib/vim/compiler/yanshi.vim:
--------------------------------------------------------------------------------
1 | "if exists('current_compiler')
2 | " finish
3 | "endif
4 | let current_compiler = 'yanshi'
5 |
6 | if exists(':CompilerSet') != 2
7 | command -nargs=* CompilerSet setlocal
8 | endif
9 | CompilerSet errorformat=
10 | \%E%f\ %l:%c-%*\\d\ error\ %m,
11 | \%E%f\ %l-%*\\d:%c-%*\\d\ error\ %m,
12 | \%W%f\ %l:%c-%*\\d\ warning\ %m,
13 | \%W%f\ %l-%*\\d:%c-%*\\d\ warning\ %m,
14 | \%C%.%#
15 | CompilerSet makeprg=yanshi\ -d0\ -c\ $*\ %
16 |
--------------------------------------------------------------------------------
/yanshi/contrib/vim/ftdetect/yanshi.vim:
--------------------------------------------------------------------------------
1 | au BufRead,BufNewFile *.yanshi setf yanshi
2 | au BufRead,BufNewFile *.ys setf yanshi
3 |
--------------------------------------------------------------------------------
/yanshi/contrib/vim/ftplugin/yanshi.vim:
--------------------------------------------------------------------------------
1 | if exists('b:did_ftplugin')
2 | finish
3 | endif
4 | let b:did_ftplugin = 1
5 |
6 | compiler yanshi
7 |
--------------------------------------------------------------------------------
/yanshi/contrib/vim/syntax/yanshi.vim:
--------------------------------------------------------------------------------
1 | if exists('b:current_syntax')
2 | finish
3 | endif
4 |
5 | syn cluster yanshiCommentGroup contains=yanshiTodo
6 | syn include @yanshiCcode syntax/cpp.vim
7 | syn keyword yanshiAction action
8 | syn keyword yanshiMacro semicolon nosemicolon
9 | syn keyword yanshiStorageClass export intact
10 | syn keyword yanshiTodo contained TODO FIXME XXX
11 | syn match yanshiCpp 'c++'
12 | syn match yanshiActionOperator '[>$@%]'
13 | syn match yanshiCall '\^\w\+\(::\w\+\)\?'
14 | syn match yanshiCollapse '!\w\+\(::\w\+\)\?'
15 | syn match yanshiHighOp '[+\*?]'
16 | syn match yanshiIdent '\w\+\(::\w\+\)\?'
17 | syn match yanshiCpp display "^c++\s*" skipwhite nextgroup=yanshiBrace
18 | syn match yanshiImport display "^import\s*" contains=yanshiImported
19 | syn match yanshiLowOp '[-&|]'
20 | syn match yanshiSpecial display contained "\\\(x\x\x\|.\|$\)"
21 | syn region yanshiBrace matchgroup=Delimiter start='{' end='}' fold contains=@yanshiCcode
22 | syn region yanshiBracket start='\[' skip=+\\\\\|\\]+ end=']'
23 | syn region yanshiComment start='/\*' end='\*/' keepend contains=@yanshiCommentGroup,@Spell
24 | syn region yanshiImported display contained start="+" skip=+\\\\\|\\"+ end=+"+
25 | syn region yanshiLineComment start='#\|//' skip='\\$' end='$' keepend contains=@yanshiCommentGroup,@Spell
26 | syn region yanshiPreprocess start="#define" skip="\\$" end="$" keepend
27 | syn region yanshiQQString start=+"+ skip=+\\.+ end=+"+ contains=yanshiSpecial
28 | syn region yanshiQString start=+'+ skip=+\\.+ end=+'+
29 |
30 | syn region yanshiDefineStmt start='^\w\+\s*[=:]' end='$' skipnl contains=@yanshiExpr,yanshiComment,yanshiLineComment,yanshiParen0
31 |
32 | syn cluster yanshiExpr contains=yanshiActionOperator,yanshiBrace,yanshiBracket,yanshiCall,yanshiCollapse,yanshiIdent,yanshiHighOp,yanshiLowOp,yanshiQString,yanshiQQString,
33 | sy region yanshiParen0 matchgroup=yanshiParen0 start='(' end=')' contains=@yanshiExpr,yanshiParen1
34 | sy region yanshiParen1 matchgroup=yanshiParen1 start='(' end=')' contains=@yanshiExpr,yanshiParen2 contained
35 | sy region yanshiParen2 matchgroup=yanshiParen2 start='(' end=')' contains=@yanshiExpr,yanshiParen3 contained
36 | sy region yanshiParen3 matchgroup=yanshiParen3 start='(' end=')' contains=@yanshiExpr,yanshiParen4 contained
37 | sy region yanshiParen4 matchgroup=yanshiParen4 start='(' end=')' contains=@yanshiExpr,yanshiParen5 contained
38 | sy region yanshiParen5 matchgroup=yanshiParen5 start='(' end=')' contains=@yanshiExpr,yanshiParen0 contained
39 | hi yanshiParen0 ctermfg=brown guifg=#3bb9ff
40 | hi yanshiParen1 ctermfg=DarkBlue guifg=#f88017
41 | hi yanshiParen2 ctermfg=darkgray guifg=#5efb6e
42 | hi yanshiParen3 ctermfg=darkgreen guifg=#f62817
43 | hi yanshiParen4 ctermfg=darkcyan guifg=#fdd017
44 | hi yanshiParen5 ctermfg=darkmagenta guifg=#faafba
45 |
46 | hi link yanshiIdent Identifier
47 | "TODO color mismatch of {}
48 | "hi link yanshiBrace Statement
49 | "hi link yanshiDefineStmt Statement
50 | hi def link yanshiCall Constant
51 | hi def link yanshiCollapse Constant
52 | hi def link yanshiAction Structure
53 | hi def link yanshiActionOperator Type
54 | hi def link yanshiBracket Function
55 | hi def link yanshiCpp Structure
56 | hi def link yanshiComment Comment
57 | hi def link yanshiHighOp Operator
58 | hi def link yanshiImport Include
59 | hi def link yanshiImported String
60 | hi def link yanshiLineComment Comment
61 | hi def link yanshiLowOp Conditional
62 | hi def link yanshiMacro Macro
63 | hi def link yanshiPreprocess Macro
64 | hi def link yanshiQQString String
65 | hi def link yanshiQString String
66 | hi def link yanshiSpecial SpecialChar
67 | hi def link yanshiStorageClass StorageClass
68 | hi def link yanshiTodo Todo
69 |
70 | let b:current_syntax = 'yanshi'
71 |
--------------------------------------------------------------------------------
/yanshi/contrib/vim/syntax_checkers/yanshi/yanshi.vim:
--------------------------------------------------------------------------------
1 | if exists('g:loaded_syntastic_yanshi_yanshi_checker')
2 | finish
3 | endif
4 | let g:loaded_syntastic_yanshi_yanshi_checker = 1
5 |
6 | let s:save_cpo = &cpo
7 | set cpo&vim
8 |
9 | fu! SyntaxCheckers_yanshi_yanshi_GetLocList() dict
10 | let makeprg = self.makeprgBuild({ 'args': '-d0 -c' })
11 |
12 | let errorformat =
13 | \ '%C %.%#,'.
14 | \ '%E%f %l:%c-%*\d error %m,'.
15 | \ '%E%f %l-%*\d:%c-%*\d error %m,'.
16 | \ '%W%f %l:%c-%*\d warning %m,'.
17 | \ '%W%f %l-%*\d:%c-%*\d warning %m'
18 |
19 | return SyntasticMake({
20 | \ 'makeprg': makeprg,
21 | \ 'errorformat': errorformat })
22 | endf
23 |
24 | call g:SyntasticRegistry.CreateAndRegisterChecker({
25 | \ 'filetype': 'yanshi',
26 | \ 'name': 'yanshi'})
27 |
28 | let &cpo = s:save_cpo
29 | unlet s:save_cpo
30 |
--------------------------------------------------------------------------------
/yanshi/contrib/zsh/_yanshi:
--------------------------------------------------------------------------------
1 | #compdef yanshi
2 |
3 | _arguments \
4 | '(-b --bytes)'{-b,--bytes}'[make labels range over \[0,256), Unicode literals will be treated as UTF-8 bytes]' \
5 | '(-c --check)'{-c,--check}'[check syntax & use/def]' \
6 | '-C[generate C source code (default: C++)]' \
7 | '(-d --debug)'{-d,--debug}'+[debug level]:level:(0 1 2 3 4 5)' \
8 | '--dump-action[dump associated actions for each edge]' \
9 | '--dump-assoc[dump associated AST Expr for each state]' \
10 | '--dump-automaton[dump automata]' \
11 | '--dump-embed[dump statistics of EmbedExpr]' \
12 | '--dump-module[dump module use/def/...]' \
13 | '--dump-tree[dump AST]' \
14 | '(-G --graph)'{-G,--graph}'[output a Graphviz dot file]' \
15 | '(-I --import)'{-I,--import}'=[add to search path for "import"]' \
16 | '(-i --interactive)'{-i,--interactive}'[interactive mode]' \
17 | '(-k --keep-inaccessible)'{-k,--keep-inaccessible}'[do not perform accessible/co-accessible]' \
18 | '(-l --debug-output)'{-l,--debug-output}'=[filename for debug output]:file:_files' \
19 | '--max-return-stack=[max length of return stack in C generator]:len:' \
20 | '(-o --output)'{-o,--output}'=[.cc output filename]:file:_files' \
21 | '(-O --output-header)'{-O,--output-header}'=[.hh output filename]:file:_files' \
22 | '(-s --substring-grammar)'{-s,--substring-grammar}'[construct regular approximation of the substring grammar. Inner states of nonterminals labeled 'intact' are not connected to start/final]' \
23 | '(-h --help)'{-h,--help}'[display this help]' \
24 | '1:file:_files -g "*.{ys,yanshi}"'\
25 |
--------------------------------------------------------------------------------
/yanshi/src/common.hh:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #ifndef _GNU_SOURCE
3 | # define _GNU_SOURCE
4 | #endif
5 | #include
6 | #include