Cloudflare — отличная штука для защиты сайтов от разных компьютерных жуликов — хацкеров. Однако, если они всё же узнали как-то оригинальный IP веб-сервера, на котором расположен сайт, они как минимум будут пробовать атаковать его по IP, минуя прокси. Можно городить редиректы, слать NGINX-ом ресеты кодом 444 при попытке зайти на несуществующие домены, но самый железный выход из ситуации такой: открыть http/https трафик на сервер только для IP адресов нашей защитной прокси.

Кстати, данный метод также может сделать отчасти бесполезным разного рода сайты вроде crimeflare.org. Ну узнал «сыщик», что домен когда-то был доступен по такому-то IP — проверить, там ли он ещё, попытавшись зайти директом на IP:443 или IP:80 будет уже бесполезно.
А если на сервере закрыть вообще все порты, отключить ICMP и реализовать доступ только через IPMI/VNC, никто не узнает, что на нашем IP вообще что-то существует.

Сделаем это в iptables.

У CloudFlare есть огромное количество адресов, но все они ужимаются в небольшое количество подсетей. Предвидя такой запрос, ребята опубликовали статью, рассказывающую, где можно найти их актуальные подсети и даже что писать в iptables. Одна проблема — делать это предполагается вручную, что довольно неудобно и ненадёжно: адресация в CloudFlare может меняться со временем, и когда-нибудь может получиться так, что прокся, расположенная на новых адресах, будет не разрешена у вас на сервере. Соответственно клиенты, чьи сесссии будут проходить через эти новые адреса, не смогут зайти на ваш сайт.

К счастью, проблема автоматизируема. Итак:

1. Запрещаем в iptables весь HTTP/HTTPS трафик:

iptables -I INPUT 1 -p tcp -m multiport --dports http,https -j DROP

2. Кладём куда-нибудь, например, по /root/cloudflare-update.sh скрипт cloudflare-update.sh со следующим содержимым:

#!/bin/bash
while read ip ; do iptables -D INPUT -p tcp -m multiport --dports http,https -s "$ip" -j ACCEPT ; done <<< "$(curl https://www.cloudflare.com/ips-v4)"
while read ip ; do iptables -I INPUT -p tcp -m multiport --dports http,https -s "$ip" -j ACCEPT ; done <<< "$(curl https://www.cloudflare.com/ips-v4)"
iptables-save > /etc/iptables/rules.v4

То есть мы удаляем все существующие записи, добавленные ранее, заново добавляем всё, что имеется в списке адресов CloudFlare. Таким образом избегаем дубликатов правил. К конце — сохраняемся.

3. Делаем скрипт исполняемым:

chmod +x /root/cloudflare-update.sh

4. В крон (например, в конец файла /etc/crontab) добавляем задание обновлять адреса каждые 12 часов:

0 */12 * * * root /root/cloudflare-update.sh &> /dev/null

Всё! Теперь попасть по 80 и 443 портам на ваш сервер можно только через прокси, т.к. в любой момент времени только адреса, принадлежащие прокси, разрешены на сервере.

Комментарии (7)


  1. lostmsu
    21.06.2018 19:23

    Если CloudFlare поменяет свои адреса, ваш сайт может быть полностью или частично недоступен в среднем около 6 часов.


    Неужели у них нет push или http хуков?


  1. mihver1
    21.06.2018 20:05
    +3

    В этой статье очень вредный рецепт. В момент работы скрипта пользователи будут страдать.
    В вашем случае лучше сделать правило:
    -A INPUT -p tcp -m set --match-set cloudflare src -m multiports --dports 80,443 -j ACCEPT

    А в скрипте поддерживать два сета (cloudflare и temp_cloudflare), свопая их содержимое.


    1. zCooler
      22.06.2018 10:05

      Вы забыли добавить что сеты создаються в ipset.

      В дополнение могу сказать что надо в конфиге ipset (/etc/sysconfig/ipset-config для CentOS) указать
      IPSET_SAVE_ON_STOP="yes"

      Ну и скрипт будет выглядеть:

      #!/bin/bash
      while read ip ; do ipset -A cloudfare "$ip" ; done <<< "$(curl https://www.cloudflare.com/ips-v4)"



  1. MMik
    21.06.2018 20:05
    +3

    Если в промежутке между запусками скрипта cloudflare удалит часть сетей из www.cloudflare.com/ips-v4, то вы об этом не узнаете и их не удалите — это раз.
    Используйте отдельную цепочку, чтобы очищать её всю, когда нужно, и вы избежите проблемы, описанной выше — это два.
    Используйте ipset вместо индивидуальных правил — это три, и об этом Cloudflare написал в заметке, на которую вы ссылаетесь.

    Вашу заметку можно было свести к пункту 4.

    0 */12 * * * root /root/cloudflare-update.sh &> /dev/null
    , потому что всё остальное Сloudflare описал.


  1. rionnagel
    22.06.2018 02:12

    Надо на всякий случай попробовать). Но лучше всё таки не компрометировать адрес. Например если придёт много трафика на порт будет уже сложно что-то сделать, провайдер пошлет его например в блекхол, ресурс потухнет и придется менять срочно адрес(.


  1. zhengxi
    22.06.2018 12:01

    Только имейте ввиду: если Cloudflare вас выкинет — по абузе или если им покажется, что вы слишком много траффика прокачиваете на бесплатном тарифе — то они внезапно, без предупреждения, выключат проксирование, но оставят DNS.

    IP вашего сайта станет IP вашего сервера.

    А к нему доступ запрещён для всех кроме Cloudflare.

    То есть, к вашему решению полезно ещё добавить проверку, что сайт пока еще проксируется Cloudflare.


  1. selivanov_pavel
    22.06.2018 15:20

    Если в правилах iptables начинают появляться длинные списки IP-адресов, надо начинать использовать ipset. Кроме того, это позволяет добалять/удалять адреса не перегружая все правила iptables целиком.