完善使用说明
This commit is contained in:
435
README.md
435
README.md
@@ -1,34 +1,435 @@
|
||||
> Sponsored by [Warp](https://go.warp.dev/sing-box), built for coding with multiple AI agents
|
||||
> Sponsored by CodeX
|
||||
|
||||
<a href="https://go.warp.dev/sing-box">
|
||||
<img alt="Warp sponsorship" width="400" src="https://github.com/warpdotdev/brand-assets/raw/refs/heads/main/Github/Sponsor/Warp-Github-LG-02.png">
|
||||
</a>
|
||||
# sing-box Xboard Fork
|
||||
|
||||
---
|
||||
这是一个基于上游 [SagerNet/sing-box](https://github.com/SagerNet/sing-box) 的定制分支,主要面向 Xboard / UniProxy 面板联动部署场景。
|
||||
|
||||
# sing-box
|
||||
它保留了上游 `sing-box` 内核能力,同时补充了:
|
||||
|
||||
The universal proxy platform.
|
||||
- Xboard 动态入站服务
|
||||
- 多节点托管
|
||||
- 面板协议自动识别
|
||||
- VLESS / REALITY 面板字段映射
|
||||
- Shadowsocks 2022 用户同步与密钥处理
|
||||
- AnyTLS / Trojan / Hysteria / TUIC 的本地 TLS / ACME 支持
|
||||
- 安装脚本与分离式配置模板
|
||||
- PROXY protocol 客户端真实 IP 传递
|
||||
|
||||
## Repository Notice
|
||||
如果你要查看官方功能基线、通用配置文档、原始内核行为,请优先参考上游:
|
||||
|
||||
This repository is a customized fork based on the upstream [SagerNet/sing-box](https://github.com/SagerNet/sing-box) project.
|
||||
- 上游仓库:https://github.com/SagerNet/sing-box
|
||||
- 上游文档:https://sing-box.sagernet.org
|
||||
|
||||
- Upstream project: `sing-box`
|
||||
- Upstream documentation: https://sing-box.sagernet.org
|
||||
- This repository may contain local modifications for Xboard integration, deployment scripts, and protocol handling behavior
|
||||
## 适用场景
|
||||
|
||||
If you are looking for the official project, feature baseline, or upstream release notes, please refer to the upstream `sing-box` repository first.
|
||||
这个仓库更适合以下用途:
|
||||
|
||||
[](https://repology.org/project/sing-box/versions)
|
||||
- 从 Xboard / UniProxy 面板拉取节点配置
|
||||
- 从面板拉取用户并动态更新
|
||||
- 单机运行多个节点
|
||||
- 给面板型机场节点准备安装脚本
|
||||
- 对接面板下发的 `protocol`、`cert_config`、`accept_proxy_protocol`、REALITY 字段等
|
||||
|
||||
## Documentation
|
||||
## 主要特性
|
||||
|
||||
https://sing-box.sagernet.org
|
||||
- `services.xboard` 动态服务
|
||||
- 支持单节点和多节点
|
||||
- 协议优先从面板返回的 `protocol` 识别
|
||||
- 支持面板回包控制 `accept_proxy_protocol`
|
||||
- 支持 VLESS REALITY 的 `server_name`、`public_key`、`private_key`、`short_id`
|
||||
- 支持 ACME:
|
||||
- `auto_tls`
|
||||
- `cert_mode = http`
|
||||
- `cert_mode = dns`
|
||||
- 当前已支持的 ACME DNS provider:
|
||||
- `cloudflare`
|
||||
- `alidns`
|
||||
- `tencentcloud`
|
||||
- `dnspod`
|
||||
- `acmedns`
|
||||
- 安装脚本默认生成:
|
||||
- `/etc/sing-box/config.d/10-base.json`
|
||||
- `/etc/sing-box/config.d/20-outbounds.json`
|
||||
- 安装后的服务名为:
|
||||
- `singbox.service`
|
||||
|
||||
## 仓库内关键文件
|
||||
|
||||
- [install.sh](./install.sh)
|
||||
Linux 安装脚本
|
||||
- [option/xboard.go](./option/xboard.go)
|
||||
`services.xboard` 配置结构
|
||||
- [service/xboard/service.go](./service/xboard/service.go)
|
||||
Xboard 动态服务实现
|
||||
- [configs](./configs)
|
||||
配置示例目录
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 编译并安装
|
||||
|
||||
在 Linux 服务器上进入仓库目录:
|
||||
|
||||
```bash
|
||||
chmod +x install.sh
|
||||
./install.sh
|
||||
```
|
||||
|
||||
脚本会做这些事情:
|
||||
|
||||
1. 检查 Go 环境
|
||||
2. 编译当前仓库代码
|
||||
3. 生成分离配置
|
||||
4. 创建 `singbox.service`
|
||||
5. 启动服务
|
||||
|
||||
### 2. 安装过程会询问的内容
|
||||
|
||||
- `Panel URL`
|
||||
- `Panel Token`
|
||||
- 一个或多个 `Node ID`
|
||||
- DNS 模式:
|
||||
- `udp`
|
||||
- `local`
|
||||
- 当前节点前面是否有发送 PROXY protocol 的四层代理
|
||||
|
||||
### 3. 多节点输入规则
|
||||
|
||||
- 安装脚本会持续要求输入 `Node ID`
|
||||
- 输入 `NO` 才结束
|
||||
- 至少要有一个节点
|
||||
|
||||
## 运行与管理
|
||||
|
||||
查看状态:
|
||||
|
||||
```bash
|
||||
systemctl status singbox
|
||||
```
|
||||
|
||||
查看日志:
|
||||
|
||||
```bash
|
||||
journalctl -u singbox -f
|
||||
```
|
||||
|
||||
重启服务:
|
||||
|
||||
```bash
|
||||
systemctl restart singbox
|
||||
```
|
||||
|
||||
手动运行:
|
||||
|
||||
```bash
|
||||
sing-box -D /var/lib/sing-box -C /etc/sing-box/config.d run
|
||||
```
|
||||
|
||||
## 推荐配置结构
|
||||
|
||||
建议把配置拆成两部分。
|
||||
|
||||
### `10-base.json`
|
||||
|
||||
放这些内容:
|
||||
|
||||
- 日志
|
||||
- DNS
|
||||
- `services`
|
||||
- 基础路由规则
|
||||
|
||||
### `20-outbounds.json`
|
||||
|
||||
放这些内容:
|
||||
|
||||
- 全部出站
|
||||
- 出站标签
|
||||
- 你自己的分流依赖
|
||||
|
||||
这样更方便:
|
||||
|
||||
- 面板动态服务和你的自定义出站分离
|
||||
- 安装脚本生成的基础配置不容易被误改
|
||||
- 调整出站时不会影响 Xboard 服务主体
|
||||
|
||||
示例已放在:
|
||||
|
||||
- [configs/10-base.single-node.json](./configs/10-base.single-node.json)
|
||||
- [configs/10-base.multi-node.json](./configs/10-base.multi-node.json)
|
||||
- [configs/20-outbounds.example.json](./configs/20-outbounds.example.json)
|
||||
|
||||
## `services.xboard` 配置说明
|
||||
|
||||
配置结构定义见 [option/xboard.go](./option/xboard.go)。
|
||||
|
||||
### 最小单节点示例
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "xboard",
|
||||
"panel_url": "https://panel.example.com",
|
||||
"key": "replace-with-node-token",
|
||||
"sync_interval": "1m",
|
||||
"report_interval": "1m",
|
||||
"node_id": 286
|
||||
}
|
||||
```
|
||||
|
||||
### 多节点示例
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "xboard",
|
||||
"panel_url": "https://panel.example.com",
|
||||
"key": "replace-with-node-token",
|
||||
"sync_interval": "1m",
|
||||
"report_interval": "1m",
|
||||
"nodes": [
|
||||
{
|
||||
"node_id": 286
|
||||
},
|
||||
{
|
||||
"node_id": 774
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 当前推荐做法
|
||||
|
||||
- 只传 `panel_url`
|
||||
- 只传 `key`
|
||||
- 只传 `node_id` 或 `nodes`
|
||||
|
||||
下面这些字段仍然保留兼容,但常规部署一般不需要:
|
||||
|
||||
- `config_panel_url`
|
||||
- `user_panel_url`
|
||||
- `config_node_id`
|
||||
- `user_node_id`
|
||||
- `node_type`
|
||||
|
||||
说明:
|
||||
|
||||
- 当前逻辑会优先从面板回包中的 `protocol` 自动识别协议
|
||||
- `node_type` 更适合做历史兼容,不建议再依赖它做主配置
|
||||
|
||||
## 面板配置回包约定
|
||||
|
||||
### 1. 协议识别
|
||||
|
||||
推荐面板显式返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"protocol": "vless"
|
||||
}
|
||||
```
|
||||
|
||||
当前服务会按如下顺序识别协议:
|
||||
|
||||
1. `protocol`
|
||||
2. `node_type`
|
||||
3. 如果是 Shadowsocks 且存在 `cipher`,则回退识别为 `shadowsocks`
|
||||
|
||||
### 2. 监听地址与端口
|
||||
|
||||
推荐面板返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"listen_ip": "0.0.0.0",
|
||||
"server_port": 443
|
||||
}
|
||||
```
|
||||
|
||||
### 3. PROXY protocol
|
||||
|
||||
如果前面有四层代理,并且它会发送 PROXY protocol 头,需要面板返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"accept_proxy_protocol": true
|
||||
}
|
||||
```
|
||||
|
||||
如果用户是直连节点,不要开启这个字段,否则连接会失败。
|
||||
|
||||
### 4. VLESS REALITY
|
||||
|
||||
当前支持从面板获取这些字段:
|
||||
|
||||
- `tls_settings.server_name`
|
||||
- `tls_settings.public_key`
|
||||
- `tls_settings.private_key`
|
||||
- `tls_settings.short_id`
|
||||
- 顶层 `server_name`
|
||||
- 顶层 `public_key`
|
||||
- 顶层 `private_key`
|
||||
- 顶层 `short_id`
|
||||
|
||||
示例见:
|
||||
|
||||
- [configs/panel-response.vless-reality.json](./configs/panel-response.vless-reality.json)
|
||||
|
||||
### 5. Shadowsocks 2022
|
||||
|
||||
推荐面板返回:
|
||||
|
||||
- `protocol: "shadowsocks"`
|
||||
- `cipher`
|
||||
- `server_key`
|
||||
|
||||
示例见:
|
||||
|
||||
- [configs/panel-response.shadowsocks2022.json](./configs/panel-response.shadowsocks2022.json)
|
||||
|
||||
### 6. AnyTLS / Trojan / Hysteria / TUIC 的证书要求
|
||||
|
||||
这些协议通常要求本地具备可用 TLS 证书。当前支持:
|
||||
|
||||
- 文件证书
|
||||
- 证书内容直传
|
||||
- ACME 自动签发
|
||||
|
||||
如果面板没有下发可用证书,也没有有效 ACME 配置,常见报错是:
|
||||
|
||||
```text
|
||||
Xboard setup error: missing certificate
|
||||
```
|
||||
|
||||
示例见:
|
||||
|
||||
- [configs/panel-response.anytls-acme-dns.json](./configs/panel-response.anytls-acme-dns.json)
|
||||
|
||||
## ACME 说明
|
||||
|
||||
当前支持:
|
||||
|
||||
- `auto_tls: true`
|
||||
- `cert_mode: "http"`
|
||||
- `cert_mode: "dns"`
|
||||
|
||||
### DNS-01 provider
|
||||
|
||||
已支持:
|
||||
|
||||
- `cloudflare`
|
||||
- `alidns`
|
||||
- `tencentcloud`
|
||||
- `dnspod`
|
||||
- `acmedns`
|
||||
|
||||
### DNSPod 说明
|
||||
|
||||
仓库已经内置 DNSPod provider 适配,不再依赖旧版 `github.com/libdns/dnspod` 的接口兼容。
|
||||
|
||||
你可以从面板下发:
|
||||
|
||||
```json
|
||||
{
|
||||
"cert_config": {
|
||||
"cert_mode": "dns",
|
||||
"dns_provider": "dnspod",
|
||||
"dns_env": {
|
||||
"DNSPOD_TOKEN": "id,token"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
也可以下发腾讯云凭据:
|
||||
|
||||
```json
|
||||
{
|
||||
"cert_config": {
|
||||
"cert_mode": "dns",
|
||||
"dns_provider": "tencentcloud",
|
||||
"dns_env": {
|
||||
"TENCENTCLOUD_SECRET_ID": "xxx",
|
||||
"TENCENTCLOUD_SECRET_KEY": "xxx"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 配置示例目录
|
||||
|
||||
[configs](./configs) 目录中已经提供了这些示例:
|
||||
|
||||
- [configs/10-base.single-node.json](./configs/10-base.single-node.json)
|
||||
单节点基础配置
|
||||
- [configs/10-base.multi-node.json](./configs/10-base.multi-node.json)
|
||||
多节点基础配置
|
||||
- [configs/20-outbounds.example.json](./configs/20-outbounds.example.json)
|
||||
出站配置模板
|
||||
- [configs/panel-response.vless-reality.json](./configs/panel-response.vless-reality.json)
|
||||
VLESS REALITY 面板回包
|
||||
- [configs/panel-response.shadowsocks2022.json](./configs/panel-response.shadowsocks2022.json)
|
||||
Shadowsocks 2022 面板回包
|
||||
- [configs/panel-response.anytls-acme-dns.json](./configs/panel-response.anytls-acme-dns.json)
|
||||
AnyTLS + ACME DNS 验证面板回包
|
||||
|
||||
## 常见问题
|
||||
|
||||
### `unsupported protocol: empty`
|
||||
|
||||
原因通常是:
|
||||
|
||||
- 面板没有返回 `protocol`
|
||||
- 兼容字段 `node_type` 也为空
|
||||
|
||||
建议:
|
||||
|
||||
- 面板显式返回顶层 `protocol`
|
||||
|
||||
### `Xboard setup error: missing certificate`
|
||||
|
||||
原因通常是:
|
||||
|
||||
- AnyTLS / Trojan / Hysteria / TUIC 需要证书
|
||||
- 面板没有下发证书文件、证书内容或 ACME 参数
|
||||
|
||||
### `TLS handshake: REALITY: processed invalid connection`
|
||||
|
||||
多数情况下表示客户端参数和当前 REALITY 节点配置不匹配,例如:
|
||||
|
||||
- `server_name` 错误
|
||||
- `public_key` 错误
|
||||
- `short_id` 错误
|
||||
- 客户端实际上不是按 REALITY 模式连入
|
||||
|
||||
### `Server does not exist`
|
||||
|
||||
通常是:
|
||||
|
||||
- 面板里不存在该 `node_id`
|
||||
- `token` 不匹配
|
||||
- 拉取配置或拉取用户的节点 ID 写错
|
||||
|
||||
### 真实 IP 没有正确获取
|
||||
|
||||
请确认:
|
||||
|
||||
1. 前置代理确实发送了 PROXY protocol
|
||||
2. 面板确实下发了 `accept_proxy_protocol: true`
|
||||
|
||||
否则服务只能看到上游代理 IP。
|
||||
|
||||
## 开发验证
|
||||
|
||||
近期已验证通过的命令:
|
||||
|
||||
```bash
|
||||
go test ./common/dnspod ./common/tls ./service/acme ./service/xboard
|
||||
go build -trimpath -tags 'with_quic,with_utls,with_clash_api,with_gvisor,with_acme' ./cmd/sing-box
|
||||
```
|
||||
|
||||
如果你改动了 Xboard、协议映射、ACME 或证书相关逻辑,建议至少执行一次以上命令。
|
||||
|
||||
## License
|
||||
|
||||
```
|
||||
```text
|
||||
Copyright (C) 2022 by nekohasekai <contact-sagernet@sekai.icu>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
||||
50
configs/10-base.multi-node.json
Normal file
50
configs/10-base.multi-node.json
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"log": {
|
||||
"level": "info",
|
||||
"timestamp": true
|
||||
},
|
||||
"experimental": {
|
||||
"cache_file": {
|
||||
"enabled": true,
|
||||
"path": "/var/lib/sing-box/cache.db"
|
||||
}
|
||||
},
|
||||
"dns": {
|
||||
"servers": [
|
||||
{
|
||||
"tag": "dns-local",
|
||||
"type": "local"
|
||||
}
|
||||
]
|
||||
},
|
||||
"services": [
|
||||
{
|
||||
"type": "xboard",
|
||||
"panel_url": "https://panel.example.com",
|
||||
"key": "replace-with-node-token",
|
||||
"sync_interval": "1m",
|
||||
"report_interval": "1m",
|
||||
"nodes": [
|
||||
{
|
||||
"node_id": 286
|
||||
},
|
||||
{
|
||||
"node_id": 774
|
||||
},
|
||||
{
|
||||
"node_id": 815
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inbounds": [],
|
||||
"route": {
|
||||
"rules": [
|
||||
{
|
||||
"protocol": "dns",
|
||||
"action": "hijack-dns"
|
||||
}
|
||||
],
|
||||
"auto_detect_interface": true
|
||||
}
|
||||
}
|
||||
42
configs/10-base.single-node.json
Normal file
42
configs/10-base.single-node.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"log": {
|
||||
"level": "info",
|
||||
"timestamp": true
|
||||
},
|
||||
"experimental": {
|
||||
"cache_file": {
|
||||
"enabled": true,
|
||||
"path": "/var/lib/sing-box/cache.db"
|
||||
}
|
||||
},
|
||||
"dns": {
|
||||
"servers": [
|
||||
{
|
||||
"tag": "dns-upstream",
|
||||
"type": "udp",
|
||||
"server": "1.1.1.1",
|
||||
"server_port": 53
|
||||
}
|
||||
]
|
||||
},
|
||||
"services": [
|
||||
{
|
||||
"type": "xboard",
|
||||
"panel_url": "https://panel.example.com",
|
||||
"key": "replace-with-node-token",
|
||||
"sync_interval": "1m",
|
||||
"report_interval": "1m",
|
||||
"node_id": 286
|
||||
}
|
||||
],
|
||||
"inbounds": [],
|
||||
"route": {
|
||||
"rules": [
|
||||
{
|
||||
"protocol": "dns",
|
||||
"action": "hijack-dns"
|
||||
}
|
||||
],
|
||||
"auto_detect_interface": true
|
||||
}
|
||||
}
|
||||
12
configs/20-outbounds.example.json
Normal file
12
configs/20-outbounds.example.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"outbounds": [
|
||||
{
|
||||
"type": "direct",
|
||||
"tag": "direct"
|
||||
},
|
||||
{
|
||||
"type": "block",
|
||||
"tag": "block"
|
||||
}
|
||||
]
|
||||
}
|
||||
33
configs/panel-response.anytls-acme-dns.json
Normal file
33
configs/panel-response.anytls-acme-dns.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"protocol": "anytls",
|
||||
"listen_ip": "0.0.0.0",
|
||||
"server_port": 45365,
|
||||
"network": null,
|
||||
"networkSettings": null,
|
||||
"server_name": "code.example.com",
|
||||
"accept_proxy_protocol": false,
|
||||
"padding_scheme": [
|
||||
"stop=8",
|
||||
"0=30-30",
|
||||
"1=100-400",
|
||||
"2=400-500,c,500-1000,c,500-1000,c,500-1000,c,500-1000",
|
||||
"3=9-9,500-1000",
|
||||
"4=500-1000",
|
||||
"5=500-1000",
|
||||
"6=500-1000",
|
||||
"7=500-1000"
|
||||
],
|
||||
"cert_config": {
|
||||
"cert_mode": "dns",
|
||||
"domain": "code.example.com",
|
||||
"dns_provider": "tencentcloud",
|
||||
"dns_env": {
|
||||
"TENCENTCLOUD_SECRET_ID": "replace-with-secret-id",
|
||||
"TENCENTCLOUD_SECRET_KEY": "replace-with-secret-key"
|
||||
}
|
||||
},
|
||||
"base_config": {
|
||||
"push_interval": 60,
|
||||
"pull_interval": 60
|
||||
}
|
||||
}
|
||||
16
configs/panel-response.shadowsocks2022.json
Normal file
16
configs/panel-response.shadowsocks2022.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"protocol": "shadowsocks",
|
||||
"listen_ip": "0.0.0.0",
|
||||
"server_port": 30009,
|
||||
"network": null,
|
||||
"networkSettings": null,
|
||||
"cipher": "2022-blake3-aes-256-gcm",
|
||||
"plugin": null,
|
||||
"plugin_opts": null,
|
||||
"server_key": "NjQzMWVlNjVmYTkwODk0OTMyOTg3MzZmYzczMmFlMTI=",
|
||||
"accept_proxy_protocol": false,
|
||||
"base_config": {
|
||||
"push_interval": 60,
|
||||
"pull_interval": 60
|
||||
}
|
||||
}
|
||||
21
configs/panel-response.vless-reality.json
Normal file
21
configs/panel-response.vless-reality.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"protocol": "vless",
|
||||
"listen_ip": "0.0.0.0",
|
||||
"server_port": 18443,
|
||||
"network": "tcp",
|
||||
"tls": 2,
|
||||
"flow": "xtls-rprx-vision",
|
||||
"accept_proxy_protocol": false,
|
||||
"tls_settings": {
|
||||
"server_name": "git.example.com",
|
||||
"server_port": "443",
|
||||
"public_key": "replace-with-client-visible-public-key",
|
||||
"private_key": "replace-with-server-private-key",
|
||||
"short_id": "0123456789abcdef",
|
||||
"allow_insecure": false
|
||||
},
|
||||
"base_config": {
|
||||
"push_interval": 60,
|
||||
"pull_interval": 60
|
||||
}
|
||||
}
|
||||
@@ -95,10 +95,6 @@ build_sing_box() {
|
||||
echo -e "${RED}Failed to download Go modules.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
if ! go get github.com/libdns/dnspod@v0.0.3 github.com/libdns/tencentcloud@v1.4.3; then
|
||||
echo -e "${RED}Failed to download ACME DNS provider modules.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
if ! go mod tidy; then
|
||||
echo -e "${RED}Failed to refresh Go module metadata.${NC}"
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user