July 12, 2025

Windows 下 sing-box tun 全局代理配置踩坑记

背景

最近在 Windows 系统上配置 sing-box 的 tun 模式全局代理时,遇到了一个典型的"虚拟网卡冲突"问题。经过一番折腾,最终发现问题的根源和解决方案。记录下这个过程,希望能帮助遇到类似问题的朋友。

过程有大模型辅助

问题描述

目标是配置 sing-box 的 tun 模式,实现系统级别的全局代理,让所有流量(包括 curl、浏览器等)都经过 sing-box 转发。更重要的是,我们要通过 SSH 隧道将本地的 socks5 代理分享到远程服务器

整体架构

本地 Windows 机器 (192.168.5.20)
├── sing-box (tun 模式,全局代理)
├── socks5 代理 (127.0.0.1:7890)
└── SSH 隧道 (将本地 7890 端口转发到远程)

配置过程

1. 建立 SSH 隧道

首先建立 SSH 隧道,将本地的 socks5 代理端口转发到远程:

ssh -R 7890:127.0.0.1:7890 -N -f [email protected]

这个命令的含义:

  • -R 7890:127.0.0.1:7890:将远程的 7890 端口转发到本地的 127.0.0.1:7890
  • -N:不执行远程命令,仅用于端口转发
  • -f:后台运行
  • [email protected]:目标服务器

2. 初始配置文件

创建 sing-box 配置文件 config.json

{
    // 日志配置
    "log": {
        "level": "debug",
        "timestamp": true
    },
    // 入站连接配置
    "inbounds": [
        {
            "type": "tun",
            "tag": "tun-in",
            "interface_name": "tun0",
            "mtu": 1500,
            "strict_route": true,
            "auto_route": true,
            "stack": "gvisor",
            "endpoint_independent_nat": true,
            "sniff": true,
            "sniff_override_destination": true
        }
    ],
    // 出站连接配置
    "outbounds": [
        {
            "type": "socks",
            "tag": "socks-out",
            "server": "127.0.0.1",
            "server_port": 7890,
            "version": "5"
        }
    ]
}

3. 第一个问题:配置文件解析失败

启动 sing-box 后发现,虽然进程启动了,但 tun 功能没有生效。检查发现:

  • tun0 网卡创建了,但 IP 是系统自动分配的 169.254.34.95
  • 路由表没有自动修改,默认路由依然指向物理网卡
  • curl 流量没有经过 sing-box

原因:JSON 文件中的注释导致 sing-box 解析失败,auto_route 等功能没有生效。

解决:清理配置文件,去除所有注释,确保是合法的 JSON 格式。

4. 第二个问题:手动分配 IP 冲突

为了测试,手动为 tun0 分配了 IP:

netsh interface ip set address name="tun0" static 10.10.0.2 255.255.255.0

这导致 tun0 有了正确的 IP,但 sing-box 无法接管。

5. 第三个问题:虚拟网卡冲突

重启 sing-box 时出现错误:

FATAL[0000] start service: start inbound/tun[tun-in]: configure tun interface: Cannot create a file when that file already exists.

原因:tun0 虚拟网卡已经存在,sing-box 无法重新创建。

解决方案

1. 彻底清理虚拟网卡

# 停止 sing-box 进程
taskkill /f /im sing-box.exe

# 禁用 tun0 网卡
netsh interface set interface name="tun0" admin=disable

# 删除 tun0 的 IP 配置
netsh interface ip delete address name="tun0" addr=10.10.0.2

2. 优化配置文件

创建无注释的配置文件,并添加必要的字段:

{
    "log": {
        "level": "debug",
        "timestamp": true
    },
    "dns": {
        "servers": [
            {
                "tag": "dns-local",
                "address": "https://223.5.5.5/dns-query",
                "detour": "direct"
            },
            {
                "tag": "dns-remote",
                "address": "https://1.1.1.1/dns-query",
                "detour": "proxy"
            }
        ],
        "final": "dns-remote",
        "strategy": "prefer_ipv4"
    },
    "inbounds": [
        {
            "type": "tun",
            "tag": "tun-in",
            "interface_name": "tun0",
            "address": ["10.10.0.2/24"],
            "mtu": 1500,
            "strict_route": true,
            "auto_route": true,
            "stack": "system",
            "endpoint_independent_nat": true,
            "sniff": true,
            "sniff_override_destination": true,
            "route_address": ["0.0.0.0/1", "128.0.0.0/1"],
            "route_exclude_address": ["192.168.0.0/16"]
        }
    ],
    "outbounds": [
        {
            "type": "direct",
            "tag": "direct"
        },
        {
            "type": "block",
            "tag": "block"
        },
        {
            "type": "dns",
            "tag": "dns-out"
        },
        {
            "type": "socks",
            "tag": "socks-out",
            "server": "127.0.0.1",
            "server_port": 7890,
            "version": "5"
        },
        {
            "type": "selector",
            "tag": "proxy",
            "outbounds": ["socks-out"]
        }
    ],
    "route": {
        "rules": [
            {
                "protocol": "dns",
                "outbound": "dns-out"
            },
            {
                "ip_is_private": true,
                "outbound": "direct"
            }
        ],
        "final": "proxy"
    }
}

