Безпечний, стандартний набір правил iptables для базового веб-сервера HTTP (s)


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 .


Ви кажете, що це 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 :)

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


Чи є якісь популярні інструменти, які використовують SNMP (161) через TCP? Я думаю, що ці правила повинні бути UDP / 161.
kubanczyk

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: DenyHosts - це парна купа. У мене він працював на одній машині, яка постійно отримувала спроби вторгнення від китайців. Протягом декількох місяців /etc/hosts.deny виріс, що в ньому було кілька тисяч IP-адрес, і в цей момент це спричинило sshd вичерпати ресурси на коробці, прискоривши навантаження до 60+ на одній машині процесора. Я перейшов на fail2ban і ніколи не оглядався.
hobodave

@hobodave Я щойно розпочав з DenyHosts, тому я зроблю цей розум як перше, що потрібно переключитися, коли це стане проблемою.
Xeoncross

1
@Xeoncross, якщо ви хочете повернути журнал iptables, ви можете написати свій власний скрипт logrotate.d для нього. Погляньте на /etc/logrotate.d і скопіюйте ще один і змініть ім'я файлу журналу, і він буде обертатися з іншими файлами журналу. Сторінка man для логротату пояснює різні варіанти.
Алан Іві

1

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

Для базового сервера HTTP потрібно відкрити вхідний доступ до порту 80 та порту 443, якщо ви використовуєте HTTPS. Як правило, бажаний вхід SSH з кількох обмежених адрес. Ви також можете заблокувати вихідний доступ. Відкрийте брандмауер лише для потрібних серверів та служб. Слід відкрити NTP та DNS, а також канал для отримання виправлень.


1

Я б сказав, що це досить гарний брандмауер, за винятком того, що він спрямований на зупинку в'їзного трафіку, а не зосереджений на виїзді чи виїзному трафіку. У багатьох випадках так само важливо зосередити увагу на з'єднаннях, що виходять з коробки, як і на вхідних. У нещасному випадку, що машина фактично експлуатується, було б непогано мати можливість запобігти завантаженню додаткових кореневих наборів, або підключенню до командних та керуючих вузлів, або будь-чого іншого.

БіллТор почав говорити про це вище, але я відповідаю лише конкретними прикладами. Однією з приємних речей про iptables є те, що він може запам’ятовувати стан з'єднання, це може мати наслідки для продуктивності на веб-сайтах з великою торгівлею людьми, але ви можете змінити вхідний доступ на http / https, щоб дозволити відповідь, наприклад, на встановлені з'єднання, або спеціально обмежити певні непривілейовані користувачі взагалі не мають вихідного доступу. Тоді ваші вихідні правила мали б ПОВ'ЯЗАНІ, Встановлені положення, які запобігали б цілому ряду допоміжних атак та уповільнили б ті, для яких потрібен вторинний етап, щоб фактично використовувати коробку, що дуже часто.

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


Так що я повинен змінити , -A INPUT -j REJECTщоб -A INPUT -P DROP?
Xeoncross
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.