Ограничение потока ввода Java: защита от DoS-атак - PullRequest
2 голосов
/ 02 сентября 2010

Я кодирую инструмент, который при любом URL-адресе будет периодически получать свои выходные данные. Проблема заключается в том, что выводом может быть не простая и легкая HTML-страница (в большинстве случаев ожидается), а какой-то большой поток данных (т. Е. Прямо из / dev / urandom, возможная атака DoS).

Я использую java.net.URL + java.net.URLConnection, устанавливая время ожидания соединения и чтения на 30 секунд. В настоящее время ввод читается java.io.BufferedReader, используя readLine().

Возможные решения:

  1. Используйте java.io.BufferedReader.read() побайтно, считая их и закрывая соединение после достижения лимита. Проблема в том, что злоумышленник может передавать один байт каждые 29 секунд, поэтому время ожидания чтения / подключения почти никогда не наступит (204800B * 29sec = 68 дней)
  2. Ограничить выполнение потока до 1-5 минут и использовать java.io.BufferedReader.readLine(). Есть какие-нибудь проблемы здесь?

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

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 02 сентября 2010

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

Однако это и предлагаемые вами средства защиты работают только в том случае, если выходные данные поступают в режиме частичной передачи. В противном случае HttpURLConnection может буферизовать весь ответ до того, как вы его прочитаете. Обычное решение этого - фильтр в брандмауэре.

0 голосов
/ 02 сентября 2010

Кажется, здесь есть несколько путей отказа в обслуживании.

Огромная большая линия, которая сожирает память. Вероятно, самым простым является использование MeteredInputStream до того, как даже начнется декодирование символов. Чтение char по char будет чрезвычайно медленным при любых обстоятельствах. Вы можете читать длинные char[] за один раз, но это, вероятно, слишком усложнит код.

Работа с злоумышленником (или багом), поддерживающим много соединений одновременно. Вы, вероятно, хотите, чтобы неблокирующий ввод-вывод читал все сообщение, а затем продолжал нормально.

...