Я установил ограничение скорости, чтобы остановить атаки методом перебора на мой ssh-сервер. Я использую следующие правила iptables:
iptables -A INPUT -p tcp -m tcp --dport 22 -m hashlimit --hashlimit-upto 4/min
--hashlimit-burst 6 --hashlimit-mode srcip --hashlimit-name ssh
--hashlimit-htable-expire 60000 -m state --state NEW -j ACCEPT
iptables -A INPUT -m tcp -p tcp --dport 22 -m state --state NEW -j REJECT
Когда я открываю одно SSH-соединение (например, через PuTTY), а затем, через минуту, пытаюсь открыть другое (например, для передачи файла), второе соединение иногда отклоняется без ответа от сервера . Если мне удастся открыть второе соединение SSH, а затем я попытаюсь открыть третье соединение, это станет еще сложнее (высокая вероятность отсутствия ответа.)
Я убедился, что когда я отключаю вышеуказанные правила, все работает нормально. Увеличение - hashlimit-up до
и / или - hashlimit-burst
помогает, но не решает
проблема полностью - это только снижает вероятность ее возникновения. Отказ по-прежнему случается, но если я отключу правило iptables, этого никогда не произойдет.
Что происходит? В приведенных выше правилах iptables говорится, что количество TCP-пакетов, связанных с новыми подключениями, должно быть ограничено до 4 в минуту. Так что я легко смогу открывать до 4 соединений в минуту.
(Отвечая на мой собственный вопрос, чтобы оставить запись для других.)
Ваше первое правило:
iptables -A INPUT -p tcp -m tcp --dport 22 -m hashlimit --hashlimit-upto 4/min
--hashlimit-burst 6 --hashlimit-mode srcip --hashlimit-name ssh
--hashlimit-htable-expire 60000 -m state --state NEW -j ACCEPT
не делать того, что, по вашему мнению, он делает. Когда вы говорите -m tcp
, -m hashlimit
и -m state
, вы вызываете три модуля iptables. Вы думаете, что хеш-лимит будет применяться только к пакетам, удовлетворяющим всем остальным условиям правила. Но это не то, что происходит. Вместо этого модули выполняются в порядке, указанном в правиле.
(Насколько мне известно, этот факт не является интуитивно очевидным и нигде явно не задокументирован.)
В приведенном выше правиле -m hashlimit
предшествует -m state
. Это означает, что каждый TCP-пакет (а не только НОВЫЙ пакет) будет первым отправляться в модуль ограничения хэшей. Hashlimit подсчитает этот пакет и, если он находится в пределах 4/мин
, он будет передан в состояние -m
. Только теперь модуль state
может просмотреть пакет и проверить, представляет ли он новое соединение.
В вашем случае вы открываете свое первое SSH-соединение, которое время от времени передает некоторые пакеты.Эти пакеты не являются «НОВЫМИ» пакетами, поэтому они не отбрасываются (условие --state NEW
во втором правиле не выполняется). Но они обрабатываются по хэшлиму и будут учитываться в вашем 4/мин
лимите. Если они приходят достаточно быстро, они израсходуют квоту, и если вы затем попытаетесь открыть другое соединение, первый пакет для этого соединения столкнется с квотой, и ваше первое правило не будет соответствовать.
Очевидным решением является изменение порядка:
iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m hashlimit
--hashlimit-upto 4/min --hashlimit-burst 6 --hashlimit-mode srcip --hashlimit-name ssh
--hashlimit-htable-expire 60000 -j ACCEPT
В общем, я думаю, что хорошее эмпирическое правило состоит в том, чтобы всегда ставить -m hashlimit
последним в правиле iptables.