sing-box 作为代理工具的集大成者,支持多协议多功能,且覆盖多平台,但是配置起来比较复杂,这里给出一个适合 Linux 桌面使用的配置样本,供参考。

本配置适合 Linux 桌面,不适配 Windows 和 Android,Mac OS 也许可以参考部分。

配置策略

本配置主要实现的目的:

  1. 提供本地 HTTP/HTTPS/SOCKS5 代理,供给浏览器(Firefox)和命令行工具等使用,自动分流国内和国外流量(基于 GeoIP 和 GeoSite);
  2. 通过代理的 DNS 同样提供国内和国外分流;
  3. 提供本地 DNS 服务器,通过该服务器可以实现 DNS 国内和国外分流;
  4. 避免 DNS 泄漏(DNS 泄漏可以认为是:访问的境外域名泄漏给国内 DNS 服务商,使之可以获悉你访问的境外网站);
  5. 过滤广告;

配置内容

本配置主要内容如下,适合 sing-box 1.10 beta 以上版本,如果使用版本为 1.9.x,则可以考虑删除广告过滤的配置即可:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
{
  "log": {
    "disabled": false,
    "level": "info",
    "timestamp": false
  },
  "dns": {
    "servers": [
      {
        "tag": "dns-remote",
        "address": "https://1.1.1.1/dns-query",
        "detour": "proxy",
        "client_subnet": "1.0.1.0"
      },
      {
        "tag": "dns-local",
        "address": "local",
        "detour": "direct"
      },
      {
        "tag": "dns-default",
        "address": "https://223.5.5.5/dns-query",
        "detour": "direct"
      },
      {
        "tag": "dns-block",
        "address": "rcode://refused"
      }
    ],
    "rules": [
      {
        "rule_set": [
          "anti-ad"
        ],
        "server": "dns-block",
        "disable_cache": true
      },
      {
        "inbound": [
          "global"
        ],
        "server": "dns-remote"
      },
      {
        "rule_set": [
          "geosite-cn"
        ],
        "server": "dns-default"
      },
      {
        "outbound": "any",
        "server": "dns-default"
      }
    ],
    "final": "dns-remote",
    "independent_cache": true
  },
  "inbounds": [
    {
      "tag": "dns-in",
      "type": "direct",
      "listen": "127.0.0.1",
      "listen_port": 5335,
      "network": "udp",
      "sniff": true,
    },
    {
      "tag": "global",
      "type": "mixed",
      "listen": "127.0.0.1",
      "listen_port": 1091,
      "sniff": true,
      "set_system_proxy": false
    },
    {
      "tag": "auto",
      "type": "mixed",
      "listen": "127.0.0.1",
      "listen_port": 1090,
      "sniff": true,
      "set_system_proxy": false
    }
  ],
  "outbounds": [
    {
      "tag": "proxy",
      "type": "selector",
      "outbounds": [
        "trojan",
        "hysteria"
      ],
      "default": "hysteria"
    },
    {
      "tag": "trojan",
      "type": "trojan",
      ...
    },
    {
      "tag": "hysteria",
      "type": "hysteria",
      ...
    },
    {
      "tag": "direct",
      "type": "direct"
    },
    {
      "tag": "block",
      "type": "block"
    },
    {
      "tag": "dns-out",
      "type": "dns"
    }
  ],
  "route": {
    "rules": [
      {
        "inbound": "dns-in",
        "outbound": "dns-out"
      },
      {
        "rule_set": [
          "anti-ad"
        ],
        "outbound": "block"
      },
      {
        "inbound": [
          "global"
        ],
        "outbound": "proxy"
      },
      {
        "rule_set": [
          "geoip-cn",
          "geosite-cn"
        ],
        "ip_is_private": true,
        "outbound": "direct"
      },
      {
        "protocol": "dns",
        "outbound": "dns-out"
      }
    ],
    "final": "proxy",
    "rule_set": [
      {
        "tag": "anti-ad",
        "type": "remote",
        "format": "binary",
        "url": "https://anti-ad.net/anti-ad-sing-box.srs",
        "download_detour": "proxy"
      },
      {
        "tag": "geosite-cn",
        "type": "remote",
        "format": "binary",
        "url": "https://github.com/SagerNet/sing-geosite/raw/rule-set/geosite-cn.srs",
        "download_detour": "proxy"
      },
      {
        "tag": "geoip-cn",
        "type": "remote",
        "format": "binary",
        "url": "https://github.com/SagerNet/sing-geoip/raw/rule-set/geoip-cn.srs",
        "download_detour": "proxy"
      }
    ]
  },
  "experimental": {
    "cache_file": {
      "enabled": true
    }
  }
}

备注

