Безопасный стандартный набор правил iptables для базового веб-сервера HTTP.

15

Я пытался собрать базовый серверный сценарий iptables, который будет работать для большинства сайтов, просто использующих базовый веб-сервер с использованием HTTP (S) и SSH (порты 80, 443 и 22). В конце концов, большинству VPS нужны только эти правила запуска портов, и они могут добавлять почтовые или игровые порты позже, когда это необходимо.

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

*filter

#  Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

#  Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#  Allows all outbound traffic
#  You can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT

# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

#  Allows SSH connections (only 4 attempts by an IP every 3 minutes, drop the rest)
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsource
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 180 --hitcount 4 --name DEFAULT --rsource -j DROP
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# Reject all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

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

Какой самый безопасный способ открыть только основные порты, необходимые для веб-сервера?

Обновление: у cyberciti.biz есть еще один скрипт iptables, который выглядит довольно неплохо.

Кроме того, вместо использования Denyhosts или fail2ban вы можете использовать сам iptables, чтобы заблокировать неудачные повторные попытки SSH .

оборота Xeoncross
источник
Вы говорите, что это VPS. Я предполагаю, что у него есть IP-адрес локальной сети, верно? Доверяете ли вы каждой машине в вашей подсети? Как бы вы не хотели быть здесь параноиком, вы можете использовать OUTPUT-фильтрацию для дополнительной защиты вашей машины. Дайте мне знать, и я могу ответить тем, что я бы предложил вам использовать.
hobodave
Хороший вопрос, учитывая, что большинство VPS находятся в виртуальной машине с другими, возможно, доступными из локальной сети, я бы сказал, что недоверие к ним будет разумной отправной точкой. Если у вас есть дополнительные VPS, вы можете добавить правила позже для доступа к ним (например, веб-сервер к базе данных).
Xeoncross
1
ВНИМАНИЕ: если вы выполните упомянутый скрипт cyberciti.biz и modprobeон не установлен (или перед открытием порта 22 возникнет какая-либо другая ошибка), вы заблокируете себя на сервере.
EoghanM

Ответы:

14

