SagerNet / sing-box

The universal proxy platform
https://sing-box.sagernet.org/
Other
18.4k stars 2.2k forks source link

5894b40d61acdaad745cd38ffafff7a2fe2e481b 存在严重的内存泄漏问题 #1436

Closed yingziwu closed 7 months ago

yingziwu commented 7 months ago

操作系统

Linux

系统版本

Arch Linux 6.6.14-1-lts

安装类型

sing-box 原始命令行程序

如果您使用图形客户端程序,请提供该程序版本。

No response

版本

$ ./sing-box version
sing-box version 1.8.5-5894b40d

Environment: go1.21.6 linux/amd64
Tags: with_gvisor,with_dhcp,with_wireguard,with_reality_server,with_clash_api,with_quic,with_ech,with_utls
Revision: 5894b40d61acdaad745cd38ffafff7a2fe2e481b
CGO: enabled

描述

将 sing-box-git 由 r1232.cc05a5cb-1 升级至 r1243.5894b40d-1 后( https://github.com/SagerNet/sing-box/compare/cc05a5cb...5894b40d ),sing-box 出现了严重的内存泄漏问题,几十秒即可消耗完所有内存+swap,进而导致 OOM kill。

# systemctl status sing-box@ss.service 
● sing-box@ss.service - sing-box service
     Loaded: loaded (/usr/lib/systemd/system/sing-box@.service; enabled; preset: disabled)
     Active: active (running) since Sun 2024-02-04 02:02:38 CST; 30s ago
       Docs: https://sing-box.sagernet.org
   Main PID: 340612 (sing-box)
      Tasks: 22 (limit: 16568)
     Memory: 10.2G (peak: 10.6G swap: 6.0G swap peak: 6.0G zswap: 1.0G)
        CPU: 3min 59.169s
     CGroup: /system.slice/system-sing\x2dbox.slice/sing-box@ss.service
             └─340612 /usr/bin/sing-box -D /var/lib/sing-box/sing-box-ss -c /etc/sing-box/ss.json run

Feb 04 02:03:09 arch sing-box[340612]: INFO[0015] outbound/shadowsocks[git.rel.bgme.org]: outbound connection to 1.1.1.1:443
Feb 04 02:03:09 arch sing-box[340612]: DEBUG[0030] dns: lookup failed for git.rel.bgme.org: exchange6: Post "https://1.1.1.1/dns-query": context canceled | exchange4: Post "https://1.1.1.1/dns-quer>
Feb 04 02:03:09 arch sing-box[340612]: DEBUG[0015] dns: lookup failed for git.rel.bgme.org: exchange4: Post "https://1.1.1.1/dns-query": context canceled | exchange6: Post "https://1.1.1.1/dns-quer>
Feb 04 02:03:09 arch sing-box[340612]: ERROR[0030] outbound/urltest[auto]: exchange4: Post "https://1.1.1.1/dns-query": context canceled | exchange6: Post "https://1.1.1.1/dns-query": context cance>
Feb 04 02:03:09 arch sing-box[340612]: ERROR[0028] outbound/urltest[auto]: exchange6: Post "https://1.1.1.1/dns-query": context canceled | exchange4: Post "https://1.1.1.1/dns-query": context cance>
Feb 04 02:03:09 arch sing-box[340612]: DEBUG[0023] dns: lookup domain git.rel.bgme.org
Feb 04 02:03:09 arch sing-box[340612]: DEBUG[0026] dns: lookup domain git.rel.bgme.org
Feb 04 02:03:09 arch sing-box[340612]: DEBUG[0026] dns: lookup failed for git.rel.bgme.org: exchange6: Post "https://1.1.1.1/dns-query": context canceled | exchange4: Post "https://1.1.1.1/dns-quer>
Feb 04 02:03:09 arch sing-box[340612]: ERROR[0030] outbound/urltest[auto]: exchange6: Post "https://1.1.1.1/dns-query": context canceled | exchange4: Post "https://1.1.1.1/dns-query": context cance>
Feb 04 02:03:09 arch sing-box[340612]: ERROR[0023] outbound/urltest[auto]: exchange6: Post "https://1.1.1.1/dns-query": context canceled | exchange4: Post "https://1.1.1.1/dns-query": context cance>

通过 git bisect 确定该问题由 5894b40d61acdaad745cd38ffafff7a2fe2e481b 引入。

bisect log:

$ git bisect start
status: waiting for both good and bad commits

$ git bisect bad  
status: waiting for good commit(s), bad commit known

$ git bisect good c8318058bb4a15e9d6751a71e78bdd3b68c57b32
Bisecting: 7 revisions left to test after this (roughly 3 steps)
[2239b5993339bedafc3ac5571d7d573e8814a0bb] Remove duplicated rules

$ git bisect good
Bisecting: 3 revisions left to test after this (roughly 2 steps)
[5c6e24ba112cf473dae29d1e693b0c013e8399f8] badtls: Support uTLS and TLS ECH for read waiter

$ git bisect good
Bisecting: 1 revision left to test after this (roughly 1 step)
[7b68cbbb72a5a8c20c9e3eb8f8516b642a64cc17] Improve domain suffix match behavior

$ git bisect good
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[5d1738b2807226f32e71bf59e3bbdb06293668e5] Fix timezone for Android and iOS

$ git bisect good
5894b40d61acdaad745cd38ffafff7a2fe2e481b is the first bad commit
commit 5894b40d61acdaad745cd38ffafff7a2fe2e481b
Author: 世界 <i@sekai.icu>
Date:   Sat Feb 3 17:45:27 2024 +0800

    Add address limit support for DNS rules

 adapter/inbound.go          |  12 +--
 adapter/router.go           |   3 +
 go.mod                      |   2 +-
 go.sum                      |   4 +-
 option/rule_dns.go          |   3 +
 route/router_dns.go         | 182 +++++++++++++++++++++++++++++++-------------
 route/router_rule.go        |   4 +
 route/rule_abstract.go      |  15 +++-
 route/rule_dns.go           |  86 +++++++++++++++++++++
 route/rule_item_rule_set.go |   9 ++-
 route/rule_set_local.go     |   1 +
 route/rule_set_remote.go    |   1 +
 12 files changed, 257 insertions(+), 65 deletions(-)

重现方式

使用 5894b40d61acdaad745cd38ffafff7a2fe2e481b 版本,并使用如下配置文件可稳定复现。

(配置文件移除了敏感信息)

./sing-box -D /tmp/sing-box-ss -c /etc/sing-box/ss.json run

ss.json

{
  "log": {
    "level": "debug"
  },
  "dns": {
    "servers": [
      {
        "tag": "remote",
        "address": "https://1.1.1.1/dns-query",
        "address_resolver": "local",
        "detour": "proxy"
      },
      {
        "tag": "local",
        "address": "local",
        "address_strategy": "prefer_ipv6",
        "detour": "direct"
      },
      {
        "tag": "block",
        "address": "rcode://success"
      }
    ],
    "rules": [
      {
        "geosite": "category-ads-all",
        "server": "block",
        "disable_cache": true
      },
      {
        "geosite": "cn",
        "server": "local"
      },
      {
        "domain_suffix": [
          ".lan",
          ".server.example.org",
          ".local.example.org",
          ".local2.example.org",
          ".wireguard.example.org",
          ".pool.ntp.org"
        ],
        "domain": [
          "nc.example.org",
          "files.example.org",
          "aria2.example.org",
          "kms.example.org",
          "repo.example.org",
          "build.example.org",
          "ocr.example.org"
        ],
        "server": "local"
      }
    ],
    "strategy": "prefer_ipv6",
    "final": "remote"
  },
  "inbounds": [
    {
      "type": "mixed",
      "tag": "mixed-in",
      "listen": "127.0.0.1",
      "listen_port": 1080
    }
  ],
  "outbounds": [
    {
      "type": "direct",
      "tag": "_direct",
      "connect_timeout": "30s"
    },
    {
      "type": "selector",
      "tag": "direct",
      "outbounds": [
        "proxy",
        "_direct"
      ],
      "default": "_direct"
    },
    {
      "type": "block",
      "tag": "block"
    },
    {
      "type": "dns",
      "tag": "dns-out"
    },
    {
      "type": "shadowsocks",
      "tag": "one.server.example.org",
      "server": "one.server.example.org",
      "server_port": 53756,
      "method": "2022-blake3-chacha20-poly1305",
      "password": "password",
      "udp_over_tcp": false,
      "connect_timeout": "10s",
      "domain_strategy": "prefer_ipv6",
      "fallback_delay": "5s"
    },
    {
      "type": "shadowsocks",
      "tag": "two.server.example.org",
      "server": "two.server.example.org",
      "server_port": 53756,
      "method": "2022-blake3-chacha20-poly1305",
      "password": "password",
      "udp_over_tcp": false,
      "connect_timeout": "10s",
      "domain_strategy": "prefer_ipv6",
      "fallback_delay": "5s"
    },
    {
      "type": "shadowsocks",
      "tag": "three.server.example.org",
      "server": "three.server.example.org",
      "server_port": 53756,
      "method": "2022-blake3-chacha20-poly1305",
      "password": "password",
      "udp_over_tcp": false,
      "connect_timeout": "10s",
      "domain_strategy": "prefer_ipv6",
      "fallback_delay": "5s"
    },
    {
      "type": "shadowsocks",
      "tag": "four.server.example.org",
      "server": "four.server.example.org",
      "server_port": 53756,
      "method": "2022-blake3-chacha20-poly1305",
      "password": "password",
      "udp_over_tcp": false,
      "connect_timeout": "10s",
      "domain_strategy": "prefer_ipv6",
      "fallback_delay": "5s"
    },
    {
      "type": "urltest",
      "tag": "auto",
      "outbounds": [
        "one.server.example.org",
        "two.server.example.org",
        "three.server.example.org",
        "four.server.example.org"
      ],
      "url": "https://www.gstatic.com/generate_204",
      "interval": "1m",
      "tolerance": 50
    },
    {
      "type": "selector",
      "tag": "proxy",
      "outbounds": [
        "one.server.example.org",
        "two.server.example.org",
        "three.server.example.org",
        "four.server.example.org",
        "auto"
      ],
      "default": "auto"
    },
    {
      "type": "selector",
      "tag": "global",
      "outbounds": [
        "proxy",
        "direct"
      ],
      "default": "proxy"
    }
  ],
  "route": {
    "auto_detect_interface": true,
    "rule_set": [
      {
        "tag": "geoip-cn",
        "type": "remote",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-cn.srs",
        "download_detour": "proxy"
      },
      {
        "tag": "geosite-cn",
        "type": "remote",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-cn.srs",
        "download_detour": "proxy"
      }
    ],
    "rules": [
      {
        "protocol": "dns",
        "outbound": "dns-out"
      },
      {
        "geosite": "category-ads-all",
        "outbound": "block"
      },
      {
        "rule_set": [
          "geoip-cn",
          "geosite-cn"
        ],
        "outbound": "direct"
      },
      {
        "domain_suffix": [
          ".lan",
          ".server.example.org",
          ".local.example.org",
          ".local2.example.org",
          ".wireguard.example.org",
          ".pool.ntp.org"
        ],
        "domain": [
          "nc.example.org",
          "files.example.org",
          "aria2.example.org",
          "kms.example.org",
          "repo.example.org",
          "build.example.org",
          "ocr.example.org"
        ],
        "outbound": "direct"
      }
    ],
    "final": "global"
  },
  "experimental": {
    "cache_file": {
      "enabled": true,
      "path": "cache.db"
    },
    "clash_api": {
      "external_controller": "127.0.0.1:9090",
      "secret": "secret",
      "external_ui": "ui",
      "external_ui_download_url": "https://github.com/MetaCubeX/Yacd-meta/archive/gh-pages.zip",
      "external_ui_download_detour": "auto"
    }
  }
}

sing-box.log.gz

日志

./sing-box -D /tmp/sing-box-ss -c /etc/sing-box/ss.json run

日志由于体积过大,省略了后面部分众多重复内容,完整日志见上文。 对代理域名等敏感信息进行了一定的替换处理。

INFO[0000] router: updated default interface wlp1s0, index 2
INFO[0000] router: updated default interface wlp1s0, index 2
INFO[0000] router: loaded geosite database: 1416 codes
INFO[0000] router: loaded geosite database: 1416 codes
INFO[0000] clash-api: restful api listening at 127.0.0.1:9090
INFO[0000] clash-api: restful api listening at 127.0.0.1:9090
INFO[0000] inbound/mixed[mixed-in]: tcp server started at 127.0.0.1:1080
INFO[0000] inbound/mixed[mixed-in]: tcp server started at 127.0.0.1:1080
INFO[0000] sing-box started (0.55s)
INFO[0000] sing-box started (0.55s)
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to www.gstatic.com:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to www.gstatic.com:443
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
INFO[0000] outbound/shadowsocks[two.server.example.org]: outbound connection to www.gstatic.com:443
INFO[0000] outbound/shadowsocks[two.server.example.org]: outbound connection to www.gstatic.com:443
INFO[0000] outbound/shadowsocks[four.server.example.org]: outbound connection to www.gstatic.com:443
INFO[0000] outbound/shadowsocks[four.server.example.org]: outbound connection to www.gstatic.com:443
DEBUG[0000] dns: lookup domain four.server.example.org
DEBUG[0000] dns: lookup domain four.server.example.org
INFO[0000] outbound/shadowsocks[three.server.example.org]: outbound connection to www.gstatic.com:443
INFO[0000] outbound/shadowsocks[three.server.example.org]: outbound connection to www.gstatic.com:443
DEBUG[0000] dns: lookup domain three.server.example.org
DEBUG[0000] dns: lookup domain three.server.example.org
DEBUG[0000] dns: lookup domain two.server.example.org
DEBUG[0000] dns: lookup domain two.server.example.org
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
DEBUG[0000] dns: lookup domain one.server.example.org
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
DEBUG[0000] dns: lookup domain one.server.example.org
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
DEBUG[0000] dns: lookup domain one.server.example.org
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
DEBUG[0000] dns: lookup domain one.server.example.org
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
DEBUG[0000] dns: lookup domain one.server.example.org
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
INFO[0000] outbound/shadowsocks[one.server.example.org]: outbound connection to 1.1.1.1:443
...

完整性要求

nekohasekai commented 7 months ago

Try fd705d965e0dfdc7252a5d4df40bebb8890c32af

yingziwu commented 7 months ago

Try fd705d9

测试了一下,这个没有问题。

另外,话说为什么要直接 force push ,而不是发一个新 comiit ? 这种 force push 对于 lilac 这样的自动打包系统非常的不友好。

nekohasekai commented 7 months ago

稳定版本通常连续。且我不认为打包尚未以任何形式发布的东西是好的,这可能造成任何后果。