SafeLine Documentation

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

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy SafeLine on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name safeline --restart always safeline-mcp:local
Configured Services & Ports
⚙️ mcp_server
image: safeline-mcp:local
🔌 Ports: ${MCP_PUBLISH_ADDRESS:-127.0.0.1}:${LISTEN_PORT:-5678}:${LISTEN_PORT:-5678}
docker-compose.yml
yaml (docker-compose.yml)
services:
  mcp_server:
    build: .
    image: safeline-mcp:local
    container_name: safeline-mcp
    restart: unless-stopped
    ports:
      - "${MCP_PUBLISH_ADDRESS:-127.0.0.1}:${LISTEN_PORT:-5678}:${LISTEN_PORT:-5678}"
    environment:
      LISTEN_ADDRESS: "0.0.0.0"
      LISTEN_PORT: "${LISTEN_PORT:-5678}"
      # Required because LISTEN_ADDRESS is not loopback.
      MCP_TLS_CERT: "${MCP_TLS_CERT:-}"
      MCP_TLS_KEY: "${MCP_TLS_KEY:-}"
      # Authentication is enabled by default. Only set MCP_AUTH_DISABLED=true
      # for a loopback-only deployment; a non-loopback listener without a token
      # is refused at startup.
      MCP_AUTH_DISABLED: "${MCP_AUTH_DISABLED:-}"
      MCP_AUTH_STATE_FILE: "/var/lib/safeline-mcp/auth.json"
    read_only: true
    security_opt:
      - no-new-privileges:true
    tmpfs:
      - /tmp:size=16m,mode=1777
    volumes:
      - type: bind
        source: ${SAFELINE_MCP_CONFIG_FILE:-./config.yaml}
        target: /etc/safeline-mcp/config.yaml
        read_only: true
        bind:
          create_host_path: false
      - type: bind
        source: ${SAFELINE_MCP_SECRETS_DIR:-./secrets}
        target: /run/secrets
        read_only: true
        bind:
          create_host_path: false
      - type: bind
        source: ${SAFELINE_MCP_STATE_DIR:-./state}
        target: /var/lib/safeline-mcp
        bind:
          create_host_path: false

File: README.md

SafeLine - Make your web apps secure

🏆 Achievements

👋 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

🔥 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]
中国大陆用户安装国际版可能会导致无法连接云服务,请查看 中文版安装文档

📦 Installing

Information on how to install SafeLine can be found in the Install Guide

⚙️ Protecting Web Apps

to see Configuration

📋 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.

🌟 Community Recognition

🔌 Ecosystem Integrations

🙋‍♂️ Community

Join our Discord to get community support, the core team members are identified by the STAFF role in Discord.

  • channel #feedback: for new features discussion.
  • channel #FAQ: for FAQ.
  • channel #general: 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.

 
 

💪 PRO Edition

SafeLine PRO is now available! Explore plans and pricing or start a 7-day trial.

📝 License

See LICENSE 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/[email protected]
go install google.golang.org/grpc/cmd/[email protected]

# 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/[email protected]
go install google.golang.org/grpc/cmd/[email protected]

# 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) that provides complete management and control capabilities for SafeLine WAF.


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 (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.

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

text
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
}
  1. [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
}
  1. 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



Name

Lua implementation of the T1K protocol for Chaitin/SafeLine Web Application Firewall.

Status

Production ready.

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, 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 ❌ ✅

* APISIX implements health check functionality for the chaitin-waf plugin. For more information, please see the chaitin-waf documentation.


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 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:

    text
    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.

    text
    % 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.

    text
    % 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

    text
    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)

    text
    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

    text
    # 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

    text
    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

    text
    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

    text
    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

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

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

Internals

text
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

SafeLine - 雷池 - 不让黑客越过半步

🏆 项目荣誉

👋 项目介绍

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 访问控制

⚡️ 项目截图

查看 演示环境

🔥 核心能力

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

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

🧩 核心能力展示

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

🚀 上手指南

📦 安装

查看 安装雷池

⚙️ 配置防护站点

查看 快速配置

📋 更多信息

防护效果测试

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%

雷池可以投入生产使用吗

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

🌟 社区认可

🔌 生态集成

🙋‍♂️ 用户社区

欢迎加入雷池 社区微信群 进行技术交流。

也可以加入雷池 Discord 来获取更多社区支持。


 
 

💪 专业版

雷池专业版现已发布!查看 社区版 vs 专业版,选择适合你的版本。