Безопасность контроллера
API контроллера (external-controller, external-controller-tls, external-controller-unix, external-controller-pipe) может менять конфиг, правила, пользователей входящих, перезапускать и обновлять ядро. Его единственный ключ — secret: все пути, кроме проверок здоровья, файлов /ui и пути DoH, требуют Authorization: Bearer <secret> (WebSocket из браузера использует одноразовый билет; основной секрет в ?token= требует явной опции совместимости).
Secret на сетевом адресе
Заголовок раздела «Secret на сетевом адресе»Любому TCP-контроллеру нужен ключ, включая loopback. Обычный HTTP external-controller по умолчанию разрешён только на loopback: на удалённом адресе bearer-secret шёл бы открытым текстом. Отказ пишется в лог, а PUT /configs отвечает 400 и ничего не применяет.
Без secret работают:
external-controller-unixиexternal-controller-pipe— их защищают права файла и ACL канала;external-controller-tlsсtls.client-auth-type: require-and-verify(или с заданнымtls.client-auth-cert): ключом служит сертификат клиента.
external-controller-allow-insecure: true (или -ext-ctl-allow-insecure, CLASH_OVERRIDE_EXTERNAL_CONTROLLER_ALLOW_INSECURE=true) — явный legacy opt-in для TCP без secret или удалённого plaintext HTTP с bearer. Для удалённого доступа используйте external-controller-tls.
Веб-страницы и контроллер без secret
Заголовок раздела «Веб-страницы и контроллер без secret»TCP-контроллер без secret существует только в явном insecure-режиме либо с проверенным клиентским TLS-сертификатом. Для второго случая browser guard остаётся дополнительной защитой:
- отвечает только на запросы, где
Host— IP-адрес илиlocalhost; - отклоняет запросы с заголовком
Origin(все кросс-доменные запросы и вебсокеты из браузера), если источник не сам контроллер (встроенный/ui) и не указан явно вexternal-controller-cors.allow-origins;"*"не считается.
Программы (скрипты, панели, curl) не шлют Origin. Дашборду на внешнем сайте нужен secret или проверенный клиентский сертификат, а при необходимости — явный источник в allow-origins. Insecure-режим отключает эту защиту.
Перезагрузка конфига
Заголовок раздела «Перезагрузка конфига»PUT /configs, SIGHUP (systemctl reload citrus) и перезапуск применяют настройки контроллера из нового конфига: secret, адреса, tls, external-controller-cors, external-ui. Если что-то из них изменилось, листенеры контроллера перезапускаются (ответ на PUT /configs уходит раньше), а открытые вебсокет-потоки (/logs, /traffic, /memory, /connections, /events) закрываются — ничто, разрешённое старым secret, не остаётся открытым. Переопределения действуют при каждой перезагрузке. Используйте -secret-file: литеральные -secret, -age-secret-key и -config отклоняются, если только -allow-secret-arguments явно не возвращает риск утечки через список процессов. Перезагрузка, не меняющая контроллер, его соединения не трогает.
Версия ядра
Заголовок раздела «Версия ядра»GET /version отвечает так же, как mihomo, и с одним полем сверху:
{"meta": true, "version": "v1.0.0-beta.3", "core": "citrus"}Клиенты mihomo лишнее поле пропускают. Приложение, которое работает с обоими ядрами, может назвать ядро по core, а если поля нет — считать его mihomo.
Ограничения
Заголовок раздела «Ограничения»Каждый листенер контроллера обрывает клиента, который за 10 секунд не прислал заголовки запроса (или не закончил TLS-рукопожатие), закрывает простаивающие keep-alive соединения через 2 минуты и принимает не больше 256 КиБ заголовков. Потоки по времени не ограничены.
GET /connections как вебсокет принимает interval в миллисекундах от 1 до 3600000; на другое значение ответ 400.
