## File: README.md

<h4 align="center">
  SafeLine - Make your web apps secure
</h4>



<h3 align="center">🏆 Achievements</h3>



## 👋 INTRODUCTION

SafeLine is a self-hosted **`WAF(Web Application Firewall)`** to protect your web apps from attacks and exploits.

A web application firewall helps protect web apps by filtering and monitoring HTTP traffic between a web application and the Internet. It typically protects web apps from attacks such as `SQL injection`, `XSS`, `code injection`, `os command injection`, `CRLF injection`, `ldap injection`, `xpath injection`, `RCE`, `XXE`, `SSRF`, `path traversal`, `backdoor`, `bruteforce`, `http-flood`, `bot abused`, among others.

#### 💡 How It Works



By deploying a WAF in front of a web application, a shield is placed between the web application and the Internet. While a proxy server protects a client machine’s identity by using an intermediary, a WAF is a type of reverse-proxy, protecting the server from exposure by having clients pass through the WAF before reaching the server.

A WAF protects your web apps by filtering, monitoring, and blocking any malicious HTTP/S traffic traveling to the web application, and prevents any unauthorized data from leaving the app. It does this by adhering to a set of policies that help determine what traffic is malicious and what traffic is safe. Just as a proxy server acts as an intermediary to protect the identity of a client, a WAF operates in similar fashion but acting as a reverse proxy intermediary that protects the web app server from a potentially malicious client.

its core capabilities include:

- Defenses for web attacks
- Proactive bot abused defense 
- HTML & JS code encryption
- IP-based rate limiting
- Web Access Control List

#### ⚡️ Screenshots

|  |  |
| ------------------------------------------------- | ------------------------------------------------- | 
|  |  | 

