Разрешение адресов outbound в xray-core мимо системного DNS

Есть простой конфиг:

"outbounds": [
  {
    "tag": "some-vless",
    "protocol": "vless",
    "settings": {
    "vnext": [
      {
        "address": "some-name.tld.org",
        "port": 443,
        "users": [
...

После запуска xray-core идёт за адресом имени some-name.tld.org в системный DNS. Для Linux это то, что написано в /etc/resolv.conf, для Windows вызов какого-то API. Если системный DNS по какой-то причине недоступен, то xray-core не может подняться. Как сделать, что бы он ресолвил адреса outbound через сервера, которые я укажу?

Из разных инструкций в интернете, в том числе и здесь, а так же советов ИИшенок попробовал такое:

  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {
        "domainStrategy": "AsIs",
        "redirect": "",
        "noises": []
      }
    },
...
    {
      "tag": "resolver01",
      "protocol": "dns",
      "settings": {
        "network": "udp",
        "address": "1.1.1.1",
        "port": 53,
        "nonIPQuery": "drop",
        "blockTypes": []
      }
    },
...
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
...
      {
        "type": "field",
        "port": "53",
        "network": "UDP",
        "outboundTag": "resolver01"
      },
...
      {
        "type": "field",
        "inboundTag": [
          "dns_inbound"
        ],
        "outboundTag": "direct"
      },
...
  "dns": {
    "servers": [
      "1.0.0.1",
      "1.1.1.1",
      "8.8.4.4",
      "8.8.8.8",
      "9.9.9.9"
    ],
    "queryStrategy": "UseIPv4",
    "tag": "dns_inbound"
  },

Но нет, не помогает. Проверяю очень просто – останавливаю системный DNS, xray-core становится бесполезным с руганью:

WARNING - XRAY: app/observatory: the outbound some-vless is dead: GET request failed:app/observatory: outbound failed to relay connection > Get "https://www.gstatic.com/generate_204": io: read/write on closed pipewith outbound handler report underlying connection failed > app/observatory: underlying connection error > app/proxyman/outbound: failed to process outbound traffic > proxy/vless/outbound: failed to find an available destination > common/retry: [dial tcp: lookup some-name.tld.org on [::1]:53: read udp [::1]:40333->[::1]:53: read: connection refused dial tcp: lookup some-name.tld.org on [::1]:53: read udp [::1]:50115->[::1]:53: read: connection refused dial tcp: lookup some-name.tld.org on [::1]:53: read udp [::1]:50297->[::1]:53: read: connection refused dial tcp: lookup some-name.tld.org on [::1]:53: read udp [::1]:45542->[::1]:53: read: connection refused dial tcp: lookup some-name.tld.org on [::1]:53: read udp [::1]:39453->[::1]:53: read: connection refused] > common/retry: all retry attempts failed

конфиг нужно давать полный, вот мой пример

{
    "dns": {
        "queryStrategy": "UseIPv4",
        "servers": [
            "tcp://1.1.1.2:53"
        ]
    },
    "inbounds": [
        {
            "listen": "127.0.0.1",
            "port": 1080,
            "protocol": "socks",
            "settings": {
                "auth": "noauth",
                "udp": true
            },
            "tag": "socks"
        }
    ],
    "log": {
        "loglevel": "debug"
    },
    "outbounds": [
        {
            "protocol": "vless",
            "settings": {
                "vnext": [
                    {
                        "address": "example.org",
                        "port": 443,
                        "users": [
                            {
                                "encryption": "none",
                                "flow": "",
                                "id": "asdf"
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
				"sockopt": {"domainStrategy": "UseIP"}
            },
            "tag": "proxy"
        },
        {
            "protocol": "freedom",
            "tag": "direct"
        },
        {
            "protocol": "blackhole",
            "tag": "block"
        },
        {
            "protocol": "dns",
            "tag": "dns-out"
        }
    ],
    "remarks": "test-4",
    "routing": {
        "domainStrategy": "AsIs",
        "rules": [
            {
				"protocol": "dns",
                "outboundTag": "dns-out"
            },
            {
                "ip": [
                    "10.0.0.0/8",
                    "172.16.0.0/12",
                    "192.168.0.0/16",
                    "169.254.0.0/16",
                    "224.0.0.0/4",
                    "255.255.255.255"
                ],
                "outboundTag": "direct"
            }
        ]
    }
}

прикол в добавлении "sockopt": {"domainStrategy": "UseIP"} в streamSettings во влесс и роутинга днс протокола в dns-out

Спасибо, получилось добавлением "sockopt": {"domainStrategy": "UseIP"} к outbound, а из остального оказалось достаточно этого:

...
  "dns": {
    "servers": [
      "1.0.0.1",
      "1.1.1.1",
      "8.8.4.4",
      "8.8.8.8",
      "9.9.9.9"
    ],
    "queryStrategy": "UseIPv4",
    "tag": "dns_inbound"
  },
...
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
...
      {
        "type": "field",
        "inboundTag": [
          "dns_inbound"
        ],
        "outboundTag": "direct"
      },
...

Причём без роутинга работает тоже, хотя в доке написано чётко, что “запрос следует правилам маршрутизации”. Но если в роутинге ему прописать outbound с blocked или тот, который должен подниматься с помощью этих DNS, тогда работать перестаёт. Попробовал ещё tcp+local, тоже по факту работает по роутингу. Пока нет времени копаться, оставил циферки, мою задачу выполняет

можно явно указать хосты во встроенном dns, если ip стабильный

{
    "dns": {
        "hosts": {
            "some-name.tld.org": "<ip>"
        },
        ...
    }
}

если ip может меняться, то такой конфиг должен работать без дополнительных правил маршрутизации

{
    "dns": {
        // необязательный параметр
        "disableFallbackIfMatch": true,
        "servers": [
            {
                //локалхост это системный днс
                //такие запросы не проходят через модуль маршрутизации
                "address": "localhost",
                "domains": [
                    "domain:some-name.tld.org"
                ],
                "skipFallback": true
            },
            "тут какой нибудь днс по умолчанию, можно указать дох"
        ]
    }
}

дополнительные правила маршрутизации не нужны, потому что при наличии доменного имени в outbound xray должен сразу кидать запрос через встроенный днс. а во встроенном днс указан локалхост, который идет в обход модуля маршрутизации.

но если вы заворачиваете все системные днс запросы в xray, то придётся добавить маршрут по примеру оки. только у меня правило завязано на 53 порт, потому что по документации в правилах для выбора маршрута нет протокола днс и оно не работает. не знаю, как оно работает у оки.

это какое то незадокументированное поведение, но я его кажется тоже замечал. у меня оно возникало, когда в роутинге было правило, которое отправляло запросы с 53 портом в outbound днс. по идее должен был произойти цикл и провал резолвинга, но почему то запросы просто уходили наружу.