Самый безопасный способ работы с iptables - закрыть все и открыть только то, что вам нужно. Я немного отвлечен, поэтому я всегда стараюсь быть как можно более ленивым, поэтому я не делаю ошибок, которые могут привести к небезопасности сервера.

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

  #!/bin/bash +x

  # first author: marcos de vera
  # second: joan marc riera

  ip=/sbin/iptables
  mriera="xx.xx.xx.xx"
  nsancho="yy.yy.yy.yy"
  admins="$mriera $nsancho "
  sshers=""
  mysqlrs="zz.zz.zz.zz/23"
  snmprs="uu.uu.uu.uu"
  tcpservices="80 443 22"
  udpservices=""

  # Firewall script for servername

  echo -n ">> Applying iptables rules... "

  ## flushing...
  $ip -F
  $ip -X
  $ip -Z
  $ip -t nat -F

  # default: DROP!
  $ip -P INPUT DROP
  $ip -P OUTPUT DROP
  $ip -P FORWARD DROP

  # filtering...

  # localhost: free pass!
  $ip -A INPUT -i lo -j ACCEPT
  $ip -A OUTPUT -o lo -j ACCEPT

  # administration ips: free pass!
  for admin in $admins ; do
      $ip -A INPUT -s $admin -j ACCEPT
      $ip -A OUTPUT -d $admin -j ACCEPT
  done

  # allow ssh access to sshers
  for ssher in $sshers ; do
      $ip -A INPUT -s $ssher -p tcp -m tcp --dport 22 -j ACCEPT
      $ip -A OUTPUT -d $ssher -p tcp -m tcp --sport 22 -j ACCEPT
  done

  # allow access to mysql port to iReport on sugar

  for mysql in $mysqlrs ; do
      $ip -A INPUT -s $mysql -p tcp -m tcp --dport 3306 -j ACCEPT
      $ip -A OUTPUT -d $mysql -p tcp -m tcp --sport 3306 -j ACCEPT
      $ip -A INPUT -s $mysql -p udp -m udp --dport 3306 -j ACCEPT
      $ip -A OUTPUT -d $mysql -p udp -m udp --sport 3306 -j ACCEPT
  done


  # allowed services
  for service in $tcpservices ; do
      $ip -A INPUT -p tcp -m tcp --dport $service -j ACCEPT
      $ip -A OUTPUT -p tcp -m tcp --sport $service -m state --state RELATED,ESTABLISHED -j ACCEPT
  done
  for service in $udpservices ; do
      $ip -A INPUT -p udp -m udp --dport $service -j ACCEPT
      $ip -A OUTPUT -p udp -m udp --sport $service -m state --state RELATED,ESTABLISHED -j ACCEPT
  done

  $ip -A INPUT -j LOG --log-level 4
  # VAS and VGP
  #88 tcp udp
  #389 tcp ldap queries , udp ldap ping
  #464 tcp upd kerberos
  #3268 tcp global catalog access
  for dc in ip.ip.ip.ip ; do # our dc servers for some ldap auth
      vas=88
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $vas -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $vas -j ACCEPT
      $ip -A INPUT -s $dc -p udp -m udp --dport $vas -j ACCEPT
      $ip -A OUTPUT -d $dc -p udp -m udp --dport $vas -j ACCEPT
      ldap=389
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $ldap -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $ldap -j ACCEPT
      $ip -A INPUT -s $dc -p udp -m udp --dport $ldap -j ACCEPT
      $ip -A OUTPUT -d $dc -p udp -m udp --dport $ldap -j ACCEPT
      kpasswd=464
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $kpasswd -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $kpasswd -j ACCEPT
      $ip -A INPUT -s $dc -p udp -m udp --dport $kpasswd -j ACCEPT
      $ip -A OUTPUT -d $dc -p udp -m udp --dport $kpasswd -j ACCEPT
      gca=3268
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $gca -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $gca -j ACCEPT
      vgp=445
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $vgp -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $vgp -j ACCEPT
  done


  # allow the machine to browse the internet
  $ip -A INPUT -p tcp -m tcp --sport 80 -m state --state RELATED,ESTABLISHED -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT
  $ip -A INPUT -p tcp -m tcp --sport 443 -m state --state RELATED,ESTABLISHED -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT

  $ip -A INPUT -p tcp -m tcp --sport 8080 -m state --state RELATED,ESTABLISHED -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 8080 -j ACCEPT


  # don't forget the dns...
  $ip -A INPUT -p udp -m udp --sport 53 -j ACCEPT
  $ip -A OUTPUT -p udp -m udp --dport 53 -j ACCEPT
  $ip -A INPUT -p tcp -m tcp --sport 53 -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 53 -j ACCEPT

  # ... neither the ntp... (hora.rediris.es)
  #$ip -A INPUT -s 130.206.3.166 -p udp -m udp --dport 123 -j ACCEPT
  #$ip -A OUTPUT -d 130.206.3.166 -p udp -m udp --sport 123 -j ACCEPT

  $ip -A INPUT -p udp -m udp --dport 123 -j ACCEPT
  $ip -A OUTPUT -p udp -m udp --sport 123 -j ACCEPT


  # and last but not least, the snmp access
  for monitor in $snmprs ; do
      $ip -A INPUT -s $monitor -p tcp -m tcp --sport 161 -j ACCEPT   # monitoring service
      $ip -A OUTPUT -d $monitor -p tcp -m tcp --dport 161 -j ACCEPT  # monitoring service
  end
  # outgoing SMTP
  $ip -A INPUT -p tcp -m tcp --sport 25 -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 25 -j ACCEPT


  # temporary backup if we change from DROP to ACCEPT policies
  $ip -A INPUT -p tcp -m tcp --dport 1:1024 -j DROP
  $ip -A INPUT -p udp -m udp --dport 1:1024 -j DROP


  echo "OK. Check rules with iptables -L -n"

  # end :)

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

marc.riera
источник
Есть ли какие-нибудь популярные инструменты, которые используют SNMP (161) поверх TCP? Я думаю, что эти правила должны быть UDP / 161.
Кубанчик
1

Это выглядит довольно хорошо, но вы могли бы немного ужесточить ситуацию. Флаг -s - это исходный IP-адрес или имя домена, и вы добавляете «-s 198.23.12.32» или любой другой ваш IP-адрес, чтобы разрешить SSH только из исходного IP-адреса. Вы также можете выбрать диапазон исходных IP-адресов, используя нотацию в стиле CIDR .