Get [Live Demo](https://demo.waf.chaitin.com:9443/)

## 🔥 FEATURES

List of the main features as follows:

- **`Block Web Attacks`**
  - It defenses for all of web attacks, such as `SQL injection`, `XSS`, `code injection`, `os command injection`, `CRLF injection`, `XXE`, `SSRF`, `path traversal` and so on.
- **`Rate Limiting`**
  - Defend your web apps against `DoS attacks`, `bruteforce attempts`, `traffic surges`, and other types of abuse by throttling traffic that exceeds defined limits.
- **`Anti-Bot Challenge`**
  - Anti-Bot challenges to protect your website from `bot attacks`, human users will be allowed, crawlers and bots will be blocked.
- **`Authentication Challenge`**
  - When authentication challenge turned on, visitors need to enter the password, otherwise they will be blocked.
- **`Dynamic Protection`**
  - When dynamic protection turned on, html and js codes in your web server will be dynamically encrypted by each time you visit.

#### 🧩 Showcases

|                               | Legitimate User                                     | Malicious User                                                   |
| ----------------------------- | --------------------------------------------------- | ---------------------------------------------------------------- | 
| **`Block Web Attacks`**       |        |  |
| **`Rate Limiting`**           |        |  |
| **`Anti-Bot Challenge`**       |       |                      |
| **`Auth Challenge`**          |          |                         |
| **`HTML Dynamic Protection`** |  |               |
| **`JS Dynamic Protection`**   |    |                 | 

## 🚀 Quickstart

> [!WARNING]
> 中国大陆用户安装国际版可能会导致无法连接云服务，请查看 [中文版安装文档](https://docs.waf-ce.chaitin.cn/zh/%E4%B8%8A%E6%89%8B%E6%8C%87%E5%8D%97/%E5%AE%89%E8%A3%85%E9%9B%B7%E6%B1%A0)

#### 📦 Installing

Information on how to install SafeLine can be found in the [Install Guide](https://docs.waf.chaitin.com/en/GetStarted/Deploy)

#### ⚙️ Protecting Web Apps

to see [Configuration](https://docs.waf.chaitin.com/en/GetStarted/AddApplication)

## 📋 More Informations

#### Effect Evaluation

| Metric            | ModSecurity, Level 1 | CloudFlare, Free     | SafeLine, Balance      | SafeLine, Strict      |
| ----------------- | -------------------- | -------------------- | ---------------------- | --------------------- |
| Total Samples     | 33669                | 33669                | 33669                  | 33669                 |
| **Detection**     | 69.74%               | 10.70%               | 71.65%                 | **76.17%**            |
| **False Positive**| 17.58%               | 0.07%                | **0.07%**              | 0.22%                 |
| **Accuracy**      | 82.20%               | 98.40%               | **99.45%**             | 99.38%                |


#### Is SafeLine Production-Ready?

Yes, SafeLine is production-ready.

- Over [400,000 installations worldwide](https://cyberpress.org/safeline-waf-reaches-400000-global-deployments/)
- Protecting over 1,000,000 Websites
- Handling over 30,000,000,000 HTTP Requests Daily

#### 🌟 Community Recognition

- Rated **10.0/10** by [HelloGitHub](https://hellogithub.com/en/repository/0d07cfe266af4c25ba3eadf2c3d06f50)
- Listed in [awesome-selfhosted](https://github.com/awesome-selfhosted/awesome-selfhosted-data/blob/master/software/safeline.yml)
- Featured on [Product Hunt](https://www.producthunt.com/products/safeline-waf/launches/safeline-waf)
- Recognized by [Cyber Press](https://cyberpress.org/safeline-waf-reaches-400000-global-deployments/) as the most popular open-source web firewall on GitHub

#### 🔌 Ecosystem Integrations

- [SafeLine MCP Server](./mcp_server/README.md) for AI-assisted management and control
- [Ingress-NGINX](./sdk/ingress-nginx/README.md) plugin for protecting Kubernetes ingress traffic
- [Kong Gateway](./sdk/kong/Readme.md) plugin for protecting APIs and services

#### 🙋‍♂️ Community

Join our [Discord](https://discord.gg/SVnZGzHFvn) to get community support, the core team members are identified by the STAFF role in Discord.

- channel [#feedback](https://discord.com/channels/1243085666485534830/1243120292822253598): for new features discussion.
- channel [#FAQ](https://discord.com/channels/1243085666485534830/1263761679619981413): for FAQ.
- channel [#general](https://discord.com/channels/1243085666485534830/1243115843919806486): for any other questions.

Several contact options exist for our community, the primary one being Discord. These are in addition to GitHub issues for creating a new issue.


  <a target="_blank" href="https://discord.gg/SVnZGzHFvn"></a> &nbsp;
  <a target="_blank" href="https://x.com/safeline_waf"></a> &nbsp;
  <a target="_blank" href="/images/wechat.png"></a>


#### 💪 PRO Edition

SafeLine PRO is now available! [Explore plans and pricing](https://cyberserval.tech/landing/safeline#safeline-price) or [start a 7-day trial](https://safeline.app.cyberserval.tech/).

#### 📝 License

See [LICENSE](/LICENSE.md) for details.

---

## File: management/tcontrollerd/README.md

# TControllerD

Tengine Controller Daemon (abbr. TCD) will be running in the Tengine container, 
designed to be in place with minion on the host machine.

## Requirements

Go 1.18+

## Development

### init protobuf

```shell
# Refer: https://grpc.io/docs/languages/go/quickstart/
# 1. Install protoc
# https://grpc.io/docs/protoc-installation/

# 2. Install Go plugins
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.30.0
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0

# 3. Update your PATH so that the protoc compiler can find the plugins
# export PATH="$PATH:$(go env GOPATH)/bin"

# 4. Generate proto go code
# cd /path/to/management
./scripts/genproto.sh
```

---

## File: management/webserver/README.md

# Web Server

web server for mgt-api

## Requirements

Go 1.18+

## Development

### Init protobuf

```shell
# Refer: https://grpc.io/docs/languages/go/quickstart/
# 1. Install protoc
# https://grpc.io/docs/protoc-installation/

# 2. Install Go plugins
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.30.0
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0

# 3. Update your PATH so that the protoc compiler can find the plugins
# export PATH="$PATH:$(go env GOPATH)/bin"

# 4. Generate proto go code
# cd /path/to/management
./scripts/genproto.sh
```

### Init fvm libs

```shell
# Due to the fvm c header files
mkdir -p management/webserver/submodule/fvm/
mkdir -p management/webserver/submodule/libct/

cd management/webserver/submodule/fvm/
# Download https://chaitin.cn/patronus/fvm/-/tags 1.8.21 release:release, https://chaitin.cn/patronus/fvm/-/jobs/6716645
unzip artifacts.zip
rm artifacts.zip

cd management/webserver/submodule/libct/
# Download https://chaitin.cn/patronus/libct/-/tags 1.1.1.0 release, https://chaitin.cn/patronus/libct/-/jobs/7229201
# rename
rm artifacts.zip

cd management/webserver/submodule/
# Download https://chaitin.cn/patronus/fusion-2/-/tags 5.3.9-r1 build:release, https://chaitin.cn/patronus/fusion-2/-/jobs/7326007
# rename
unzip artifacts.zip
mv artifacts/lib/libfusion.so libfvm.so
rm artifacts.zip
rm -r artifacts/
```

### Build

```shell
cd management/
docker run -it --rm -w="/mnt" --mount type=bind,source="$(pwd)",target=/mnt chaitin.cn/ci/golang:1.18 bash
cp webserver/submodule/libfvm.so /usr/lib/
make build-webserver
```

---

## File: mcp_server/README.md

# SafeLine MCP Server

SafeLine MCP Server is an implementation of the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) that provides complete management and control capabilities for SafeLine WAF.

[](docker-compose.yml)
[](go.mod)

## Use Cases

- Automated management and control of SafeLine WAF instances
- WAF configuration and policy management through API
- Building AI-based security protection tools and applications

## Prerequisites

1. Install [Docker](https://www.docker.com/) (if running in container)
2. Configure SafeLine API Token (obtained from SafeLine console)

## Features

- Complete MCP (Management Control Protocol) server implementation
- Support for SafeLine WAF instance management and control
- Flexible configuration system supporting file configuration and environment variables
- Docker containerization support
- Secure API communication

## Quick Start

### Environment Variables

| Environment Variable | Description | Default Value | Required |
|---------|------|--------|-----|
| LISTEN_PORT | Service listening port | 5678 | No |
| LISTEN_ADDRESS | Service listening address | 0.0.0.0 | No |
| SAFELINE_SECRET | SSE server secret | - | No |
| SAFELINE_ADDRESS | SafeLine API address | - | Yes |
| SAFELINE_API_TOKEN | SafeLine API authentication token | - | Yes |

### Using Docker

#### Method 1: Using docker run

```bash
docker run -d \
  --name safeline-mcp \
  -p 5678:5678 \
  -e SAFELINE_API_TOKEN="your_api_token" \
  -e SAFELINE_ADDRESS="https://your.safeline.com" \
  -e LISTEN_PORT=5678 \
  -e LISTEN_ADDRESS="0.0.0.0" \
  chaitin/safeline-mcp:latest
```

#### Method 2: Using docker-compose

```bash
# 1. Clone repository
git clone https://github.com/chaitin/safeline-mcp.git
cd safeline-mcp

# 2. Edit docker-compose.yml to configure environment variables
# Example docker-compose.yml:
# version: '3'
# services:
#   mcp:
#     image: chaitin/safeline-mcp:latest
#     container_name: safeline-mcp
#     ports:
#       - "5678:5678"
#     environment:
#       - SAFELINE_API_TOKEN=your_api_token
#       - SAFELINE_ADDRESS=https://your.safeline.com
#       - LISTEN_PORT=5678
#       - LISTEN_ADDRESS=0.0.0.0

# 3. Start service
docker compose -f docker-compose.yml up -d
```

#### Method 3: Using Go

```bash
# 1. Clone repository
git clone https://github.com/chaitin/SafeLine.git
cd safeline-mcp

# 2. Install dependencies
go mod download

# 3. Configure config.yaml
cp config.yaml.example config.yaml
# Edit config.yaml with necessary configurations

# 4. Run service
go run main.go
```

For more API details, please refer to the [API Documentation](https://demo.waf.chaitin.com:9443/swagger/index.html).

## Tools

### Application Management

- **create_application**

### Rule Management
- **create_blacklist_rule**
- **create_whitelist_rule**

### Analyze
- **get_attack_events**

## Development Guide

The Go API in this project is currently under development, and APIs may change. If you have specific requirements, please submit an Issue for discussion.

### Directory Structure

```
internal/
├── api/              # API implementation
│   ├── app/         # Application-related APIs
│   │   └── create_application.go
│   └── rule/        # Rule-related APIs
│       └── create_rule.go
└── tools/           # MCP tool implementation
    ├── app/         # Application-related tools
    │   └── create_application.go
    └── rule/        # Rule-related tools
        └── create_rule.go
```

### Adding New Tools

1. **Create Tool File**
   - Create corresponding directory and file under `internal/tools`
   - File name should match tool name
   - Use separate file for each tool
   - Example: `internal/tools/app/create_application.go`

2. **Tool Implementation Template**
```go
package app

type ToolName struct{}

type ToolParams struct {
    // Parameter definitions
    Param1 string `json:"param1" desc:"parameter description" required:"true"`
    Param2 int    `json:"param2" desc:"parameter description" required:"false"`
}

type ToolResult struct {
    Field1 string `json:"field1"`
}

func (t *ToolName) Name() string {
    return "tool_name"
}

func (t *ToolName) Description() string {
    return "tool description"
}

func (t *ToolName) Validate(params ToolParams) error {
    // Parameter validation logic
    return nil
}

func (t *ToolName) Execute(ctx context.Context, params ToolParams) (result ToolResult, err error) {
    // Tool execution logic
    return result, nil
}
```

3. **[Optional]Create API Implementation**

If you need to use some APIs that have not been implemented yet, you need to create corresponding files in the api directory for implementation
   - Create same directory structure under `internal/api`
   - File name should match tool func
   - Example: `internal/api/app/create_application.go`

**API Implementation Template**
```go
package app

type RequestType struct {
    // Request parameter definitions
    Param1 string `json:"param1"`
    Param2 int    `json:"param2"`
}

func APIName(ctx context.Context, req *RequestType) (ResultType, error) {
    if req == nil {
        return nil, errors.New("request is required")
    }

    var resp api.Response[ResultType]
    err := api.Service().Post(ctx, "/api/path", req, &resp)
    if err != nil {
        return nil, errors.Wrap(err, "failed to execute")
    }

    if resp.Err != nil {
        return nil, errors.New(resp.Msg)
    }

    return resp.Data, nil
}
```
4. **Tool Registration (init.go)**

The tool registration file `internal/tools/init.go` is used to centrally manage all tool registrations
  - Register all tools uniformly in the `init()` function
  - Use the `AppendTool()` method for registration
  - Example:
    ```go
    // Register create application tool
    AppendTool(&app.CreateApp{})
    
    // Register create blacklist rule tool
    AppendTool(&rule.CreateBlacklistRule{})
    ```

### Development Standards

1. **Naming Conventions**
   - Use lowercase letters and underscores for tool names
   - File names should match tool names

2. **Directory Organization**
   - Divide directories by functional modules (e.g., app, rule, etc.)
   - Maintain consistent structure between tools and api directories
   - Keep related functionality in the same directory

3. **Code Standards**
   - Follow Go standard code conventions
   - Add necessary parameter validation
   - Use unified error handling approach
   - Add appropriate logging

4. **Documentation Requirements**
   - Provide clear functional description in tool Description
   - Add detailed description for parameters
   - Update API toolkit documentation in README

### Example

Refer to the implementation of the `create_application` tool:
- Tool implementation: `internal/tools/app/create_application.go`
- API implementation: `internal/api/app/create_application.go`

---

## File: sdk/lua-resty-t1k/README.md

# lua-resty-t1k

[](https://luarocks.org/modules/blaisewang/lua-resty-t1k)
[](https://github.com/chaitin/lua-resty-t1k/releases)
[](https://github.com/chaitin/lua-resty-t1k/blob/main/LICENSE)

## Name

Lua implementation of the T1K protocol for [Chaitin/SafeLine](https://github.com/chaitin/safeline) Web Application Firewall.

## Status

Production ready.

[](https://github.com/chaitin/lua-resty-t1k/actions)

## Installation

```bash
luarocks install lua-resty-t1k
```

If you are in Mainland China

```bash
luarocks install lua-resty-t1k --server https://luarocks.cn
```

## Synopsis

```lua
location / {
    access_by_lua_block {
        local t1k = require "resty.t1k"

        local t = {
            mode = "block",                            -- block or monitor or off, default off
            host = "unix:/workdir/snserver.sock",      -- required, SafeLine WAF detection service host, unix domain socket, IP, or domain is supported, string
            port = 8000,                               -- required when the host is an IP or domain, SafeLine WAF detection service port, integer
            connect_timeout = 1000,                    -- connect timeout, in milliseconds, integer, default 1s (1000ms)
            send_timeout = 1000,                       -- send timeout, in milliseconds, integer, default 1s (1000ms)
            read_timeout = 1000,                       -- read timeout, in milliseconds, integer, default 1s (1000ms)
            req_body_size = 1024,                      -- request body size, in KB, integer, default 1MB (1024KB)
            keepalive_size = 256,                      -- maximum concurrent idle connections to the SafeLine WAF detection service, integer, default 256
            keepalive_timeout = 60000,                 -- idle connection timeout, in milliseconds, integer, default 60s (60000ms)
            remote_addr = "http_x_forwarded_for: 1",   -- remote address from ngx.var.VARIABLE, string, default from ngx.var.remote_addr
        }

        local ok, err, _ = t1k.do_access(t, true)
        if not ok then 
            ngx.log(ngx.ERR, err)
        end
    }

    header_filter_by_lua_block {
        local t1k = require "resty.t1k"
        t1k.do_header_filter()
    }
}
```

## Lua Resty T1K vs. C T1K

[C T1K](https://t1k.chaitin.com/), as part of SafeLine's enterprise edition, is a deployment mode crafted in C language for enhanced performance.
It is compatible with all versions of Nginx and does not require deployment via OpenResty (lua_nginx_module).

|                       | Lua Resty T1K | C T1K |
|-----------------------|---------------|-------|
| Request Detection     | ✅             | ✅     |
| Response Detection    | ❌             | ✅     |
| Health Checks*        | ❌             | ✅     |
| Cookie Protection     | ❌             | ✅     |
| Bot Protection        | ❌             | ✅     |
| Proxy-side Statistics | ❌             | ✅     |

&ast; APISIX implements health check functionality for the `chaitin-waf` plugin. For more information, please see the [chaitin-waf documentation](https://apisix.apache.org/docs/apisix/next/plugins/chaitin-waf/).

---

## File: sdk/kong/Readme.md

# Kong Safeline Plugin
Kong plugin for Chaitin SafeLine Web Application Firewall (WAF). This plugin is used to protect your API from malicious requests. It can be used to block requests that contain malicious content in the request body, query parameters, headers, or URI.

## Safeline Prepare
The detection engine of the SafeLine provides services by default via Unix socket. We need to modify it to use TCP, so it can be called by the t1k plugin.

1.Navigate to the configuration directory of the SafeLine detection engine:
```shell
cd /data/safeline/resources/detector/
```
2.Open the `detector.yml` file in a text editor. Modify the bind configuration from Unix socket to TCP by adding the following settings:
```yaml
bind_addr: 0.0.0.0
listen_port: 8000
```
These configuration values will override the default settings in the container, making the SafeLine engine listen on port 8000.

3.Next, map the container’s port 8000 to the host machine. First, navigate to the SafeLine installation directory:
```shell
cd /data/safeline
```

4.Open the compose.yaml file in a text editor and add the ports field to the detector container to expose port 8000:
```yaml
...
detect:
  ports:
    - 8000:8000
...
```

5.Save the changes and restart SafeLine with the following commands:
```shell
docker-compose down
docker-compose up -d
```
This will apply the changes and activate the new configuration.

## Plugin Installation
To install the plugin, run the following command in your Kong server:

```shell
$ luarocks install kong-safeline
```

## Plugin Configuration
You can add the plugin to your API by making the following request:

```shell
# if your detector is running on tcp port
$ curl -X POST http://kong:8001/services/{name}/plugins \
    --data "name=safeline" \
    --data "config.host=your_detector_host" \
    --data "config.port=your_detector_port"
# if your detector is running on unix socket
$ curl -X POST http://kong:8001/services/{name}/plugins \
    --data "name=safeline" \
    --data "config.host=unix:/path/to/your/unix/socket"
```

## Test
You can test the plugin by sending a request to your API with malicious content. If the request is blocked, you will receive a `403 Forbidden` response.

```shell
$ curl -X POST http://kong:8000?1=1%20and%202=2

# you will receive a 403 Forbidden response
{"code": 403, "success":false, "message": "blocked by Chaitin SafeLine Web Application Firewall", "event_id": "8b41a021ea9541c89bb88f3773b4da24"}
```

---

## File: sdk/ingress-nginx/README.md

# ingress-nginx-safeline

[Ingress-nginx](https://kubernetes.github.io/ingress-nginx/) plugin for Chaitin SafeLine Web Application Firewall (WAF). This plugin is used to protect your API from malicious requests. It can be used to block requests that contain malicious content in the request body, query parameters, headers, or URI.

## Safeline Prepare
The detection engine of the SafeLine provides services by default via Unix socket. We need to modify it to use TCP, so it can be called by the t1k plugin.

1.Navigate to the configuration directory of the SafeLine detection engine:
```shell
cd /data/safeline/resources/detector/
```
2.Open the `detector.yml` file in a text editor. Modify the bind configuration from Unix socket to TCP by adding the following settings:
```yaml
bind_addr: 0.0.0.0
listen_port: 8000
```
These configuration values will override the default settings in the container, making the SafeLine engine listen on port 8000.

3.Next, map the container’s port 8000 to the host machine. First, navigate to the SafeLine installation directory:
```shell
cd /data/safeline
```

4.Open the compose.yaml file in a text editor and add the ports field to the detector container to expose port 8000:
```yaml
...
detect:
  ports:
    - 8000:8000
...
```

5.Save the changes and restart SafeLine with the following commands:
```shell
docker-compose down
docker-compose up -d
```
This will apply the changes and activate the new configuration.

## Plugin Usage

### Step 1: Install the plugin

way 1: Build your own ingress-nginx/controller image with the plugin installed.

```dockerfile
FROM registry.k8s.io/ingress-nginx/controller:v1.10.1

USER root

RUN apk add --no-cache make gcc unzip wget

# install luaroncks
RUN wget https://luarocks.org/releases/luarocks-3.11.0.tar.gz && \
    tar zxpf luarocks-3.11.0.tar.gz && \
    cd luarocks-3.11.0 && \
    ./configure && \
    make && \
    make install && \
    cd .. && \
    rm -rf luarocks-3.11.0 luarocks-3.11.0.tar.gz

RUN luarocks install ingress-nginx-safeline && \
    ln -s /usr/local/share/lua/5.1/safeline /etc/nginx/lua/plugins/safeline

USER www-data
```

way 2: Use the chaitin ingress-nginx-controller image.

replace image ingress-nginx-controller with `docker.io/chaitin/ingress-nginx-controller:v1.10.1` in your deployment.

### Step 2: Configure the plugin

use a ConfigMap to configure the plugin

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: safeline
  namespace: default
data:
  host: "YOUR_DETECTOR_HOST"
  port: "YOUR_DETECTOR_PORT"
```

### Step 3: Configure the ingress-controller

inject env `SAFELINE_HOST` and `SAFELINE_PORT` to the ingress-controller deployment

```yaml
...
env:
  - name: SAFELINE_HOST
    valueFrom:
      configMapKeyRef:
        name: safeline
        key: host
  - name: SAFELINE_PORT
    valueFrom:
      configMapKeyRef:
        name: safeline
        key: port
...

```

### Step 3: Enable the plugin

enable safeline plugin in configmap

```yaml
apiVersion: v1
data:
  allow-snippet-annotations: "false"
  plugins: "safeline"
kind: ConfigMap
metadata:
  name: ingress-nginx-controller
  namespace: default
```

### Step 4: Set externalTrafficPolicy to Local
by default, the ingress-nginx-controller service is of type LoadBalancer, which means the source IP of the request will be the IP of the LoadBalancer. If you want to get the real source IP, you can set the externalTrafficPolicy to Local.

### Step 5: Test the plugin

use a simple http sql injection test

```bash
curl -X POST http://localhost/ -d "select * from users where id=1 or 1=1" 
```

you should get a 403 response.
```bash
{"code": 403, "success":false, "message": "blocked by Chaitin SafeLine Web Application Firewall", "event_id": "b53eb5b95796475699c52a019abb8e6a"}
```

---

## File: yanshi/README.md

# 偃师 (yanshi)

yanshi is a finite state automaton generator like Ragel. Use inline operators to embed C++ code in the recognition of a language. yanshi is enhanced with features to approximate context-free grammar:

- Approximation of substring grammar
- Approximation of recursive automaton to match expressions with recursion.

The motivation to create yanshi is that Ragel does not provide a mechanism to serialize its representation of finite state automata, making it difficult to post-process generated automata and obtain the substring grammar recognizer.

Later on, I found a simplified SQL grammar might contain more than 10000 states. It was not only slow to generate the automaton, making it hard to do trial-and-error experiments, but wasted memory to store the automaton. I introduced `CollapseExpr` to allow circular references.

`CallExpr` takes one step further, maintains a return address stack to imitate function calls. It can be seen as an augmented `CollapseExpr`, removing a lot of false positive cases.

## Name

From <https://en.wikipedia.org/wiki/Automaton>:


In ancient China, a curious account of automata is found in the Lie Zi text (列子), written in the 3rd century BC. Within it there is a description of a much earlier encounter between King Mu of Zhou (周穆王, 1023-957 BC) and a mechanical engineer known as Yan Shi (偃师), an 'artificer'.


## Build

* Debug: `make`
* Release: `make build=release`

## Getting Started

* Create file `a.ys`:
  ```
  export foo = 'hello'
  ```

  Run `yanshi -S a.ys -o /tmp/a.cc` to generate a C++ file from the yanshi source file `a.ys`.

  + `yanshi_foo_start`: the start state is 0. States are represented by natural numbers.
  + `yanshi_foo_is_final`: leave aside `ret_stack` and look at the last line, it checks whether `u` is one of the final states.
  + `yanshi_foo_transit`: leave aside `ret_stack`, `u` is the current state and `c` is the next input codepoint or label.

  With the `-S` option, yanshi will generate a standalone C++ file.
  ```
  % make -C /tmp a
  make: Entering directory '/tmp'
  g++     a.cc   -o a
  make: Leaving directory '/tmp'
  % /tmp/a hello
  0 h 1 e 2 l 3 l 4 o 5
  len: 5
  pref: 5
  state: 5
  final: true
  % /tmp/a
  hello0 h 1 e 2 l 3 l 4 o 5
  len: 5
  pref: 5
  state: 5
  final: true
  ```

  States are yellow and interleaved with transition labels. Final states are bold yellow.
  + `len`: the length of input codepoints or labels
  + `pref`: the length of the longest prefix that does not enter the dead state
  + `state`: the state entered after consuming the input
  + `final`: whether the state is one of final states

* Interactive mode

  The `-i` option enables interactive mode.
  ```
  % yanshi -i a.ys
  Testing foo
  foo :: DefineStmt
  .integer mode
  Commands available from the prompt:
    .automaton    dump automaton
    .assoc        dump associated AST Expr for each state
    .help         display this help
    .integer      input is a list of non-negative integers, macros(#define) or ''  quoted strings
    .macro        display defined macros
    .string       input is a string
    .stmt  change target DefineStmt to 
    .quit         exit interactive mode
  λ 104 101 108 108 111
  0 104 1 101 2 108 3 108 4 111 5
  export foo = 'hello':
  λ .string
  .string mode
  λ hello
  0 h 1 e 2 l 3 l 4 o 5
  export foo = 'hello':
  λ
  ```

* Regex-like syntax
  ```
  export hello = [gh] 'e' l{2} 'o'
  l = 'l'
  ```

  `[gh]` is a bracket expression and `l{2}` denotes to matches `l` at least twice. This grammar matches `hello`, `gello`, `helllo`, ...

  + Union: `c = a | b`
  + Intersection: `c = a && b`
  + Difference: `c = a - b`
  + Concatenation: `c = a b`
  + Complement: `c = ~ a`

* Actions (embedded C++ code)
  ```
  c++ {
  #include <stdio.h>
  }
  export hello = '喵' @ { puts("meow"); } {2}
  ```
  I have not thought clearly on the implementation. The executing point may be counter-intuitive.

* Modules
  ```
  # a.ys
  import 'b.ys' as B # B::bar
  import 'b.ys' # qux

  export foo = B::bar | qux
  bar = '4'

  # b.ys
  bar = '3'
  qux = '5'
  ```

* Substring grammar
  Specify the `--substring-grammar` option to generate code for substring grammar. That is, the generated code matches every substring of the grammar. The implementation creates a new start state and a new final state, connects the start state to the old start state, and old final states to the new final state.

* `EmbedExpr`, reference a nonterminal without modifiers
   ```
   foo = bar
   bar = [0-9]
   ```
   The complete automaton of bar will be duplicated in each reference site. If the referenced automaton is large, `EmbedExpr` will significantly increase the number of states. `EmbedExpr` defines dependencies among states and no cyclic dependency is allowed.

* `CollapseExpr`, reference a nonterminal with the `!` modifier
  ```
  export foo = 'pre' !bar 'post'
  bar = [\u0300-\u034E]
  quz = 'meow' !bar 'meow'
  ```
  The final state of `'pre'` and the start state of `'post'` will be connected by a special directed arc. When exporting, an epsilon transition will be added from the tail of the arc to the start state of `bar`, others will be added from the final states of `bar` to the head of the arc. `CollapseExpr` behaves like function calls, however, the return address is not preserved (hence the name `CollapseExpr`) and the state may go to other call sites. In this example, the state may go to either `foo` or `quz` after traveling through `bar`, causing false positives.

* `CallExpr`, reference a nonterminal with the `&` modifier
  ```
  export foo = 'pre' &bar 'post'
  bar = '4'
  ```
  This is a refinement of `CollapseExpr`. Suppose state `&B` is contained in `A`'s definition (`A` calls `B`). `&B` will be represented as an pseudo arc (`u -> v`), where `u` is the state before `&B` and `v` is the state after `&B`. If arcs of `u` do not collide with arcs of `B`, the transition function will push `v` to the return stack if current state set contains `u` and there is no other transition. Note `B` is disconnected from `A`, which is different from the `CollapseExpr` case. The machine will transit on automaton `B` greedily. If there is no transition, it will pop a return address(`v` in this case) and jumps to it.

## Contrib

### Vim

Syntax highlighting, and a syntax checking plugin for Synaptics

```zsh
ln -sr contrib/vim/compiler/yanshi.vim ~/.vim/compiler/
ln -sr contrib/vim/ftdetect/yanshi.vim ~/.vim/ftdetect/
ln -sr contrib/vim/ftplugin/yanshi.vim ~/.vim/ftplugin/
ln -sr contrib/vim/syntax/yanshi.vim ~/.vim/syntax/
ln -sr contrib/vim/syntax_checker/yanshi ~/.vim/syntax_checker/
```

### Zsh

Command line completion

```
# ~/.zshrc
fpath=(~/.zsh $fpath)

# ln -sr contrib/zsh/_yanshi ~/.zsh/
```

## Internals

```
src
  common.{cc,hh}
  main.{cc,hh}
  syntax.{cc,hh}
  loader.{cc,hh}
  fsa.{cc,hh}
  fsa_anno.{cc,hh}
  compiler.{cc,hh}
  parser.y
  lexer.l
  location.cc
```

* Lex `lexer.l`
* Parse and generate a syntax tree `parser.y`
* `loader.cc`
  + Get a list of definitions
  + Recursively load for each `import`
  + Resolve references and associate uses to definitions
  + Build a dependency graph from `EmbedExpr`
  + Compile automaton for each nonterminal in topological order. `CollapseExpr` and `CallExpr` are represented by special directed arcs.
  + Generate code for `export` nonterminals, resolving `CollapseExpr` and `CallExpr`

### Finite state automaton

Each node of the syntax tree corresponds to an automaton. The parent builds an automaton from its children according to the semantics. The automaton of the parent may contain states from the automaton of one of the children, or it is a state introduced by the parent.

`assoc[i]` records the associative nodes in the automaton tree (which part of the syntax tree has associations with this state) and positions (start state, final state or inner state) for state `i`. It serves three purposes:

* Check which action should be triggered
* Look for inner states (neither start nor final) in the implementation of substring grammar
* Check whether it is associated to a `CallExpr` or `CollapseExpr`

### `CollapseExpr`

---

## File: README_CN.md

<h4 align="center">
  SafeLine - 雷池 - 不让黑客越过半步
</h4>



<h3 align="center">🏆 项目荣誉</h3>



## 👋 项目介绍

SafeLine，中文名 "雷池"，是一款简单好用, 效果突出的 **`Web 应用防火墙(WAF)`**，可以保护 Web 服务不受黑客攻击。

雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 `SQL 注入`、`XSS`、 `代码注入`、`命令注入`、`CRLF 注入`、`ldap 注入`、`xpath 注入`、`RCE`、`XXE`、`SSRF`、`路径遍历`、`后门`、`暴力破解`、`CC`、`爬虫` 等攻击。

#### 💡 工作原理



雷池通过阻断流向 Web 服务的恶意 HTTP 流量来保护 Web 服务。雷池作为反向代理接入网络，通过在 Web 服务前部署雷池，可在 Web 服务和互联网之间设置一道屏障。

雷池的核心功能如下:

- 防护 Web 攻击
- 防爬虫, 防扫描
- 前端代码动态加密
- 基于源 IP 的访问速率限制
- HTTP 访问控制

#### ⚡️ 项目截图

|  |  |
| ------------------------------------------------- | ------------------------------------------------- | 
|  |  | 

查看 [演示环境](https://demo.waf-ce.chaitin.cn:9443/)

## 🔥 核心能力

对于你的网站而言, 雷池可以实现如下效果:

- **`阻断 Web 攻击`**
  - 可以防御所有的 Web 攻击，例如 `SQL 注入`、`XSS`、`代码注入`、`操作系统命令注入`、`CRLF 注入`、`XXE`、`SSRF`、`路径遍历` 等等。
- **`限制访问频率`**
  - 限制用户的访问速率，让 Web 服务免遭 `CC 攻击`、`暴力破解`、`流量激增` 和其他类型的滥用。
- **`人机验证`**
  - 互联网上有来自真人用户的流量，但更多的是由爬虫, 漏洞扫描器, 蠕虫病毒, 漏洞利用程序等自动化程序发起的流量，开启雷池的人机验证功能后真人用户会被放行，恶意爬虫将会被阻断。
- **`身份认证`**
  - 雷池的 "身份认证" 功能可以很好的解决 "未授权访问" 漏洞，当用户访问您的网站时，需要输入您配置的用户名和密码信息，不持有认证信息的用户将被拒之门外。
- **`动态防护`**
  - 在用户浏览到的网页内容不变的情况下，将网页赋予动态特性，对 HTML 和 JavaScript 代码进行动态加密，确保每次访问时这些代码都以随机且独特的形态呈现。

#### 🧩 核心能力展示

|                               | Legitimate User                                     | Malicious User                                                   |
| ----------------------------- | --------------------------------------------------- | ---------------------------------------------------------------- | 
| **`阻断 Web 攻击`**            |        |  |
| **`限制访问频率`**             |        |  |
| **`人机验证`**                 |       |                      |
| **`身份认证`**                 |          |                         |
| **`HTML 动态防护`**            |  |               |
| **`JS 动态防护`**              |    |                 | 

## 🚀 上手指南

#### 📦 安装

查看 [安装雷池](https://docs.waf-ce.chaitin.cn/zh/%E4%B8%8A%E6%89%8B%E6%8C%87%E5%8D%97/%E5%AE%89%E8%A3%85%E9%9B%B7%E6%B1%A0)

#### ⚙️ 配置防护站点

查看 [快速配置](https://docs.waf-ce.chaitin.cn/zh/%E4%B8%8A%E6%89%8B%E6%8C%87%E5%8D%97/%E5%BF%AB%E9%80%9F%E9%85%8D%E7%BD%AE)

## 📋 更多信息

#### 防护效果测试

| Metric            | ModSecurity, Level 1 | CloudFlare           | 雷池, 平衡            | 雷池, 严格             |
| ----------------- | -------------------- | -------------------- | ---------------------- | --------------------- |
| 样本数量          | 33669                | 33669                | 33669                  | 33669                 |
| **检出率**        | 69.74%               | 10.70%               | 71.65%                 | **76.17%**            |
| **误报率**        | 17.58%               | 0.07%                | **0.07%**              | 0.22%                 |
| **准确率**        | 82.20%               | 98.40%               | **99.45%**             | 99.38%                |


#### 雷池可以投入生产使用吗

是的，已经有不少用户将雷池投入生产使用，截至目前

- [全球累计装机量已超过 40 万台](https://cyberpress.org/safeline-waf-reaches-400000-global-deployments/)
- 防护的网站数量超过 100 万个
- 每天清洗 HTTP 请求超过 300 亿次

#### 🌟 社区认可

- 获得 [HelloGitHub](https://hellogithub.com/en/repository/0d07cfe266af4c25ba3eadf2c3d06f50) **10.0/10** 评分
- 被 [awesome-selfhosted](https://github.com/awesome-selfhosted/awesome-selfhosted-data/blob/master/software/safeline.yml) 收录
- 被 [Cyber Press](https://cyberpress.org/safeline-waf-reaches-400000-global-deployments/) 评为 GitHub 上最受欢迎的开源 Web 应用防火墙

#### 🔌 生态集成

- [SafeLine MCP Server](./mcp_server/README.md)：支持通过 AI 辅助管理和控制雷池
- [Ingress-NGINX](./sdk/ingress-nginx/README.md)：保护 Kubernetes Ingress 流量
- [Kong Gateway](./sdk/kong/Readme.md)：保护经过 Kong 的 API 和服务

#### 🙋‍♂️ 用户社区

欢迎加入雷池 [社区微信群](/images/wechat.png) 进行技术交流。

也可以加入雷池 [Discord](https://discord.gg/SVnZGzHFvn) 来获取更多社区支持。


  <a target="_blank" href="/images/wechat.png"></a>
  <a target="_blank" href="https://discord.gg/SVnZGzHFvn"></a> &nbsp;
  <a target="_blank" href="https://x.com/safeline_waf"></a> &nbsp;


#### 💪 专业版

雷池专业版现已发布！查看 [社区版 vs 专业版](https://waf-ce.chaitin.cn/version)，选择适合你的版本。