Защищаем систему. Или как настроить и использовать port knocking

Салам-папалам всем!

Тут озадачился как же можно сделать свой сервер более безопаснее. Использование напрямую iptables с блокировкой по IP не решало проблемы, т.к. я могу к серверу подсоединяться не только с рабочего ПК, но и издому, или с другого города, или в автобусе (когда в пробках стою).
Решил использовать port knocking.
Кто ни разу не пользовался этим, милости прошу под кат.

Для тех кто не в теме кратко скажу: это демон, который «слушает» сетевой интерфейс и если «услышал», что идут запросы на 7000,8000,9000 порт, то добавляет разрешающее правило для вашего IP на определённый заранее вами порт. Она просто выполняет команду на разрешение или запрещение доступа в iptables.

Итак, я захотел прикрыть от всех ssh.
Сперва установим сам демон (для тестов я использовал свой рабочий ПК на Ubuntu):

sudo apt-get install knockd


Для CentOS можно установить так:

sudo rpm -Uhv http://pkgs.repoforge.org/knock/knock-0.5-3.el6.rf.x86_64.rpm


Далее нам надо отредактировать конфиг этого демона ( /etc/knockd.conf ):

[options]
        UseSyslog

[openSSH]
        sequence    = 7000:tcp,8000:tcp, 9000:udp
        seq_timeout = 5
        command     = /sbin/iptables -I INPUT 1 -s %IP% -d ВАШ_IP_ГДЕ_ХОТИТЕ_ОТКРЫТЬ_ДОСТУП -p tcp --dport 22 -j ACCEPT
        tcpflags    = syn

[closeSSH]
        sequence    = 9000:udp,8000:tcp,7000:tcp
        seq_timeout = 5
        command = /sbin/iptables -D INPUT -s %IP% -d ВАШ_IP_ГДЕ_ХОТИТЕ_ПРИКРЫТЬ_ДОСТУП -p tcp --dport 22 -j ACCEPT
        tcpflags    = syn



Затем перезапускаем демон:

sudo /etc/init.d/knockd restart


Далее, добавляем запрещающее правило для всех на 22-ой порт:

sudo iptables -A INPUT -s 0/0 -d ВАШ_IP_ГДЕ_ХОТИТЕ_ПРИКРЫТЬ_ДОСТУП -p tcp --dport 22 -j REJECT


В секции [openSSH] обратите внимание на строчки -I INPUT 1. Если мы просто напишем вместо этого -A INPUT, то оно будет добавляться в конец цепочки правил, и следовательно будет срабатывать только самое верхнее правило. Поэтому мы пишем так, что бы запрещающее правило было добавлено в конец.
sequence указывает на то, какими последовательностями портов мы будем открывать себе доступ. Обязательно укажите на своё.
Можно еще указать протокол, допустим так: 7000:udp, 8000:udp, 9000:tcp
tcpflags — тут мы указываем какие заголовки должны содержаться в передаваемых пакетах.

В секции [closeSSH] указываем обратную последовательность для закрытия 22-го порта. И там же команда на удаление вашего IP из списка разрешенных.

Теперь встаёт вопрос: как же послать эту волшебную последовательность на порты?
С сайта разработчика можно скачать программу для популярных платформ. Там же можно увидеть другие примеры использования.
В Windows я пользовался так: скачал, распаковал. Открыл командную строку,
cd ПУТЬ_ДО_ПАПКИ_С_ПРОГРАММОЙ
knock 192.168.0.1 7000:tcp 8000:tcp 9000:udp

Всё, открыли порт. Теперь мы можем заходить по SSH!

Если хотите для другого протокола это использовать, то таким же способом напишите секцию [openFTP], [closeFTP] с теми же правлами, только порты поменяйте на нужное и всё.
Минусы этой штуки в том, что надо дополнительную прогу использовать прежде чем подсоединиться. Но, мне кажется, что ради безопасности потерпеть можно.

