VPS – Virtual Private Server,也就是虚拟专用服务器。虽说是虚拟的,但是和普通服务器一样:有内存、有CPU、有HDD当然也直接接入互联网。
实话实说,网络的凶险程度一点也不比人类社会低。接入互联网的设备,无时无刻不承受着来自各方面的攻击:比如最常见的端口扫描。
下面就是一部分log,可见一些常用服务的端口都在不断地被一些机器扫描。
(IP和MAC已隐去)
Log中:
IN是流量输入的设备
SRC为源IP
DST为目标IP(这里就是本机IP)
PROTO为通信协议
SPT为源机器上发起连接的端口
DPT为目标机器的端口
3306,MySQL的默认通讯端口。
[602629.442704] iptables INPUT denied: IN=eth0 OUT= MAC=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx SRC=123.122.***.*** DST=***.***.***.*** LEN=40 TOS=0x00 PREC=0x00 TTL=109 ID=5996 PROTO=TCP SPT=6000 DPT=3306 WINDOW=16384 RES=0x00 SYN URGP=0
22,默认的SSH端口
[598952.744557] iptables INPUT denied: IN=eth0 OUT= MAC=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx SRC=115.231.***.*** DST=***.***.***.*** LEN=40 TOS=0x00 PREC=0x00 TTL=239 ID=51179 PROTO=TCP SPT=9091 DPT=22 WINDOW=65535 RES=0x00 SYN URGP=0
[601118.593734] iptables INPUT denied: IN=eth0 OUT= MAC=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx SRC=195.238.***.*** DST=***.***.***.*** LEN=52 TOS=0x00 PREC=0x00 TTL=51 ID=9710 DF PROTO=TCP SPT=59403 DPT=22 WINDOW=42340 RES=0x00 SYN URGP=0
等等……
对于这些潜在隐患,最基本的就是利用iptables规则来处理
对于SSH的22端口这个重灾区,情况允许的话,可以通过修改默认端口,以及禁止密码登录来防范。
iptables
何为iptables:iptables作为Linux系统的包过滤规则集(ruleset),对进出的数据包进行处理,你也可以将其理解为系统防火墙。在Ubuntu,Debian系统中通常是自带的,只不过默认情况下允许所有访问流量通过。
可以输入命令 iptables -L -n
进行查看(iptables命令需要root权限,必要时记得加上sudo)
会看到默认情况下的三个链(Chain)允许所有流量通过(ACCEPT):
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
基本选项
在继续之前,先让我们来了解下iptables命令的基本选项:
先来看看之前用到的:
-L 列出当前规则链中的全部规则
-n 以数字形式显示IP和端口号,常跟-L一起使用,以避免长时间进行IP地址解析而卡住。
下面是些iptables的基本选项:
选项
释义
-A
为append,追加新规则到规则链(Rule Chain)尾部
-I
为insert,插入新规则到规则链的头部
因为iptables的规则链中的规则是从上至下依次进行匹配的,所以append或insert规则时记得注意顺序,可以通过使用序号来指定append或insert的位置。
每条规则的序号可通过 iptables -L -n -v 命令查看。
比如在INPUT链的第3条规则后追加一条规则,命令的开头可以这么写:
iptables -A INPUT 3
-D
用来删除规则 比如:-D INPUT 2 表示删除INPUT链的第2条规则
-P
设定规则链的默认策略(policy)
-p
protocol,规则需要匹配的协议
--sport
源端口
--dport
目标端口
-s
源IP/[MASK] 如:192.168.0.123/32
-d
目标IP/[MASK]
-j
跳转(jump)到指定目标,默认情况下iptables提供4个可用目标:
ACCEPT 接受此数据包,并停止处理当前链中后续的规则。
DROP 丢弃数据包不作回应,停止处理当前链的后续规则。
REJECT 拒绝数据包并告知发送者,停止处理当前链的后续规则。
LOG 在日志中记录此数据包,然后继续处理当前链中的后续规则。
--log-prefix 日志的前缀,比如“INPUT Denied”
--log-level syslog的级别,一般可以选用 7
-i
匹配指定的输入界面
-o
匹配指定的输出界面
-v
在输出中显示更多信息
-m state
根据当前连接的状态进行匹配,状态有
NEW 之前未见到的连接(新连接)
RELATED 新连接,不过跟已允许的连接有关。
ESTABLISHED 已经建立的连接
INVALID 此流量无法被辨识
-m multiport
在一条规则中同时匹配多个端口
-m limit
limit模块,限定匹配的次数
比如可与--limit一起使用,限制log的频率
--limit 5/min 意思为每分钟5次匹配
主动防御
说了那么多,开始动手吧。防御的基本思路是:
- 仅开放必要的端口
- 规则链默认策略从ACCEPT修改为DROP
首先处理INPUT链
如果你是从SSH登录的服务器,记得先把允许SSH的规则加入规则链顶端,否则就会自己把自己关在门外了。
假定你的服务器使用的是SSH默认的tcp 22端口,那么要插入允许22端口输入的规则:
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
以及,允许所有已建立的连接及其关联连接进入:
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
还有,本地的loopback介面(也就是localhost)也需要允许,否则会有问题
iptables -I INPUT -i lo -j ACCEPT
若机器上有运行web服务或其他服务,记得允许相关端口的输入连接,下面的例子是运行了http和https服务情况下需要的规则:
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
最后把INPUT链的默认策略改为DROP
iptables -P INPUT DROP
然后是OUTPUT链
允许SSH端口输出已经建立的连接
iptables -A OUTPUT -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
允许DNS查询连接的输入,当然指定一下目标的IP较保险,免得被黑然后被当作DNS放大攻击肉鸡。这条规则是允许对Google DNS进行查询。
iptables -A OUTPUT -p udp --dport 53 -m state --state NEW,ESTABLISHED -d 8.8.8.8 -j ACCEPT
允许HTTP,HTTPS的访问,要不然连wget个tarball都会有问题哦。若需要开放更多需要的端口,可按需在dports后面修改。
iptables -A OUTPUT -p tcp -m multiport --dports 80,443 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
允许相关和已建立的连接输出
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
最后,当然是修改默认策略为DROP
iptables -P OUTPUT DROP
记录坏蛋
现在我们把要侵入的坏蛋给挡住了,把能出去的口也尽可能进行了限制。当然,在挡住坏蛋同时,也可以进行一些记录。比如在INPUT链里面添加如下的日志记录规则:
规则加在INPUT链的最后,每分钟最多5条(若你想记多点也没问题,当然别太多哦,否则硬盘空间被耗光就糗了),LOG的前缀为iptables INPUT denied,syslog级别为7(debug)
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables INPUT denied: " --log-level 7
加好规则后,过一会儿再回来用dmesg|tail
查看,应该就能看到类似于文章开头那样被阻止的记录了。