Безопасность
DarkWS берёт на себя фрейминг, лимиты и инфраструктуру аутентификации. Проверка токенов, срок их действия, отзыв и доменные права доступа остаются за приложением. На этой странице перечислено, что нужно настроить для продакшена.
Чек-лист
- Обслуживайте эндпоинт только через WSS.
- Ограничьте origin'ы, если используете cookie.
- Не передавайте токены в URL или используйте короткоживущие тикеты.
- Реализуйте аутентификатор, который проверяет токены; аутентификатор по умолчанию доверяет только HTTP-идентичности.
- Проверяйте доменные права доступа в действиях.
- Самостоятельно обеспечивайте истечение и отзыв сессий.
- Ограничивайте число соединений на пользователя или IP на уровне хоста или прокси.
- Изолируйте Redis сетевыми правилами и ACL.
- Маскируйте токены и payload в логах.
Межсайтовый перехват WebSocket
CORS не действует на WebSocket. При аутентификации через cookie страница на другом сайте может открыть сокет к вашему эндпоинту; браузер приложит cookie пользователя, и сокет станет DarkWS-сессией этого пользователя.
Ограничьте origin'ы:
app.UseWebSockets(new WebSocketOptions { AllowedOrigins = { "https://app.example.com" } });
Другие origin'ы получают 403 ещё до того, как DarkWS их аутентифицирует. Запросы без
заголовка Origin (небраузерные клиенты) по-прежнему принимаются. Пустой список —
значение по умолчанию для UseWebSockets() — разрешает любые origin'ы.
В DarkWS 4.x нет собственного параметра для origin'ов. WebSocketOptions.AllowedOrigins
применяется ко всем WebSocket-эндпоинтам приложения.
Токены в URL
Токены в URL WebSocket могут попасть в логи прокси, логи доступа и телеметрию.
- Предпочитайте передавать в URL короткоживущий одноразовый тикет подключения.
- Либо, если ваш эндпоинт допускает анонимный upgrade и ваш аутентификатор это
поддерживает, оставьте URL чистым и аутентифицируйтесь через сокет до отправки
защищённых запросов:
authenticate(token)(браузер) либоAuthenticateAsyncилиAuthenticationTokenProvider(.NET). Браузерный клиент не повторяетauthenticate()после переподключения; вызывайте его заново при каждомopen. - Маскируйте учётные данные при логировании URL и сообщений. См. рекомендации ASP.NET Core по логированию токенов доступа.
Попытки аутентификации
DarkWS не ограничивает попытки auth:: одно соединение может перебирать токены так
быстро, как позволяет сеть, и каждая попытка с непустым токеном запускает ваш
аутентификатор.
- Используйте токены с высокой энтропией.
- Если тикеты короткие или проверка дорогая, считайте неудачи в аутентификаторе (по
ключу
HttpContext.Connection.Id, пользователя или IP клиента) и вызывайтеHttpContext.Abort(), чтобы разорвать соединение по достижении лимита.
Время жизни сессии
Истечение срока действия или отзыв токена не закрывает существующее соединение. Сокет может оставаться открытым несколько дней.
- Храните срок действия в своей сессии и проверяйте его в своих действиях.
- При отзыве найдите соединения через
ConnectionStorage.GetBySession(id)и закройте их с помощьюCloseAsync().ConnectionStorageсодержит только соединения текущего инстанса. - Отклонённая команда
auth:очищает прежнюю сессию, поэтому неудачное обновление оставляет соединение анонимным. - Клиенты не хранят токены, переданные вручную. После logout очистите источник токенов приложения, чтобы переподключение не восстановило старые учётные данные.
Авторизация
Обработчикам нужна аутентифицированная сессия, если они не помечены
[AllowAnonymous]. Встроенной авторизации по ролям или политикам нет: [Authorize]
приводит к ошибке регистрации, чтобы его нельзя было молча проигнорировать.
Проверяйте права в действиях и возвращайте контролируемые ошибки через
ErrorResponseException. См. Обработчики и действия.
Лимиты ресурсов
Для каждого соединения DarkWS ограничивает размер сообщения (MaxMessageSizeBytes,
1 MiB), число параллельных запросов (16; при достижении лимита он перестаёт читать из
сокета) и время отправки. См. Конфигурация и лимиты.
DarkWS не ограничивает:
- число соединений: используйте хост (лимиты
Kestrel) или обратный прокси; - частоту запросов на пользователя или IP: считайте запросы в своих действиях;
- размер сообщений Redis: ограничивайте то, что отправляют ваши издатели.
Redis
Любой, кто может публиковать в канал backplane, может отправлять уведомления всем клиентам. Ограничьте доступ сетевой изоляцией и ACL Redis. Номера логических баз данных не изолируют Pub/Sub. См. Redis backplane.
Подробности ошибок
Непредвиденные исключения логируются, а в ответ отправляется
darkws:error:request-failed; их сообщения никогда не доходят до клиентов.
Отправляются только данные, которые вы передаёте в Error(code, details) или
ErrorResponseException<T>.
Сообщение об уязвимости
Не открывайте публичный issue. Сообщите приватно через GitHub Security Advisories, указав затронутый пакет и версию, последствия и шаги воспроизведения. Исправления выпускаются для последней мажорной версии.