Настройка sing-box. Как зароутить в прокси ipv6-only домены не сломав все остальное?

Привет!
После недавних событий с “блокировкой” VLESS + reality решил перейти на чистый sing-box клиент для windows.
Через боль смог настроить рабочий конфиг, но у меня все еще 2 вопроса:

  1. Я хочу, чтобы DNS resolve proxy трафика шел через DOH, а все что direct - локальный DNS провайдера. Не уверен, что у меня получилось.
  2. Основной вопрос: хочу чтобы домены, которые 1. роутятся в proxy 2. имеют только ipv6 - отправлялись через прокси.
    С текущим конфигом (см. ниже - ipv6 в TUN нет) ipv6 сайты не открываются.
    Если я добавлю в TUN ipv6 - все ок с ipv6 и proxy доменами, но перестают открываться все direct домен (потому что мой провайдер не выдал мне ipv6).
    В общем как бы я не крутил конфиг - что-то одно не работает.

Подскажите, пожалуйста, это я что-то не так делаю, или при таких вводных это невозможно настроить?

Контекст:

  1. windows 11 + TUN режим
  2. sing-box 1.12.12
  3. VLESS+reality+vision
  4. Собственный VPS + домен + сайт-заглушка
  5. У моего провайдера нет ipv6
  6. У vps ipv6 включен
sinb-box config.json
 {
  "log": {
    "level": "warn"
  },
  "dns": {
    "servers": [
	  {
        "type": "https",
        "server": "dns.google",
        "domain_resolver": "dns-cloudflare",
		"tag": "dns-remote"
      },
	  {
        "type": "udp",
        "server": "1.1.1.1",
		"tag": "dns-cloudflare"
      },
	  {
        "type": "local",
        "tag": "dns-direct"
      }
    ],
	"rules": [
      {
        "rule_set": [
          "geosite:category-ads-all"
        ],
        "action": "predefined",
        "rcode": "REFUSED"
      },
      {
        "domain_suffix": [
          "appcenter.ms",
          "firebase.io",
          "crashlytics.com"
        ],
        "action": "predefined",
        "rcode": "REFUSED"
      },
	  {
		"action": "predefined",
		"domain_suffix": [
          "ntc.party"
        ],
        "answer": [
		  "ntc.party. IN A 130.255.77.28"
		]
      }
    ]
  },
  "inbounds": [
    {
      "type": "tun",
      "tag": "tun-proxy",
      "interface_name": "tun-proxy",
      "address": [
		"172.19.0.1/24"
	  ],
      "mtu": 1500,
      "auto_route": true,
      "stack": "mixed"
    },
	{
      "type": "mixed",
      "tag": "mixed-proxy",
	  "listen": "0.0.0.0",
      "listen_port": 1234,
	  "set_system_proxy": false
    }
  ],
  "outbounds": [
    {
      "type": "direct",
      "tag": "direct",
      "domain_resolver": {
        "server": "dns-direct",
        "strategy": "prefer_ipv4"
      }
    },
	{
      "type": "selector",
      "tag": "vps-proxy-selector",
      "outbounds": ["vless-sfy", "vless-yahoo", "ss2"],
      "default": "vless-yahoo"
    },
	{
      "type": "vless",
      "tag": "vless-sfy",
      "server": "",
      "server_port": 443,
      "uuid": "",
      "flow": "xtls-rprx-vision",
      "network": "tcp",
      "tls": {
        "enabled": true,
        "insecure": false,
        "server_name": "",
        "utls": {
          "enabled": true,
          "fingerprint": "chrome"
        },
        "reality": {
          "enabled": true,
          "public_key": "",
          "short_id": ""
        }
      },
      "domain_resolver": {
        "server": "dns-remote",
        "strategy": "prefer_ipv4"
      }
    },
    {
      "type": "vless",
      "tag": "vless-yahoo",
      "server": "",
      "server_port": 443,
      "uuid": "",
      "flow": "xtls-rprx-vision",
      "network": "tcp",
      "tls": {
        "enabled": true,
        "insecure": false,
        "server_name": "",
        "utls": {
          "enabled": true,
          "fingerprint": "chrome"
        },
        "reality": {
          "enabled": true,
          "public_key": "",
          "short_id": ""
        }
      },
      "domain_resolver": {
        "server": "dns-remote",
        "strategy": "prefer_ipv4"
      }
    },
    {
      "type": "shadowsocks",
      "tag": "ss2",
      "server": "",
      "server_port": 17019,
      "method": "2022-blake3-aes-256-gcm",
      "password": "",
      "domain_resolver": {
        "server": "dns-remote",
        "strategy": "prefer_ipv4"
      }
    }
  ],
  "route": {
	"auto_detect_interface": true,
    "rules": [
      {
        "action": "sniff"
      },
      {
        "protocol": "dns",
        "action": "hijack-dns"
      },
	  {
		"ip_is_private": true,
		"outbound": "direct"
	  },
      {
		"action": "reject",
        "network": "udp",
        "port": 443
      },
      {
		"action": "reject",
        "rule_set": [
          "geosite:category-ads-all"
        ]
      },
      {
        "protocol": "bittorrent",
		"outbound": "direct"
      },
      {
        "domain_suffix": [
          ".ru",
          ".su",
          ".рф",
          ".by",
		  ".ru.com",
		  ".ru.net",
		  ".moscow",
		  ".xn--p1ai",
		  ".xn--p1acf",
		  ".xn--80aswg",
		  ".xn--c1avg",
		  ".xn--80asehdb",
		  ".xn--d1acj3b",
		  ".xn--90ais"
        ],
		"rule_set": [
          "geosite:category-ru"
        ],
        "rule_set": [
          "geoip:ru",
          "geoip:by"
        ],
        "outbound": "direct"
      },
      {
        "domain_suffix": [
          ...
        ],
		"rule_set": [
          ...
        ],
        "ip_cidr": [
        ],
        "outbound": "vps-proxy-selector"
      }
    ],
    "rule_set": [
		...
    ]
  },
  "experimental": {
      "cache_file": {
  	  "enabled": true
    }
  }
}

