适用于基本 HTTP(s) Web 服务器的安全、标准 iptables 规则集

适用于基本 HTTP(s) Web 服务器的安全、标准 iptables 规则集

我一直在尝试编写一个基本的服务器 iptables 脚本,该脚本适用于大多数网站,只需运行使用 HTTP(S) 和 SSH(端口 80、443 和 22)的基本 Web 服务器即可。毕竟,大多数 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),但是有很多人像我一样很难理解为我们的服务器构建一个安全的基本防火墙所需要的一切。

仅打开 Web 服务器所需的基本端口的最安全方法是什么?

更新:cyberciti.biz 还有另一个iptables 脚本看起来不错。

另外,除了使用 Denyhosts 或 fail2ban,您还可以使用iptables 本身可以阻止错误的重复 SSH 尝试

答案1

使用 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 :)

我已经使用它有一段时间了,如果它能使它更容易管理,任何修改都将非常感激。

答案2

这看起来很不错,但你可以再严格一点。-s 标志是源 IP 或域名,你可以添加“-s 198.23.12.32”或任何你的 IP 地址,以仅允许从你的源 IP 进行 SSH。你也可以使用以下方式选择源 IP 范围跨域路由风格符号。

记录被拒绝的呼叫时应谨慎。您的服务器的 IP 地址将被机器人、脚本小子等扫描,并且日志文件可能会很快变大。除非您尝试诊断您认为可能与某人试图破坏您的防火墙有关的特定问题,否则我会删除此选项。

你也可以加入失败2baniptables 是一个伪 IDS。fail2ban 将扫描您的日志文件,如果 IP 试图强行进入您的系统,则可以阻止该 IP。例如,如果某个 IP 地址 5 次无法登录 SSH,您可以将其锁定一整天。它还适用于 FTP 和许多其他(包括攻击 Apache 的恶意机器人)。我在我的所有服务器上都使用它来提供一些额外的缓冲,以抵御暴力攻击。

答案3

我想说这是一个相当不错的防火墙,只是它旨在阻止入站流量,而不是专注于出站或出站流量。在许多情况下,关注从盒子发出的连接与关注入站连接同样重要。如果不幸机器被利用,那么能够阻止下载额外的 root 工具包或连接到命令和控制节点等就好了。

BillThor 在上面开始谈论这个问题,但我只是用具体的例子来回答。iptables 的一个优点是它可以记住连接状态,这可能会对流量很大的网站的性能产生影响,但您可以更改 http/https 上的入站访问,例如仅允许在已建立的连接上回复,或者专门限制某些非特权用户完全拥有出站访问权限。然后,您的出站规则将具有 RELATED、ESTABLISHED 子句,这将阻止大量辅助攻击并减缓需要第二阶段才能真正利用盒子的攻击,这种情况非常常见。

最后,我想说,最好将 iptables 策略设置为 -P DROP,而不是在末尾附加 REJECT。这主要是个人喜好问题,但可以减少在附加到现有规则的链时出现错误,而不是插入或刷新/重置。

答案4

看看 Shorewall。单一接口默认配置是一个很好的起点。它易于配置,并且具有用于 SSH 和 Web 访问等的宏。它可以配置为在防火墙关闭时将服务器锁定到所需的级别。使用 Shorewall-lite,您可以在另一台服务器上运行防火墙构建。日志记录很容易配置到所需的级别。

对于基本的 HTTP 服务器,如果您使用 HTTPS,则需要打开对端口 80 和端口 443 的传入访问。通常需要从几个受限制的地址进行 SSH 传入访问。您可能还想锁定传出访问。仅对所需的服务器和服务打开防火墙。应打开 NTP 和 DNS,以及获取补丁的通道。

相关内容