基本HTTP Web服务器的安全,标准iptables规则集


15

我一直在尝试将基本服务器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脚本,看起来很不错。

另外,您可以使用iptables本身来阻止对SSH的错误重复尝试,而不是使用Denyhosts或fail2ban 。


您说这是VPS。我认为它也具有LAN IP吗?您信任子网上的每台计算机吗?您想在这里有多大的偏执,可以使用OUTPUT过滤来进一步保护计算机。让我知道,我会以我建议您使用的方式回应。
hobodave

很好,鉴于大多数VPS都位于VM中,而其他VPS则可以从LAN访问,所以我要说,不信任它们将是明智的起点。如果您有其他VPS,则可以在以后添加规则以访问它们(即,从Web服务器到数据库)。
Xeoncross

1
警告:如果执行上述提到的cyberciti.biz脚本并且modprobe未安装(或在打开端口22之前出现任何其他错误),则您将自己锁定在服务器之外。
EoghanM

Answers:


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

我已经使用了一段时间了,如果它可以简化管理工作,则可以进行任何形式的修改。


是否有通过TCP使用SNMP(161)的流行工具?我认为这些规则应该是UDP / 161。
kubanczyk

1

这看起来不错,但是您可以收紧一些工作。-s标志是源IP或域名,您添加“ -s 198.23.12.32”或任何IP地址仅允许源IP进行SSH。您还可以使用CIDR样式表示法选择一系列源IP 。

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

您还可以将fail2ban绑定到iptables以获取伪IDS。fail2ban将扫描您的日志文件,如果它们试图强行进入系统,则可以阻止IP。例如,如果某个IP地址无法登录SSH 5次,则可以将其锁定一整天。它也可以在FTP和许多其他工具上使用(包括恶意的bot攻击Apache)。


我实际上使用DenyHosts,因为它比fail2ban节省15MB左右。但是,fail2ban功能更强大,并且可以与许多应用程序一起使用(不仅仅是像DenyHosts这样的SSH)。鉴于已禁止攻击者,我是否还要担心日志文件会很快填满?有没有办法在文件变满时旋转文件?如果我禁用了登录fail2ban的功能,Denyhosts / Fail2ban仍然需要扫描日志条目吗?另外,source选项对某些人来说也很好-但是由于我的目标是默认规则集,因此像我这样移动很多的人不能使用该选项。
Xeoncross

@ Xeoncross:DenyHosts是一个蒸蒸日上的imo。我让它在一台机器上运行,该机器不断受到来自中国人的入侵尝试。在几个月的时间里/etc/hosts.deny增长了几千个IP,这时sshd耗尽了设备上的资源,在一台CPU机器上将负载提高到60+。我切换到fail2ban,再也没有回头。
hobodave

@hobodave我刚开始使用DenyHosts,所以当这成为问题时,我将首先记住这一点。
Xeoncross

1
@Xeoncross如果您想旋转iptables日志,则可以为其编写自己的logrotate.d脚本。看一看/etc/logrotate.d并复制另一个并更改日志文件名,它将随其他日志文件一起旋转。logrotate的手册页介绍了各种选项。
艾伦·艾维

1

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

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


1

我想说这是一个非常好的防火墙,除了它旨在阻止入站流量,而不是专注于出口或出站流量。在许多情况下,关注从框出站的连接与入站的连接一样重要。在不幸地实际使用了计算机的情况下,能够防止下载其他根工具包或连接到命令和控制节点,或者其他任何事情,将是一个很好的选择。

BillThor在上面开始谈论这一点,但我只是在举一些具体的例子。iptables的优点之一是它可以记住连接状态,这可能会对通信量大的站点产生性能影响,但是您可以更改对http / https的入站访问,例如仅允许对已建立的连接进行回复,或者专门限制某些非特权用户用户完全没有出站访问权限。然后,您的出站规则将具有RELATED,ESTABLISHED子句,该子句将阻止大量的辅助攻击,并放慢那些需要辅助阶段才能实际利用盒子的攻击,这很常见。

最后,我要说的是,最好将iptables策略设置为-P DROP,而不要在结尾处附加一个REJECT。这主要是一个优先事项,但是当使用现有规则将其附加到链上而不是插入或刷新/重置时,可以减少错误。


所以,我应该改变-A INPUT -j REJECT-A INPUT -P DROP
Xeoncross'3
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.