- deploy/: Xray VLESS+REALITY (11443, 经宿主 nginx SNI 分流) + sing-box Hysteria2 (UDP 443) docker-compose - 幂等 deploy.sh / gen-secrets.sh / print-clients.sh;受限 nginx-apply 特权脚本 + 一次性 root-setup - .gitea/workflows/deploy.yml: NAS runner 经 SSH 远程部署到 EC2 - docs/ plan/: 设计方案与实施计划 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
# 可选环境变量(deploy.sh / print-clients.sh 读取)。
|
||||
# 真正的密钥由 gen-secrets.sh 自动生成到 deploy/secrets/pangolin.env,无需手填。
|
||||
|
||||
# 覆盖客户端导入串里的服务器地址(默认自动取 EC2 公网 IP)
|
||||
# PANGOLIN_PUBLIC_IP=18.136.60.128
|
||||
|
||||
# root-setup.sh 授权的部署用户(默认 ec2-user)
|
||||
# PANGOLIN_DEPLOY_USER=ec2-user
|
||||
@@ -0,0 +1,50 @@
|
||||
# Pangolin 部署(Phase 0)
|
||||
|
||||
容器化数据面:**Xray VLESS+REALITY** + **sing-box Hysteria2**,经 CI/CD 自动部署到节点。
|
||||
与现网 marzban/blog/jiu 完全隔离。设计详见 [`../docs/技术方案.md`](../docs/技术方案.md) 与 [`../plan/`](../plan/)。
|
||||
|
||||
## 端口与隔离
|
||||
|
||||
| 服务 | 监听 | 经由 | 说明 |
|
||||
|------|------|------|------|
|
||||
| Xray REALITY | 容器内 `0.0.0.0:11443` → 宿主 `127.0.0.1:11443` | 宿主 nginx `ssl_preread`(SNI=`www.apple.com`)| 复用 443/TCP,不占公网端口 |
|
||||
| sing-box Hy2 | 公网 `0.0.0.0:443/udp` | 直接暴露 | 与 TCP 443 不同协议栈,互不冲突 |
|
||||
|
||||
现网 Marzban xray 在 `10443`、各站在 `8443-8445`,均不受影响。
|
||||
|
||||
## 自动部署链路
|
||||
|
||||
```
|
||||
本地改 deploy/** → push gitea(NAS) → NAS act_runner → ssh ec2 → docker-compose up + nginx 增量 reload
|
||||
```
|
||||
|
||||
## 一次性前置(首次,人工)
|
||||
|
||||
1. **安全组开 UDP 443**(本地 aws):给 `sg-040cf4cd11bdf4d5b` 加 `udp/443 0.0.0.0/0`。
|
||||
2. **root 前置**(EC2 上一次,需 root):
|
||||
```bash
|
||||
sudo bash /opt/pangolin/setup/root-setup.sh
|
||||
```
|
||||
安装受限特权脚本 `pangolin-nginx-apply.sh` + sudoers,使 CI 能非交互更新 nginx 路由(且拿不到通用 root)。
|
||||
3. **Gitea Actions Secrets**(仓库 Settings → Actions → Secrets):
|
||||
- `EC2_SSH_KEY` = ec2-user 私钥(可登录 18.136.60.128)
|
||||
- `EC2_HOST` = `18.136.60.128`
|
||||
- `EC2_USER` = `ec2-user`
|
||||
4. **确认 runner label**,据此改 `.gitea/workflows/deploy.yml` 的 `runs-on`。
|
||||
|
||||
## 手动部署(不走 CI)
|
||||
|
||||
```bash
|
||||
rsync -az --exclude secrets deploy/ ec2-user@18.136.60.128:/opt/pangolin/
|
||||
ssh ec2 'cd /opt/pangolin && ./scripts/deploy.sh'
|
||||
```
|
||||
|
||||
## 取客户端导入信息(含密钥,不进日志)
|
||||
|
||||
```bash
|
||||
ssh ec2 'cat /opt/pangolin/secrets/clients.txt'
|
||||
```
|
||||
|
||||
## 幂等性
|
||||
|
||||
`deploy.sh` 可重复执行:密钥已存在则复用、nginx 路由已存在则跳过、compose 无变更则不动。
|
||||
@@ -0,0 +1,28 @@
|
||||
# Pangolin Phase-0 数据面:Xray(VLESS+REALITY) + sing-box(Hysteria2)
|
||||
# 独立 project 名 pangolin,与现网 marzban/blog/jiu 完全隔离。
|
||||
# 镜像固定版本,避免 latest 漂移(EC2 实测:Xray 26.3.27 / sing-box 1.13.12)。
|
||||
name: pangolin
|
||||
|
||||
services:
|
||||
xray:
|
||||
image: ghcr.io/xtls/xray-core:26.3.27
|
||||
container_name: pangolin-xray
|
||||
restart: unless-stopped
|
||||
# 仅监听本地 11443,由宿主 nginx 的 ssl_preread 按 SNI(www.apple.com)转入
|
||||
ports:
|
||||
- "127.0.0.1:11443:11443"
|
||||
volumes:
|
||||
- ./xray/config.json:/etc/xray/config.json:ro
|
||||
command: ["run", "-c", "/etc/xray/config.json"]
|
||||
|
||||
singbox:
|
||||
image: ghcr.io/sagernet/sing-box:v1.13.12
|
||||
container_name: pangolin-singbox
|
||||
restart: unless-stopped
|
||||
# Hysteria2 直接对外暴露 UDP 443(与 TCP 443 不同协议栈,互不冲突)
|
||||
ports:
|
||||
- "443:443/udp"
|
||||
volumes:
|
||||
- ./singbox/config.json:/etc/sing-box/config.json:ro
|
||||
- ./secrets/hy2:/etc/sing-box/cert:ro
|
||||
command: ["run", "-c", "/etc/sing-box/config.json"]
|
||||
Executable
+56
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
# pangolin-nginx-apply.sh —— 受限特权脚本(以 root 安装到 /usr/local/sbin/)
|
||||
#
|
||||
# 作用:把 pangolin REALITY 的 SNI 路由 (www.apple.com -> 127.0.0.1:11443)
|
||||
# 幂等地插入宿主机 nginx 的 stream map,并热重载。
|
||||
#
|
||||
# 安全设计:
|
||||
# - 唯一被 sudoers 授权 NOPASSWD 的命令,作用域锁死本脚本;
|
||||
# - 幂等:已存在则直接退出;
|
||||
# - 改前备份 + nginx -t 校验 + 失败自动回滚,不影响其他服务(热 reload 不断连)。
|
||||
set -euo pipefail
|
||||
|
||||
STREAM_CONF="/etc/nginx/stream.conf"
|
||||
BACKEND="127.0.0.1:11443"
|
||||
SNI="www.apple.com"
|
||||
ROUTE_LINE=" ${SNI} ${BACKEND};"
|
||||
|
||||
if [[ ! -f "$STREAM_CONF" ]]; then
|
||||
echo "[nginx-apply] $STREAM_CONF 不存在,放弃(本机预期已有 nginx)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 幂等:路由已存在则跳过
|
||||
if grep -qF "$BACKEND" "$STREAM_CONF"; then
|
||||
echo "[nginx-apply] 路由已存在,跳过"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
BACKUP="${STREAM_CONF}.pangolin.bak"
|
||||
cp -a "$STREAM_CONF" "$BACKUP"
|
||||
|
||||
TMP="$(mktemp)"
|
||||
# 在 map 的 default 行之前插入我们的 SNI 路由
|
||||
awk -v ins="$ROUTE_LINE" '
|
||||
$0 ~ /default[[:space:]]+127\.0\.0\.1:10443;/ && !done { print ins; done=1 }
|
||||
{ print }
|
||||
' "$STREAM_CONF" > "$TMP"
|
||||
|
||||
# 校验:确实插入了我们的后端,且没有破坏文件
|
||||
if ! grep -qF "$BACKEND" "$TMP"; then
|
||||
echo "[nginx-apply] 插入失败(未找到 default 锚点?),不改动" >&2
|
||||
rm -f "$TMP"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat "$TMP" > "$STREAM_CONF"
|
||||
rm -f "$TMP"
|
||||
|
||||
if nginx -t 2>/dev/null; then
|
||||
nginx -s reload
|
||||
echo "[nginx-apply] 已插入路由并热重载成功"
|
||||
else
|
||||
echo "[nginx-apply] nginx -t 失败,回滚" >&2
|
||||
cp -a "$BACKUP" "$STREAM_CONF"
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1 @@
|
||||
www.apple.com 127.0.0.1:11443;
|
||||
@@ -0,0 +1,23 @@
|
||||
# 仅当宿主机【没有】nginx 时使用的完整 stream 配置(deploy.sh 自动判断)。
|
||||
# 本机已有宿主 nginx,故此文件不会被使用 —— 留作「无 nginx 则先部署」的兜底。
|
||||
#
|
||||
# 用法(deploy.sh 在无 nginx 分支里):
|
||||
# 1. 安装 nginx + stream 模块
|
||||
# 2. 将本文件渲染到 /etc/nginx/stream.conf 并 include
|
||||
# 3. nginx -t && systemctl enable --now nginx
|
||||
|
||||
stream {
|
||||
map $ssl_preread_server_name $pangolin_backend {
|
||||
www.apple.com 127.0.0.1:11443; # pangolin REALITY
|
||||
default 127.0.0.1:11443;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443;
|
||||
listen [::]:443;
|
||||
proxy_pass $pangolin_backend;
|
||||
ssl_preread on;
|
||||
proxy_connect_timeout 10s;
|
||||
proxy_timeout 3600s;
|
||||
}
|
||||
}
|
||||
Executable
+61
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
# deploy.sh —— 在 EC2 上幂等编排 pangolin 数据面。
|
||||
# 由 CI(NAS runner via ssh)调用,也可手动 `ssh ec2 'cd /opt/pangolin && ./scripts/deploy.sh'`。
|
||||
#
|
||||
# 步骤:生成密钥 -> 渲染配置 -> docker-compose up -> (幂等)加 nginx 路由 -> 健康检查 -> 输出客户端信息
|
||||
# 全程不触碰 marzban/blog/jiu;唯一特权动作是 sudo 调用受限的 nginx-apply 脚本。
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.." # -> deploy/
|
||||
|
||||
COMPOSE="docker-compose -p pangolin"
|
||||
NGINX_APPLY="/usr/local/sbin/pangolin-nginx-apply.sh"
|
||||
|
||||
echo "==> [1/5] 生成/复用密钥与证书"
|
||||
./scripts/gen-secrets.sh
|
||||
|
||||
echo "==> [2/5] 渲染配置(模板 -> config.json)"
|
||||
# shellcheck disable=SC1091
|
||||
source ./secrets/pangolin.env
|
||||
render() { # render <tmpl> <out>
|
||||
sed -e "s|__UUID__|${UUID}|g" \
|
||||
-e "s|__REALITY_PRIVATE_KEY__|${REALITY_PRIVATE_KEY}|g" \
|
||||
-e "s|__REALITY_SHORT_ID__|${REALITY_SHORT_ID}|g" \
|
||||
-e "s|__HY2_PASSWORD__|${HY2_PASSWORD}|g" \
|
||||
"$1" > "$2"
|
||||
}
|
||||
render ./xray/config.tmpl.json ./xray/config.json
|
||||
render ./singbox/config.tmpl.json ./singbox/config.json
|
||||
|
||||
echo "==> [3/5] 拉起容器(docker-compose up -d)"
|
||||
$COMPOSE pull --quiet || true
|
||||
$COMPOSE up -d
|
||||
$COMPOSE ps
|
||||
|
||||
echo "==> [4/5] nginx SNI 路由(幂等)"
|
||||
if grep -qF "127.0.0.1:11443" /etc/nginx/stream.conf 2>/dev/null; then
|
||||
echo " 路由已存在,跳过"
|
||||
elif [[ -x "$NGINX_APPLY" ]]; then
|
||||
sudo "$NGINX_APPLY"
|
||||
else
|
||||
echo " !! 未找到 $NGINX_APPLY(需先执行一次性 root 前置 setup/root-setup.sh)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> [5/5] 健康检查"
|
||||
ok=1
|
||||
# REALITY:经宿主 nginx 用 www.apple.com 做 TLS 握手应成功
|
||||
if echo | timeout 10 openssl s_client -connect 127.0.0.1:443 -servername www.apple.com >/dev/null 2>&1; then
|
||||
echo " [REALITY] 443/www.apple.com 握手 OK"
|
||||
else
|
||||
echo " [REALITY] 握手失败"; ok=0
|
||||
fi
|
||||
# Hy2:UDP 443 应有 sing-box 在监听
|
||||
if ss -uln 2>/dev/null | grep -q ":443 "; then
|
||||
echo " [Hy2] UDP 443 监听 OK"
|
||||
else
|
||||
echo " [Hy2] UDP 443 未监听"; ok=0
|
||||
fi
|
||||
|
||||
./scripts/print-clients.sh
|
||||
|
||||
[[ "$ok" == "1" ]] && echo "==> 部署完成 ✅" || { echo "==> 健康检查未通过 ❌"; exit 1; }
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
# gen-secrets.sh —— 首次在 EC2 生成并持久化密钥/证书(幂等)。
|
||||
# 产物存于 ./secrets/(700,gitignore,绝不进仓库/CI 日志)。
|
||||
# - pangolin.env : UUID / REALITY 公私钥 / shortId / Hy2 口令
|
||||
# - hy2/hy2.crt, hy2/hy2.key : Hysteria2 自签证书(ECDSA)
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.." # -> deploy/
|
||||
|
||||
SECRETS_DIR="./secrets"
|
||||
ENV_FILE="${SECRETS_DIR}/pangolin.env"
|
||||
HY2_DIR="${SECRETS_DIR}/hy2"
|
||||
XRAY_IMAGE="ghcr.io/xtls/xray-core:26.3.27"
|
||||
MASQ_CN="www.bing.com"
|
||||
|
||||
mkdir -p "$HY2_DIR"
|
||||
chmod 700 "$SECRETS_DIR"
|
||||
|
||||
if [[ -f "$ENV_FILE" ]]; then
|
||||
echo "[gen-secrets] $ENV_FILE 已存在,跳过密钥生成(幂等)"
|
||||
else
|
||||
echo "[gen-secrets] 生成 REALITY 密钥对 / UUID / shortId / Hy2 口令 ..."
|
||||
# REALITY x25519 密钥对(从 xray 输出解析 Private/Public)
|
||||
KP="$(docker run --rm "$XRAY_IMAGE" x25519)"
|
||||
REALITY_PRIVATE_KEY="$(printf '%s\n' "$KP" | awk -F': ' '/Private/{print $2}')"
|
||||
REALITY_PUBLIC_KEY="$(printf '%s\n' "$KP" | awk -F': ' '/Public/{print $2}')"
|
||||
UUID="$(cat /proc/sys/kernel/random/uuid)"
|
||||
REALITY_SHORT_ID="$(openssl rand -hex 8)"
|
||||
HY2_PASSWORD="$(openssl rand -base64 18 | tr -d '/+=' | cut -c1-24)"
|
||||
|
||||
umask 177
|
||||
cat > "$ENV_FILE" <<EOF
|
||||
# pangolin Phase-0 secrets —— 切勿提交/外泄
|
||||
UUID=${UUID}
|
||||
REALITY_PRIVATE_KEY=${REALITY_PRIVATE_KEY}
|
||||
REALITY_PUBLIC_KEY=${REALITY_PUBLIC_KEY}
|
||||
REALITY_SHORT_ID=${REALITY_SHORT_ID}
|
||||
HY2_PASSWORD=${HY2_PASSWORD}
|
||||
EOF
|
||||
echo "[gen-secrets] 已写入 $ENV_FILE"
|
||||
fi
|
||||
|
||||
# Hysteria2 自签证书(幂等)
|
||||
if [[ -f "${HY2_DIR}/hy2.crt" && -f "${HY2_DIR}/hy2.key" ]]; then
|
||||
echo "[gen-secrets] Hy2 证书已存在,跳过"
|
||||
else
|
||||
echo "[gen-secrets] 生成 Hy2 自签证书 (CN=${MASQ_CN}) ..."
|
||||
openssl ecparam -genkey -name prime256v1 -out "${HY2_DIR}/hy2.key"
|
||||
openssl req -new -x509 -days 3650 -key "${HY2_DIR}/hy2.key" \
|
||||
-out "${HY2_DIR}/hy2.crt" -subj "/CN=${MASQ_CN}"
|
||||
# sing-box 容器内以 root 运行,证书需可读
|
||||
chmod 644 "${HY2_DIR}/hy2.crt" "${HY2_DIR}/hy2.key"
|
||||
echo "[gen-secrets] 已写入 Hy2 证书"
|
||||
fi
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# print-clients.sh —— 生成两条客户端导入串,写入 ./secrets/clients.txt。
|
||||
# 注意:含口令/密钥,【不打印到 stdout】以免进入 CI 日志;手动 `ssh ec2 cat` 取用。
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.." # -> deploy/
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source ./secrets/pangolin.env
|
||||
|
||||
# 公网 IP:优先 IMDSv2,可用 PANGOLIN_PUBLIC_IP 覆盖
|
||||
HOST="${PANGOLIN_PUBLIC_IP:-}"
|
||||
if [[ -z "$HOST" ]]; then
|
||||
TOKEN="$(curl -s -X PUT 'http://169.254.169.254/latest/api/token' -H 'X-aws-ec2-metadata-token-ttl-seconds: 60' || true)"
|
||||
HOST="$(curl -s -H "X-aws-ec2-metadata-token: ${TOKEN}" http://169.254.169.254/latest/meta-data/public-ipv4 || true)"
|
||||
fi
|
||||
[[ -z "$HOST" ]] && HOST="YOUR_SERVER_IP"
|
||||
|
||||
REALITY_LINK="vless://${UUID}@${HOST}:443?encryption=none&flow=xtls-rprx-vision&security=reality&sni=www.apple.com&fp=chrome&pbk=${REALITY_PUBLIC_KEY}&sid=${REALITY_SHORT_ID}&type=tcp#pangolin-reality"
|
||||
HY2_LINK="hysteria2://${HY2_PASSWORD}@${HOST}:443?insecure=1&sni=www.bing.com#pangolin-hy2"
|
||||
|
||||
OUT="./secrets/clients.txt"
|
||||
umask 177
|
||||
cat > "$OUT" <<EOF
|
||||
# pangolin Phase-0 客户端导入信息 (生成于 $(date -u +%FT%TZ))
|
||||
# 含敏感信息,勿外泄。
|
||||
|
||||
[REALITY / VLESS+Vision] —— 平时主线
|
||||
${REALITY_LINK}
|
||||
|
||||
[Hysteria2] —— 晚高峰加速线(自签证书,客户端需允许不安全/insecure)
|
||||
${HY2_LINK}
|
||||
|
||||
字段速查:
|
||||
server = ${HOST}
|
||||
REALITY sni = www.apple.com port=443/tcp flow=xtls-rprx-vision
|
||||
REALITY pbk = ${REALITY_PUBLIC_KEY}
|
||||
REALITY sid = ${REALITY_SHORT_ID}
|
||||
uuid = ${UUID}
|
||||
Hy2 sni = www.bing.com port=443/udp insecure=1
|
||||
EOF
|
||||
echo "[print-clients] 已写入 ${OUT}(用 'ssh ec2 cat /opt/pangolin/secrets/clients.txt' 取用)"
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
# root-setup.sh —— 一次性 root 前置(在 EC2 上以 root 执行一次)。
|
||||
# sudo bash /opt/pangolin/setup/root-setup.sh
|
||||
#
|
||||
# 作用:
|
||||
# 1. 安装受限特权脚本到 /usr/local/sbin/pangolin-nginx-apply.sh(root:root 0755)
|
||||
# 2. 安装 sudoers 片段,授权 ec2-user 仅 NOPASSWD 调用上述脚本
|
||||
# 之后 CI(ec2-user)即可非交互地增量更新 nginx 路由,且无法获得通用 root。
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "$(id -u)" -ne 0 ]]; then
|
||||
echo "请以 root 运行:sudo bash $0" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SRC_DIR="$(cd "$(dirname "$0")/.." && pwd)" # -> /opt/pangolin/deploy 或仓库 deploy/
|
||||
APPLY_SRC="${SRC_DIR}/nginx/pangolin-nginx-apply.sh"
|
||||
APPLY_DST="/usr/local/sbin/pangolin-nginx-apply.sh"
|
||||
SUDOERS="/etc/sudoers.d/pangolin"
|
||||
DEPLOY_USER="${PANGOLIN_DEPLOY_USER:-ec2-user}"
|
||||
|
||||
[[ -f "$APPLY_SRC" ]] || { echo "找不到 $APPLY_SRC" >&2; exit 1; }
|
||||
|
||||
install -o root -g root -m 0755 "$APPLY_SRC" "$APPLY_DST"
|
||||
echo "[root-setup] 已安装 $APPLY_DST"
|
||||
|
||||
cat > "$SUDOERS" <<EOF
|
||||
${DEPLOY_USER} ALL=(root) NOPASSWD: ${APPLY_DST}
|
||||
EOF
|
||||
chmod 0440 "$SUDOERS"
|
||||
visudo -cf "$SUDOERS" >/dev/null && echo "[root-setup] 已安装并校验 $SUDOERS"
|
||||
|
||||
echo "[root-setup] 完成。现在 ${DEPLOY_USER} 可执行: sudo ${APPLY_DST}"
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"log": { "level": "warn", "timestamp": true },
|
||||
"inbounds": [
|
||||
{
|
||||
"type": "hysteria2",
|
||||
"tag": "hy2-in",
|
||||
"listen": "::",
|
||||
"listen_port": 443,
|
||||
"users": [
|
||||
{ "name": "phase0", "password": "__HY2_PASSWORD__" }
|
||||
],
|
||||
"masquerade": "https://www.bing.com",
|
||||
"tls": {
|
||||
"enabled": true,
|
||||
"alpn": ["h3"],
|
||||
"certificate_path": "/etc/sing-box/cert/hy2.crt",
|
||||
"key_path": "/etc/sing-box/cert/hy2.key"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{ "type": "direct", "tag": "direct" }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"log": { "loglevel": "warning" },
|
||||
"inbounds": [
|
||||
{
|
||||
"tag": "vless-reality-in",
|
||||
"listen": "0.0.0.0",
|
||||
"port": 11443,
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"clients": [
|
||||
{ "id": "__UUID__", "flow": "xtls-rprx-vision" }
|
||||
],
|
||||
"decryption": "none"
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "tcp",
|
||||
"security": "reality",
|
||||
"realitySettings": {
|
||||
"show": false,
|
||||
"dest": "www.apple.com:443",
|
||||
"xver": 0,
|
||||
"serverNames": ["www.apple.com"],
|
||||
"privateKey": "__REALITY_PRIVATE_KEY__",
|
||||
"shortIds": ["__REALITY_SHORT_ID__"]
|
||||
}
|
||||
},
|
||||
"sniffing": {
|
||||
"enabled": true,
|
||||
"destOverride": ["http", "tls", "quic"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{ "protocol": "freedom", "tag": "direct" }
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user