Актуальные proxy-клиенты на старых Mac часто ведут себя одинаково: если устанавливаются, импортируют профиль, и даже показывают список серверов, не доводят дело до рабочего подключения. На практике это особенно заметно на macOS Catalina 10.15.8. Текущий Happ для Mac официально требует macOS 12.0 или новее, а значит для Catalina уже не подходит как штатный путь. IRBox в релизах заявляет поддержку macOS 10.15+, но в моём тесте на Catalina встроенный core упёрся в несовместимость с системой. Рабочий результат в итоге дал V2RayXS 1.5.9 для x86_64: не через обычный импорт подписки, а через ручную сборку VLESS + Reality outbound.

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

Эта статья рассчитана на ситуацию, когда у вас старый Intel Mac, macOS Catalina 10.15.x, подписка с VLESS-узлами и обычный импорт подписки в клиенте либо не работает, либо создаёт пустой конфиг.

macOS Catalina 10.15.8 на Intel iMac 2013 — исходная система, на которой проводилась настройка
macOS Catalina 10.15.8 на Intel iMac 2013 — исходная система, на которой проводилась настройка

Как определить, какая версия V2RayXS подходит для Catalina

Это важный шаг, который легко пропустить. На старом macOS нельзя просто скачать «самую новую» версию клиента и ожидать, что она будет работать.

Логика выбора для Intel Mac с Catalina 10.15.x была такой:

  1. сначала нужно смотреть не только на название приложения, но и на архитектуру сборки — в нашем случае нужна именно x86_64, а не arm64;

  2. затем нужно проверить release notes старых версий на странице релизов V2RayXS;

  3. если в релизе разработчик сам предупреждает о проблеме именно в x86_64-сборке, такую версию для Catalina лучше не брать;

  4. если в более раннем релизе есть правка, связанная с realitySettings или импортом VLESS, такая версия становится приоритетной.

В моём случае это привело к такому выводу:

  • V2RayXS 1.5.9 x86_64 — лучший кандидат для Catalina;

  • V2RayXS 1.5.10 x86_64 — нежелателен, потому что сам разработчик предупреждает, что в этой сборке встроен неправильный bundled xray core package;

  • более новые версии на старом Intel Mac стоит проверять только после явного изучения release notes.

Практическое правило простое: для Catalina сначала искать последнюю стабильную x86_64-сборку до проблемного релиза, а уже потом экспериментировать с более новыми.

Где скачивать старые версии V2RayXS

Искать старые версии лучше в двух местах:

1. Официальные GitHub Releases

Основной источник — страница релизов проекта V2RayXS. Там можно проверить историю версий, changelog и названия файлов.

Релизы V2RayXS: для Catalina важна именно x86_64-сборка и примечания к конкретной версии
Релизы V2RayXS: для Catalina важна именно x86_64-сборка и примечания к конкретной версии

2. Exact mirror на SourceForge

Для старых сборок V2RayXS есть удобное зеркало на SourceForge. Это полезно, когда GitHub-asset неудобно скачивать напрямую или нужна конкретная старая версия.

Важный нюанс: старые версии V2RayXS обычно распространяются не как DMG, а как ZIP-архив с .app внутри. То есть для Catalina не стоит искать именно DMG любой ценой: для V2RayXS рабочий формат старых релизов — это чаще V2RayXS_x86_64.app.zip.

Схема загрузки такая:

  1. открыть релизы проекта;

  2. найти нужную версию;

  3. выбрать x86_64-сборку;

  4. скачать ZIP-архив;

  5. распаковать его и перенести .app в Applications.

Старая x86_64-версия V2RayXS для Catalina распространяется как архив приложения, а не как DMG
Старая x86_64-версия V2RayXS для Catalina распространяется как архив приложения, а не как DMG

Что не сработало

Happ

Как основной клиент для Catalina его лучше не брать: текущая версия в Mac App Store требует macOS 12.0 or later. То есть для Catalina этот путь закрыт официально.

IRBox

В релизах IRBox прямо указаны сборки для macOS Intel и Apple Silicon, а в описании релиза сказано, что приложение включает sing-box и xray-core. Формально это выглядит перспективно для Catalina. Но в реальном тесте на 10.15.8 bundled core может оказаться несовместимым с системой.

IRBox на Catalina формально запускается, но на практике упирается в несовместимость встроенного core
IRBox на Catalina формально запускается, но на практике упирается в несовместимость встроенного core

Что в итоге сработало

