Безопасность
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'ы.
Если другим WebSocket-эндпоинтам приложения нужны другие origin'ы, задайте вместо
этого DarkWsOptions.AllowedOrigins. Этот параметр применяется только к эндпоинту
DarkWS, сравнивается без учёта регистра и проверяется до запуска аутентификатора.
Токены в URL
Токены в URL WebSocket могут попасть в логи прокси, логи доступа и телеметрию.
- Предпочитайте передавать в URL короткоживущий одноразовый тикет подключения.
- Либо, если ваш эндпоинт допускает анонимный upgrade, оставьте URL чистым и
аутентифицируйтесь через сокет с помощью
authenticationToken(браузер) илиAuthenticationTokenProvider(.NET). Тогда каждый сокет проходит аутентификацию до отправки защищённых запросов. - Маскируйте учётные данные при логировании URL и сообщений. См. рекомендации ASP.NET Core по логированию токенов доступа.
Попытки аутентификации
DarkWS не ограничивает попытки auth:: одно соединение может перебирать токены так
быстро, как позволяет сеть, и каждая попытка запускает ваш аутентификатор.
- Используйте токены с высокой энтропией.
- Если тикеты короткие или проверка дорогая, считайте неудачи в аутентификаторе (по
ключу
HttpContext.Connection.Id, пользователя или IP клиента) и вызывайтеHttpContext.Abort(), чтобы разорвать соединение по достижении лимита.
Время жизни сессии
Истечение срока действия или отзыв токена не закрывает существующее соединение. Сокет может оставаться открытым несколько дней.
- Храните срок действия в своей сессии и проверяйте его в фильтре действий.
- При отзыве найдите соединения через
IDarkWsConnections.GetBySession(id)и закройте их. KeepSessionOnFailedAuthenticationсохраняет старую сессию после неудачного обновления; включайте его, только если срок действия проверяется в другом месте.- Клиенты не хранят токены, переданные вручную. После logout очистите источник токенов приложения, чтобы переподключение не восстановило старые учётные данные.
Авторизация
Обработчикам нужна сессия, если они не помечены [AllowAnonymous]. Встроенной
авторизации по ролям или политикам нет: [Authorize] приводит к ошибке регистрации,
чтобы его нельзя было молча проигнорировать. Проверяйте права в действиях или в
фильтрах действий и возвращайте контролируемые
ошибки через ErrorResponseException.
Лимиты ресурсов
Для каждого соединения DarkWS ограничивает размер сообщения (MaxMessageSizeBytes,
1 MiB), число параллельных запросов (16), запросов в очереди и время отправки. См.
Конфигурация и лимиты. DarkWS не ограничивает:
- число соединений: используйте хост (лимиты
Kestrel) или обратный прокси; - частоту запросов на пользователя или IP: используйте rate limiting в хосте или фильтр действий;
- размер сообщений Redis: ограничивайте то, что отправляют ваши издатели.
Redis
Любой, кто может публиковать в канал backplane, может отправлять уведомления всем клиентам. Ограничьте доступ сетевой изоляцией и ACL Redis. Номера логических баз данных не изолируют Pub/Sub. См. Redis backplane.
Подробности ошибок
Непредвиденные исключения логируются, а в ответ отправляется
darkws:error:request-failed; их сообщения никогда не доходят до клиентов.
Отправляются только данные, которые вы передаёте в Error(code, details) или
ErrorResponseException<T>.
Сообщение об уязвимости
Не открывайте публичный issue. Сообщите приватно через GitHub Security Advisories, указав затронутый пакет и версию, последствия и шаги воспроизведения. Исправления выпускаются для последней мажорной версии.