通过iptables配置加强服务器安全

绪言

  VPS在公网上使用得越来越多,如何提高自己的服务器安全也变得重要起来,特别是脚本横飞的时代,如果不对服务器加以修饰,每天lastb的记录都能增加很多。而且对外提供越多的服务意味着暴露的缺陷就越多,所以掌握iptables的基本使用中解决很多问题。

主动模式

1
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

  首先对自己主动发送的请求进行响应的报文放行,这里尤其注意是对自己已发送的报文进行响应,如果是其他客户端发送过来的请求连接这里不做处理,使用默认的或后续的匹配策略处理。
因为在iptables看来每个协议都有建立连接的概念,包括“udp”、“icmp”。state支持的状态有:NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED。

  • NEW:就是双方进行通信时第一个到来的报文;
  • ESTABLISHED:state把NEW以后到来的报文都定义为ESTABLISHED状态,包括UDP等,所以说state是有类似于tcp三次握手建立连接的概念;
  • RELATED:在一个服务中,可能开启了两个进程,而且这两个进程都需要跟服务器进行通信,例如FTP有两个通信链路,命令链路和传输数据的链路,这两个链路就是存在关系的,所以他们属于RELATED状态;
  • INVALID:表示一个包不能被识别;
  • UNTRACKED:表示报文不能被追踪;

为SSH加固

1
iptables -A INPUT -p icmp --icmp-type 8 -m length --length 128 -m recent --set --name SSH --rsource -j ACCEPT

  length模块用于匹配报文长度,这里我们用ping报文的长度来充当芝麻开门的作用,recent模块功能很强,能将匹配到的报文信息记录下来,给后续规则做条件使用。它的几个参数为:

  • —name: 给用来记录报文的列表起名称;(这里应该是两个-)
  • —set: 表示将匹配到的报文记录下来;
  • —rsource: 表示记录源IP地址;

  这条指令的意思是:将ping报文长度为128的源IP地址记录到叫SSH的列表中去。这里需要注意的是ping报文头部长度就有28字节,所以实际的填充报文为:128-28=100。所以在Linux下使用ping -s 100 ip;在Windows下使用ping -l 100 ip来敲开服务器大门。

  相关的icmp报文的类型如下(因为ssh客户端是ping的请求方(发起方),所以这里要匹配类型为8的报文):

类型代码 类型描述
0 响应应答(ECHO-REPLY)
3 不可到达
4 源抑制
5 重定向
8 响应请求(ECHO-REQUEST)
11 超时
12 参数失灵
13 时间戳请求
14 时间戳应答
15 信息请求(*已作废)
16 信息应答(*已作废)
17 地址掩码请求
18 地址掩码应答
1
iptables -A INPUT -p tcp --dport 8888 -m state --state NEW -m recent --rcheck --seconds 20 --name SSH --rsource -j ACCEPT

  8888是ssh修改后的端口号,这里之所以匹配NEW状态是因为后面我们需要对INPUT使用白名单策略,而NEW之后的状态在前面已经放行,所以这里需要对NEW状态进行放行。这里再对recent的两个参数进行说明:

  • —rcheck: 检查源IP是否在列表中,以第一个匹配开始计算时间
  • —seconds: 记录的源IP地址的有效时间

  所以这一整句话是说对NEW(新建)状态下请求8888端口的源IP进行检查,看这个IP是否在名叫SSH的列表之中,有效时间是20秒,这里的有效时间是指上一条规则记录下源IP的时间离用户请求SSH服务器的时间间隔。所以用户必须在ping完的20秒内连接客户端,否则连接失败,重新ping。

PS: 如果是私有的git服务器的话,也同样适用这套规则,登陆或clone、push前都需要进行特殊的操作,这就能很好的保护数据和服务器的安全问题。不要以为这是弱智的问题,,这两天逛tools的时候就有人的git服务器被人攻破。。。

将INPUT策略改成白名单模式

  白名单是只接受自己信任的来源,而对非信任区来源采用拒绝策略;黑名单则只拒绝自己不信任的来源,接受信任或目的不明确的来源。所以采用白名单的策略系统的安全性较高,而黑名单难免会有疏忽。

  要使用白名单,只需将INPUT的默认策略从ACCEPT改成DROP。可以使用iptables -P DROP,但如果一不小心清空了ACCEPT的规则,那么服务器将按照默认drop的策略拒绝所有的连接,导致服务器失联。所以我们使用另一种较为安全的策略:

1
iptables -A INPUT -j DROP

  我们在INPUT链的最后一条上加上DROP规则,这样即使我们不小心iptables -F INPUT清除掉INPUT规则也不用担心服务器失联。

  值得一提的是,由于采用了DROP策略,所以ping只接收长度为100的报文,也就是说正常的ping是不会被服务器接收的,这就提供了保护主机的安全的方法,相当于把主机从公网中隐藏起来,只有知道口令的人才能找得到。

保存iptables配置

  笔者主机为:Ubuntu 16.04,首先安装:

1
2
apt install iptables-persistent
apt install netfilter-persistent # ubuntu 14.04可以不用

  保存:

1
netfilter-persistent save

  在/etc/rc.local中添加开机时自动执行恢复操作:

1
netfilter-persistent reload

后言

  这里只是简单的在INPUT中加固了ssh连接,但对其他类似web的服务没有讲解,但这并不是说iptables对这些服务没有办法,相反,iptables能很好的加强系统安全。比如有些服务不想暴露给外部直接访问,只允许本地处理。这时我们就能使用类似于这样的规则:

1
iptables -I INPUT ! -s 127.0.0.1 -j DROP

  通过配置iptables还可以在有限程度上防止CC攻击DDOS等攻击,它可用的一些模块还有:

  • string: 可以匹配链路中出现的特定字符;
  • time: 对链路的时间规则;
  • limit: 对IP的并发限制;

这在后续博文中可能有所涉及。

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×