Вот здесь написано решение вашей проблемы. Если быть кратким то вам нужно в tun добавить частный адрес ipv6, ну и может еще что-то подкрутить и должно заработать.

Сингбоксом не пользуюсь, но тут предложили заменить dns.strategy на ipv4_only. Я, например, через GOST настраиваю.

У меня примерно так (удалил лишнее и свои outbounds). Суть в том, что есть отдельное правило dns для нужных доменов, где стоит prefer_ipv4, а по умолчанию ipv4_only. Плюс пускаем ipv6 домены через прокси, который поддерживает ipv6.

{
  "dns": {
    "strategy": "ipv4_only",
    "reverse_mapping": true,
    "servers": [
      {
        "type": "https",
        "tag": "doh1",
        "server": "1.1.1.1",
        "server_port": 443,
        "path": "/dns-query",
        "tls": {
          "enabled": true,
          "server_name": "cloudflare-dns.com"
        },
        "detour": "proxy-select"
      }
    ],
    "rules": [
      {
        "server": "doh1",
        "domain_suffix": [
          "ntc.party"
        ],
        "strategy": "prefer_ipv4"
      }
    ],
    "final": "doh1"
  },
  "inbounds": [
    {
      "type": "mixed",
      "tag": "mixed-in",
      "listen": "127.0.0.1",
      "listen_port": 1080
    }
  ],
  "outbounds": [
    {
      "type": "direct",
      "tag": "direct"
    },
    {
      "type": "selector",
      "tag": "proxy-select",
      "outbounds": [
        "Proxy1",
        "Proxy2"
      ],
      "default": "Proxy1",
      "interrupt_exist_connections": true
    }
  ],
  "route": {
    "final": "proxy-select",
    "auto_detect_interface": true,
    "rules": [
      {
        "inbound": "mixed-in",
        "action": "sniff",
        "sniffer": [
          "http",
          "tls",
          "dns",
          "quic"
        ],
        "timeout": "300ms"
      },
      {
        "protocol": "dns",
        "action": "hijack-dns"
      },
      {
        "domain_suffix": [
          "ntc.party"
        ],
        "action": "route",
        "outbound": "Proxy1"
      },
      {
        "domain_suffix": [
          ".ru"
        ],
        "action": "route",
        "outbound": "direct"
      }
    ]
  }
}

Это не ответ на вопросы - на них уже ответили выше, но всё же:

После недавних событий с “блокировкой” VLESS + reality решил перейти на чистый sing-box клиент для windows.

Честно, не вижу в этом логики. После тех событий есть смысл перейти на чистое xray ядро на клиенте. Sing-box не поддерживает xhttp, его алгоритмы Multiplex не совместимы с mux серверного xray ядра. Можно конечно поставить sing-box и на сервер, но в качестве сервера xray намного лучше, думаю с этим спорить никто не будет. То есть, в ситуации “сибирской язвы”, когда стоит фильтр по кол-ву соединений, от клиента sing-box будет работать только конфиг с транспортом grpc.

Я как-то пробовал пускать весь трафик через ipv6 и свой DNS. Сложилось впечатление, что его поддерживают полтора инвалида. В итоге пришлось поставить не строгую маршрутизацию, а приоритет ipv6.

Если так сделать, винда начинает в приоритет брать резолвинг ipv6 и все direct домены роутятся на прямую, а на прямую у меня нет ipv6 интерфейса - это не работает :melting_face:

Попробую, но мне кажется я уже так делал :thinking:

Спасибо! :fire: Буду пробовать

UPD: В mixed-in режиме работает, в TUN нет :smiling_face_with_tear:. Я так понимаю, чтобы это работало в tun режиме в него надо прописать ipv6 интерфейс, иначе это не заводится. Но в этом случае, как я писал, отваливается весь direct потому что у меня нет ipv6.

Согласен абсолютно, просто привык уже сидеть в sing-box, т.к. в большинстве UI клиентов он в приоритете был всегда(кстати, не смог внятного объяснения найти почему). Но в планах следом настроить и чистый xray клиент, спасибо!