Рабочая схема выглядела так:

  1. отсеять клиенты, которые не подходят по macOS или реально не запускаются;

  2. установить V2RayXS 1.5.9 x86_64;

  3. не полагаться на auto-import подписки, если он создаёт пустой config.json;

  4. локально декодировать подписку на самом Mac;

  5. собрать отдельный JSON-outbound для каждого VLESS/Reality-узла;

  6. добавить нужные узлы через Advanced -> Outbounds;

  7. загрузить core и включить Global Mode;

  8. отдельно настроить Telegram Desktop на локальный SOCKS5.

V2RayXS — это GUI для xray-core на macOS. Приложение поднимает локальный SOCKS5 на 127.0.0.1:1081 и HTTP proxy на 127.0.0.1:8001, а также работает в режимах Global Mode, PAC Mode и Manual Mode.

V2RayXS на Catalina: ключевые режимы работы и управление загрузкой core
V2RayXS на Catalina: ключевые режимы работы и управление загрузкой core

Почему обычный импорт подписки может не сработать

У V2RayXS на Catalina может возникнуть типичная проблема: подписка подтягивается, пункты в меню появляются, но итоговый config.json содержит не реальный узел, а пустую заготовку, например:

  • address: ""

  • port: 0

  • нулевой UUID

  • security: "none"

  • пустой realitySettings

Если вы видите такую картину, значит клиент не собрал полноценный outbound из подписки, и дальше нужно идти через ручной JSON.

"outbounds": [
  {
    "protocol": "vless",
    "protocol": "vless",
    "settings": {
      "vnext": [
        {
          "address": "",
          "users": [
            {
              "flow": "",
              "id": "00000000-0000-0000-0000-000000000000",
              "encryption": "none"
            }
          ],
          "port": 0
        }
      ]
    },
    "tag": "VLESS",
    "streamSettings": {
      "security": "none",
      "realitySettings": {},
      "network": "tcp"
    }
  }
]

Признаки сломанного импорта: пустой address, port=0, нулевой UUID, security=none и пустой realitySettings.

Как декодировать подписку локально, не публикуя её

Если у вас есть только subscription URL, не публикуйте его и не отправляйте в онлайн-конвертеры. Всё можно сделать локально на самом Mac.

Откройте Terminal и выполните:

curl -L '<SUBSCRIPTION_URL>' | tr -d '\r\n' | base64 -D | nl -ba > ~/Desktop/vless-list.txt
open ~/Desktop/vless-list.txt

Что делает эта команда:

  • скачивает подписку;

  • декодирует base64;

  • нумерует все строки;

  • сохраняет их в ~/Desktop/vless-list.txt.

В итоге вы получаете локальный список всех vless://...-ссылок без публикации URL и без передачи содержимого на сторонние сервисы.

Подписка декодируется локально на Mac: список VLESS-узлов сохраняется в vless-list.txt без использования сторонних сервисов
Подписка декодируется локально на Mac: список VLESS-узлов сохраняется в vless-list.txt без использования сторонних сервисов

Как выглядит рабочий VLESS + Reality узел

Если взять один такой vless://...-линк и разобрать его на части, в нём обычно есть:

  • адрес сервера и порт;

  • UUID;

  • security=reality;

  • flow=xtls-rprx-vision;

  • sni, pbk, sid, fp, иногда spx.

Это нужно превратить в JSON-outbound для Xray. Базовый шаблон выглядит так:

{
  "protocol": "vless",
  "tag": "node-001",
  "settings": {
    "vnext": [
      {
        "address": "example.com",
        "port": 443,
        "users": [
          {
            "id": "UUID-HERE",
            "encryption": "none",
            "flow": "xtls-rprx-vision"
          }
        ]
      }
    ]
  },
  "streamSettings": {
    "network": "tcp",
    "security": "reality",
    "realitySettings": {
      "serverName": "SNI-HERE",
      "fingerprint": "firefox",
      "publicKey": "PUBLIC-KEY-HERE",
      "shortId": "SHORTID-HERE",
      "spiderX": "/PATH-HERE"
    }
  }
}

Важно: tag должен быть уникальным. Не используйте main: в V2RayXS это служебный тег.

Как добавить узел вручную в V2RayXS

Откройте Configure... -> Advanced... -> Outbounds.

Дальше:

  1. нажмите +;

  2. вставьте JSON одного узла;

  3. нажмите Finish;

  4. вернитесь в основное окно Configure...;

  5. обязательно нажмите OK.

Ручное добавление VLESS + Reality узла через Advanced -> Outbounds
Ручное добавление VLESS + Reality узла через Advanced -> Outbounds

Если после Finish вы не нажмёте OK в основном окне Configure, правка может не сохраниться.