3. 关键发现:关闭其他终端

在多次尝试后,发现一个关键问题:其他正在运行的终端或进程可能占用了 tun 相关的系统资源

最终解决方案

  1. 关闭所有相关的终端窗口
  2. 确保没有其他 sing-box 进程在运行
  3. 以管理员权限启动 sing-box
Start-Process -FilePath ".\sing-box-1.11.15-windows-amd64\sing-box.exe" -ArgumentList "run", "-c", ".\sing-box-1.11.15-windows-amd64\config.json" -Verb RunAs

完整的工作流程

1. 建立 SSH 隧道

# 在远程服务器上执行,将本地 7890 端口转发到远程
ssh -R 7890:127.0.0.1:7890 -N -f [email protected]

2. 启动 sing-box

# 以管理员权限启动 sing-box
Start-Process -FilePath ".\sing-box-1.11.15-windows-amd64\sing-box.exe" -ArgumentList "run", "-c", ".\sing-box-1.11.15-windows-amd64\config.json" -Verb RunAs

3. 验证配置

# 检查 tun0 网卡状态
netsh interface ipv4 show addresses name="tun0"

# 检查路由表
route print

# 测试流量
curl www.google.com

验证方法

1. 检查 tun0 网卡状态

netsh interface ipv4 show addresses name="tun0"

应该显示:

接口 "tun0" 的配置
    DHCP 已启用:                          否
    IP 地址:                           10.10.0.2
    子网前缀:                        10.10.0.0/24 (掩码 255.255.255.0)

2. 检查路由表

route print

应该看到默认路由(0.0.0.0/0)指向 tun0。

3. 测试流量

curl www.google.com

如果配置成功,curl 的流量会经过 sing-box,在日志中能看到流量记录。

4. 检查 SSH 隧道

# 在远程服务器上检查端口是否监听
netstat -tlnp | grep 7890

经验总结

  1. SSH 隧道配置:使用 -R 参数进行反向端口转发,将远程端口映射到本地。

  2. 配置文件格式:sing-box 的配置文件必须是严格的 JSON 格式,不能包含注释。

  3. 虚拟网卡管理:Windows 下的虚拟网卡管理比较严格,一旦创建就很难完全删除,需要彻底清理。

  4. 进程冲突:多个终端或进程可能占用相同的系统资源,导致 tun 网卡创建失败。

  5. 权限要求:tun 模式需要管理员权限,且需要确保没有其他程序干扰。

  6. 调试方法:通过检查网卡状态、路由表和进程状态,可以快速定位问题。

常见错误及解决方案

错误信息原因解决方案
Cannot create a file when that file already existstun0 网卡已存在彻底清理 tun0 网卡
open interface take too much time to finish系统资源被占用关闭其他终端,重启系统
路由表未修改auto_route 未生效检查配置文件格式,确保无注释
tun0 IP 为 169.254.x.x自动分配失败在配置文件中指定 address 字段
SSH 隧道连接失败网络或权限问题检查 SSH 配置和防火墙设置

应用场景

这个配置的主要应用场景是:

  • 远程办公:在远程服务器上通过 SSH 隧道使用本地的代理服务
  • 网络隔离环境:在内网环境中通过隧道访问外网资源
  • 开发调试:在远程开发环境中使用本地的网络代理

这个踩坑过程让我深刻理解了 Windows 下虚拟网卡管理的复杂性,也学会了如何系统地排查和解决这类问题。通过 SSH 隧道结合 sing-box tun 模式,实现了灵活的全局代理配置。


最后,想起 sing-box 支持 SSH 出站

Reference