This commit is contained in:
commit
b6c038d5f5
|
|
@ -0,0 +1,176 @@
|
||||||
|
---
|
||||||
|
name: singboxed
|
||||||
|
description: "sing-box proxy platform specialist. Helps configure sing-box JSON configs, tune system settings (TUN, nftables, DNS), design routing rules, select protocols, and troubleshoot connectivity. /singboxed [topic] for help, /singboxed audit to review a config, /singboxed template <type> to generate configs."
|
||||||
|
user-invocable: true
|
||||||
|
argument-hint: "<audit|template|topic> [args]"
|
||||||
|
---
|
||||||
|
|
||||||
|
# sing-box Configuration Specialist
|
||||||
|
|
||||||
|
You are a sing-box expert (v1.13.x stable / v1.14.x alpha). You have deep knowledge of sing-box's configuration format, all supported protocols, routing engine, DNS resolution, TUN networking, and platform-specific system tuning.
|
||||||
|
|
||||||
|
## Setup — Load References
|
||||||
|
|
||||||
|
Before performing ANY operation, read the relevant reference files from `~/.claude/skills/singboxed/references/`:
|
||||||
|
|
||||||
|
1. **Always read**: `ref-overview.md` (config structure, protocol list, version info)
|
||||||
|
2. **For routing/rules**: `ref-routing.md`
|
||||||
|
3. **For DNS**: `ref-dns.md`
|
||||||
|
4. **For TUN/system**: `ref-tun-system.md`
|
||||||
|
5. **For protocols**: `ref-protocols.md`
|
||||||
|
6. **For TLS/transport**: `ref-tls-transport.md`
|
||||||
|
|
||||||
|
Read files in parallel. Only load what's relevant to the user's question.
|
||||||
|
|
||||||
|
## Argument Parsing
|
||||||
|
|
||||||
|
Parse the user's arguments after `/singboxed`:
|
||||||
|
|
||||||
|
- **No arguments**: Show capabilities summary and ask what they need help with
|
||||||
|
- **`audit`** or **`audit <path>`**: Validate and review a sing-box config file
|
||||||
|
- **`template client`**: Generate a client proxy config
|
||||||
|
- **`template server`**: Generate a server config
|
||||||
|
- **`template tun`**: Generate a TUN transparent proxy config
|
||||||
|
- **`template dns`**: Generate a DNS-focused config
|
||||||
|
- **`template wireguard`**: Generate a WireGuard endpoint config
|
||||||
|
- **`template urltest`**: Generate auto-select proxy group config
|
||||||
|
- **Any other text**: Treat as a question/topic about sing-box configuration
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Audit Procedure
|
||||||
|
|
||||||
|
When auditing a config:
|
||||||
|
|
||||||
|
### Step 1 — Load Config
|
||||||
|
|
||||||
|
Read the config file (default: look for `config.json`, `sing-box.json`, or `*.json` in cwd).
|
||||||
|
|
||||||
|
### Step 2 — Validate Structure
|
||||||
|
|
||||||
|
Check for:
|
||||||
|
|
||||||
|
| Check | Severity | Description |
|
||||||
|
|-------|----------|-------------|
|
||||||
|
| STRUCT-01 | CRITICAL | Valid JSON with correct top-level keys |
|
||||||
|
| STRUCT-02 | CRITICAL | All inbound/outbound tags are unique |
|
||||||
|
| STRUCT-03 | CRITICAL | Route rules reference existing outbound tags |
|
||||||
|
| STRUCT-04 | CRITICAL | DNS rules reference existing DNS server tags |
|
||||||
|
| STRUCT-05 | WARNING | No deprecated fields (geoip/geosite → rule_set, legacy DNS format) |
|
||||||
|
| STRUCT-06 | WARNING | No removed features (dns outbound type removed in 1.13.0) |
|
||||||
|
|
||||||
|
### Step 3 — Check Security
|
||||||
|
|
||||||
|
| Check | Severity | Description |
|
||||||
|
|-------|----------|-------------|
|
||||||
|
| SEC-01 | CRITICAL | No plaintext passwords in non-local configs |
|
||||||
|
| SEC-02 | WARNING | TLS enabled for remote connections where supported |
|
||||||
|
| SEC-03 | WARNING | Clash API `secret` set if `external_controller` is non-localhost |
|
||||||
|
| SEC-04 | INFO | ECH or Reality used for anti-censorship setups |
|
||||||
|
| SEC-05 | WARNING | `strict_route` enabled when using TUN with `auto_route` |
|
||||||
|
|
||||||
|
### Step 4 — Check Performance
|
||||||
|
|
||||||
|
| Check | Severity | Description |
|
||||||
|
|-------|----------|-------------|
|
||||||
|
| PERF-01 | WARNING | DNS cache enabled (not disabled) |
|
||||||
|
| PERF-02 | INFO | Multiplex (mux) configured for high-throughput scenarios |
|
||||||
|
| PERF-03 | INFO | `gvisor` or `mixed` stack for TUN (not `system` unless needed) |
|
||||||
|
| PERF-04 | WARNING | `auto_detect_interface` or `default_interface` set to prevent routing loops |
|
||||||
|
| PERF-05 | INFO | `urltest` interval not too aggressive (≥1m recommended) |
|
||||||
|
|
||||||
|
### Step 5 — Check Routing Logic
|
||||||
|
|
||||||
|
| Check | Severity | Description |
|
||||||
|
|-------|----------|-------------|
|
||||||
|
| ROUTE-01 | WARNING | `final` outbound specified in route |
|
||||||
|
| ROUTE-02 | WARNING | DNS hijack rule present when using TUN |
|
||||||
|
| ROUTE-03 | INFO | Private IP bypass rule for LAN access |
|
||||||
|
| ROUTE-04 | INFO | Rule sets preferred over inline geoip/geosite |
|
||||||
|
| ROUTE-05 | WARNING | `sniff` action configured for protocol detection |
|
||||||
|
|
||||||
|
### Step 6 — Report
|
||||||
|
|
||||||
|
```
|
||||||
|
═══ sing-box Config Audit ═══
|
||||||
|
File: <path>
|
||||||
|
Version compatibility: v1.X.X+
|
||||||
|
|
||||||
|
CRITICAL: N issues
|
||||||
|
WARNING: N issues
|
||||||
|
INFO: N suggestions
|
||||||
|
|
||||||
|
Issues:
|
||||||
|
[SEVERITY] [CHECK-ID]: description
|
||||||
|
→ Fix: suggested remediation
|
||||||
|
|
||||||
|
Recommendations:
|
||||||
|
1. Most impactful improvement
|
||||||
|
2. ...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Topic Help
|
||||||
|
|
||||||
|
When answering questions about sing-box, follow these principles:
|
||||||
|
|
||||||
|
### Always Provide Complete JSON
|
||||||
|
|
||||||
|
Never give partial snippets without context. Show where the JSON fits in the overall config structure. Use comments to explain non-obvious fields.
|
||||||
|
|
||||||
|
### Version Awareness
|
||||||
|
|
||||||
|
- Note when features require specific versions (e.g., `anytls` requires v1.12.0+, endpoints require v1.11.0+)
|
||||||
|
- Flag deprecated features and suggest modern alternatives
|
||||||
|
- Key deprecations:
|
||||||
|
- `geoip`/`geosite` → `rule_set` (since 1.8.0)
|
||||||
|
- `dns` outbound → `hijack-dns` rule action (removed in 1.13.0)
|
||||||
|
- Per-inbound `sniff`/`domain_strategy` → route rule actions (since 1.11.0)
|
||||||
|
- WireGuard outbound → WireGuard endpoint (since 1.11.0)
|
||||||
|
- ACME in TLS → `certificate_providers` (since 1.14.0)
|
||||||
|
|
||||||
|
### Platform-Specific Guidance
|
||||||
|
|
||||||
|
When the user's platform is known, tailor advice:
|
||||||
|
- **Linux**: TUN + auto_route + auto_redirect (nftables), iptables redirect/tproxy, routing marks, UID filtering, systemd service
|
||||||
|
- **macOS**: TUN + auto_route, platform HTTP proxy, find_neighbor
|
||||||
|
- **Windows**: TUN + auto_route + strict_route (WFP-based)
|
||||||
|
- **Android**: TUN with include/exclude_package, android_user filtering
|
||||||
|
- **iOS**: TUN with platform HTTP proxy, network strategy for cellular/wifi
|
||||||
|
|
||||||
|
### System Tuning Topics
|
||||||
|
|
||||||
|
When asked about system settings, cover:
|
||||||
|
- **nftables/iptables**: redirect vs tproxy modes, mark-based routing, auto_redirect marks
|
||||||
|
- **iproute2**: custom table index, rule index, policy routing
|
||||||
|
- **DNS**: system resolver configuration, DNS hijacking setup
|
||||||
|
- **Network namespaces**: netns support for containerized setups
|
||||||
|
- **systemd**: service file, auto-restart, capabilities (CAP_NET_ADMIN, CAP_NET_RAW)
|
||||||
|
- **sysctl**: IP forwarding, rp_filter, TCP optimizations
|
||||||
|
- **File descriptors**: ulimit for high-connection scenarios
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template Generation
|
||||||
|
|
||||||
|
When generating templates, read the appropriate template from `~/.claude/skills/singboxed/templates/` and customize based on user requirements. Ask clarifying questions if needed:
|
||||||
|
|
||||||
|
- Protocol preference
|
||||||
|
- Client or server role
|
||||||
|
- Platform (Linux/macOS/Windows/Android/iOS)
|
||||||
|
- Use case (bypass censorship, privacy, LAN proxy, VPN replacement)
|
||||||
|
- Whether they need TUN (transparent proxy) or explicit proxy (SOCKS/HTTP)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key sing-box Concepts to Always Remember
|
||||||
|
|
||||||
|
1. **Tags are identifiers** — inbound/outbound/DNS server tags must be unique and are referenced by route rules
|
||||||
|
2. **Route rules are ordered** — first match wins; `final` is the fallback
|
||||||
|
3. **Rule actions replace inbound options** — sniffing, DNS resolution, domain strategy are now route rule actions (v1.11.0+)
|
||||||
|
4. **`auto_detect_interface: true`** is almost always needed in route to prevent routing loops
|
||||||
|
5. **DNS rules and route rules are separate** — DNS rules route DNS queries to DNS servers; route rules route connections to outbounds
|
||||||
|
6. **`hijack-dns` action** replaces the old `dns` outbound type for intercepting DNS in TUN mode
|
||||||
|
7. **Listable fields** accept both single values and arrays (e.g., `"address": "172.19.0.1/30"` or `"address": ["172.19.0.1/30", "fdfe:dcba:9876::1/126"]`)
|
||||||
|
8. **Rule sets** come in `source` (JSON) and `binary` (.srs) formats; remote rule sets auto-update
|
||||||
|
|
@ -0,0 +1,363 @@
|
||||||
|
# sing-box DNS Reference
|
||||||
|
|
||||||
|
## DNS Configuration Structure
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dns": {
|
||||||
|
"servers": [],
|
||||||
|
"rules": [],
|
||||||
|
"final": "dns-default",
|
||||||
|
"strategy": "",
|
||||||
|
"disable_cache": false,
|
||||||
|
"disable_expire": false,
|
||||||
|
"independent_cache": false,
|
||||||
|
"cache_capacity": 0,
|
||||||
|
"reverse_mapping": false,
|
||||||
|
"client_subnet": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## DNS Server Types (13)
|
||||||
|
|
||||||
|
### `local` — System DNS resolver
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "local",
|
||||||
|
"tag": "dns-local"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `udp` — Plain UDP DNS
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "udp",
|
||||||
|
"tag": "dns-udp",
|
||||||
|
"server": "8.8.8.8",
|
||||||
|
"server_port": 53
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `tcp` — Plain TCP DNS
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "tcp",
|
||||||
|
"tag": "dns-tcp",
|
||||||
|
"server": "8.8.8.8",
|
||||||
|
"server_port": 53
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `tls` — DNS over TLS (DoT)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "tls",
|
||||||
|
"tag": "dns-dot",
|
||||||
|
"server": "dns.google",
|
||||||
|
"server_port": 853
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `quic` — DNS over QUIC (DoQ)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "quic",
|
||||||
|
"tag": "dns-doq",
|
||||||
|
"server": "dns.adguard-dns.com",
|
||||||
|
"server_port": 853
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `https` — DNS over HTTPS (DoH)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "https",
|
||||||
|
"tag": "dns-doh",
|
||||||
|
"server": "dns.google",
|
||||||
|
"server_port": 443,
|
||||||
|
"path": "/dns-query"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `h3` — DNS over HTTP/3
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "h3",
|
||||||
|
"tag": "dns-h3",
|
||||||
|
"server": "dns.google",
|
||||||
|
"server_port": 443,
|
||||||
|
"path": "/dns-query"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `dhcp` — DHCP-provided DNS
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "dhcp",
|
||||||
|
"tag": "dns-dhcp",
|
||||||
|
"interface": "eth0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `fakeip` — Fake IP DNS
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "fakeip",
|
||||||
|
"tag": "dns-fakeip",
|
||||||
|
"inet4_range": "198.18.0.0/15",
|
||||||
|
"inet6_range": "fc00::/18"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `hosts` — Static hosts file
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "hosts",
|
||||||
|
"tag": "dns-hosts",
|
||||||
|
"path": "/etc/hosts"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `rcode` — Return specific response code
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "rcode",
|
||||||
|
"tag": "dns-block",
|
||||||
|
"rcode": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Rcodes: `success`, `format_error`, `server_failure`, `name_error` (NXDOMAIN), `not_implemented`, `refused`
|
||||||
|
|
||||||
|
### `tailscale` — Tailscale MagicDNS
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "tailscale",
|
||||||
|
"tag": "dns-tailscale"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `resolved` — Reference to resolved service
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "resolved",
|
||||||
|
"tag": "dns-resolved",
|
||||||
|
"service_tag": "resolved-service"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## DNS Server Common Fields
|
||||||
|
|
||||||
|
All DNS server types support:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "...",
|
||||||
|
"tag": "unique-tag",
|
||||||
|
"detour": "outbound-tag",
|
||||||
|
"domain_resolver": {
|
||||||
|
"server": "bootstrap-dns-tag",
|
||||||
|
"strategy": "prefer_ipv4"
|
||||||
|
},
|
||||||
|
"strategy": "prefer_ipv4",
|
||||||
|
"disable_cache": false,
|
||||||
|
"disable_expire": false,
|
||||||
|
"independent_cache": false,
|
||||||
|
"cache_capacity": 0,
|
||||||
|
"rewrite_ttl": 0,
|
||||||
|
"client_subnet": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- **`detour`**: Outbound used for DNS transport connection (e.g., send DoH queries through proxy)
|
||||||
|
- **`domain_resolver`**: Bootstrap DNS for resolving the DNS server's own domain name
|
||||||
|
- **`strategy`**: `prefer_ipv4`, `prefer_ipv6`, `ipv4_only`, `ipv6_only`
|
||||||
|
- **`client_subnet`**: EDNS Client Subnet for geo-aware responses
|
||||||
|
|
||||||
|
## DNS Rules
|
||||||
|
|
||||||
|
DNS rules route queries to specific DNS servers. Same match criteria as route rules plus:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dns": {
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"query_type": ["A", "AAAA"],
|
||||||
|
"domain_suffix": [".cn"],
|
||||||
|
"action": "route",
|
||||||
|
"server": "dns-cn"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### DNS Rule Actions
|
||||||
|
|
||||||
|
#### `route` — Route to DNS server
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "route",
|
||||||
|
"server": "dns-server-tag",
|
||||||
|
"strategy": "prefer_ipv4",
|
||||||
|
"disable_cache": false,
|
||||||
|
"rewrite_ttl": 0,
|
||||||
|
"client_subnet": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `route-options` — Modify DNS options
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "route-options",
|
||||||
|
"disable_cache": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `reject` — Reject DNS query
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "reject"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `predefined` — Return predefined response
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "predefined",
|
||||||
|
"rcode": "success",
|
||||||
|
"answer": [],
|
||||||
|
"ns": [],
|
||||||
|
"extra": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common DNS Patterns
|
||||||
|
|
||||||
|
### Pattern: Split DNS (domestic + foreign)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dns": {
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"type": "https",
|
||||||
|
"tag": "dns-google",
|
||||||
|
"server": "dns.google",
|
||||||
|
"server_port": 443,
|
||||||
|
"path": "/dns-query",
|
||||||
|
"detour": "proxy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "https",
|
||||||
|
"tag": "dns-alidns",
|
||||||
|
"server": "dns.alidns.com",
|
||||||
|
"server_port": 443,
|
||||||
|
"path": "/dns-query",
|
||||||
|
"detour": "direct"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "udp",
|
||||||
|
"tag": "dns-bootstrap",
|
||||||
|
"server": "223.5.5.5"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"rule_set": ["geosite-cn"],
|
||||||
|
"action": "route",
|
||||||
|
"server": "dns-alidns"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"final": "dns-google"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern: FakeIP for TUN
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dns": {
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"type": "https",
|
||||||
|
"tag": "dns-remote",
|
||||||
|
"server": "dns.google",
|
||||||
|
"path": "/dns-query",
|
||||||
|
"detour": "proxy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fakeip",
|
||||||
|
"tag": "dns-fakeip",
|
||||||
|
"inet4_range": "198.18.0.0/15",
|
||||||
|
"inet6_range": "fc00::/18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "udp",
|
||||||
|
"tag": "dns-local",
|
||||||
|
"server": "223.5.5.5"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"rule_set": ["geosite-cn"],
|
||||||
|
"action": "route",
|
||||||
|
"server": "dns-local"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"query_type": ["A", "AAAA"],
|
||||||
|
"action": "route",
|
||||||
|
"server": "dns-fakeip"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"final": "dns-remote"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern: Ad-blocking DNS
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dns": {
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"rule_set": ["adblock-domains"],
|
||||||
|
"action": "predefined",
|
||||||
|
"rcode": "name_error"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern: DNS Bootstrap Chain
|
||||||
|
When a DoH server needs DNS to resolve its own hostname:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"type": "https",
|
||||||
|
"tag": "dns-secure",
|
||||||
|
"server": "dns.google",
|
||||||
|
"domain_resolver": {
|
||||||
|
"server": "dns-bootstrap",
|
||||||
|
"strategy": "ipv4_only"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "udp",
|
||||||
|
"tag": "dns-bootstrap",
|
||||||
|
"server": "8.8.8.8"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern: EDNS Client Subnet
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "https",
|
||||||
|
"tag": "dns-with-subnet",
|
||||||
|
"server": "dns.google",
|
||||||
|
"client_subnet": "1.2.3.0/24"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,171 @@
|
||||||
|
# sing-box Configuration Overview
|
||||||
|
|
||||||
|
## Version Info
|
||||||
|
- **Stable**: v1.13.3 (March 2026)
|
||||||
|
- **Alpha**: v1.14.0-alpha.6
|
||||||
|
- **Repository**: github.com/SagerNet/sing-box (31.8k stars)
|
||||||
|
- **Docs**: https://sing-box.sagernet.org
|
||||||
|
|
||||||
|
## Top-Level Config Structure
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"$schema": "",
|
||||||
|
"log": {
|
||||||
|
"disabled": false,
|
||||||
|
"level": "info",
|
||||||
|
"output": "",
|
||||||
|
"timestamp": true
|
||||||
|
},
|
||||||
|
"dns": {},
|
||||||
|
"ntp": {
|
||||||
|
"enabled": false,
|
||||||
|
"server": "time.apple.com",
|
||||||
|
"server_port": 123,
|
||||||
|
"interval": "30m"
|
||||||
|
},
|
||||||
|
"certificate": {},
|
||||||
|
"certificate_providers": [],
|
||||||
|
"endpoints": [],
|
||||||
|
"inbounds": [],
|
||||||
|
"outbounds": [],
|
||||||
|
"route": {},
|
||||||
|
"services": [],
|
||||||
|
"experimental": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## All Inbound Protocol Types (17)
|
||||||
|
|
||||||
|
| Type | Description | Platform |
|
||||||
|
|------|-------------|----------|
|
||||||
|
| `direct` | Direct/injectable forwarding | All |
|
||||||
|
| `mixed` | SOCKS + HTTP combined proxy | All |
|
||||||
|
| `socks` | SOCKS4/4a/5 proxy server | All |
|
||||||
|
| `http` | HTTP/HTTPS proxy server | All |
|
||||||
|
| `shadowsocks` | Shadowsocks server (incl. 2022 ciphers) | All |
|
||||||
|
| `vmess` | VMess protocol server | All |
|
||||||
|
| `vless` | VLESS server (XTLS-Vision flow) | All |
|
||||||
|
| `trojan` | Trojan server with fallback | All |
|
||||||
|
| `naive` | NaiveProxy server | All |
|
||||||
|
| `hysteria` | Hysteria QUIC-based server | All |
|
||||||
|
| `hysteria2` | Hysteria2 with masquerade | All |
|
||||||
|
| `shadowtls` | ShadowTLS server | All |
|
||||||
|
| `tuic` | TUIC QUIC-based server | All |
|
||||||
|
| `anytls` | AnyTLS server (v1.12.0+) | All |
|
||||||
|
| `tun` | TUN virtual interface | All |
|
||||||
|
| `redirect` | TCP redirect transparent proxy | Linux |
|
||||||
|
| `tproxy` | Full transparent proxy (TCP+UDP) | Linux |
|
||||||
|
|
||||||
|
## All Outbound Protocol Types (20)
|
||||||
|
|
||||||
|
| Type | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `direct` | Direct connection |
|
||||||
|
| `block` | Block/reject traffic |
|
||||||
|
| `socks` | SOCKS proxy client |
|
||||||
|
| `http` | HTTP proxy client |
|
||||||
|
| `shadowsocks` | Shadowsocks client |
|
||||||
|
| `vmess` | VMess client |
|
||||||
|
| `vless` | VLESS client (XTLS-Vision) |
|
||||||
|
| `trojan` | Trojan client |
|
||||||
|
| `naive` | NaiveProxy client |
|
||||||
|
| `wireguard` | WireGuard (deprecated → endpoint) |
|
||||||
|
| `hysteria` | Hysteria client |
|
||||||
|
| `hysteria2` | Hysteria2 client (port hopping) |
|
||||||
|
| `shadowtls` | ShadowTLS client |
|
||||||
|
| `tuic` | TUIC client |
|
||||||
|
| `anytls` | AnyTLS client (v1.12.0+) |
|
||||||
|
| `tor` | Tor network client |
|
||||||
|
| `ssh` | SSH tunnel client |
|
||||||
|
| `dns` | DNS outbound (removed in 1.13.0) |
|
||||||
|
| `selector` | Manual proxy selection group |
|
||||||
|
| `urltest` | Auto latency-based selection group |
|
||||||
|
|
||||||
|
## Endpoint Types
|
||||||
|
|
||||||
|
| Type | Description | Since |
|
||||||
|
|------|-------------|-------|
|
||||||
|
| `wireguard` | WireGuard VPN endpoint (replaces outbound) | v1.11.0 |
|
||||||
|
| `tailscale` | Tailscale integration | v1.11.0 |
|
||||||
|
|
||||||
|
## Experimental Section
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"experimental": {
|
||||||
|
"cache_file": {
|
||||||
|
"enabled": true,
|
||||||
|
"path": "cache.db",
|
||||||
|
"cache_id": "",
|
||||||
|
"store_fakeip": false,
|
||||||
|
"store_rdrc": false,
|
||||||
|
"rdrc_timeout": "7d"
|
||||||
|
},
|
||||||
|
"clash_api": {
|
||||||
|
"external_controller": "127.0.0.1:9090",
|
||||||
|
"external_ui": "",
|
||||||
|
"external_ui_download_url": "",
|
||||||
|
"external_ui_download_detour": "",
|
||||||
|
"secret": "",
|
||||||
|
"default_mode": ""
|
||||||
|
},
|
||||||
|
"v2ray_api": {
|
||||||
|
"listen": "127.0.0.1:8080",
|
||||||
|
"stats": {
|
||||||
|
"enabled": true,
|
||||||
|
"inbounds": ["in-tag"],
|
||||||
|
"outbounds": ["out-tag"],
|
||||||
|
"users": ["user"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Services (v1.13.0+)
|
||||||
|
|
||||||
|
Background services configured in the `services` array:
|
||||||
|
- **resolved** — Built-in DNS resolver service
|
||||||
|
- **ccm** — Client Configuration Manager
|
||||||
|
- **ocm** — Outbound Configuration Manager
|
||||||
|
- **ssmapi** — SSM API service
|
||||||
|
- **derp** — DERP relay service
|
||||||
|
- **oom_killer** — OOM killer service
|
||||||
|
|
||||||
|
## CLI Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sing-box run -c config.json # Run with config
|
||||||
|
sing-box run -C /etc/sing-box/ # Run with config directory (merges all .json)
|
||||||
|
sing-box check -c config.json # Validate config
|
||||||
|
sing-box format -c config.json -w # Format config (pretty-print, -w writes back)
|
||||||
|
sing-box merge output.json -C dir/ # Merge multiple configs into one
|
||||||
|
sing-box version # Show version
|
||||||
|
sing-box generate tls-keypair # Generate TLS key pair
|
||||||
|
sing-box generate reality-keypair # Generate Reality key pair
|
||||||
|
sing-box generate rand --base64 32 # Generate random bytes
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Deprecations Timeline
|
||||||
|
|
||||||
|
| Version | Deprecated | Replacement |
|
||||||
|
|---------|-----------|-------------|
|
||||||
|
| v1.8.0 | `geoip`, `geosite` databases | `rule_set` (local/remote) |
|
||||||
|
| v1.11.0 | Inbound `sniff`, `domain_strategy` | Route rule actions |
|
||||||
|
| v1.11.0 | WireGuard outbound | WireGuard endpoint |
|
||||||
|
| v1.11.0 | Separate `inet4_address`/`inet6_address` | Unified `address` |
|
||||||
|
| v1.13.0 | `dns` outbound type | `hijack-dns` rule action |
|
||||||
|
| v1.14.0 | ACME in TLS inbound | `certificate_providers` |
|
||||||
|
|
||||||
|
## Shadowsocks Cipher Methods
|
||||||
|
|
||||||
|
**Modern (recommended):**
|
||||||
|
- `2022-blake3-aes-128-gcm`
|
||||||
|
- `2022-blake3-aes-256-gcm`
|
||||||
|
- `2022-blake3-chacha20-poly1305`
|
||||||
|
|
||||||
|
**Legacy:**
|
||||||
|
- `aes-128-gcm`, `aes-192-gcm`, `aes-256-gcm`
|
||||||
|
- `chacha20-ietf-poly1305`, `xchacha20-ietf-poly1305`
|
||||||
|
- `none` (no encryption)
|
||||||
|
|
@ -0,0 +1,409 @@
|
||||||
|
# sing-box Protocol Reference
|
||||||
|
|
||||||
|
## Shadowsocks
|
||||||
|
|
||||||
|
### Client
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "shadowsocks",
|
||||||
|
"tag": "ss-out",
|
||||||
|
"server": "server.example.com",
|
||||||
|
"server_port": 8388,
|
||||||
|
"method": "2022-blake3-aes-256-gcm",
|
||||||
|
"password": "base64-encoded-key",
|
||||||
|
"plugin": "",
|
||||||
|
"plugin_opts": "",
|
||||||
|
"network": "tcp",
|
||||||
|
"udp_over_tcp": false,
|
||||||
|
"multiplex": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Server
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "shadowsocks",
|
||||||
|
"tag": "ss-in",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": 8388,
|
||||||
|
"method": "2022-blake3-aes-256-gcm",
|
||||||
|
"password": "base64-encoded-key",
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"name": "user1",
|
||||||
|
"password": "user-key"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Key generation:
|
||||||
|
```bash
|
||||||
|
# For 2022-blake3-aes-256-gcm (32 bytes)
|
||||||
|
sing-box generate rand --base64 32
|
||||||
|
# For 2022-blake3-aes-128-gcm (16 bytes)
|
||||||
|
sing-box generate rand --base64 16
|
||||||
|
```
|
||||||
|
|
||||||
|
## VMess
|
||||||
|
|
||||||
|
### Client
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "vmess",
|
||||||
|
"tag": "vmess-out",
|
||||||
|
"server": "server.example.com",
|
||||||
|
"server_port": 443,
|
||||||
|
"uuid": "uuid-here",
|
||||||
|
"security": "auto",
|
||||||
|
"alter_id": 0,
|
||||||
|
"global_padding": true,
|
||||||
|
"authenticated_length": true,
|
||||||
|
"tls": {},
|
||||||
|
"transport": {},
|
||||||
|
"multiplex": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Server
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "vmess",
|
||||||
|
"tag": "vmess-in",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": 443,
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"name": "user1",
|
||||||
|
"uuid": "uuid-here",
|
||||||
|
"alterId": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tls": {},
|
||||||
|
"transport": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## VLESS
|
||||||
|
|
||||||
|
### Client
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "vless",
|
||||||
|
"tag": "vless-out",
|
||||||
|
"server": "server.example.com",
|
||||||
|
"server_port": 443,
|
||||||
|
"uuid": "uuid-here",
|
||||||
|
"flow": "xtls-rprx-vision",
|
||||||
|
"tls": {
|
||||||
|
"enabled": true,
|
||||||
|
"server_name": "example.com",
|
||||||
|
"utls": {
|
||||||
|
"enabled": true,
|
||||||
|
"fingerprint": "chrome"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"transport": {},
|
||||||
|
"multiplex": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Server
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "vless",
|
||||||
|
"tag": "vless-in",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": 443,
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"name": "user1",
|
||||||
|
"uuid": "uuid-here",
|
||||||
|
"flow": "xtls-rprx-vision"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tls": {},
|
||||||
|
"transport": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Trojan
|
||||||
|
|
||||||
|
### Client
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "trojan",
|
||||||
|
"tag": "trojan-out",
|
||||||
|
"server": "server.example.com",
|
||||||
|
"server_port": 443,
|
||||||
|
"password": "password",
|
||||||
|
"tls": {
|
||||||
|
"enabled": true,
|
||||||
|
"server_name": "example.com"
|
||||||
|
},
|
||||||
|
"transport": {},
|
||||||
|
"multiplex": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Server
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "trojan",
|
||||||
|
"tag": "trojan-in",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": 443,
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"name": "user1",
|
||||||
|
"password": "password"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tls": {},
|
||||||
|
"fallback": {
|
||||||
|
"server": "127.0.0.1",
|
||||||
|
"server_port": 8080
|
||||||
|
},
|
||||||
|
"fallback_for_alpn": {
|
||||||
|
"h2": {
|
||||||
|
"server": "127.0.0.1",
|
||||||
|
"server_port": 8081
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hysteria2
|
||||||
|
|
||||||
|
### Client
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "hysteria2",
|
||||||
|
"tag": "hy2-out",
|
||||||
|
"server": "server.example.com",
|
||||||
|
"server_port": 443,
|
||||||
|
"up_mbps": 100,
|
||||||
|
"down_mbps": 200,
|
||||||
|
"password": "password",
|
||||||
|
"obfs": {
|
||||||
|
"type": "salamander",
|
||||||
|
"password": "obfs-password"
|
||||||
|
},
|
||||||
|
"tls": {
|
||||||
|
"enabled": true,
|
||||||
|
"server_name": "example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Server
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "hysteria2",
|
||||||
|
"tag": "hy2-in",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": 443,
|
||||||
|
"up_mbps": 0,
|
||||||
|
"down_mbps": 0,
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"name": "user1",
|
||||||
|
"password": "password"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"obfs": {
|
||||||
|
"type": "salamander",
|
||||||
|
"password": "obfs-password"
|
||||||
|
},
|
||||||
|
"masquerade": "https://example.com",
|
||||||
|
"tls": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## TUIC
|
||||||
|
|
||||||
|
### Client
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "tuic",
|
||||||
|
"tag": "tuic-out",
|
||||||
|
"server": "server.example.com",
|
||||||
|
"server_port": 443,
|
||||||
|
"uuid": "uuid-here",
|
||||||
|
"password": "password",
|
||||||
|
"congestion_control": "bbr",
|
||||||
|
"udp_relay_mode": "quic",
|
||||||
|
"zero_rtt_handshake": false,
|
||||||
|
"heartbeat": "10s",
|
||||||
|
"tls": {
|
||||||
|
"enabled": true,
|
||||||
|
"server_name": "example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Congestion control: `cubic` (default), `new_reno`, `bbr`
|
||||||
|
UDP relay: `native` (default), `quic`
|
||||||
|
|
||||||
|
## ShadowTLS
|
||||||
|
|
||||||
|
### Client (chained with another outbound)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "shadowtls",
|
||||||
|
"tag": "shadowtls-out",
|
||||||
|
"server": "server.example.com",
|
||||||
|
"server_port": 443,
|
||||||
|
"version": 3,
|
||||||
|
"password": "password",
|
||||||
|
"tls": {
|
||||||
|
"enabled": true,
|
||||||
|
"server_name": "www.microsoft.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Chaining ShadowTLS + Shadowsocks
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"type": "shadowsocks",
|
||||||
|
"tag": "ss-out",
|
||||||
|
"detour": "shadowtls-out",
|
||||||
|
"method": "2022-blake3-aes-256-gcm",
|
||||||
|
"password": "ss-key"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "shadowtls",
|
||||||
|
"tag": "shadowtls-out",
|
||||||
|
"server": "server.example.com",
|
||||||
|
"server_port": 443,
|
||||||
|
"version": 3,
|
||||||
|
"password": "stls-password",
|
||||||
|
"tls": {
|
||||||
|
"enabled": true,
|
||||||
|
"server_name": "www.microsoft.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## AnyTLS (v1.12.0+)
|
||||||
|
|
||||||
|
### Client
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "anytls",
|
||||||
|
"tag": "anytls-out",
|
||||||
|
"server": "server.example.com",
|
||||||
|
"server_port": 443,
|
||||||
|
"password": "password",
|
||||||
|
"idle_timeout": "15m",
|
||||||
|
"min_idle_session": 2,
|
||||||
|
"padding_scheme": "",
|
||||||
|
"tls": {
|
||||||
|
"enabled": true,
|
||||||
|
"server_name": "example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## WireGuard (Endpoint)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"type": "wireguard",
|
||||||
|
"tag": "wg-ep",
|
||||||
|
"system": false,
|
||||||
|
"name": "wg0",
|
||||||
|
"mtu": 1420,
|
||||||
|
"address": [
|
||||||
|
"10.0.0.2/32",
|
||||||
|
"fd00::2/128"
|
||||||
|
],
|
||||||
|
"private_key": "private-key-base64",
|
||||||
|
"listen_port": 51820,
|
||||||
|
"peers": [
|
||||||
|
{
|
||||||
|
"address": "server.example.com",
|
||||||
|
"port": 51820,
|
||||||
|
"public_key": "peer-public-key-base64",
|
||||||
|
"pre_shared_key": "",
|
||||||
|
"allowed_ips": ["0.0.0.0/0", "::/0"],
|
||||||
|
"persistent_keepalive_interval": "25s",
|
||||||
|
"reserved": [0, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## SSH Tunnel
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "ssh",
|
||||||
|
"tag": "ssh-out",
|
||||||
|
"server": "server.example.com",
|
||||||
|
"server_port": 22,
|
||||||
|
"user": "username",
|
||||||
|
"password": "password",
|
||||||
|
"private_key": "",
|
||||||
|
"private_key_path": "~/.ssh/id_ed25519",
|
||||||
|
"private_key_passphrase": "",
|
||||||
|
"host_key_algorithms": [],
|
||||||
|
"client_version": "SSH-2.0-OpenSSH_8.9"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Selector (Manual Proxy Group)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "selector",
|
||||||
|
"tag": "proxy",
|
||||||
|
"outbounds": ["hy2-hk", "vless-jp", "ss-us", "direct"],
|
||||||
|
"default": "hy2-hk",
|
||||||
|
"interrupt_exist_connections": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## URLTest (Auto Proxy Group)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "urltest",
|
||||||
|
"tag": "auto",
|
||||||
|
"outbounds": ["hy2-hk", "vless-jp", "ss-us"],
|
||||||
|
"url": "https://www.gstatic.com/generate_204",
|
||||||
|
"interval": "3m",
|
||||||
|
"tolerance": 50,
|
||||||
|
"idle_timeout": "30m",
|
||||||
|
"interrupt_exist_connections": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Multiplex (Mux) — Shared Options
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"multiplex": {
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "h2mux",
|
||||||
|
"max_connections": 4,
|
||||||
|
"min_streams": 4,
|
||||||
|
"max_streams": 0,
|
||||||
|
"padding": true,
|
||||||
|
"brutal": {
|
||||||
|
"enabled": true,
|
||||||
|
"up_mbps": 100,
|
||||||
|
"down_mbps": 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Protocols: `smux`, `yamux`, `h2mux` (default, recommended)
|
||||||
|
|
@ -0,0 +1,316 @@
|
||||||
|
# sing-box Routing Reference
|
||||||
|
|
||||||
|
## Route Options
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"route": {
|
||||||
|
"rules": [],
|
||||||
|
"rule_set": [],
|
||||||
|
"final": "direct",
|
||||||
|
"auto_detect_interface": true,
|
||||||
|
"override_android_vpn": false,
|
||||||
|
"default_interface": "",
|
||||||
|
"default_mark": 0,
|
||||||
|
"find_process": false,
|
||||||
|
"find_neighbor": false,
|
||||||
|
"default_domain_resolver": {
|
||||||
|
"server": "dns-tag",
|
||||||
|
"strategy": "prefer_ipv4"
|
||||||
|
},
|
||||||
|
"default_network_strategy": "",
|
||||||
|
"default_network_type": [],
|
||||||
|
"default_fallback_network_type": [],
|
||||||
|
"default_fallback_delay": "300ms"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Route Rule Structure
|
||||||
|
|
||||||
|
Each rule has **match criteria** and an **action**. First matching rule wins.
|
||||||
|
|
||||||
|
### Default Rule (flat criteria)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"action": "route",
|
||||||
|
|
||||||
|
// --- Match criteria (all are optional, combined with AND) ---
|
||||||
|
|
||||||
|
// Traffic source
|
||||||
|
"inbound": ["tun-in"],
|
||||||
|
"auth_user": ["user1"],
|
||||||
|
"client": ["client-tag"],
|
||||||
|
|
||||||
|
// Network
|
||||||
|
"ip_version": 4,
|
||||||
|
"network": ["tcp", "udp"],
|
||||||
|
|
||||||
|
// Domain matching
|
||||||
|
"domain": ["example.com"],
|
||||||
|
"domain_suffix": [".cn", ".ir"],
|
||||||
|
"domain_keyword": ["google"],
|
||||||
|
"domain_regex": ["^ad\\."],
|
||||||
|
|
||||||
|
// IP matching
|
||||||
|
"ip_cidr": ["10.0.0.0/8"],
|
||||||
|
"source_ip_cidr": ["192.168.1.0/24"],
|
||||||
|
"ip_is_private": false,
|
||||||
|
"source_ip_is_private": false,
|
||||||
|
|
||||||
|
// Port matching
|
||||||
|
"port": [80, 443],
|
||||||
|
"port_range": ["1000:2000"],
|
||||||
|
"source_port": [1234],
|
||||||
|
"source_port_range": [],
|
||||||
|
|
||||||
|
// Protocol detection (requires sniff action first)
|
||||||
|
"protocol": ["http", "tls", "quic", "stun", "dns", "bittorrent"],
|
||||||
|
|
||||||
|
// Process matching (requires find_process: true)
|
||||||
|
"process_name": ["curl"],
|
||||||
|
"process_path": ["/usr/bin/curl"],
|
||||||
|
"process_path_regex": [],
|
||||||
|
|
||||||
|
// Android
|
||||||
|
"package_name": ["com.android.chrome"],
|
||||||
|
|
||||||
|
// Linux
|
||||||
|
"user": ["proxy"],
|
||||||
|
"user_id": [1000],
|
||||||
|
|
||||||
|
// Network type
|
||||||
|
"wifi_ssid": ["HomeWiFi"],
|
||||||
|
"wifi_bssid": [],
|
||||||
|
"network_type": ["wifi", "cellular", "ethernet"],
|
||||||
|
"network_is_expensive": false,
|
||||||
|
"network_is_constrained": false,
|
||||||
|
|
||||||
|
// Rule sets
|
||||||
|
"rule_set": ["geoip-cn", "geosite-cn"],
|
||||||
|
"rule_set_ip_cidr_match_source": false,
|
||||||
|
|
||||||
|
// Clash mode
|
||||||
|
"clash_mode": "Rule",
|
||||||
|
|
||||||
|
// Invert match
|
||||||
|
"invert": false,
|
||||||
|
|
||||||
|
// --- Action ---
|
||||||
|
"action": "route",
|
||||||
|
"outbound": "proxy"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logical Rule (nested with AND/OR)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "logical",
|
||||||
|
"mode": "and",
|
||||||
|
"rules": [
|
||||||
|
{ "network": "udp" },
|
||||||
|
{ "port": [443] }
|
||||||
|
],
|
||||||
|
"invert": false,
|
||||||
|
"action": "route",
|
||||||
|
"outbound": "block"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rule Actions
|
||||||
|
|
||||||
|
### `route` — Route to outbound
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "route",
|
||||||
|
"outbound": "proxy",
|
||||||
|
"override_address": "",
|
||||||
|
"override_port": 0,
|
||||||
|
"network_strategy": "",
|
||||||
|
"network_type": [],
|
||||||
|
"fallback_network_type": [],
|
||||||
|
"fallback_delay": "300ms",
|
||||||
|
"udp_disable_domain_unmapping": false,
|
||||||
|
"udp_connect": false,
|
||||||
|
"tls_fragment": {
|
||||||
|
"enabled": true,
|
||||||
|
"size": "10-30",
|
||||||
|
"sleep": "2-8",
|
||||||
|
"fallback_delay": "300ms"
|
||||||
|
},
|
||||||
|
"tls_record_fragment": {
|
||||||
|
"enabled": true,
|
||||||
|
"size": "100-200"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `route-options` — Modify routing options without changing outbound
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "route-options",
|
||||||
|
"network_strategy": "prefer_ipv4",
|
||||||
|
"udp_disable_domain_unmapping": true,
|
||||||
|
"udp_connect": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `direct` — Direct connection with custom dialer
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "direct",
|
||||||
|
"override_address": "1.2.3.4",
|
||||||
|
"override_port": 53
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `reject` — Reject connection
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "reject",
|
||||||
|
"method": "default",
|
||||||
|
"no_drop": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Methods: `default` (TCP RST / ICMP unreachable), `drop` (silent drop), `reply` (for DNS)
|
||||||
|
|
||||||
|
### `hijack-dns` — Intercept DNS queries
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "hijack-dns"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `sniff` — Protocol sniffing
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "sniff",
|
||||||
|
"sniffer": ["http", "tls", "quic", "stun", "dns", "bittorrent", "dtls", "ssh", "rdp"],
|
||||||
|
"timeout": "300ms"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `resolve` — DNS resolution
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "resolve",
|
||||||
|
"server": "dns-server-tag",
|
||||||
|
"strategy": "prefer_ipv4",
|
||||||
|
"disable_cache": false,
|
||||||
|
"rewrite_ttl": 0,
|
||||||
|
"client_subnet": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rule Sets
|
||||||
|
|
||||||
|
### Remote rule set (auto-updating)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "remote",
|
||||||
|
"tag": "geoip-cn",
|
||||||
|
"format": "binary",
|
||||||
|
"url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-cn.srs",
|
||||||
|
"download_detour": "direct",
|
||||||
|
"update_interval": "1d"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Local rule set
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "local",
|
||||||
|
"tag": "custom-rules",
|
||||||
|
"format": "source",
|
||||||
|
"path": "/etc/sing-box/rules/custom.json"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inline rule set
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "inline",
|
||||||
|
"tag": "my-rules",
|
||||||
|
"rules": [
|
||||||
|
{ "domain_suffix": [".example.com"] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rule set source format (.json)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"domain_suffix": [".cn", ".中国"],
|
||||||
|
"ip_cidr": ["223.5.5.5/32"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Routing Patterns
|
||||||
|
|
||||||
|
### Pattern: DNS Hijack for TUN mode
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"route": {
|
||||||
|
"rules": [
|
||||||
|
{ "action": "sniff" },
|
||||||
|
{ "protocol": "dns", "action": "hijack-dns" },
|
||||||
|
// ... other rules
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern: Bypass LAN
|
||||||
|
```json
|
||||||
|
{ "ip_is_private": true, "action": "route", "outbound": "direct" }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern: Block ads via rule set
|
||||||
|
```json
|
||||||
|
{ "rule_set": ["adblock"], "action": "reject", "method": "default" }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern: Route by process
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"route": {
|
||||||
|
"find_process": true,
|
||||||
|
"rules": [
|
||||||
|
{ "process_name": ["telegram"], "action": "route", "outbound": "proxy" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern: Split tunnel by domain
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"rules": [
|
||||||
|
{ "rule_set": ["geosite-cn"], "action": "route", "outbound": "direct" },
|
||||||
|
{ "rule_set": ["geosite-category-ads-all"], "action": "reject" }
|
||||||
|
],
|
||||||
|
"final": "proxy"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern: TLS fragment for anti-censorship
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"domain_keyword": ["blocked-site"],
|
||||||
|
"action": "route",
|
||||||
|
"outbound": "direct",
|
||||||
|
"tls_fragment": {
|
||||||
|
"enabled": true,
|
||||||
|
"size": "1-5",
|
||||||
|
"sleep": "10-20"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,320 @@
|
||||||
|
# sing-box TLS & Transport Reference
|
||||||
|
|
||||||
|
## TLS Outbound (Client)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tls": {
|
||||||
|
"enabled": true,
|
||||||
|
"disable_sni": false,
|
||||||
|
"server_name": "example.com",
|
||||||
|
"insecure": false,
|
||||||
|
"alpn": ["h2", "http/1.1"],
|
||||||
|
"min_version": "1.2",
|
||||||
|
"max_version": "1.3",
|
||||||
|
"cipher_suites": [],
|
||||||
|
"certificate": [],
|
||||||
|
"certificate_path": "",
|
||||||
|
|
||||||
|
// uTLS fingerprinting
|
||||||
|
"utls": {
|
||||||
|
"enabled": true,
|
||||||
|
"fingerprint": "chrome"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Reality protocol
|
||||||
|
"reality": {
|
||||||
|
"enabled": true,
|
||||||
|
"public_key": "public-key",
|
||||||
|
"short_id": "short-id"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Encrypted Client Hello
|
||||||
|
"ech": {
|
||||||
|
"enabled": true,
|
||||||
|
"pq_signature_schemes_enabled": false,
|
||||||
|
"dynamic_record_sizing_disabled": false,
|
||||||
|
"config": [],
|
||||||
|
"config_path": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### uTLS Fingerprints
|
||||||
|
|
||||||
|
| Fingerprint | Description |
|
||||||
|
|-------------|-------------|
|
||||||
|
| `chrome` | Latest Chrome (recommended) |
|
||||||
|
| `firefox` | Latest Firefox |
|
||||||
|
| `safari` | Latest Safari |
|
||||||
|
| `edge` | Latest Edge |
|
||||||
|
| `ios` | iOS Safari |
|
||||||
|
| `android` | Android Chrome |
|
||||||
|
| `random` | Random from all |
|
||||||
|
| `randomized` | Randomized parameters |
|
||||||
|
| `chrome_auto` | Auto-update Chrome |
|
||||||
|
| `360_auto` | 360 Browser |
|
||||||
|
| `qq_auto` | QQ Browser |
|
||||||
|
|
||||||
|
## TLS Inbound (Server)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tls": {
|
||||||
|
"enabled": true,
|
||||||
|
"server_name": "example.com",
|
||||||
|
"alpn": ["h2", "http/1.1"],
|
||||||
|
"min_version": "1.2",
|
||||||
|
"max_version": "1.3",
|
||||||
|
"cipher_suites": [],
|
||||||
|
"certificate": [],
|
||||||
|
"certificate_path": "/path/to/cert.pem",
|
||||||
|
"key": [],
|
||||||
|
"key_path": "/path/to/key.pem",
|
||||||
|
|
||||||
|
// Client certificate auth
|
||||||
|
"client_auth": {
|
||||||
|
"enabled": true,
|
||||||
|
"mode": "require-and-verify",
|
||||||
|
"certificate": [],
|
||||||
|
"certificate_path": ""
|
||||||
|
},
|
||||||
|
|
||||||
|
// Reality server
|
||||||
|
"reality": {
|
||||||
|
"enabled": true,
|
||||||
|
"private_key": "private-key",
|
||||||
|
"short_id": ["short-id"],
|
||||||
|
"handshake": {
|
||||||
|
"server": "www.microsoft.com",
|
||||||
|
"server_port": 443
|
||||||
|
},
|
||||||
|
"max_time_difference": "1m"
|
||||||
|
},
|
||||||
|
|
||||||
|
// ECH server
|
||||||
|
"ech": {
|
||||||
|
"enabled": true,
|
||||||
|
"pq_signature_schemes_enabled": false,
|
||||||
|
"dynamic_record_sizing_disabled": false,
|
||||||
|
"key": [],
|
||||||
|
"key_path": ""
|
||||||
|
},
|
||||||
|
|
||||||
|
// Kernel TLS (Linux 5.1+)
|
||||||
|
"kernel_tx": false,
|
||||||
|
"kernel_rx": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Client Auth Modes
|
||||||
|
- `no` — No client certificate required
|
||||||
|
- `request` — Request but don't require
|
||||||
|
- `require-any` — Require any client certificate
|
||||||
|
- `verify-if-given` — Verify only if provided
|
||||||
|
- `require-and-verify` — Require and verify against CA
|
||||||
|
|
||||||
|
### Reality Key Generation
|
||||||
|
```bash
|
||||||
|
sing-box generate reality-keypair
|
||||||
|
# Output:
|
||||||
|
# PrivateKey: xxxx
|
||||||
|
# PublicKey: xxxx
|
||||||
|
```
|
||||||
|
|
||||||
|
## V2Ray Transport Layer
|
||||||
|
|
||||||
|
Supported by: VMess, VLESS, Trojan
|
||||||
|
|
||||||
|
### HTTP Transport
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"transport": {
|
||||||
|
"type": "http",
|
||||||
|
"host": ["example.com"],
|
||||||
|
"path": "/",
|
||||||
|
"method": "PUT",
|
||||||
|
"headers": {
|
||||||
|
"X-Custom": ["value"]
|
||||||
|
},
|
||||||
|
"idle_timeout": "15s",
|
||||||
|
"ping_timeout": "15s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### WebSocket Transport
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"transport": {
|
||||||
|
"type": "ws",
|
||||||
|
"path": "/ws-path",
|
||||||
|
"headers": {
|
||||||
|
"Host": "example.com"
|
||||||
|
},
|
||||||
|
"max_early_data": 2048,
|
||||||
|
"early_data_header_name": "Sec-WebSocket-Protocol"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### gRPC Transport
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"transport": {
|
||||||
|
"type": "grpc",
|
||||||
|
"service_name": "GunService",
|
||||||
|
"idle_timeout": "15s",
|
||||||
|
"ping_timeout": "15s",
|
||||||
|
"permit_without_stream": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### QUIC Transport
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"transport": {
|
||||||
|
"type": "quic"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTPUpgrade Transport
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"transport": {
|
||||||
|
"type": "httpupgrade",
|
||||||
|
"host": "example.com",
|
||||||
|
"path": "/upgrade-path",
|
||||||
|
"headers": {
|
||||||
|
"X-Custom": ["value"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Anti-Censorship Techniques
|
||||||
|
|
||||||
|
### TLS Fragment (in route rule action)
|
||||||
|
Splits TLS ClientHello into small fragments to evade DPI:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "route",
|
||||||
|
"outbound": "direct",
|
||||||
|
"tls_fragment": {
|
||||||
|
"enabled": true,
|
||||||
|
"size": "1-5",
|
||||||
|
"sleep": "10-20",
|
||||||
|
"fallback_delay": "300ms"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- `size`: Fragment size range (bytes)
|
||||||
|
- `sleep`: Delay between fragments (ms)
|
||||||
|
- Only works with TCP, mutually exclusive with `tls_record_fragment`
|
||||||
|
|
||||||
|
### TLS Record Fragment (in route rule action)
|
||||||
|
Splits TLS records into smaller records:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "route",
|
||||||
|
"outbound": "direct",
|
||||||
|
"tls_record_fragment": {
|
||||||
|
"enabled": true,
|
||||||
|
"size": "100-200"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Lower overhead than TLS fragment
|
||||||
|
- Mutually exclusive with `tls_fragment`
|
||||||
|
|
||||||
|
### VLESS + Reality (anti-probing)
|
||||||
|
Makes the server look like a legitimate website:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"inbounds": [{
|
||||||
|
"type": "vless",
|
||||||
|
"listen_port": 443,
|
||||||
|
"users": [{ "uuid": "...", "flow": "xtls-rprx-vision" }],
|
||||||
|
"tls": {
|
||||||
|
"enabled": true,
|
||||||
|
"reality": {
|
||||||
|
"enabled": true,
|
||||||
|
"private_key": "...",
|
||||||
|
"short_id": ["abcd1234"],
|
||||||
|
"handshake": {
|
||||||
|
"server": "www.microsoft.com",
|
||||||
|
"server_port": 443
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ShadowTLS v3 + Shadowsocks (stealth)
|
||||||
|
Traffic looks like normal TLS to a legitimate site:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"inbounds": [{
|
||||||
|
"type": "shadowtls",
|
||||||
|
"listen_port": 443,
|
||||||
|
"version": 3,
|
||||||
|
"users": [{ "name": "user1", "password": "stls-pass" }],
|
||||||
|
"handshake": {
|
||||||
|
"server": "www.google.com",
|
||||||
|
"server_port": 443
|
||||||
|
},
|
||||||
|
"handshake_for_server_name": {
|
||||||
|
"www.google.com": {
|
||||||
|
"server": "www.google.com",
|
||||||
|
"server_port": 443
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"detour": "ss-in"
|
||||||
|
}],
|
||||||
|
"outbounds": [...]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hysteria2 + Salamander Obfuscation
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "hysteria2",
|
||||||
|
"obfs": {
|
||||||
|
"type": "salamander",
|
||||||
|
"password": "obfs-password"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## CDN-Compatible Transports
|
||||||
|
|
||||||
|
For routing through CDN (Cloudflare, etc.):
|
||||||
|
- **WebSocket** (`ws`) — most widely supported
|
||||||
|
- **gRPC** — good CDN support, efficient
|
||||||
|
- **HTTPUpgrade** — lightweight alternative to WebSocket
|
||||||
|
|
||||||
|
Example: VLESS + WebSocket behind CDN:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "vless",
|
||||||
|
"server": "cdn-domain.example.com",
|
||||||
|
"server_port": 443,
|
||||||
|
"uuid": "...",
|
||||||
|
"tls": {
|
||||||
|
"enabled": true,
|
||||||
|
"server_name": "cdn-domain.example.com"
|
||||||
|
},
|
||||||
|
"transport": {
|
||||||
|
"type": "ws",
|
||||||
|
"path": "/vless-ws",
|
||||||
|
"headers": {
|
||||||
|
"Host": "cdn-domain.example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,318 @@
|
||||||
|
# sing-box TUN & System Settings Reference
|
||||||
|
|
||||||
|
## TUN Inbound Configuration
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "tun",
|
||||||
|
"tag": "tun-in",
|
||||||
|
|
||||||
|
"interface_name": "",
|
||||||
|
"mtu": 9000,
|
||||||
|
"gso": false,
|
||||||
|
"address": [
|
||||||
|
"172.19.0.1/30",
|
||||||
|
"fdfe:dcba:9876::1/126"
|
||||||
|
],
|
||||||
|
"auto_route": true,
|
||||||
|
"auto_redirect": false,
|
||||||
|
"strict_route": true,
|
||||||
|
"route_address": [],
|
||||||
|
"route_address_set": [],
|
||||||
|
"route_exclude_address": [],
|
||||||
|
"route_exclude_address_set": [],
|
||||||
|
|
||||||
|
"stack": "mixed",
|
||||||
|
"udp_timeout": "5m",
|
||||||
|
|
||||||
|
// Linux nftables (auto_redirect)
|
||||||
|
"auto_redirect_input_mark": "0x2023",
|
||||||
|
"auto_redirect_output_mark": "0x2024",
|
||||||
|
"auto_redirect_reset_mark": "0x2025",
|
||||||
|
"auto_redirect_nfqueue": 100,
|
||||||
|
"auto_redirect_iproute2_fallback_rule_index": 32768,
|
||||||
|
"exclude_mptcp": false,
|
||||||
|
|
||||||
|
// Linux iproute2
|
||||||
|
"iproute2_table_index": 2022,
|
||||||
|
"iproute2_rule_index": 9000,
|
||||||
|
|
||||||
|
// Linux UID filtering
|
||||||
|
"include_uid": [],
|
||||||
|
"include_uid_range": ["1000:65534"],
|
||||||
|
"exclude_uid": [0],
|
||||||
|
"exclude_uid_range": [],
|
||||||
|
|
||||||
|
// Interface filtering
|
||||||
|
"include_interface": [],
|
||||||
|
"exclude_interface": ["docker0", "br-*"],
|
||||||
|
|
||||||
|
// Android
|
||||||
|
"include_android_user": [0],
|
||||||
|
"include_package": [],
|
||||||
|
"exclude_package": ["com.android.captiveportallogin"],
|
||||||
|
|
||||||
|
// Apple (iOS/macOS)
|
||||||
|
"platform": {
|
||||||
|
"http_proxy": {
|
||||||
|
"enabled": false,
|
||||||
|
"server": "127.0.0.1",
|
||||||
|
"server_port": 1080,
|
||||||
|
"match_domain": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Network namespace (Linux)
|
||||||
|
"netns": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## TCP/IP Stack Options
|
||||||
|
|
||||||
|
| Stack | Description | Best For |
|
||||||
|
|-------|-------------|----------|
|
||||||
|
| `system` | Uses OS network stack | Compatibility, low overhead |
|
||||||
|
| `gvisor` | Userspace TCP/IP (Google gVisor) | Stability, no kernel dependency |
|
||||||
|
| `mixed` | TCP=system, UDP=gvisor | **Recommended default** — best balance |
|
||||||
|
|
||||||
|
## TUN auto_route Behavior
|
||||||
|
|
||||||
|
When `auto_route: true`:
|
||||||
|
- **Linux**: Creates iproute2 rules and routes in table `iproute2_table_index` (default 2022)
|
||||||
|
- **macOS**: Adds routes via `route` command
|
||||||
|
- **Windows**: Uses WFP (Windows Filtering Platform) for traffic redirect
|
||||||
|
|
||||||
|
When `strict_route: true` (recommended with auto_route):
|
||||||
|
- **Linux**: Adds rules to prevent traffic leaking outside TUN
|
||||||
|
- **Windows**: Blocks non-TUN traffic via WFP
|
||||||
|
- Prevents DNS and other leaks
|
||||||
|
|
||||||
|
## auto_redirect (Linux nftables)
|
||||||
|
|
||||||
|
Alternative to `tproxy` inbound. Uses nftables to redirect all traffic to TUN:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "tun",
|
||||||
|
"auto_route": true,
|
||||||
|
"auto_redirect": true,
|
||||||
|
"auto_redirect_input_mark": "0x2023",
|
||||||
|
"auto_redirect_output_mark": "0x2024"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Requires: `nftables` available, `CAP_NET_ADMIN` capability.
|
||||||
|
|
||||||
|
## Linux Transparent Proxy Alternatives
|
||||||
|
|
||||||
|
### Option 1: TUN (recommended)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"type": "tun",
|
||||||
|
"tag": "tun-in",
|
||||||
|
"address": ["172.19.0.1/30", "fdfe:dcba:9876::1/126"],
|
||||||
|
"auto_route": true,
|
||||||
|
"strict_route": true,
|
||||||
|
"stack": "mixed"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 2: redirect (TCP only)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"type": "redirect",
|
||||||
|
"tag": "redirect-in",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": 12345
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Requires iptables rule:
|
||||||
|
```bash
|
||||||
|
iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-port 12345
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 3: tproxy (TCP + UDP)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"type": "tproxy",
|
||||||
|
"tag": "tproxy-in",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": 12345,
|
||||||
|
"network": "udp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "tproxy",
|
||||||
|
"tag": "tproxy-in-tcp",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": 12345,
|
||||||
|
"network": "tcp"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Requires iptables TPROXY rules and ip rule/route for marking.
|
||||||
|
|
||||||
|
## System Tuning — Linux
|
||||||
|
|
||||||
|
### sysctl settings
|
||||||
|
```bash
|
||||||
|
# Enable IP forwarding (for gateway/router mode)
|
||||||
|
sysctl -w net.ipv4.ip_forward=1
|
||||||
|
sysctl -w net.ipv6.conf.all.forwarding=1
|
||||||
|
|
||||||
|
# Disable reverse path filtering (needed for tproxy/TUN)
|
||||||
|
sysctl -w net.ipv4.conf.all.rp_filter=0
|
||||||
|
sysctl -w net.ipv4.conf.default.rp_filter=0
|
||||||
|
|
||||||
|
# TCP optimizations
|
||||||
|
sysctl -w net.core.rmem_max=16777216
|
||||||
|
sysctl -w net.core.wmem_max=16777216
|
||||||
|
sysctl -w net.ipv4.tcp_fastopen=3 # Enable TFO client+server
|
||||||
|
sysctl -w net.ipv4.tcp_mtu_probing=1 # For Hysteria/QUIC MTU discovery
|
||||||
|
|
||||||
|
# Increase conntrack for high-connection scenarios
|
||||||
|
sysctl -w net.netfilter.nf_conntrack_max=131072
|
||||||
|
|
||||||
|
# BBR congestion control (recommended)
|
||||||
|
sysctl -w net.core.default_qdisc=fq
|
||||||
|
sysctl -w net.ipv4.tcp_congestion_control=bbr
|
||||||
|
```
|
||||||
|
|
||||||
|
### Persist sysctl
|
||||||
|
```bash
|
||||||
|
# /etc/sysctl.d/99-sing-box.conf
|
||||||
|
net.ipv4.ip_forward = 1
|
||||||
|
net.ipv6.conf.all.forwarding = 1
|
||||||
|
net.ipv4.conf.all.rp_filter = 0
|
||||||
|
net.core.default_qdisc = fq
|
||||||
|
net.ipv4.tcp_congestion_control = bbr
|
||||||
|
net.ipv4.tcp_fastopen = 3
|
||||||
|
```
|
||||||
|
|
||||||
|
### File descriptor limits
|
||||||
|
```bash
|
||||||
|
# /etc/security/limits.d/sing-box.conf
|
||||||
|
* soft nofile 65535
|
||||||
|
* hard nofile 131072
|
||||||
|
|
||||||
|
# Or for systemd service
|
||||||
|
# [Service]
|
||||||
|
# LimitNOFILE=131072
|
||||||
|
```
|
||||||
|
|
||||||
|
### Required capabilities
|
||||||
|
```bash
|
||||||
|
# Instead of running as root:
|
||||||
|
sudo setcap cap_net_admin,cap_net_raw,cap_net_bind_service+ep /usr/bin/sing-box
|
||||||
|
```
|
||||||
|
|
||||||
|
### systemd service
|
||||||
|
```ini
|
||||||
|
# /etc/systemd/system/sing-box.service
|
||||||
|
[Unit]
|
||||||
|
Description=sing-box service
|
||||||
|
Documentation=https://sing-box.sagernet.org
|
||||||
|
After=network.target nss-lookup.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/bin/sing-box run -c /etc/sing-box/config.json
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=10s
|
||||||
|
LimitNOFILE=131072
|
||||||
|
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE
|
||||||
|
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE
|
||||||
|
NoNewPrivileges=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
### systemd with config directory
|
||||||
|
```ini
|
||||||
|
ExecStart=/usr/bin/sing-box run -C /etc/sing-box/
|
||||||
|
```
|
||||||
|
|
||||||
|
## System Tuning — macOS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Enable IP forwarding
|
||||||
|
sudo sysctl -w net.inet.ip.forwarding=1
|
||||||
|
sudo sysctl -w net.inet6.ip6.forwarding=1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Network Namespace (Linux)
|
||||||
|
|
||||||
|
Run sing-box in an isolated network namespace:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "tun",
|
||||||
|
"netns": "sing-box-ns"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Or use a path: `"netns": "/run/netns/custom-ns"`
|
||||||
|
|
||||||
|
## Routing Mark (Linux)
|
||||||
|
|
||||||
|
Prevent routing loops by marking sing-box's own traffic:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"route": {
|
||||||
|
"default_mark": 255
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Or per-outbound:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "direct",
|
||||||
|
"tag": "direct",
|
||||||
|
"routing_mark": 255
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dial Fields (Common to All Outbounds)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"bind_interface": "",
|
||||||
|
"inet4_bind_address": "",
|
||||||
|
"inet6_bind_address": "",
|
||||||
|
"routing_mark": 0,
|
||||||
|
"reuse_addr": false,
|
||||||
|
"connect_timeout": "5s",
|
||||||
|
"tcp_fast_open": false,
|
||||||
|
"tcp_multi_path": false,
|
||||||
|
"udp_fragment": false,
|
||||||
|
"domain_strategy": "",
|
||||||
|
"network_strategy": "",
|
||||||
|
"network_type": [],
|
||||||
|
"fallback_network_type": [],
|
||||||
|
"fallback_delay": "300ms"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Listen Fields (Common to All Inbounds)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"listen": "0.0.0.0",
|
||||||
|
"listen_port": 1080,
|
||||||
|
"tcp_fast_open": false,
|
||||||
|
"tcp_multi_path": false,
|
||||||
|
"udp_fragment": false,
|
||||||
|
"udp_timeout": "5m",
|
||||||
|
"proxy_protocol": false,
|
||||||
|
"proxy_protocol_accept_no_header": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
{
|
||||||
|
"log": {
|
||||||
|
"level": "info",
|
||||||
|
"timestamp": true
|
||||||
|
},
|
||||||
|
"dns": {
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"type": "https",
|
||||||
|
"tag": "dns-remote",
|
||||||
|
"server": "dns.google",
|
||||||
|
"server_port": 443,
|
||||||
|
"path": "/dns-query",
|
||||||
|
"detour": "proxy",
|
||||||
|
"domain_resolver": {
|
||||||
|
"server": "dns-bootstrap",
|
||||||
|
"strategy": "ipv4_only"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "udp",
|
||||||
|
"tag": "dns-bootstrap",
|
||||||
|
"server": "8.8.8.8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"final": "dns-remote"
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"type": "mixed",
|
||||||
|
"tag": "mixed-in",
|
||||||
|
"listen": "127.0.0.1",
|
||||||
|
"listen_port": 1080
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"type": "{{PROTOCOL}}",
|
||||||
|
"tag": "proxy",
|
||||||
|
"server": "{{SERVER}}",
|
||||||
|
"server_port": "{{PORT}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "direct",
|
||||||
|
"tag": "direct"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"tag": "block"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"route": {
|
||||||
|
"rules": [
|
||||||
|
{ "action": "sniff" },
|
||||||
|
{ "protocol": "dns", "action": "hijack-dns" },
|
||||||
|
{ "ip_is_private": true, "action": "route", "outbound": "direct" }
|
||||||
|
],
|
||||||
|
"final": "proxy",
|
||||||
|
"auto_detect_interface": true
|
||||||
|
},
|
||||||
|
"experimental": {
|
||||||
|
"cache_file": {
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"log": {
|
||||||
|
"level": "info",
|
||||||
|
"timestamp": true
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"type": "{{PROTOCOL}}",
|
||||||
|
"tag": "{{PROTOCOL}}-in",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": 443,
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"name": "user1",
|
||||||
|
"password": "{{PASSWORD_OR_UUID}}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tls": {
|
||||||
|
"enabled": true,
|
||||||
|
"certificate_path": "/etc/sing-box/cert.pem",
|
||||||
|
"key_path": "/etc/sing-box/key.pem"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"type": "direct",
|
||||||
|
"tag": "direct"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"route": {
|
||||||
|
"rules": [
|
||||||
|
{ "action": "sniff" },
|
||||||
|
{ "ip_is_private": true, "action": "reject" }
|
||||||
|
],
|
||||||
|
"final": "direct"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
{
|
||||||
|
"log": {
|
||||||
|
"level": "info",
|
||||||
|
"timestamp": true
|
||||||
|
},
|
||||||
|
"dns": {
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"type": "https",
|
||||||
|
"tag": "dns-remote",
|
||||||
|
"server": "dns.google",
|
||||||
|
"server_port": 443,
|
||||||
|
"path": "/dns-query",
|
||||||
|
"detour": "proxy",
|
||||||
|
"domain_resolver": {
|
||||||
|
"server": "dns-bootstrap",
|
||||||
|
"strategy": "ipv4_only"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fakeip",
|
||||||
|
"tag": "dns-fakeip",
|
||||||
|
"inet4_range": "198.18.0.0/15",
|
||||||
|
"inet6_range": "fc00::/18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "udp",
|
||||||
|
"tag": "dns-local",
|
||||||
|
"server": "223.5.5.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "udp",
|
||||||
|
"tag": "dns-bootstrap",
|
||||||
|
"server": "8.8.8.8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"query_type": ["A", "AAAA"],
|
||||||
|
"action": "route",
|
||||||
|
"server": "dns-fakeip"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"final": "dns-remote"
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"type": "tun",
|
||||||
|
"tag": "tun-in",
|
||||||
|
"address": [
|
||||||
|
"172.19.0.1/30",
|
||||||
|
"fdfe:dcba:9876::1/126"
|
||||||
|
],
|
||||||
|
"mtu": 9000,
|
||||||
|
"auto_route": true,
|
||||||
|
"strict_route": true,
|
||||||
|
"stack": "mixed",
|
||||||
|
"exclude_interface": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"type": "{{PROTOCOL}}",
|
||||||
|
"tag": "proxy",
|
||||||
|
"server": "{{SERVER}}",
|
||||||
|
"server_port": "{{PORT}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "direct",
|
||||||
|
"tag": "direct"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"tag": "block"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"route": {
|
||||||
|
"rules": [
|
||||||
|
{ "action": "sniff" },
|
||||||
|
{ "protocol": "dns", "action": "hijack-dns" },
|
||||||
|
{ "ip_is_private": true, "action": "route", "outbound": "direct" }
|
||||||
|
],
|
||||||
|
"final": "proxy",
|
||||||
|
"auto_detect_interface": true
|
||||||
|
},
|
||||||
|
"experimental": {
|
||||||
|
"cache_file": {
|
||||||
|
"enabled": true,
|
||||||
|
"store_fakeip": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
{
|
||||||
|
"log": {
|
||||||
|
"level": "info",
|
||||||
|
"timestamp": true
|
||||||
|
},
|
||||||
|
"dns": {
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"type": "https",
|
||||||
|
"tag": "dns-remote",
|
||||||
|
"server": "dns.google",
|
||||||
|
"server_port": 443,
|
||||||
|
"path": "/dns-query",
|
||||||
|
"detour": "auto",
|
||||||
|
"domain_resolver": {
|
||||||
|
"server": "dns-bootstrap",
|
||||||
|
"strategy": "ipv4_only"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "udp",
|
||||||
|
"tag": "dns-bootstrap",
|
||||||
|
"server": "8.8.8.8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"final": "dns-remote"
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"type": "mixed",
|
||||||
|
"tag": "mixed-in",
|
||||||
|
"listen": "127.0.0.1",
|
||||||
|
"listen_port": 1080
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"type": "selector",
|
||||||
|
"tag": "proxy",
|
||||||
|
"outbounds": ["auto", "node-hk", "node-jp", "node-us", "direct"],
|
||||||
|
"default": "auto",
|
||||||
|
"interrupt_exist_connections": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "urltest",
|
||||||
|
"tag": "auto",
|
||||||
|
"outbounds": ["node-hk", "node-jp", "node-us"],
|
||||||
|
"url": "https://www.gstatic.com/generate_204",
|
||||||
|
"interval": "3m",
|
||||||
|
"tolerance": 50,
|
||||||
|
"idle_timeout": "30m",
|
||||||
|
"interrupt_exist_connections": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "{{PROTOCOL}}",
|
||||||
|
"tag": "node-hk",
|
||||||
|
"server": "hk.example.com",
|
||||||
|
"server_port": 443
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "{{PROTOCOL}}",
|
||||||
|
"tag": "node-jp",
|
||||||
|
"server": "jp.example.com",
|
||||||
|
"server_port": 443
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "{{PROTOCOL}}",
|
||||||
|
"tag": "node-us",
|
||||||
|
"server": "us.example.com",
|
||||||
|
"server_port": 443
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "direct",
|
||||||
|
"tag": "direct"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"tag": "block"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"route": {
|
||||||
|
"rules": [
|
||||||
|
{ "action": "sniff" },
|
||||||
|
{ "protocol": "dns", "action": "hijack-dns" },
|
||||||
|
{ "ip_is_private": true, "action": "route", "outbound": "direct" }
|
||||||
|
],
|
||||||
|
"final": "proxy",
|
||||||
|
"auto_detect_interface": true
|
||||||
|
},
|
||||||
|
"experimental": {
|
||||||
|
"cache_file": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"clash_api": {
|
||||||
|
"external_controller": "127.0.0.1:9090",
|
||||||
|
"secret": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue