Проблема с Sing-box на Android

Буду краток. Как заставить поделие работать на андроиде? В Xray всё сразу интуитивно работает, здесь что-то даже ChatGPT по ходу бессилен.
Симптомы: интернет просто вообще отрубается. Зайти куда-либо невозможно.

Текущая попытка конфига ниже (некоторые значения удалил). Смысл:

  • Есть vless и wireguard outbounds. При этом последний хочется завернуть в vless (собственно, главная причина, почему пробую Sing-box).
  • РФ напрямую, остальное в прокси, всё стандартно.

Телефон без рута, если это что-то меняет.

{
  "log": {
    "level": "warn",
    "timestamp": true
  },
  "dns": {
    "servers": [
      {
        "tag": "remote",
        "address": "8.8.8.8",
        "strategy": "prefer_ipv4",
        "detour": "proxy"
      },
      {
        "tag": "local",
        "address": "77.88.8.8",
        "strategy": "prefer_ipv4",
        "detour": "direct"
      },
      {
        "tag": "block",
        "address": "rcode://success"
      }
    ],
    "rules": [
      {
        "server": "block",
        "rule_set": [
          "geosite-category-ads-all"
        ]
      },
      {
        "server": "local",
        "domain_suffix": [
          "ru",
          "su",
          "by",
          "xn--p1ai"
        ],
        "rule_set": [
          "geoip-ru"
        ]
      }
    ],
    "final": "remote",
    "strategy": "prefer_ipv4"
  },
  "inbounds": [
    {
      "type": "tun",
      "tag": "tun-in",
      "interface_name": "utun",
      "address": "10.0.0.1/24",
      "route_exclude_address": "192.168.0.0/16",
      "mtu": 9000,
      "auto_route": true,
      "strict_route": false
    },
    {
      "type": "mixed",
      "tag": "socks",
      "listen": "127.0.0.1",
      "listen_port": 2080,
      "sniff": true,
      "sniff_override_destination": true
    }
  ],
  "endpoints": [
    {
      "type": "wireguard",
      "tag": "wg-in",
      "address": [
        "<removed>"
      ],
      "private_key": "<removed>",
      "listen_port": <removed>,
      "peers": [
        {
          "address": "<removed>",
          "port": <removed>,
          "public_key": "<removed>",
          "pre_shared_key": "<removed>",
          "allowed_ips": [
            "<removed>"
          ],
          "persistent_keepalive_interval": 25,
          "reserved": [0, 0, 0]
        }
      ],
      "detour": "proxy"
    }
  ],
  "outbounds": [
    {
      "type": "vless",
      "tag": "proxy",
      "server": "<removed>",
      "server_port": 443,
      "uuid": "<removed>",
      "flow": "xtls-rprx-vision",
      "packet_encoding": "xudp",
      "tls": {
        "enabled": true,
        "server_name": "<removed>",
        "insecure": false,
        "utls": {
          "enabled": true,
          "fingerprint": "chrome"
        },
        "reality": {
          "enabled": true,
          "public_key": "<removed>",
          "short_id": "<removed>"
        }
      }
    },
    {
      "type": "direct",
      "tag": "direct"
    },
    {
      "type": "dns",
      "tag": "dns_out"
    }
  ],
  "route": {
    "override_android_vpn": true,
    "auto_detect_interface": false,
    "default_interface": "rmnet_data0",
    "rules": [
      {
        "outbound": "dns_out",
        "protocol": [
          "dns"
        ]
      },
      {
        "outbound": "direct",
        "clash_mode": "Direct"
      },
      {
        "outbound": "proxy",
        "clash_mode": "Global"
      },
      {
        "action": "reject",
        "rule_set": [
          "geosite-category-ads-all"
        ]
      },
      {
        "outbound": "direct",
        "ip_is_private": true
      },
      {
        "outbound": "wg-in",
        "ip_cidr": [
          "<removed>"
        ]
      },
      {
        "outbound": "direct",
        "domain_suffix": [
          "ru",
          "su",
          "by",
          "xn--p1ai"
        ],
        "rule_set": [
          "category-gov-ru",
          "geoip-ru"
        ]
      },
      {
        "outbound": "proxy",
        "port_range": [
          "0:65535"
        ]
      }
    ],
    "rule_set": [
      {
        "tag": "geosite-category-ads-all",
        "type": "remote",
        "format": "binary",
        "url": "https://cdn.jsdelivr.net/gh/SagerNet/sing-geosite@rule-set/geosite-category-ads-all.srs"
      },
      {
        "tag": "category-gov-ru",
        "type": "remote",
        "format": "binary",
        "url": "https://cdn.jsdelivr.net/gh/SagerNet/sing-geosite@rule-set/geosite-category-gov-ru.srs",
        "download_detour": "direct"
      },
      {
        "tag": "geoip-ru",
        "type": "remote",
        "format": "binary",
        "url": "https://cdn.jsdelivr.net/gh/SagerNet/sing-geoip@rule-set/geoip-ru.srs",
        "download_detour": "direct"
      }
    ]
  }
}