主要配置思路:

  1. dns 服务器部分,国内使用 alidns 作为境内 dns 服务器,有普通和 DOH 两个,国外使用 Cloudflare 的 DOH dns 服务器,同时创建了一个用于屏蔽的 dns-block 服务器;

  2. dns 规则部分较为简单,基于 anti-ad 规则进行 dns 屏蔽;对于全局代理入口 global 则都转发到 dns-remote 解析;对于域名匹配了 GeoIP-CN 和 GeoSite-CN 规则集,则使用境内 dns 服务器; final 使用 dns-remote。这里实现了 dns 分流和广告屏蔽。outbound=any 规则保证了代理服务器域名的解析,否则代理无法正常启动。

  3. inbounds 提供了 3 个服务入口:

    • dns-in 提供本地 dns 服务,后续可以将系统 dns 请求转发到这里(配合 systemd-resolved);
    • global 提供本地全局代理,支持 HTTP/HTTPS/SOCKS5,代理流量全部走境外;
    • auto 提供本地分流代理,支持 HTTP/HTTPS/SOCKS5,代理流量会自动分流;
  4. outbounds 除了常规的 direct、block 外,创建了一个 dns-out 服务,以及用于代理的 selector 和真正的 trojan/hyseria,这里具体配置则根据实际的来。

  5. route 规则部分,主要包括:

    • dns-in 转发给 dns-out,用于本地 dns 服务器;
    • 基于 anti-ad 的广告屏蔽;
    • global 的全局代理路由;
    • 基于境内网站、IP 匹配或私有网络 IP 匹配,则流量通过本地;
    • final 设置为 proxy 走境外来保证境外流量规则;
    • protocol=dns 部分走 dns-out 是为了 dns 分流;
  6. 规则集部分,除了 anti-ad 需要 1.10 beta 以上版本支持,其他都兼容 1.9.x。这里都是用远程规则集,并使用了 experimental.cache_file 来保证本地缓存。

  7. 需要额外注意的是,不要在 DNS 规则中使用 IP 规则集(比如 GeoIP 等),这会导致在 DNS 路由处理前将域名解析为 IP 进行匹配,以至于在这个阶段发生 DNS 泄漏。

自启动管理

为了实现 sing-box 自启动和权限,则可以使用如下 systemd service 文件,需要注意可执行文件路径及配置文件路径:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# path: /usr/local/lib/systemd/system/sing-box.service
[Unit]
Description=Sing-Box
After=network.target 
Wants=network-online.target

[Service]
Type=simple
# 限制用户权限
DynamicUser=yes
ExecStart=/usr/local/bin/sing-box run -D ${CACHE_DIRECTORY} -c /usr/local/etc/sing-box/config.json
# 提供特权端口监听权限
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
CacheDirectory=sing-box
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

通过 systemctl enable sing-box –now 后,通过 systemctl status sing-box 查看状态,通过 journalctl -u sing-box 查看日志。

DNS 转发

另外,如果想将系统 DNS 全部转发给 sing-box,我们则可以通过 systemd-resolved dnsmasq 来转发请求(dnsmasq 可以利用 strict-order 来实现 fallback 机制)。

安装完 dnsmasq 后,新增配置文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# path: /etc/dnsmasq.d/dns-servers.conf
# only bind to lo
interface=lo
bind-interfaces
# not use or poll /etc/resolv.conf
no-resolv
no-poll
# cache
# max live in cache
max-cache-ttl=3600
# min live in cache
min-cache-ttl=300
# cache size
cache-size=1000
# keep strict order on servers
strict-order
# sing-box server
server=127.0.0.1#5335
# fallback server if sing-box failed
server=223.5.5.5

然后 systemctl restart dnsmasq 来重启服务。

同时,需要手动修改 /etc/resolv.conf 文件来指定使用 dnsmasq 服务器:

1
2
3
4
# path: /etc/resolv.conf
nameserver ::1
nameserver 127.0.0.1
options edns0 trust-ad

为了避免 /etc/resolv.conf 被以外修改,可以使用 sudo chattr +i /etc/resolv.conf 来标记不可变属性。

对于 Firefox,需要将配置中的代理配置为 127.0.0.1:1090,所有协议共用这个端口。对于普通命令行工具,则可以在 ~/.bashrc 文件中追加两行:

1
2
export http_proxy=http://127.0.0.1:1090
export https_proxy=$http_proxy

DNS 泄漏检测

所有正常后,想检查是否存在 DNS 泄漏,则可以用 Firefox 访问以下两个网站任意一个即可:

  1. https://ipleak.net/
  2. https://browserleaks.com/dns

如果访问的 ip 显示境外,且 dns 服务器也在境外,则表明不存在泄漏。另外,还可以使用 wireshark 来抓 dns 包检查。