sing-box
Github Repo
前置工作
目录结构
准备一个目录,构建好如下结构:
text
/opt/singbox
├─ .env
├─ docker-compose.yml
├─ templates/
│ └─ config.json.template
├─ generated/
│ └─ config.json
├─ data/
├─ www/
└─ ssl/
└─ example.com/
├─ fullchain.pem
└─ privkey.pem证书准备
VLESS + Reality 不依赖你自己的证书域名做握手目标Hysteria2 / Naive / TUIC 都依赖你自己的真实 TLS 证书
所以你需要把 example.com 对应的证书放到:
text
/opt/singbox/ssl/example.com/fullchain.pem
/opt/singbox/ssl/example.com/privkey.pem密钥和凭据
1)生成 Reality 密钥对
TLS 文档明确写了:Reality 服务端要用 private_key,客户端要用 public_key,都由 sing-box generate reality-keypair 生成。short_id 是必填,长度是 0 到 8 位十六进制字符串。(Sing Box)
bash
docker run --rm ghcr.io/sagernet/sing-box generate reality-keypair你会拿到两项:
PrivateKey→ 服务端配置里用PublicKey→ 客户端配置里用
自己再准备一个 8 位十六进制 short_id,例如:
bash
openssl rand -hex 82)生成 UUID
给 VLESS 和 TUIC 各准备一个 UUID:
bash
cat /proc/sys/kernel/random/uuid
cat /proc/sys/kernel/random/uuid3)生成强密码
给 Hysteria2、Naive、TUIC 分别准备长随机密码:
bash
openssl rand -base64 24
openssl rand -base64 24
openssl rand -base64 24
openssl rand -base64 24其中 Hysteria2 我建议准备两个:
passwordobfs.password
templates/config.json.template
把下面内容保存为 /opt/singbox/templates/config.json.template:
json
{
"log": {
"level": "${LOG_LEVEL}",
"timestamp": true
},
"inbounds": [
{
"type": "vless",
"tag": "vless-reality-in",
"listen": "::",
"listen_port": ${VLESS_PORT},
"users": [
{
"name": "vless-user",
"uuid": "${VLESS_UUID}",
"flow": "xtls-rprx-vision"
}
],
"tls": {
"enabled": true,
"server_name": "${REALITY_HANDSHAKE_SERVER}",
"min_version": "1.3",
"max_version": "1.3",
"reality": {
"enabled": true,
"handshake": {
"server": "${REALITY_HANDSHAKE_SERVER}",
"server_port": ${REALITY_HANDSHAKE_PORT}
},
"private_key": "${REALITY_PRIVATE_KEY}",
"short_id": [
"${REALITY_SHORT_ID}"
],
"max_time_difference": "1m"
}
}
},
{
"type": "hysteria2",
"tag": "hy2-in",
"listen": "::",
"listen_port": ${HY2_PORT},
"up_mbps": ${HY2_UP_MBPS},
"down_mbps": ${HY2_DOWN_MBPS},
"obfs": {
"type": "salamander",
"password": "${HY2_OBFS_PASSWORD}"
},
"users": [
{
"name": "hy2-user",
"password": "${HY2_PASSWORD}"
}
],
"ignore_client_bandwidth": false,
"tls": {
"enabled": true,
"certificate_path": "${TLS_CERT_PATH}",
"key_path": "${TLS_KEY_PATH}",
"min_version": "1.3",
"max_version": "1.3",
"alpn": [
"h3"
]
},
"masquerade": {
"type": "file",
"directory": "/srv/www"
}
},
{
"type": "naive",
"tag": "naive-in",
"listen": "::",
"listen_port": ${NAIVE_PORT},
"users": [
{
"username": "${NAIVE_USERNAME}",
"password": "${NAIVE_PASSWORD}"
}
],
"tls": {
"enabled": true,
"certificate_path": "${TLS_CERT_PATH}",
"key_path": "${TLS_KEY_PATH}"
}
},
{
"type": "tuic",
"tag": "tuic-in",
"listen": "::",
"listen_port": ${TUIC_PORT},
"users": [
{
"name": "tuic-user",
"uuid": "${TUIC_UUID}",
"password": "${TUIC_PASSWORD}"
}
],
"congestion_control": "${TUIC_CONGESTION_CONTROL}",
"auth_timeout": "3s",
"zero_rtt_handshake": false,
"heartbeat": "10s",
"tls": {
"enabled": true,
"certificate_path": "${TLS_CERT_PATH}",
"key_path": "${TLS_KEY_PATH}",
"min_version": "1.3",
"max_version": "1.3",
"alpn": [
"h3"
]
}
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct"
},
{
"type": "block",
"tag": "block"
}
],
"route": {
"final": "direct"
}
}env
TZ=UTC
HOST_IP=0.0.0.0
VLESS_PORT=17000
HY2_PORT=26000
NAIVE_PORT=35000
TUIC_PORT=48000
SERVER_DOMAIN=example.com
REALITY_HANDSHAKE_SERVER=www.microsoft.com
REALITY_HANDSHAKE_PORT=443
VLESS_UUID=
REALITY_PRIVATE_KEY=
REALITY_PUBLIC_KEY=
REALITY_SHORT_ID=
HY2_PASSWORD=
HY2_OBFS_PASSWORD=
HY2_UP_MBPS=200
HY2_DOWN_MBPS=200
NAIVE_USERNAME=naive-user
NAIVE_PASSWORD=
TUIC_UUID=
TUIC_PASSWORD=
TUIC_CONGESTION_CONTROL=cubic
LOG_LEVEL=warn
TLS_CERT_PATH=/etc/ssl/sing-box/fullchain.pem
TLS_KEY_PATH=/etc/ssl/sing-box/privkey.pemdocker-compose
yaml
networks:
1panel-network:
external: true
services:
singbox-config:
image: alpine:3.20
container_name: singbox-config
restart: "no"
env_file:
- .env
volumes:
- ./templates:/templates:ro
- ./generated:/generated
command: >
sh -c "
apk add --no-cache gettext &&
envsubst < /templates/config.json.template > /generated/config.json &&
echo 'generated /generated/config.json'
"
networks:
- 1panel-network
sing-box:
image: ghcr.io/sagernet/sing-box:latest
container_name: sing-box
restart: unless-stopped
depends_on:
singbox-config:
condition: service_completed_successfully
env_file:
- .env
ports:
- ${HOST_IP}:${VLESS_PORT}:${VLESS_PORT}/tcp
- ${HOST_IP}:${HY2_PORT}:${HY2_PORT}/udp
- ${HOST_IP}:${NAIVE_PORT}:${NAIVE_PORT}/tcp
- ${HOST_IP}:${TUIC_PORT}:${TUIC_PORT}/udp
volumes:
- ./generated:/etc/sing-box:ro
- ./data:/var/lib/sing-box
- ./www:/srv/www:ro
- ./ssl/example.com:/etc/ssl/sing-box:ro
command: -D /var/lib/sing-box -C /etc/sing-box run
read_only: true
tmpfs:
- /tmp
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
networks:
- 1panel-networksingbox-config 只负责把模板渲染成 generated/config.json
防火墙记得放开对应端口