default_interface убери, auto_detect_interface в true, дальше без debug log (чистого и понятного) сказать ничего нельзя, ну и начинать тестировать нужно с минимального конфига (только vless), а затем добавлять нужные фичи по ходу

Так… Починил. Взял за основу работающий конфиг Hiddify и добавил нужное (см.споилер). В итоге тут скорее всего много дичи, оставшейся по-дефолту, но по-крайней мере работает, включая проброс Wireguard.
Точно могу сказать, что одна из проблем была в опции “stack” в tun: без рута работает только значение “gvisor”. В остальном - :man_shrugging:

В процессе выяснился довольно неприятный минус Sing-box: опция “sniff_override_destination” похоже здесь просто не работает. Из-за этого Xray на VPS не видит исходные домены сайтов, а только уже их IP, поэтому не может у себя делать маршрутизацию. Печально, я этим пользуюсь на VPS для проброса на WARP и подобные. Ну да ладно.

Summary
{
  "log": {
    "level": "warn",
    "output": "box.log",
    "timestamp": true
  },
  "dns": {
    "servers": [
      {
        "tag": "dns-remote",
        "address": "udp://1.1.1.1",
        "address_resolver": "dns-direct"
      },
      {
        "tag": "dns-direct",
        "address": "1.1.1.1",
        "address_resolver": "dns-local",
        "detour": "direct"
      },
      {
        "tag": "dns-local",
        "address": "local",
        "detour": "direct"
      },
      {
        "tag": "dns-block",
        "address": "rcode://success"
      }
    ],
    "rules": [
      {
        "domain": "connectivitycheck.gstatic.com",
        "server": "dns-remote",
        "rewrite_ttl": 3000
      },
      {
        "domain_suffix": [
          ".ru",
          ".su",
          ".by",
          ".xn--p1ai"
        ],
        "server": "dns-direct"
      },
      {
        "rule_set": [
          "geoip-ru",
          "geosite-ru"
        ],
        "server": "dns-direct"
      }
    ],
    "final": "dns-remote",
    "independent_cache": true
  },
  "endpoints": [
    {
      "type": "wireguard",
      "tag": "wg-in",
      "address": "<removed>",
      "private_key": "<removed>",
      "listen_port": <removed>,
      "peers": [
        {
          "address": "<removed>",
          "port": <removed>,
          "public_key": "<removed>",
          "pre_shared_key": "<removed>",
          "allowed_ips": "<removed>",
          "persistent_keepalive_interval": 25,
          "reserved": "AAAA"
        }
      ],
      "detour": "proxy"
    }
  ],
  "inbounds": [
    {
      "type": "tun",
      "tag": "tun-in",
      "mtu": 9000,
      "address": "172.19.0.1/28",
      "auto_route": true,
      "strict_route": true,
      "stack": "gvisor",
      "sniff": true,
      "sniff_override_destination": true,
      "endpoint_independent_nat": true
    },
    {
      "type": "mixed",
      "tag": "mixed-in",
      "listen": "127.0.0.1",
      "listen_port": 12334,
      "sniff": true,
      "sniff_override_destination": true
    },
    {
      "type": "direct",
      "tag": "dns-in",
      "listen": "127.0.0.1",
      "listen_port": 16450
    }
  ],
  "outbounds": [
    {
      "type": "urltest",
      "tag": "auto",
      "outbounds": [
        "proxy"
      ],
      "url": "http://connectivitycheck.gstatic.com/generate_204",
      "interval": "10m0s",
      "tolerance": 1,
      "idle_timeout": "30m0s"
    },
    {
      "type": "vless",
      "tag": "proxy",
      "server": "<removed>",
      "server_port": 443,
      "uuid": "<removed>",
      "flow": "xtls-rprx-vision",
      "tls": {
        "enabled": true,
        "server_name": "<removed>",
        "alpn": "null",
        "utls": {
          "enabled": true,
          "fingerprint": "chrome"
        },
        "reality": {
          "enabled": true,
          "public_key": "<removed>",
          "short_id": "<removed>"
        }
      },
      "packet_encoding": "xudp"
    },
    {
      "type": "direct",
      "tag": "direct"
    },
    {
      "type": "direct",
      "tag": "direct-fragment"
    },
    {
      "type": "direct",
      "tag": "bypass"
    }
  ],
  "route": {
    "rules": [
      {
        "protocol": "dns",
        "action": "hijack-dns"
      },
      {
        "process_name": "sing-box",
        "outbound": "bypass"
      },
      {
        "ip_cidr": "<removed>",
        "outbound": "wg-in"
      },
      {
        "ip_is_private": true,
        "outbound": "bypass"
      },
      {
        "rule_set": [
          "geosite-ads",
          "geosite-malware",
          "geosite-phishing",
          "geosite-cryptominers",
          "geoip-malware",
          "geoip-phishing"
        ],
        "action": "reject",
        "method": "default"
      },
      {
        "domain_suffix": [
          ".ru",
          ".su",
          ".by",
          ".xn--p1ai"
        ],
        "outbound": "direct"
      },
      {
        "rule_set": [
          "geoip-ru",
          "geosite-ru"
        ],
        "outbound": "direct"
      }
    ],
    "rule_set": [
      {
        "type": "remote",
        "tag": "geosite-ads",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/block/geosite-category-ads-all.srs",
        "update_interval": "120h0m0s"
      },
      {
        "type": "remote",
        "tag": "geosite-malware",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/block/geosite-malware.srs",
        "update_interval": "120h0m0s"
      },
      {
        "type": "remote",
        "tag": "geosite-phishing",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/block/geosite-phishing.srs",
        "update_interval": "120h0m0s"
      },
      {
        "type": "remote",
        "tag": "geosite-cryptominers",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/block/geosite-cryptominers.srs",
        "update_interval": "120h0m0s"
      },
      {
        "type": "remote",
        "tag": "geoip-phishing",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/block/geoip-phishing.srs",
        "update_interval": "120h0m0s"
      },
      {
        "type": "remote",
        "tag": "geoip-malware",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/block/geoip-malware.srs",
        "update_interval": "120h0m0s"
      },
      {
        "type": "remote",
        "tag": "geoip-ru",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/country/geoip-ru.srs",
        "update_interval": "120h0m0s"
      },
      {
        "type": "remote",
        "tag": "geosite-ru",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/hiddify/hiddify-geo/rule-set/country/geosite-ru.srs",
        "update_interval": "120h0m0s"
      }
    ],
    "final": "proxy",
    "auto_detect_interface": true,
    "override_android_vpn": true
  },
  "experimental": {
    "cache_file": {
      "enabled": true,
      "path": "clash.db"
    },
    "clash_api": {
      "external_controller": "127.0.0.1:16756",
      "secret": "<removed>"
    }
  }
}