如何在 Linux 上按国家/地区阻止流量
作为维护生产 Linux 服务器的系统管理员,在某些情况下您需要根据地理位置有选择地阻止或允许网络流量。例如,您遇到的拒绝服务攻击主要来自在特定国家/地区注册的 IP 地址。在其他情况下,出于安全原因,您希望阻止来自未知国家的 SSH 登录。或者您的公司拥有在线视频的发行权,这使得它只能合法地传输到特定国家/地区。或者,由于公司政策的地理限制,您需要阻止任何本地主机将文档上传到任何非美国远程云存储。
所有这些场景都需要能够设置防火墙来进行基于国家/地区的流量过滤。有几种方法可以做到这一点。其一,您可以使用 TCP 包装器为单个应用程序(例如 SSH、NFS、httpd)设置条件阻止。缺点是您想要保护的应用程序必须使用 TCP 包装器支持来构建。此外,TCP 包装器并非在不同平台上普遍可用(例如,Arch Linux 放弃了支持)。另一种方法是使用基于国家/地区的 GeoIP 信息设置 ipset 并将其应用于 iptables 规则。后一种方法更有前途,因为基于 iptables 的过滤与应用程序无关并且易于设置。
在本教程中,我将介绍基于 iptables
的 GeoIP 过滤,该过滤是通过 xtables-addons
实现的。对于那些不熟悉它的人来说,xtables-addons
是 netfilter/iptables
的一套扩展。 xtables-addons
中包含一个名为 xt_geoip
的模块,它扩展了 netfilter/iptables
以根据源/目标国家/地区过滤、NAT 或 mangle 数据包。要使用 xt_geoip
,您不需要重新编译内核或 iptables
,而只需使用当前内核构建环境 (/lib/modules/`uname -r`/build
) 将 xtables-addons
构建为模块。也不需要重新启动。一旦您构建并安装了xtables-addons
,xt_geoip
就可以立即与iptables
一起使用。
至于xt_geoip
和ipset
的比较,xtables-addons
的官方来源提到xt_geoip
在内存占用方面优于ipset
。但就匹配速度而言,基于哈希的 ipset 可能具有优势。
在本教程的其余部分中,我将展示如何使用 iptables/xt_geoip
根据源/目标国家/地区阻止网络流量。
在 Linux 上安装 xtables-addons
以下是在各种 Linux 平台上编译和安装 xtables-addons 的方法。
要构建 xtables-addons,您需要首先安装几个依赖包。
在 Ubuntu、Debian 或 Linux Mint 上安装依赖项
$ sudo apt-get install iptables-dev xtables-addons-common libtext-csv-xs-perl pkg-config
在 CentOS、RHEL 或 Fedora 上安装依赖项
CentOS/RHEL 6 要求首先设置 EPEL 存储库(对于 perl-Text-CSV_XS
)。然后运行:
$ sudo yum install gcc-c++ make automake kernel-devel-`uname -r` wget unzip iptables-devel perl-Text-CSV_XS
编译并安装xtables-addons
从官方网站下载最新的xtables-addons
源代码,并按如下方式构建/安装它。
$ wget https://inai.de/files/xtables-addons/xtables-addons-2.10.tar.xz
$ tar xf xtables-addons-2.10.tar.xz
$ cd xtables-addons-2.10
$ ./configure
$ make
$ sudo make install
请注意,对于默认启用 SELinux 的基于 Red Hat 的系统(CentOS、RHEL、Fedora),需要按如下方式调整 SELinux 策略。否则,SELinux 将阻止 iptables 加载 xt_geoip 模块。
$ sudo chcon -vR --user=system_u /lib/modules/$(uname -r)/extra/*.ko
$ sudo chcon -vR --type=lib_t /lib64/xtables/*.so
为 Xtables 插件安装 GeoIP 数据库
下一步是安装 GeoIP 数据库,xt_geoip
将使用该数据库进行 IP 到国家/地区的映射。方便的是,xtables-addons
源包附带了两个帮助程序脚本,用于从 MaxMind 下载 GeoIP 数据库并将其转换为 xt_geoip
识别的二进制形式。这些脚本位于源包内的geoip
文件夹中。请按照以下说明在您的系统上构建并安装 GeoIP 数据库。
$ cd geoip
$ ./xt_geoip_dl
$ ./xt_geoip_build GeoIPCountryWhois.csv
$ sudo mkdir -p /usr/share/xt_geoip
$ sudo cp -r {BE,LE} /usr/share/xt_geoip
据 MaxMind 称,他们的 GeoIP 数据库在国家一级的准确度为 99.8%,并且该数据库每月更新。为了使本地安装的 GeoIP 数据库保持最新,您需要设置每月的 cron
作业来经常刷新本地 GeoIP 数据库。
阻止源自或发往某个国家/地区的网络流量
一旦安装了xt_geoip
模块和GeoIP数据库,您就可以立即使用iptables
命令中的geoip
匹配选项。
$ sudo iptables -m geoip --src-cc country[,country...] --dst-cc country[,country...]
您要阻止的国家/地区使用两个字母的 ISO3166 代码指定(例如,US
(美国)、CN
(中国)、IN
(印度)、FR
(法国))。
例如,如果您想阻止来自也门 (YE
) 和赞比亚 (ZM
) 的传入流量,则可以使用以下 iptables
命令。
$ sudo iptables -I INPUT -m geoip --src-cc YE,ZM -j DROP
如果您想阻止发往中国 (CN
) 的传出流量,请运行以下命令。
$ sudo iptables -A OUTPUT -m geoip --dst-cc CN -j DROP
还可以通过在 --src-cc
或 --dst-cc
前面添加 !
来否定匹配条件。例如:
如果您想阻止服务器上所有传入的非美国流量,请运行以下命令:
$ sudo iptables -I INPUT -m geoip ! --src-cc US -j DROP

对于 Firewall-cmd 用户
一些发行版(例如 CentOS/RHEL 7 或 Fedora)已将 iptables
替换为 firewalld
作为默认防火墙服务。在此类系统上,您可以使用 firewall-cmd
类似地使用 xt_geoip
来阻止流量。上面的三个例子可以用firewall-cmd
重写如下。
$ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -m geoip --src-cc YE,ZM -j DROP
$ sudo firewall-cmd --direct --add-rule ipv4 filter OUTPUT 0 -m geoip --dst-cc CN -j DROP
$ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -m geoip ! --src-cc US -j DROP
结论
在本教程中,我介绍了 iptables/xt_geoip ,这是一种根据源/目标国家/地区过滤网络数据包的简单方法。如果需要,这可能是部署在防火墙系统中的有用武器库。作为最后的警告,我应该提到基于 GeoIP 的流量过滤并不是在您的服务器上禁止某些国家/地区的万无一失的方法。 GeoIP 数据库本质上是不准确/不完整的,并且可以使用 VPN、Tor 或任何受损的中继主机轻松欺骗源/目的地地理位置。基于地理位置的过滤甚至可以阻止不应禁止的合法流量。在决定将其部署到生产环境中之前,请先了解此限制。