Ubuntu 24.04 配置 Sing-box 代理服务器完整指南
在服务器上跑一个本地代理,让终端和 Docker 都走它,是部署里很常见的一步。这篇按 sing-box 当前文档(1.14 线)整理,配置在本机用
sing-box check与真实启动 +curl -x双向验证过。
如果你照抄的是 2023–2024 年的教程,大概率会在启动时直接失败:inbounds[].sniff在 1.13.0 被移除、geoip路由规则在 1.12.0 被移除,两者都会让 1.13 以上的版本拒绝加载配置。
1. 什么是 Sing-box
sing-box 是一个通用代理平台,服务端与客户端共用一个二进制。它支持 VMess、VLESS、Trojan、Shadowsocks、Hysteria、WireGuard 等协议,可以在服务器上把远端代理转成(或直接暴露为)本机可用的 SOCKS5 / HTTP 代理。
它的配置格式在 1.x 期间改动频繁,每次大改都会把旧字段标记 deprecated,过一两个版本再移除。所以用 sing-box 的第一条经验是:配置以官方文档为准,并留意 Deprecated 页面。
2. 准备工作
- 一台能访问外网的服务器(Ubuntu 24.04 为例),有
sudo权限 - 可用的代理服务端信息(协议、地址、端口、UUID/密码、TLS 域名)
- 已确认协议与 TLS 参数,这些要写进
outbounds
3. 安装
3.1 用官方 APT 仓库(推荐)
sing-box 有官方软件源,装完即带 systemd 服务,后续 apt upgrade 就能升级:
1 | sudo mkdir -p /etc/apt/keyrings && |
想要预览版把包名换成
sing-box-beta。这条命令取自官方 Package Manager 文档,keyring 与Signed-By是 apt 校验仓库签名的必需项,别省略。
3.2 用官方安装脚本(非 Debian 系或不想加源时)
1 | curl -fsSL https://sing-box.app/install.sh | sh |
脚本会从 GitHub Releases 取对应平台的最新包;需要指定版本时加 --version <version>,要 beta 加 --beta。
3.3 手动下载二进制
只用某个版本的临时场景可以在 Releases 页面下包:
1 | VERSION=1.14.1 # 到 https://github.com/SagerNet/sing-box/releases 确认当前版本 |
发布页的文件名带版本号。旧教程里常见的
releases/latest/download/sing-box-linux-amd64.tar.gz是固定链接的写法,现在会直接 404——这是我写这篇时实测确认的。Debian/Ubuntu 用 glibc 版本;Alpine 等 musl 系统要选文件名带-musl的包;ARM 服务器把amd64换成arm64。
4. 配置
4.1 配置文件位置
官方包把配置目录设在 /etc/sing-box:
1 | sudo vim /etc/sing-box/config.json |
4.2 示例配置
1 | { |
要改的地方:
your-server-ip/your-uuid-here/your-domain.com换成实际值outbounds按协议调整(Trojan、Shadowsocks 的字段名与 TLS 写法都不同,见官方 configuration 目录)- 想默认走代理,可在
route里加{"outbound": "vmess-out"}作为兜底规则
4.3 两处与旧教程不同、且会直接导致启动失败的地方
域名嗅探不再是入站字段。 旧配置在每个 inbound 里写 "sniff": true;该字段在 1.11.0 弃用、1.13.0 移除,现在改为路由规则动作 {"action": "sniff"},效果等价于「在路由之前嗅探」。
GeoIP 规则已移除。 旧的 {"geoip": "private", "outbound": "direct"} 在 1.8.0 弃用、1.12.0 移除。判断内网地址改用 ip_is_private;更复杂的按国家/地区分流要用 rule_set 引用规则集文件,不再有内置 GeoIP 数据库。
两条都在官方 Deprecated 页有记录,升级或照抄配置前值得扫一眼:https://sing-box.sagernet.org/deprecated/。
4.4 验证配置
1 | sing-box check -c /etc/sing-box/config.json |
配置正确时没有任何输出、退出码 0(用 echo $? 确认;旧版本会打印 config check passed,现在不打印了)。配置有问题会打印 FATAL 一行。把上面配置换回带 sniff 的旧写法,1.14.1 的实际输出是:
1 | FATAL[0000] decode config at config.json: inbounds[0]: legacy inbound fields are deprecated in sing-box 1.11.0 and removed in sing-box 1.13.0, checkout migration: https://sing-box.sagernet.org/migration/#migrate-legacy-inbound-fields-to-rule-actions |
4.5 启动前先手动跑一次
check 只验证语法与字段,不证明代理真的能用。正式配服务之前先前台跑一遍:
1 | sudo sing-box run -c /etc/sing-box/config.json |
正常时能看到两个入站开始监听:
1 | INFO inbound/socks[socks-in]: tcp server started at 127.0.0.1:10808 |
然后另开一个终端,两个入站都测:
1 | curl -x http://127.0.0.1:10809 -s -o /dev/null -w '%{http_code}\n' https://example.com |
两个都返回 200 说明入站、路由与出站串通了。日志里对应的连接长这样:
1 | INFO [1013616736 0ms] inbound/socks[socks-in]: inbound connection from 127.0.0.1:53406 |
5. 配置系统服务
如果你用第 3.1 节的官方包安装,systemd 服务已经随包装好,直接用即可:
1 | sudo systemctl enable --now sing-box |
日志按官方文档的写法看:
1 | sudo journalctl -u sing-box --output cat -e # 最近的日志 |
如果用的是手动下载的二进制,需要自己写 unit。下面是官方 deb 包内置的单元(/usr/lib/systemd/system/sing-box.service),只把可执行文件路径改成手动安装的位置 /usr/local/bin/sing-box:
1 | [Unit] |
1 | sudo useradd --system --no-create-home sing-box # 单元里指定了 User=sing-box |
说明几点:
-D /var/lib/sing-box是工作目录(缓存等运行期文件),StateDirectory=会让 systemd 自动建好并处理权限-C /etc/sing-box表示加载该目录下所有.json;只用一个文件时也可以写成run -c /etc/sing-box/config.json- 官方包还带一个模板单元
sing-box@.service,systemctl start sing-box@home会加载/etc/sing-box/home.json,适合一台机器跑多份配置 - 那几项
CapabilityBoundingSet是给 TUN / 透明代理预留的;纯 SOCKS/HTTP 入站用不上,但保留它们不影响运行
6. 测试代理连接
6.1 终端临时使用
1 | export http_proxy=http://127.0.0.1:10809 |
6.2 永久写入 shell 配置
1 | echo 'export http_proxy=http://127.0.0.1:10809' >> ~/.bashrc |
zsh 用户写 ~/.zshrc。注意环境变量只对交互式 shell 与显式继承的程序生效,守护进程(包括 Docker)不会读到它们,需要单独配置——见下一节。
7. 让 Docker 走代理
Docker 守护进程要单独告诉它代理地址,否则 docker pull 不会经过 sing-box:
1 | sudo mkdir -p /etc/systemd/system/docker.service.d |
1 | [Service] |
NO_PROXY 里记得放两样东西:内网网段(避免容器间调用被绕进代理),以及你自己的私有 registry 域名。漏掉后者时,docker pull 会拿代理去访问一个只能内网到达的地址,报连接超时。
1 | sudo systemctl daemon-reload |
上面这段只解决守护进程拉镜像这一层。还有两层它管不到,需要另外配:
容器里跑的程序(比如前面那个下载服务)不继承守护进程的代理,要在运行时注入:
1 | docker run -e HTTP_PROXY=http://172.17.0.1:10809 -e HTTPS_PROXY=http://172.17.0.1:10809 ... |
172.17.0.1 是默认 bridge 网络的网关地址,用 ip -4 addr show docker0 确认;自定义网络下形如 172.18.0.1,用 docker network inspect <网络名> 看 Gateway 字段。注意 sing-box 的入站默认只监听 127.0.0.1,容器连不上,要把它绑到网关上:
1 | { |
绑非回环地址之后务必用防火墙把来源限定在 docker 网段,否则同网段的机器都能拿它当代理用。
代理不可用时的排查顺序:先确认 sing-box 在跑(systemctl status sing-box),再看 docker pull 报的是连接超时还是 407 之类的鉴权错误。代理挂了而代理配置还在的话,所有镜像拉取都会失败,这是最先表现出来的症状。
docker build 的 RUN 步骤(apt install、pip install 这些)走的是客户端配置,写 ~/.docker/config.json:
1 | { |
两种方式等价;官方现在更推荐把守护进程代理写进 /etc/docker/daemon.json 的 proxies 键,两处都配时 daemon.json 优先。
8. 故障排除
8.1 常见问题
服务启动失败:先看报错文本,字段被移除类的错误会直接点明版本:
1 | sing-box check -c /etc/sing-box/config.json |
端口没有监听:netstat 属于 net-tools,Ubuntu 24.04 默认不装,用 ss:
1 | sudo ss -tlnp | grep sing-box |
测试代理端口是否可用:telnet 同样默认未安装,用 curl 即可(nc 需要 sudo apt install netcat-openbsd):
1 | curl -x socks5h://127.0.0.1:10808 -s -o /dev/null -w '%{http_code}\n' https://example.com |
Docker 仍不走代理:确认 unit 覆盖生效(systemctl show docker --property=Environment),并注意 NO_PROXY 里是否误包含了目标域名。
8.2 安全建议
- 入站只监听
127.0.0.1,需要给局域网使用时用防火墙限定来源 IP - 定期升级:
sudo apt upgrade sing-box(官方源安装时);手动安装的到 Releases 页取新包 - 开启日志轮转,避免
journalctl无限增长 - 配置文件含密钥,
sudo chmod 600 /etc/sing-box/config.json
9. 管理命令
1 | sudo systemctl start sing-box # 启动 |
总结
- 优先用官方 APT 源安装:自带 systemd 服务,升级跟着
apt走 - 配置按当前文档写:
sniff用路由动作、内网判断用ip_is_private,inbounds[].sniff与geoip都已被移除 sing-box check静默通过才算语法正确,但必须再手动run一次并用curl -x验证,否则不知道出站是否真的通- Docker 守护进程不读 shell 的环境变量,拉镜像要单独写
docker.service.d/proxy.conf(或/etc/docker/daemon.json的proxies),并且NO_PROXY要包含内网网段与私有 registry - 容器内程序与
docker build的 RUN 步骤读的是客户端配置~/.docker/config.json的proxies,与守护进程那层互不相通
参考链接
系列索引:网络与自建服务





