Перейти к содержимому
НовостиGitHubСкачать

Пользователи входящих на лету

Пользователей входящего из раздела listeners: можно менять, пока он работает: слушатель не пересоздаётся, конфиг не перезагружается, соединения остальных пользователей не рвутся.

  • Добавленный пользователь подключается сразу.
  • У удалённого пользователя закрываются все установленные соединения (вместе с mux-подпотоками и UDP-сессиями), новые подключения отклоняются, его счётчик трафика удаляется, когда байты забраны.
  • Смена секрета (или flow у VLESS) закрывает соединения пользователя, открытые со старым секретом; старый секрет больше не принимается.
  • Пользователи, запись которых не менялась, ничего не замечают.

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

Тип name secret flow
vless username UUID xtls-rprx-vision или пусто
trojan username пароль —
anytls имя пользователя пароль —
trusttunnel username пароль —
tuic (v5) UUID пользователя пароль —
shadowsocks name ключ пользователя (uPSK) —
socks, http, mixed username пароль —

Ограничения:

  • shadowsocks — только многопользовательский режим (2022-blake3-aes-* с users в конфиге). Ключи проверяются так же, как в конфиге. При смене пользователей UDP-сессии всех пользователей начинаются заново (клиент видит новую сессию сервера) — клиенты Shadowsocks 2022 это переживают.
  • socks, http, mixed — только если у входящего свои users в конфиге. Без users действует глобальная authentication, а users: [] отключает проверку — менять там нечего. Пустой список пользователей, заданный через API, никого не пускает (а не отключает проверку).
  • Глобальная authentication меняется перезагрузкой конфига — так же для входящих socks, http и mixed, которые её используют (и для слушателей socks-port, port, mixed-port): соединения удалённого пользователя или пользователя со сменённым паролем закрываются, а включение проверки закрывает соединения, пущенные без неё. Если пароль пользователя не менялся, его соединения остаются.
  • tuic — имена хранятся как UUID в нижнем регистре (так их видит IN-USER).
  • hysteria2, mieru, shadowquic и остальные пока не поддерживают: их библиотеки меняют таблицу пользователей без синхронизации или вовсе не умеют её менять. Для них API отвечает 409.

Через API у каждого пользователя должно быть непустое уникальное имя и непустой уникальный секрет; иначе — 400, и ничего не меняется. Конфиг по-прежнему допускает пользователей без имени, кроме socks, http, mixed и глобальной authentication: там пустое имя — ошибка конфига, потому что пустое имя для IN-USER, лимитов пользователей и закрытия сессий означает «нет пользователя».

Запросы идут к external-controller с тем же secret, что и остальной API. {name} — имя входящего из listeners:.

Запрос Что делает
GET /inbounds/{name}/users Список пользователей: имена и flow, без секретов.
PUT /inbounds/{name}/users Заменить всех: {"users": [{"name": "…", "secret": "…", "flow": "…"}]}.
POST /inbounds/{name}/users Добавить одного: {"name": "…", "secret": "…"}. Ответ 201.
PATCH /inbounds/{name}/users/{user} Сменить секрет и/или flow: {"secret": "…"}. Соединения пользователя закрываются.
DELETE /inbounds/{name}/users/{user} Удалить пользователя и закрыть его соединения.

Коды: 404 — нет такого входящего или пользователя; 400 — неверные данные (пустое или повторное имя, повторный секрет, неверный ключ или flow); 409 — входящий не умеет менять пользователей на лету, в сообщении указан его тип.

curl -X POST -H "Authorization: Bearer $SECRET" \
-d '{"name":"bob","secret":"b0b0b0b0-0000-4000-8000-000000000000"}' \
http://127.0.0.1:9090/inbounds/vless-in/users
curl -X DELETE -H "Authorization: Bearer $SECRET" \
http://127.0.0.1:9090/inbounds/vless-in/users/alice
{ "inbound": "vless-in", "type": "vless", "users": [{ "name": "bob" }] }

Изменения живут в памяти. Источник правды — конфиг: следующая перезагрузка (PUT /configs, перезапуск) снова ставит пользователей из конфига. Панель, которая управляет пользователями через API, хранит свой список и пишет его в конфиг, который применяет.

Перезагрузка тоже стала бережнее: если у входящего в новом конфиге изменились только пользователи, а остальное совпадает, слушатель не пересоздаётся — ему на месте ставятся пользователи из конфига, и рвутся только соединения удалённых и сменивших ключ пользователей. Если конфиг входящего не изменился, но пользователи меняли через API, перезагрузка возвращает пользователей конфига тем же способом. Если поменялось что-то кроме пользователей (порт, TLS, транспорт…), входящий пересоздаётся, как раньше.

Для встраивания ядра, пакет github.com/metacubex/mihomo/listener:

users, err := listener.InboundUsers("vless-in") // []constant.InboundUser, с секретами
err = listener.SetInboundUsers("vless-in", users) // заменить всех
err = listener.AddInboundUser("vless-in", constant.InboundUser{Name: "bob", Secret: uuid})
err = listener.RemoveInboundUser("vless-in", "alice")
err = listener.ModifyInboundUser("vless-in", "bob", func(u *constant.InboundUser) error {
u.Secret = newUUID
return nil
})

Ошибки: listener.ErrInboundNotFound, listener.ErrInboundUserNotFound, listener.ErrInboundUserExists, constant.ErrInvalidInboundUser, constant.ErrInboundUsersUnsupported (проверяются через errors.Is). Слушатель, который поддерживает обновление, реализует constant.InboundUserUpdater.