Вы должны соблюдать осторожность при регистрации отклоненных вызовов. IP-адрес вашего сервера будет проверяться ботами, сценаристами и т. Д., А файл журнала может быстро увеличиться. Если вы не пытаетесь диагностировать конкретную проблему, которая, по вашему мнению, может быть связана с тем, кто пытается сломать ваш брандмауэр, я бы удалил эту опцию.

Вы также можете привязать в fail2ban к iptables для псевдо-IDS. fail2ban сканирует ваши файлы журнала и может заблокировать IP-адрес, если они попытаются проникнуть в вашу систему. Например, если определенному IP-адресу не удается войти в SSH 5 раз, вы можете заблокировать его на весь день. Он также работает по FTP и многим другим (включая плохих ботов, поражающих Apache). Я использую его на всех своих серверах, чтобы обеспечить дополнительную защиту от атак методом перебора.

Алан Айви
источник
Я фактически использую DenyHosts, так как он экономит 15 МБ или около того по сравнению с fail2ban. Однако fail2ban более мощный и работает со многими приложениями (не только с SSH, как DenyHosts). Учитывая, что злоумышленники забанены, должен ли я все еще беспокоиться о быстром заполнении файлов журнала? Есть ли способ вращать файлы, когда они становятся полными? Если я отключу вход в систему fail2ban, будет ли Denyhosts / Fail2ban иметь записи в журнале для сканирования? Кроме того, вариант с исходным кодом был бы полезен для некоторых людей, но, поскольку я нацеливаюсь на набор правил по умолчанию, такие люди, как я, которые много передвигаются, не могут использовать эту опцию.
Xeoncross
@Xeoncross: DenyHosts - это дымящаяся куча имо. Я запустил его на одной машине, которая постоянно получала попытки вторжения от китайцев. За несколько месяцев /etc/hosts.deny вырос до нескольких тысяч IP-адресов, после чего sshd исчерпал ресурсы на коробке, что увеличило нагрузку до 60+ на одном процессоре. Я переключился на fail2ban и никогда не оглядывался назад.
hobodave
@hobodave Я только начал с DenyHosts, так что я буду думать об этом как о первом, что нужно переключить, когда это станет проблемой.
Xeoncross
1
@Xeoncross Если вы хотите вращать журнал iptables, вы можете написать для него собственный скрипт logrotate.d. Взгляните на /etc/logrotate.d, скопируйте еще один и измените имя файла журнала, и оно будет повернуто вместе с другими файлами журнала. Страница man для logrotate объясняет различные варианты.
Алан Айви
1

Посмотрите на Shorewall. Конфигурация по умолчанию для одного интерфейса будет хорошей отправной точкой. Он прост в настройке и имеет макросы для таких вещей, как SSH и веб-доступ. Можно настроить блокировку сервера до требуемого уровня при выключении брандмауэра. С Shorewall-lite вы можете запустить сборку брандмауэра на другом сервере. Ведение журнала легко настроить на желаемый уровень.

Для базового HTTP-сервера вы хотите открыть входящий доступ к порту 80 и порту 443, если вы используете HTTPS. SSH входящий доступ с нескольких ограниченных адресов обычно желателен. Вы также можете заблокировать исходящий доступ. Откройте брандмауэр только для необходимых серверов и служб. Должны быть открыты NTP и DNS, а также канал для извлечения исправлений.

BillThor
источник
1

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

BillThor начал говорить об этом выше, но я просто отвечаю конкретными примерами. Одна из приятных особенностей iptables заключается в том, что он может запоминать состояние соединения, это может влиять на производительность сайтов с интенсивным движением, но вы можете изменить свой входящий доступ по http / https, чтобы разрешить, например, ответ только на установленных соединениях, или специально ограничить определенные непривилегированные пользователи имеют исходящий доступ вообще. Тогда ваши исходящие правила будут иметь предложения RELATED, ESTABLISHED, которые будут предотвращать целый ряд вспомогательных атак и замедлять те, которые требуют вторичной стадии для фактического использования бокса, что очень часто встречается.

Наконец, я бы сказал, что лучше установить политику iptables -P DROP, а не добавлять в конце REJECT. В основном это вопрос предпочтений, но он может уменьшить количество ошибок при добавлении в цепочки с существующими правилами вместо вставки или очистки / сброса.

MattyB
источник
Так что я должен измениться -A INPUT -j REJECTна -A INPUT -P DROP?
Xeoncross