简介
现如今服务器成本已经比 10 几年前大幅下降了。过去不论囊中是否羞涩,不论学生还是企业,都是优先 虚拟主机→VPS→独立服务器 如此考虑的。现在不论是国内的阿里云,还是国外的各大 VPS 服务,价格跟 10 几年前相比都是白菜价了。很多企业甚至在项目还没开始就先买个阿里云空跑着或作为开发服务器,宛如不要钱一样。
而因此产生的针对于服务器的威胁也开始兴起。很多【坏人】仅靠端口扫描就攻破了很多用户的主机,大量的主机沦为不法分子的肉鸡,在网络上充当不法行为的跳板。我已经遇到过多次攻击情况,而查询到其攻击源头多数都是各种不知名小企业或学校的网站或办公系统。而当你发现这种情况时,多数都是早就被不法分子掏空所有企业数据后,最终将其服务器当做肉鸡跳板,作为废物利用的最终阶段而已。
而多数这些【被利用】主机的主人,往往都是安全意识不够,满满的侥幸心理,或者技术观念不强导致的。
而防范大多数攻击其实并不是什么非常困难的问题,最简单的 iptables 防火墙规则,往往就能帮助你防范非常多的安全问题。
使用iptables
本文只针对 linux 用户。对于使用 Windows 作为服务器使用的用户,既然您使用了收费操作系统服务,就请您合理利用您花的钱吧。
本文仅适合于初级用户,适合于对 iptables不了解 或 仅想找个方法保护自己服务器 的用户。对于更高层次的学习,请参见 iptables官网手册 和 谷歌。
代码
我直接贴一段自用的代码,根据代码中的注释理解每一条的含义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
iptables -F //清空当前iptables规则 iptables -A INPUT -i lo -j ACCEPT //接受环回请求 iptables -A INPUT -p tcp --dport 80 -j ACCEPT //接受发入80端口的tcp请求。对所有人开放HTTP服务 iptables -A INPUT -p tcp --dport 443 -j ACCEPT //接受发入443端口的tcp请求。对所有人开放HTTPS服务 iptables -A INPUT -p udp --dport 5394 -j ACCEPT //接受发入5394端口的udp请求。对所有人开放一个私有的服务 iptables -A INPUT -p tcp --dport 23322 -j ACCEPT //接受发入23322端口的tcp请求。对所有人开放一个私有的服务 iptables -I INPUT -s 121.9.245.181 -j ACCEPT //接受来自IP 121.9.245.181 的所有请求。IP 白名单 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT //接受已建立连接的所有请求。 iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT //接受 PING。 iptables -A OUTPUT -j ACCEPT //接受本机向外发出的请求。 iptables -I INPUT -p tcp --dport 3128 -j DROP //DROP 掉发入3128端口的tcp请求。防止代理扫描攻击 iptables -I INPUT -s 104.194.76.27 -j DROP //DROP 掉来自IP 104.194.76.27的所有请求。IP 黑名单。以下同 iptables -I INPUT -s 104.194.76.17 -j DROP iptables -I INPUT -s 37.26.128.179 -j DROP iptables -I INPUT -s 120.132.50.135 -j DROP iptables -I INPUT -s 120.132.55.171 -j DROP iptables -A INPUT -j DROP //DROP 掉其他发入的所有请求。 |
解释
iptables 规则参数
-F
:清空 iptables 规则
-A
:追加一条规则到规则列表尾部
-I
:插入一条规则,默认插入到规则列表头部
逐条解释
首先注意,iptables -F
会清空现有的iptables规则,如果您是企业用户或是已在运行的服务器,需要自己检查现有iptables规则,并手动合并规则,否则可能会造成很严重的网络问题。
iptables -A INPUT -p tcp --dport 23322 -j ACCEPT
等就没什么解释的了,如果您对外开放这些服务,就向公众开放这些端口。没有开放的端口,就会匹配到最后的 DROP 规则。
iptables -I INPUT -s 61.148.52.162 -j ACCEPT
,IP 白名单。如果您的管理环境拥有固定IP,比如您的公司使用固定IP上网,则可以使用这个方法放行。这是一条非必需的规则。
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
,接受已建立连接的所有请求。这其实是一条防手残规则,防止在你执行这些脚本时把你的 SSH 连接断掉。
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
,允许 PING。这是一条非必需的规则。如果您不想让自己的服务器更隐秘,则可以把 ACCEPT 替换成 DROP,但这样出现未知网络问题时,您也将 ping 不通自己的服务器,无法确认到底是谁哪里的网络问题了。(白名单不受限)
iptables -A OUTPUT -j ACCEPT
,接受本机向外发出的请求,不解释。除非你服务器要玩单机。
iptables -A INPUT -p tcp --dport 3128 -j DROP
,DROP 掉发入3128端口的tcp请求。3128端口是 squid 的默认端口,关于 squid 是什么您可以自行谷歌。额外添加此条规则可以帮助您查看有多少混蛋在扫你的这个端口。这是一条非必需的规则。
iptables -I INPUT -s 104.194.76.27 -j DROP
,IP 黑名单。这个IP是混蛋,我完全不想让这个用户访问我的任何服务(包括正常对外开放的端口、ping)
iptables -A INPUT -j DROP
,所有发入未开放端口的流量一律 drop。
关于 DROP 和 REJECT
iptables对于请求的处理方式共三种:ACCEPT、DROP、REJECT。ACCEPT不做解释。而 DROP 与 REJECT 虽然都能作出拒绝处理,但效果是不一样的。
- DROP:丢弃发入的数据包,假装自己不存在;
- REJECT:回应一个拒绝信息给发送者,告知其服务不可用。
REJECT 是一种非常友善的回应方式,非常适合回应那些因为失误将数据包发送到你服务器上的用户。他们会直接收到一个错误提示(传输层),用户的上层应用会根据传输错误提示报错进行错误处理。
而 DROP 则如同将收到的请求直接扔进冲水马桶,对请求完全忽视。发送者收不到任何回应,只能等到其认为自己请求超时。
如果用更简单的语言解释的话,那么就是:如果用接打电话还描述,当你接到了一个电话,DROP 的效果相当于打电话的人开始听不到嘟嘟嘟的拨号音,一直等到最后提示“您拨打的电话可能是空号或无法接通”;而 REJECT 则相当于在对方听到嘟嘟嘟的拨号音后你主动挂断电话,或接起电话回应一句:你打错了
显然如果对方如果是无心之举,或是你需要主动告知对方有错误的话,那么使用 REJECT 会是很好的方法。然而我们要防范的是混蛋,而不是正常用户手滑,所以使用 DROP 可以更安全的保护和隐藏自己的服务器。
您的手机是否有收到过各个商家或网站发出的垃圾促销短信?后面还接着一句类似“回复TD退订”之类的玩意。而你回复“TD”或者“TD退订”之类的则根本没鸟用,而垃圾短信反而能猖狂?
这就相当于 DROP 和 REJECT 的关系。你回复短信就相当于 REJECT,本意是告诉对方“我不想在收到这种短信了”,然而对方是个混蛋,并不屌你,你的短信回复反而让对方确认你这个手机号是有人使用的,对方便会更猖狂的向你这个号码发送垃圾短信。
配图为微博用户@惰性求治发的一条微博。之后被优酷耍并“上课”:点击http://weibo.com/1655253920/DwIkGpj4O
而正确的做法就是开启手机短信防骚扰,根据关键字黑名单,把“TD、退订、【、[”等这些垃圾短信常有的关键字和符号都干掉,设置成保存到垃圾箱且不提醒。只在手机中留下个记录,既不处理,也不回应。(为什么不设置成直接屏蔽或删除?因为可能有些如验证码等关键性短信也会包含这些关键字。另外由于像支付宝等财务产品,消费记录和垃圾促销短信都是一个套路发送的,今天你屏蔽了垃圾短信,明天支付宝被盗刷你没收到提醒,支付宝这种混蛋可不管。可以说有些大混蛋也是有流氓办法处理 DROP 这种反流氓方法的)
FTP随机传输端口问题
开放一大段端口做预留?
错!能不用 FTP 就不用 FTP。什么年代了你都用 SSH 开始管理服务器了,还用 FTP,SFTP服务都装到服务器上了你还研究 FTP。
查看效果
在 shell 中执行
1 |
iptables -t filter -nvL |
来检查匹配各规则的流量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 10 600 DROP all -- * * 120.132.55.171 0.0.0.0/0 0 0 DROP all -- * * 120.132.50.135 0.0.0.0/0 0 0 DROP all -- * * 37.26.128.179 0.0.0.0/0 60 3684 DROP all -- * * 104.194.76.17 0.0.0.0/0 0 0 DROP all -- * * 104.194.76.27 0.0.0.0/0 16 940 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:3128 2493 379K ACCEPT all -- * * 61.148.52.162 0.0.0.0/0 57 8741 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 7 873 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:5394 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:23323 2752 1658K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8 229 15402 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 5620 2178K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 |
您可以使用watch -d -n 1 iptables -t filter -nvL
来持续监视输出。
补充一些其他保护措施
服务端口
像 80、443 这种对公众开放的端口就算了。但是如 SSH 这些自用服务的端口,如果服务器放在公网上就不要使用默认的 22 端口,不然会被攻击到死,光是几个小时就能把 auth 日志撑得很大,所以一定要改成高位端口,而且也不要使用 2222 这种一看就知道还是 SSH 端口的端口。
像 redis、mysql 这些服务,如果不对外提供服务的话,能不监听端口(改为socket)就不要监听。如果网络上只针对部分固定机器开放连接就写 iptables 强制规则做匹配,固定不了能改端口就改端口。能不开放端口就不开放端口。mysql 现在自身的默认配置文件也不再接受外网的请求了,只listen 127.0.0.1:3306。
密码
有些用户觉得自己用证书做 SSH 登陆,关闭 SSH 的密码登陆就安全了。证书是什么?证书也只是个特别长的密码而已,一个证书文件也只是从几百到几千几万字节的字符串而已,其实质上与同样长密码没什么区别,就是密码长了点而已。
所以证书登录并不是必须且绝对安全的。低质量的密码是危险的。在这里再推荐一次密码管理工具:KeePass。
远程管理服务使用加密措施
有些情况下你需要使用 PhpMyAdmin 或其他类似软件做服务器管理。然而这些服务的流量几乎都是明文传输的,实际上很不安全。有一个图标是纸飞机的软件项目可以让你的所有流量都加密传输,而且是使用 AES256 等高强度的对称密钥加密,要比无认证证书的HTTPS安全很多。
自启动
我并不是很简易将这个添加到自启动脚本中,因为很多手残党往往将自己的 SSH 端口也 DROP 掉,导致服务器脱管。
不添加到自启动的话,如果手滑把自己 DROP 掉了,可以直接登录服务器管理系统,重启服务器。这些规则是不保存的,重启服务器后就清空了,你可以重新执行这些代码。
找混蛋
auth.log,access.log,tcpdump,这些日志和工具够你看的了。
总结
本文只是简单地介绍了一下使用 iptables 防护服务器的方法,描述的非常浅显,很多层面都没有覆盖到,很多能更进一步保护服务器的工具和概念(比如 ipset)也都没有提到。
iptables 以及 netfilter 都是 linux 下非常强力的网络工具,非常强大。
本文只是一个入门,如果您对相关内容感兴趣,也希望您能自行学习一下这些内容。
8 comments
Skip to comment form ↓
夏天烤洋芋
2016 年 6 月 28 日 在 上午 11:15 (UTC 8) Link to this comment
阿里云的服务器,飘过。
纯洁博客
2016 年 6 月 28 日 在 下午 2:41 (UTC 8) Link to this comment
博主那引导页看着真不错
石樱灯笼
2016 年 7 月 5 日 在 下午 5:32 (UTC 8) Link to this comment
那个Metro已经准备换掉了,只不过最近没时间
黑暗游侠
2016 年 8 月 1 日 在 下午 10:59 (UTC 8) Link to this comment
再加个fail2ban就完美了
穹庐
2016 年 8 月 29 日 在 下午 1:53 (UTC 8) Link to this comment
为啥主站加密了博客却没有
石樱灯笼
2016 年 8 月 29 日 在 下午 2:02 (UTC 8) Link to this comment
其他站都是走的Cloudflare的CDN+Flex SSL,或者用的Let’s Encrypt的免费证书。
然而Wordpress用CDN+Flex SSL会出错,又是跑在一个不支持https的虚拟主机上,所以加不上证书。
穹庐
2016 年 8 月 29 日 在 下午 4:13 (UTC 8) Link to this comment
你都分享iptables规则了怎么还用虚拟主机呢
石樱灯笼
2016 年 8 月 29 日 在 下午 4:49 (UTC 8) Link to this comment
因为穷