Всем безопасности!
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 17

    +2
    В чем преимущества данной статьи по сравнению с этой, например?
      +3
      Их нет. Для тех, кому непривычна среда *BSD, показано решение на базе Ubuntu.
      +1
      iptables может и без knoсkd это.
        +7
        $IP=’/sbin/iptables’
        $EXTIP=<Your external IP>
        
        $IPT -A INPUT -d $EXTIP -p tcp –dport 1500 -j LOG
        $IPT -A INPUT -d $EXTIP -m state –state NEW -m tcp -p tcp –dport 22 -m recent –rcheck –name SSH -j ACCEPT
        $IPT -A INPUT -d $EXTIP -m state –state NEW -m tcp -p tcp –dport 1499 -m recent –name SSH –remove -j DROP
        $IPT -A INPUT -d $EXTIP -m state –state NEW -m tcp -p tcp –dport 1500 -m recent –name SSH –set -j DROP
        $IPT -A INPUT -d $EXTIP -m state –state NEW -m tcp -p tcp –dport 1501 -m recent –name SSH –remove -j DROP
        $IPT -A INPUT -d $EXTIP -p tcp –dport 22 -j DROP
        
          +1
          Наверное, первая строчка все-таки так должна выглядеть:
          $IPT=’/sbin/iptables’
          
        +2
        Никогда не понимал смысла в стучании по портам. Авторизацию по ключам при отключённой авторизации по паролю уже кто-то научился ломать?
          0
          Так можно же не только SSH закрывать, но и другие сервисы.
            +1
            А другие сервисы надо вообще всегда закрытыми держать, доступ к ним получая через SSH port forwarding.
              0
              А как просто сделать SSH port forwarding на Android/iPhone для, например, FTP?
                0
                iSSH это делает в несколько тапов. На андройде можно попробовать обычный консольный клиент OpenSSH.
                  0
                  А зачем нужен FTP при наличии SSH?
              +1
              Насколько мне известно — нет, хотя в свете недавних событий все может быть печальнее чем нам кажется.
              Однако не очень приятно видеть в логах по 1000 безуспешных попыток авторизаций каждую ночь.

              Я использую ICMP knocking вот по этому рецепту: MikroTik + port knocking over ICMP + защиту от перебора паролей Bruteforce

              И при этом отключенная парольная авторизация. Может немного и параноидально, но лучше перебдеть.
                +1
                Я, чтоб логи не забивались, вешаю сервисы на нестандартные порты. По хорошему, надо в таком случае сразу вешать на стандартные порты fail2ban и банить тех, кто туда ломится.
                  0
                  Подсказка из зрительного зала: fail2ban мониторит логи авторизации.

                  Ему, по большей части, всё равно, кто и в какие… кхм, порты долбится. Если надо выпилить в /dev/null всех незнакомцев, ломящихся в tcp/22, то прошу любить и жаловать ipset.
              –1
              Чо-то я не понял. Т.е этот демон просто прописывает в разрешения по преопределенному правилу для ip, с которого придет определенная последовательность запросов? Почему не повесить, например, простейший http, ожидающий строго определенный пакет и делающий то же самое?
              Тогда «запрос на вход» можно отправлять штатным wget. И даже telnet. А можно нарисовать html и предлагать вводить текстовую строку + POST — это для не-владеющих-консолью будет (хотя, зачем им ssh? :)
              В общем, что-то больно сложно для элементарной вещи.
                0
                << Почему не повесить, например, простейший http, ожидающий строго определенный пакет и делающий то же самое?
                Зачем это делать, если есть инструмент, специально предназначеный для этого?
                Отмечу, что knockd не слушает никаких портов, в отличие от http. Более того, эти порты вообще могут быть закрыт фаерволом, что не помешает работе knockd.

                << Тогда «запрос на вход» можно отправлять штатным wget. И даже telnet
                В случае с knockd это вполне возможно, просто штатным клиентом это удобнее делать.
                0
                Забыли рассказать про опцию конфига: cmd_timeout = time_in_seconds — задает таймаут, после которого будет выполнена команда, указанная в блоке [closeSSH]

                Only users with full accounts can post comments. Log in, please.