现在网络安全闹得沸沸扬扬,而且前两天发现之前部门的服务器被入侵而后用来攻击别人。所以花了点儿时间对我的 VPS 安全做了些研究。下面是配置记录。
嗯,因为 Linux 发行版比较多,不同的发行版很多设置不太一样,有必要先说说我的 Linode VPS 的环境:CentOS + LAMP + phpMyAdmin。
使用强密码¶
不管采取了多少其它的安全措施,如果使用的密码不够强健,恐怕一切都是白搭,所以首先需要设定足够强健的密码。包括系统用户登录密码,特别是 root 帐户的;还有 MySQL 用户的密码;以及其它一切可以获取读取系统任何内容的权限的密码。总之,一切密码好了。同时还要注意,不要使用相同的密码。
不要怕记不住。编写一个强健的密码,然后在自己的日记本上写下来,同时在电脑上找个地方保存下来(Windows 7 的便笺就是个不错的选择)。需要通过网页登录,或者使用 SSH 登录的时候,只需要复制粘贴就可以了(在 Putty 的窗口单击鼠标右键就可以完成粘贴)。
对VPS上所有的密码都是用强密码,并且要互不相关,避免泄露一个密码后其它密码随之泄露。
清理不需要的系统用户和组¶
虽然 Linode VPS 提供的 CentOS 系统已经优化得挺不错的了,可还是有不少系统内建用户和组是不需要的。清理掉这些用户和组也有助于系统安全。当然,安全起见,还是需要先备份。
CentOS 中用户信息存储在 /etc/passwd
文件中。下面的命令可以显示出所有用户。
cat /etc/passwd
使用 root 帐户运行下面的命令来清理不需要的用户和组:
cp /etc/passwd /etc/passwd.sav cp /etc/group /etc/group.sav for a in adm lp sync news uucp operator games gopher mailnull nscd rpc; do /usr/sbin/userdel $a -f; done for a in lp news uucp games gopher users floopy nscd rpc rpcuser nfsnobody; do /usr/sbin/groupdel $a -f; done
清理用户和组的方法参考自 128M VPS 上优化 CentOS 5 一文。用户和组完全是按照该文来清理的。也许还有别的用户和组也可以禁用,留待以后测试。
加强 SSH 安全¶¶
这一部分主要通过修改 SSH 的配置文件来实现:
vim /etc/ssh/sshd_config
重点是下面 3 项。所有几个关键配置都列在这一节的后面,以供参考。
- 禁止 root 帐户远程登录Linux 系统里最知名的用户名就是 root 了,也就最容易遭到暴力破解攻击。禁止 root 用户通过 SSH 登录就可以避免这种悲剧。另外增加一个自己用的用户名,可以稍微复杂一点,让别人不容易猜。这样可以增加一些难度。不是跟你有仇的人,恐怕就不会花力气来猜你的用户名了。于是通过 SSH 来攻击也就不存在了。
PermitRootLogin no
- 限定可以登录 SSH 的用户名除了 root 帐户之外,Linux 中还有其它一些默认的帐户,有些还不能轻易删除。所以只是禁止 root 帐户 SSH 登录还不行,最好限定可以登录 SSH 的用户名。
- 更改 SSH 端口默认的 SSH 端口是 22。现在网上有无数的机器在扫描 22 端口,寻找攻击机会。在我的 VPS 刚上线的那几天里,收到了大量针对 22 端口的扫描,也就是暴利破解 SSH 密码。攻击的用户名主要是 root,也有其它一些常见的简单用户名,如 test123 之类的。上面提到的一些默认帐户也在攻击者的列表中。将 SSH 端口改为一个不常见的,例如
Port 1234
- 也可以使用证书来登录 SSH,减少密码使用的次数。这里先不讨论了。还没有配置成功。
- 配置完成后重起 SSH 服务使之生效:
service sshd restart
参考资料:
附:SSH 配置文件样本(一些用 # 注释掉的行没有列上)
Port 1234 Protocol 2 SyslogFacility AUTHPRIV PermitRootLogin no AllowUsers user1 user2 /etc/ssh/ssh_known_hosts PermitEmptyPasswords no PasswordAuthentication yes ChallengeResponseAuthentication no GSSAPIAuthentication yes GSSAPICleanupCredentials yes UsePAM no # Accept locale-related environment variables AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE AcceptEnv XMODIFIERS X11Forwarding no # override default of no subsystems Subsystem sftp /usr/libexec/openssh/sftp-server UseDNS no Banner /etc/issue
使用 iptables 对连接进行限制¶
因为 iptables 中的规则对顺序很敏感,下面先提几个方面,然后给出全部配置文件内容(以 # 注释来进行说明)。
- 限制 SSH 端口的连接错误次数(参考:Preventing brute force attacks using iptables recent matching);
- 限制单个 IP 对 80 端口的并发连接数;
- 限制 80 端口以及其它如邮件、SMTP等端口的连接速率(参考:Prevent DOS with iptables);
- 其它不符合标准的一律 DROP 掉。
我发现编辑 iptables 条目实际上不需要使用如下的命令行慢慢来操作,
iptables -A INPUT .........
而是可以将 iptables 文件下载下来,使用记事本之类的编辑器编辑(当然格式还是得参照已有的规则)来编写,然后再上传过去覆盖掉原来的,再使用下面的命令行来加载新规则即可,
service iptables restart
下面是我目前用的iptables 文件:
# Generated by iptables-save v1.4.7 on Fri Mar 9 23:08:51 2012 *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [1301:2201856] # 下面两个 chain 是用来记录 ssh 尝试登录次数的 :blacklist - [0:0] :sshscan - [0:0] # 2012.03.16 新增一个 CHAIN :syn_flood - [0:0] # rule 1 允许所有本机发出的通讯 -A INPUT -s 127.0.0.1/32 -j ACCEPT # rule 2 限制 RELATED,ESTABLISHED 一类的连接速率为每秒钟 50 个,峰值 50;超过限制的则不接受 # 似乎不需要这么做,清除这一部分 2012.03.16#-A INPUT -m state --state RELATED,ESTABLISHED -m limit --limit 50/sec --limit-burst 50 -j ACCEPT-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT # 跳转到 syn_flood CHAIN 来判断是否有“洪水”攻击,2012.03.16 -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j syn_flood # 有限接受 icmp 包,2012.03.16 -A INPUT -p icmp -m limit --limit 10/sec -j ACCEPT -A INPUT -p icmp -m limit --limit 10/sec -j LOG --log-prefix "PING-DROP: " --log-level 6 # rule 3 限制 80 端口新建连接的速度为 50 个每分钟,峰值 200;超过限制的不接受 -A INPUT -p tcp -m tcp --dport 80 -m state --state NEW -m limit --limit 50/min --limit-burst 200 -j ACCEPT # 邮件服务基本上全部由 Google 企业邮局完成,删除下面有关 465 和 25 端口的条目,禁用这 2 个端口 2012.03.16# rule 4 类似 rule 3 来限制 465 端口 #-A INPUT -p tcp -m tcp --dport 465 -m state --state NEW -m limit --limit 30/min --limit-burst 100 -j ACCEPT # rule 5 类似 rule 3 来限制 25 端口 #-A INPUT -p tcp -m tcp --dport 25 -m state --state NEW -m limit --limit 30/min --limit-burst 100 -j ACCEPT# rule 6 类似 rule 3 来限制 5678 端口(这是我特殊使用的一个端口) -A INPUT -p tcp -m tcp --dport 5678 -m state --state NEW -m limit --limit 10/min --limit-burst 20 -j ACCEPT # rule 7 限制 80 端口并发连接数不超过 20,否则发送 tcp reset 来拒绝连接 -A INPUT -p tcp -m tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -m connlimit --connlimit-above 20 --connlimit-mask 32 -j REJECT --reject-with tcp-reset# rule 8,9 开放 53 端口(DNS 服务) # 似乎不开放这个端口也没有问题,禁用掉 2012.03.16 #-A INPUT -p tcp -m tcp --sport 53 -j ACCEPT #-A INPUT -p udp -m udp --sport 53 -j ACCEPT# rule 10 配合前面提到的两个 chain 来限制 ssh 新建连接,并对超过尝试次数的连接封锁指定时间 -A INPUT -p tcp -m tcp --dport 1234 -m state --state NEW -j sshscan # rule 11 丢弃其它不满足前述规则的连接 -A INPUT -j DROP # 以下是前面提到的 2 个检查 ssh 连接的 chain,blacklist 和 sshscan -A blacklist -m recent --set --name blacklist --rsource -A blacklist -j DROP -A sshscan -m recent --update --seconds 600 --hitcount 1 --name blacklist --rsource -j DROP -A sshscan -m recent --set --name counter1 --rsource -A sshscan -m recent --set --name counter2 --rsource -A sshscan -m recent --set --name counter3 --rsource -A sshscan -m recent --update --seconds 20 --hitcount 3 --name counter1 --rsource -j blacklist -A sshscan -m recent --update --seconds 200 --hitcount 15 --name counter2 --rsource -j blacklist -A sshscan -m recent --update --seconds 2000 --hitcount 20 --name counter3 --rsource -j blacklist -A sshscan -j ACCEPT # 判断 syn_flood 攻击与否,不是则 RETURN(返回),否则 DROP 3012.03.16 -A syn_flood -m limit --limit 10/sec -j RETURN -A syn_flood -j DROP COMMIT # Completed on Fri Mar 9 23:08:51 2012
另外,也有在 iptables 中限制 ICMP 连接的,我是统统丢弃了。需要的话请参考:
http://serverfault.com/questions/287998/is-my-linux-firewall-secure
其它参考资料:¶
- ShoreWall Iptables Firewall
- Using iptables to Block Brute Force Attacks
- 25 Most Frequently Used Linux IPTables Rules Examples
- Arno’s iptables firewall
- iptables 官方网站
- Iptables 指南 1.1.19
- Using iptables to Enhance Security of your VPS
- iptables 语法重点
- iptables防火墙的基本应用教程
修订记录¶
2012.03.16
- 增加清理不需要的系统用户和组一节。
- 修改部分 iptables 设置(未修改本文中 rule 编号):
- 因为邮件服务仅仅使用其发出功能,不接收,故而不开放 465 和 25 两个端口;
- 53 端口禁用也不影响 VPS 查询 DNS,禁用;
- 增加判断 SYN flood 攻击;
- 增加对 ICMP 的有限接受(现在可以
ping cnzhx.net
了)。
本文发表于水景一页。永久链接:<https://cnzhx.net/blog/secure-my-vps/>。转载请保留此信息及相应链接。
兄弟,你的这个iptables看起来好有深度呀。又限制速率,又限制连接数的,同时还直接在iptables上,做起了SSH限制,相当伟大。
不过再我看来,你的这个iptables规则有点绕,呵呵,从前面三句看出来,你的iptables默认规则都是accept,而在你写的规则里头又是只有你想开放的那些,他人可以连接,其余的都过滤掉。
还有每条规则为何都要设定一个状态呢?不是很理解,还希望兄弟指点下。还有就是规则里头关于output的80和443端口这两条,如果去掉,真的就不能上了吗?
嗯,经过你的提醒,我看了看,OUTPUT 里的那两条的确不需要,因为 INPUT 中的第一条已经保证可以访问外网了。
设定状态是为了针对所设定的状态啊。比如对 RELATED 和 ESTABLISHED 限连接速率那一条,如果也应用在 NEW 上面的话,那就太宽松了,跟没设定规则没什么两样。
另外,我的 INPUT chain 里头最后是 DROP 所有的。
能理解点了。但对于为何要对速率做这样一个设定,是基于怎样一个场景,现在还不是很清楚,日后也要好好考虑下这问题。
哈哈,我也不是非常理解,照抄别人的。可以看上面的参考资料。
引用通告: Linode VPS 上 CentOS 6 安装 LAMP + phpMyAdmin 记录 | 水景一页
引用通告: 服务器遭到攻击,不知道是否误伤 | 水景一页
用了你iptables规则,发现直接卡在commit上。service iptables restart
Flushing firewall rules: [ OK ]
Setting chains to policy ACCEPT: security raw nat mangle fi[FAILED]
Unloading iptables modules: [ OK ]
Applying iptables firewall rules: iptables-restore: line 52 failed
[FAILED]
不知道你的iptables是如何设置的。
一番修改以后,现在重启iptables问题出现在commit上。
Flushing firewall rules: [ OK ]
Setting chains to policy ACCEPT: security raw nat mangle fi[ OK ]
Unloading iptables modules: [ OK ]
Applying iptables firewall rules: iptables-restore v1.3.5: no command specified
Error occurred at line: 52
Try `iptables-restore -h’ or ‘iptables-restore –help’ for more information.
[FAILED]
无奈中。。。
我的这个规则只是个样例,一般情况下你需要结合自己的实际情况权衡,也许还要做一点点调整。但是如果直接全部使用应该是可用的。
既然提示说第 52 行有问题,你的 52 行是什么?
引用通告: 在 Redhat / CentOS Linux 中安装 iptables 防火墙 | 水景一页
引用通告: CentOS / Redhat 上的 Iptables 防火墙配置简介 | 水景一页
引用通告: 博客搬迁 Linode VPS 配置笔记
引用通告: CentOS / RHEL IPv6 ip6tables 防火墙配置简介 | 水景一页
引用通告: CentOS 7 / RHEL 7 上安装 LAMP + phpMyAdmin | 水景一页