У вас какая-то запутанная конфигурация. Вы весь трафик заворачиваете в туннель и там перехватываются обычные DNS запросы (не DoH/DoT). Но где DNS правила, которые эти запросы как-нибудь распределят по списку серверов? Т.е. запрос, прошедший через все predefined действия, отрезолвится на первом google dns (адрес которого вы получаете через cloudflare dns, что странно? напишите 8.8.8.8 и все, так можно, у сертификата subjectAltName: “8.8.8.8”)

Сделайте DNS правило с geosite-category-ru и для него явно укажите ваш dns-direct со стратегией ipv4_only, тогда весь direct станет ipv4.

Другой интересный вопрос - а локальный DNS точно будет работать? Здесь можно легко получить петлю: DNS → tunnel → hijack → DNS → tunnel… Раньше это было проблемой на Linux с resolved, не знаю как на винде. В крайнем случае просто DoH яндекса поставьте вместо local, такое не выйдет hijack’нуть.

В приоритете потому что программно реализован он гораздо лучше, с ним приятнее работать. С xray не будет встроенного tun и таких гибких route правил.
xhttp не даст никаких преимуществ над старыми v2ray транспортами (вроде тех же вебсокетов или splithttp), да и влезать в это стоит только для абуза CDN (судя по reality-vision – не ваш случай)

Ничто не мешает использовать sing-box в связке с xray. Логику правил route или тот же tun делаешь в sing-box, а xray будет просто как коннектор с различными транспортами, а sing-box ходит в него через сокс.

Это неверно, он имеет ряд преимуществ даже без учета CDN. Как минимум подключение по h2 и quic, разделение потоков (опционально).

Имхо, это звучит костыльно и неэффективно. И совсем не ясно ради чего.

А что именно вам дает h2, quic или разделение потоков? Защиту от каких-то теоретизированных способов обнаружения подозрительного трафика через анализ временных окон статистики? Нет систем способных на такое, это безумно дорого и сложно. В контексте проброса через CDN все упирается в ограничения сервиса, вы не получите большей скорости или отзывчивости (в сравнении со старыми v2ray транспортами).

Ну и http транспорт в sing-box должен поддерживать h2 (с TLS). Я где-то читал, что в xhttp хардкодятся какие-то параметры в Referer, поэтому некоторые ру CDN его блокируют.
Будет забавно, если оригинальный http лишен этих недостатков, надо будет как-нибудь проверить.

Спасибо за наводку! Я только недавно перешел с sing-box 1.7.8 на 1.12.12 и пока плаваю в настройке, особенно DNS.

  1. У меня до этого как раз были правила для category-ru, я по какой-то причине их убрал, возможно ошибочно.
    1. UPD: я решил что вот эта конструкция(у outbound ‘vless-sfy’, например) как-то отвечает за роутинг DNS. До сих пор не понимаю в чем ее фишка:

            "domain_resolver": {
              "server": "dns-remote",
              "strategy": "prefer_ipv4"
            }
      
  2. “адрес которого вы получаете через cloudflare dns” - это пример из доки sing-box, взял его чтобы не думать :slight_smile:
  3. Про петлю не знал, нужно пробовать и смотреть :thinking:

Попробую переработать конфиг, вернусь с результатом, спасибо!

Имхо, это звучит костыльно и неэффективно.

Согласен, это просто была идея для тех, кто принципиально привязан к синтаксису синг-бокса. Сам я вместо tun использую tproxy и правила iptables.

И совсем не ясно ради чего.

Xray нужен, чтобы иметь возможность использовать какие-то другие конфиги помимо транспорта grpc (т.к. в синг боксе несовместимые алгоритмы мультиплекса).

Мне не нравится, что в grpc используется встроенный мультиплекс, которым никак нельзя управлять. Если они сделали фильтр по >=12 TLS соединений, то одно жирное соединение они тоже смогут накрыть, если все массово пересядут на grpc, там характеристики будут у всех идентичные. В xhttp можно очень тонко управлять циклами жизни соединений, делать свой трафик непохожим на других юзеров.

Можно сразу вопрос по поводу iptables. Если у меня есть определенное приложение, которое не умеет в прокси, я могу его с помощью правил iptables завернуть в тунель? Мне казалось что это не так просто, и tun тут манна небесная

У меня в таком режиме (как выше писал) на Android всё работает с таким inbound:

{
  "inbounds": [
    {
      "type": "tun",
      "tag": "tun-in",
      "address": [
        "172.19.0.1/30",
        "fdfe:dcba:9876::1/126"
      ],
      "auto_route": true,
      "stack": "system",
      "mtu": 1400
    }
  ]
}

А можно пример рабочего конфига целиком? Может я что-то не то делаю опять. У вас на android у провайдера тоже нет ipv6?

Можно указать один dns по умолчанию на весь конфиг в route.

{
  "route": {
    "default_domain_resolver": {
      "server": "tag"
    }
  }
}

Его нужно указать, если в конфиге несколько dns, иначе ошибка deprecated.