После сохранения в Configure... должны появиться реальные параметры узла, а не пустая заглушка
После сохранения в Configure... должны появиться реальные параметры узла, а не пустая заглушка

Как проверить, что конфиг действительно рабочий

Нажмите Load core, затем откройте View current config.json....

После этого в итоговом config.json должно быть видно:

  • routing.rules[].outboundTag указывает на ваш тег;

  • в outbounds указан реальный address;

  • указан реальный port;

  • streamSettings.security равно "reality";

  • realitySettings заполнен.

Если всё это есть, значит вы получили не пустой шаблон, а настоящий рабочий Xray-конфиг.

"outbounds": [
  {
    "protocol": "vless",
    "settings": {
      "vnext": [
        {
          "address": "example-server.com",
          "users": [
            {
              "flow": "xtls-rprx-vision",
              "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
              "encryption": "none"
            }
          ],
          "port": 443
        }
      ]
    },
    "tag": "reality 1",
    "streamSettings": {
      "network": "tcp",
      "realitySettings": {
        "publicKey": "PUBLIC_KEY_HERE",
        "serverName": "example-sni.com",
        "shortId": "SHORT_ID_HERE",
        "spiderX": "/example-path",
        "fingerprint": "firefox"
      },
      "security": "reality"
    }
  }
]

Признак правильного импорта: заполнены address, port, UUID, flow, security=reality и блок realitySettings

Как включить подключение

Когда ручной узел уже сохранён и виден в config.json:

  1. выберите нужный сервер в меню V2RayXS;

  2. нажмите Load core;

  3. затем включите Global Mode.

Если интернет заработал — схема рабочая.

Если интернет пропал:

  • вернитесь в Manual Mode;

  • проверьте config.json;

  • убедитесь, что выбран именно ваш ручной узел, а не пустой шаблон.

Рабочее состояние: core загружен, выбран ручной узел, включён Global Mode
Рабочее состояние: core загружен, выбран ручной узел, включён Global Mode

Почему браузер работает, а Telegram Desktop — нет

Даже если в браузере уже открываются и обычные, и заблокированные сайты, Telegram Desktop может не заработать автоматически. В таком случае проблема обычно не в VLESS и не в сервере, а в том, что Telegram не использует системный proxy V2RayXS так же, как браузер.

Решение:

  • тип proxy: SOCKS5;

  • host: 127.0.0.1;

  • port: 1081;

  • логин и пароль: пусто.

После этого Telegram начинает работать через локальный SOCKS5 V2RayXS.

Если Telegram не подхватывает системный proxy, его нужно вручную направить на локальный SOCKS5 V2RayXS
Если Telegram не подхватывает системный proxy, его нужно вручную направить на локальный SOCKS5 V2RayXS

Почему скорость может быть ниже, чем на другом Mac

Если подключение уже работает, но скорость заметно ниже, это не обязательно ошибка настройки. На старом iMac типичные причины такие:

  • выбран перегруженный узел;

  • более слабый Intel CPU;

  • iMac сидит в диапазоне 2.4 GHz, а не 5 GHz;

  • на другом компьютере используется другой клиент или другой сетевой маршрут.

На практике переход на 5 GHz может дать очень заметный прирост скорости.

Как подготовить JSON для всех VLESS-узлов, не публикуя подписку

Если узлов много, вручную собирать JSON для каждого неудобно. Ниже — локальный Python-скрипт, который:

  • скачивает подписку по URL;

  • декодирует её;

  • находит все vless://...-ссылки;

  • превращает каждый узел в отдельный JSON-файл для V2RayXS;

  • ничего не отправляет на сторонние сервисы.

Сохраните файл как ~/Desktop/convert_subscription.py:

#!/usr/bin/env python3
import base64
import json
import os
import re
import sys
import urllib.request
from urllib.parse import urlparse, parse_qs, unquote

def safe_name(s: str) -> str:
    s = unquote(s).strip()
    s = re.sub(r'[\\/:*?"<>|]+', "_", s)
    s = re.sub(r"\s+", " ", s)
    return s[:80] if s else "node"

def first(params, key, default=""):
    values = params.get(key, [])
    return values[0] if values else default

