如何拒绝国外 IP / 屏蔽国外 IP 访问服务器?
背景介绍
公网上的服务器更容易受到攻击
- 互联网上有很多扫描器,24 小时不间断扫描服务器,然后去尝试获取一定权限,进而控制您的服务器。
- 实际运维和查看服务器日志中,发现 大多数发起攻击的服务器在国外 ,如荷兰、美国、新加坡、日本等国家。
- 不论我们购买的是云服务器还是 IDC 机房托管的服务器,只要我们对外提供了一定的服务,就会暴漏服务端口。
解决方案
大多国内公司的服务器都是面向国内用户
能不能禁止国外的 IP 访问服务器呢?显著提升服务器的安全性,答案是肯定的。
我们首先介绍一些背景知识:
- 服务器上都是有防火墙工具软件的(Iptables),可以用来过滤和拦截请求
- Iptables 中包含了一个叫 Ipset 的模块,支持匹配大批量 IP 地址段,同时兼具良好的性能
- https://www.ipdeny.com/ 这个网站会定期更新全球分配的 IP 地址段
接下来我们梳理下禁止国外 IP 的思路(如下图):
- 首先把国内的 IP 地址段整理到到 Ipset 中
- 接着从 Iptables 中调用 Ipset 模块判断来源 IP 是否在国内的 IP 地址段中
- 最后如果来源 IP 是国内 IP 地址就放行,否则就将数据包丢弃。
实现步骤
操作系统环境是 CentOS7.6
不同版本 Linux 指令可能不同
有不明白的地方,可以评论沟通
下面来详细讲解基于 Iptables、Ipset、Ipdeny 来屏蔽国外 IP 访问服务器的具体实现:
整理 IP 地址段到 Ipset
1、下载 IP 地址段文件
访问网址 http://www.ipdeny.com/ipblocks/data/countries/cn.zone ,另存为国内 IP 地址段,然后将文件上传到服务器;
也可以直接在服务器上执行如下命令直接下载文件到服务器:
wget http://www.ipdeny.com/ipblocks/data/countries/cn.zone
2、将 IP 地址段转换为 Ipset 指令
执行如下脚本,将 IP 地址段中的记录转换为 Ipset 指令,保存在 ipset_result.sh
可执行文件中
for i in `cat cn.zone`; do echo "ipset add china $i" >>ipset_result.sh; done
chmod +x ipset_result.sh
3、Ipset 写入地址段数据
首先,创建一个名字叫 china
的 Ipset 的链
然后,执行前面生成的 ipset_result.sh
脚本,为 china
链添加国内地址段
ipset create china hash:net hashsize 10000 maxelem 1000000
sh ipset_result.sh
接着,添加局域网 IP 地址段,防止局域网 IP 地址被拦截
ipset add china 10.0.0.0/8
ipset add china 172.16.0.0/12
ipset add china 192.168.0.0/16
我们来检查一下 china
链的数据,大概 8000 多条数据
ipset list china
ipset list china | wc -l
最后,为了性能考虑,Ipset 数据保存在内存中。
如果服务器重启,将会导致 Ipset 中的 IP 地址段数据失效。
我们需要将数据持久化到 /etc/ipset.conf
这个文件中。
ipset save china > /etc/ipset.conf
ipset restore < /etc/ipset.conf
让服务器重启时,通过脚本在加载 /etc/ipset.conf
中的数据。
chmod +x /etc/rc.d/rc.local
echo "ipset restore < /etc/ipset.conf" >> /etc/rc.d/rc.local
在 Iptables 中调用 Ipset 的 china
链完成拦截国外 IP
1、调整或建立 Iptables 规则
Iptables 中的指令有从上到下匹配顺序的,我们需要注意拦截指令顺序
假设我们已经有 Iptables 指令,需要通过
iptables -I
指令插件到现有 INPUT 链中
注意:需要修改下面指令中的数值,即插入到 INPUT 链中的第几个位置
iptables -I INPUT 5 -m set ! --match-set china src -j DROP
如果之前没有启用 Iptables,可以通过如下脚本清除重建 Iptables
注意:不同服务器需要开放的端口和服务不同,请修改和调整如下 udp 或 tcp 端口规则
iptables -F # 清除预设链中规则
iptables -X # 清除自定义链中规则
iptables -A INPUT -i lo -j ACCEPT # 允许来自本机的全部连接
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT # 允许已建立的连接不中断
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT # 允许icmp协议,即允许ping服务器
iptables -A INPUT -m set ! --match-set china src -j DROP # 匹配china链,非国内IP则直接丢弃包
iptables -A INPUT -p udp --dport 5060 -j ACCEPT # 允许UDP协议的5060端口
iptables -A INPUT -p udp --dport 20000:30000 -j ACCEPT # 允许UDP协议的20000-30000端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT # 允许TCP协议的80端口
iptables -A INPUT -p tcp --dport 443 -j ACCEPT # 允许TCP协议的443端口
iptables -A INPUT -j DROP # 未匹配以上规则的请求直接丢弃
iptables -A OUTPUT -j ACCEPT # 允许全部出网数据包
iptables -A FORWARD -j DROP # 不允许Iptables的FORWARD转发
2、持久化 Iptables 规则
让服务器重启时,通过脚本在加载 /etc/sysconfig/iptables
中的数据。
iptables-save > /etc/sysconfig/iptables # 持久化Iptables规则
chmod +x /etc/rc.d/rc.local
echo "/usr/sbin/iptables-restore < /etc/sysconfig/iptables" >> /etc/rc.d/rc.local