def vless_to_outbound(link: str, index: int) -> dict:
    p = urlparse(link.strip())
    if p.scheme.lower() != "vless":
        raise ValueError("Not a vless link")

    params = parse_qs(p.query)
    tag = f"node-{index:03d} {safe_name(p.fragment)}".strip()

    user = {
        "id": p.username or "",
        "encryption": first(params, "encryption", "none"),
    }
    flow = first(params, "flow", "")
    if flow:
        user["flow"] = flow

    outbound = {
        "protocol": "vless",
        "tag": tag,
        "settings": {
            "vnext": [
                {
                    "address": p.hostname or "",
                    "port": p.port or 443,
                    "users": [user]
                }
            ]
        },
        "streamSettings": {
            "network": first(params, "type", "tcp"),
            "security": first(params, "security", "none")
        }
    }

    if outbound["streamSettings"]["security"] == "reality":
        reality = {
            "serverName": first(params, "sni", ""),
            "fingerprint": first(params, "fp", ""),
            "publicKey": first(params, "pbk", ""),
            "shortId": first(params, "sid", ""),
            "spiderX": unquote(first(params, "spx", "")),
        }
        reality = {k: v for k, v in reality.items() if v}
        outbound["streamSettings"]["realitySettings"] = reality

    return outbound

def main():
    if len(sys.argv) != 2:
        print("Usage: python3 convert_subscription.py '<SUBSCRIPTION_URL>'")
        sys.exit(1)

    sub_url = sys.argv[1]
    with urllib.request.urlopen(sub_url) as r:
        raw = r.read().decode("utf-8", errors="ignore").strip()

    decoded = base64.b64decode(raw).decode("utf-8", errors="ignore")
    links = [line.strip() for line in decoded.splitlines() if line.strip().lower().startswith("vless://")]

    if not links:
        print("No VLESS links found.")
        sys.exit(2)

    out_dir = os.path.expanduser("~/Desktop/v2rayxs-outbounds")
    os.makedirs(out_dir, exist_ok=True)

    index_lines = []
    for i, link in enumerate(links, start=1):
        outbound = vless_to_outbound(link, i)
        filename = f"{i:03d} - {safe_name(outbound['tag'])}.json"
        filepath = os.path.join(out_dir, filename)
        with open(filepath, "w", encoding="utf-8") as f:
            json.dump(outbound, f, ensure_ascii=False, indent=2)
        index_lines.append(f"{i:03d} -> {outbound['tag']}")

    with open(os.path.join(out_dir, "INDEX.txt"), "w", encoding="utf-8") as f:
        f.write("\n".join(index_lines))

    print(f"Done. Files saved to: {out_dir}")

if __name__ == "__main__":
    main()

Запуск:

python3 ~/Desktop/convert_subscription.py '<SUBSCRIPTION_URL>'
open ~/Desktop/v2rayxs-outbounds

После этого на рабочем столе появится папка v2rayxs-outbounds с JSON-файлами.

Скрипт раскладывает подписку на отдельные JSON-файлы.

Каждый такой файл можно открывать, копировать код и вставлять в Advanced -> Outbounds

Что сработало

Сработало:

  • отказаться от Happ как от основного сценария для Catalina;

  • не переоценивать формальную совместимость IRBox с macOS 10.15;

  • использовать V2RayXS как GUI над Xray;

  • не доверять auto-import, если он создаёт пустой конфиг;

  • собирать VLESS + Reality вручную через Advanced -> Outbounds;

  • подключить Telegram Desktop отдельно через SOCKS5 127.0.0.1:1081;

  • проверить диапазон Wi-Fi и перейти на 5 GHz.

Что не сработало

Не сработало:

  • ожидание, что «подписка импортировалась — значит всё готово»;

  • попытка работать с пустыми VLESS-пунктами из кривого импорта;

  • надежда, что браузер и Telegram поведут себя одинаково;

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

Вывод

Главный вывод из этой истории простой: на старом Intel Mac с macOS Catalina рабочее подключение зависит не столько от формальной поддержки протокола VLESS/Reality, сколько от того, насколько конкретный клиент и его bundled core реально совместимы с системой. Happ сейчас требует macOS 12+ и для Catalina отпадает официально. IRBox формально поддерживает macOS 10.15+, но на практике оказалось что это не так. А V2RayXS оказался рабочим именно потому, что позволил обойти кривой импорт и вручную собрать нормальный Xray-конфиг.

Комментарии (2)


  1. SergeMNE
    24.04.2026 18:32

    Предполагаю, что на старом Intel Mac с macOS Catalina выбор нормального vless клиента - это далеко не единственная проблема.

    А почему не сразу не воспользоваться патчером и не накатить хотя бы Вентуру?

    Вот репо с патчером https://github.com/dortania/OpenCore-Legacy-Patcher/releases


    1. BugM
      24.04.2026 18:32

      Есть старый ноут. Работает, музыку играет и видосики показывает. Больше от него ничего и не нужно.

      Что-то накатывать это перебор. Хочется просто приложеньку чтобы работала.

      PS: Старый мак у меня как раз есть. Попробую. Я уж думал что ютуб он отпоказывал.