网站屏蔽和阻止特定地区和国家的IP访问设置方法-PHP代码/Nginx/WordPress设置

分类:技术文章 时间:2023-11-16 17:21 浏览:0 评论:0
0

有不少的朋友搭建了外贸站的朋友想要限制自己的网站不让国内的 IP 访问,也有一些朋友网站存放的资源可能因为各种原因需要阻止特定的 IP 访问,还有一些朋友看到攻击源 IP 大部分来自国外,想要阻止国外的 IP 访问网站。

无论是出于什么原因,屏蔽和阻止特定地区和国家的 IP 访问都是我们日常建站中经常要用到的。如果你用的是 PHP,比较简单的方法就是在 PHP 文件加入判断 IP 的代码,利用 IP 库进行比对,如果 IP 为限定访问范围内,则阻止其继续访问。

如果网站是 Nginx,则可以直接使用 Nginx-ngx_http_geoip_module 模块,该模块可以精确到国家、省、市等一级的 IP,并且全部由 Nginx 执行识别和阻止访问,所以相对于 PHP 来说比较省资源,但是 Nginx 编译起来比较费事。

如果网站是搭建在 VPS 或者独立服务器上,那么可以直接使用Linux防火墙,利用 iptables 规则来阻止特定国家和省份的 IP 访问。当是,Wordpress 用户完全不用担心 Nginx、iptables 等配置的问题,因为 WordPress 早就有了各种限制 IP 访问的插件了。

本篇文章就来分享一下网站屏蔽和阻止特定地区和国家的 IP 访问设置四种方法:PHP 代码、Nginx 模块、iptables 防火墙和 WordPress 插件。

一、PHP 代码屏蔽特定 IP

PHP 代码比较简单,直接将以下代码丢到你的 PHP 文件中就可以实现阻止特定范围内 IP 访问网站了,根据 IP 库的精准度,可以准确到国家、省、市等一级的 IP,代码示例如下(这段代码可以用来在 BA 期间使用):

  1. <?php
  2. /**
  3. *
  4. * test.php(屏蔽国家 IP)
  5. *
  6. */
  7. $verification = '美国';//需要屏蔽国家的 IP
  8. function get_client_ip() {
  9. $ip = $_SERVER['REMOTE_ADDR'];
  10. if (isset($_SERVER['HTTP_X_REAL_FORWARDED_FOR']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_X_REAL_FORWARDED_FOR'])) {
  11. $ip = $_SERVER['HTTP_X_REAL_FORWARDED_FOR'];
  12. }
  13. elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
  14. $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
  15. }
  16. elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
  17. $ip = $_SERVER['HTTP_CLIENT_IP'];
  18. }
  19. return $ip;
  20. }
  21. $ip = get_client_ip();//获取访客 IP
  22. $antecedents = $_SERVER['HTTP_REFERER'];//访客来路地址
  23. $result = file_get_contents("http://ip.taobao.com/service/getIpInfo.php?ip=".$ip);//IP 数据库来自淘宝。
  24. $address = json_decode($result,true);
  25. //判断访客是否属于美国,是否来自百度,是否来自谷歌
  26. if($address['data']['country'] == $verification && strpos($antecedents, 'baidu') === false && strpos($antecedents, 'google') === false){
  27. sleep(10);//设置一个 10 秒等待。
  28. header('HTTP/1.1 503 Service Temporarily Unavailable');
  29. header('Status: 503 Service Temporarily Unavailable');
  30. header('Retry-After: 3600000');
  31. exit;
  32. }
  33. /****** 如果需要阻止某一个省份的 IP 访问,使用以下代码*********/
  34. <?php
  35. /**
  36. *
  37. * test.php(屏蔽地方 IP)
  38. *
  39. */
  40. $verification = '江西省';//需要屏蔽省份的 IP
  41. function get_client_ip() {
  42. $ip = $_SERVER['REMOTE_ADDR'];
  43. if (isset($_SERVER['HTTP_X_REAL_FORWARDED_FOR']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_X_REAL_FORWARDED_FOR'])) {
  44. $ip = $_SERVER['HTTP_X_REAL_FORWARDED_FOR'];
  45. }
  46. elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
  47. $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
  48. }
  49. elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
  50. $ip = $_SERVER['HTTP_CLIENT_IP'];
  51. }
  52. return $ip;
  53. }
  54. $ip = get_client_ip();//获取访客 IP
  55. $antecedents = $_SERVER['HTTP_REFERER'];//访客来路地址
  56. $result = file_get_contents("http://ip.taobao.com/service/getIpInfo.php?ip=".$ip);//IP 数据库来自淘宝。
  57. $address = json_decode($result,true);
  58. //判断访客是否属于江西省,是否来自百度,是否来自谷歌
  59. if($address['data']['region'] == $verification && strpos($antecedents, 'baidu') === false && strpos($antecedents, 'google') === false){
  60. sleep(99999999);//设置一个 999999 秒的等待。
  61. Header("HTTP/1.1 204 No Content");
  62. exit;
  63. }

二、Nginx-ngx_http_geoip_module 模块

IP 库下载:

https://dev.maxmind.com/geoip/legacy/geolite/

2.1 禁止特定国家 IP 访问

ngx_http_geoip_module 模块可以让 Nginx 根据来访者的 IP 实现不同的需要,这里我们利用 ngx_http_geoip_module 模块来阻止特定 IP 地址访问网站。

首先是将 ngx_http_geoip_module 编译到 Nginx 中。如果你用的是宝塔 BT 面板,可以采用以下命令:

  1. #安装 geoip 库
  2. yum -y install epel-release
  3. yum -y install geoip-devel
  4. #先查看一下本机的 Nginx 配置情况
  5. [root@cs ~]# nginx -V
  6. nginx version: nginx/1.14.2
  7. built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
  8. built with OpenSSL 1.0.2l 25 May 2017
  9. TLS SNI support enabled
  10. configure arguments: --user=www --group=www --prefix=/www/server/nginx --with-openssl=/www/server/nginx/src/openssl --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --add-module=/www/server/nginx/src/nginx-http-concat --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-stream --with-stream_ssl_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-pcre=pcre-8.40 --with-ld-opt=-ljemalloc
  11. #开始下载 Nginx,这里用的是 1.15.1,你也可以下载其它的版本
  12. wget http://nginx.org/download/nginx-1.15.1.tar.gz
  13. tar -xzvf nginx-1.15.1.tar.gz
  14. cd nginx-1.15.1
  15. #下面的命令只是在上面的 Nginx -v 得到的配置详情后加上了--with-http_geoip_module,目的是为了保持原来的配置不变同时又增加新的模块
  16. ./configure --user=www --group=www --prefix=/www/server/nginx --with-openssl=/www/server/nginx/src/openssl --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --add-module=/www/server/nginx/src/nginx-http-concat --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-stream --with-stream_ssl_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-pcre=pcre-8.40 --with-ld-opt=-ljemalloc --with-http_geoip_module
  17. #只编译不安装
  18. make

如果你用的是 LNMP 脚本或者 Oneinstack,可以参考这里:Oneinstack。启用 Nginx-ngx_http_geoip_module 模块。先停用 Nginx。
image.png

然后替换新的 Nginx 并查看 geoip 模块是否已经加载。命令如下:

  1. mv /www/server/nginx/sbin/nginx /www/server/nginx/sbin/nginx-lala.im
  2. cp objs/nginx /www/server/nginx/sbin/nginx
  3. ldd /www/server/nginx/sbin/nginx

image.png

到你的宝塔面板点击 Nginx,修改配置文件,加入以下代码:
geoip_country /usr/share/GeoIP/GeoIP.dat;
image.png

现在启动 Nginx,你可以往网站的 Nginx 配置中添加规则了,例如你可以将特定国家的 IP 访问返回指定错误或者导向另一个页面和网站,代码示例:

  1. #返回 403 502 404 等错误
  2. location / {
  3. default_type text/html;
  4. charset utf-8;
  5. if ($geoip_country_code = CN) {
  6. return 403;
  7. }
  8. }
  9. #导向另一个网站目录
  10. location / {
  11. default_type text/html;
  12. charset utf-8;
  13. if ($geoip_country_code = CN) {
  14. root /home/www/wzfou.com-cn/;
  15. }
  16. }

这是添加网站配置。
image.png

最后效果如下:
image.png

2.2 仅允许指定国家 IP 访问

方法和上面是一样的,先在 Nginx 主配置中引入 IP 库,然后在在网站的 Nginx 配置中加入阻止任何国家 IP 但允许指定国家 IP 的代码,示例如下 :

  1. # 引入 IP 库
  2. geoip_country /usr/share/GeoIP/GeoIP.dat;
  3. geoip_city /usr/share/GeoIP/GeoLiteCity.dat;
  4. map $geoip_country_code $allowed_country {
  5. default no;
  6. CN yes;
  7. }
  8. # 在配置中阻止 IP
  9. if ($allowed_country = no) {
  10. return 403;
  11. }

三、iptables 防火墙

先熟悉一下 iptables 用法和 ipset :

1、iptables 包含几个表,每个表由链组成。默认的是 filter 表,最常用的也是 filter 表,另一个比较常用的是 nat 表。一般封 IP 就是在 filter 表的 INPUT 链添加规则。

2、在进行规则匹配时,是从规则列表中从头到尾一条一条进行匹配。

3、ipset 提供了把这个 O(n) 的操作变成 O(1) 的方法:就是把要处理的 IP 放进一个集合,对这个集合设置一条 iptables 规则。像 iptable 一样,IP sets 是 Linux 内核中的东西,ipset 这个命令是对它进行操作的一个工具。

iptables 只允许指定 ip 访问本机的指定端口,命令如下:

  1. 1、在 tcp 协议中,禁止所有的 ip 访问本机的 3306 端口。
  2. iptables -I INPUT -p tcp dport 3306 -j DROP
  3. 2、允许 123.456.789 访问本机的 3306 端口
  4. iptables -I INPUT -s 123.456.789 -p tcp dport 3306 -j ACCEPT
  5. 以此类推…………………………………
  6. 封掉一个 IP 段:
  7. iptables -I INPUT -s 121.0.0.0/8 -j DROP
  8. 以上命令的顺序不能错
  9. 然后保存 iptables
  10. # service iptables save
  11. 重启防火墙
  12. #service iptables restart

iptables 规则删除、清空、关闭以及保存方法:

  1. #CentOS 7 请停止 firewalld 并安装 iptables-services
  2. systemctl stop firewalld
  3. systemctl mask firewalld
  4. #安装 iptables-services
  5. yum install iptables-services
  6. ################
  7. 保存 iptables 规则
  8. service iptables save
  9. 重启 iptables
  10. service iptables restart
  11. #################
  12. 执行清除命令 iptables -F 时可能会断开与服务器的连接,如果想清空的话,先执行
  13. /sbin/iptables -P INPUT ACCEPT
  14. 然后执行
  15. /sbin/iptables -F
  16. 如果关闭防火墙,执行
  17. /etc/init.d/iptables stop
  18. 或者是 services iptables stop
  19. #######################
  20. iptables 规则若重启后消失,请用以下方法
  21. 步骤 1:备份
  22. iptables-save > /etc/iptables.up.rules.bak
  23. 步骤 2:删除规则
  24. vim /etc/sysconfig/iptables
  25. vim /etc/iptables.up.rules
  26. 手动删除即可。
  27. 步骤 3:导入新规则
  28. iptables-restore < /etc/sysconfig/iptables
  29. 最后,重启 VPS 就可以生效了。

3.1 一键屏蔽指定国家 IP 访问

  1. https://github.com/iiiiiii1/Block-IPs-from-countries

原理是下载指定国家的 IP 段,然后将 IP 段添加到 iptables 规则当中,直接执行以下命令:

  1. wget https://raw.githubusercontent.com/iiiiiii1/Block-IPs-from-countries/master/block-ips.sh
  2. chmod +x block-ips.sh
  3. ./block-ips.sh

然后会要你选择是封禁 IP 还是解封 IP。

image.png

选择封禁 IP 后会让你输入国家代码,请到这里查看:http://www.ipdeny.com/ipblocks,例如美国就是输入 us,确定好完成对整个 US 的 IP 封禁。

image.png

如果想要解封的话,再次执行命令,然后选择 2 即可。

image.png

3.2 一键仅允许指定国家 IP 访问

上面我们实现了一键屏蔽特定国家的 IP 访问,但是有不少人希望让自己的网站仅让某一个国家的 IP 访问,其它的则禁止访问,这时我们就可以使用以下命令了:

  1. wget https://www.ucblog.net/wzfou/block-any.sh
  2. chmod +x block-ips.sh
  3. ./block-ips.sh

上面的代码仅允许国内的 IP 访问,并会在:/etc/rc.d/rc.local 写入规则,每次系统重启后都会重新导入 iptables 规则,如果你调整了 iptables 规则,需要编辑:/etc/rc.d/rc.local 删除相应的启动自运行代码。block-any.sh 代码如下:

  1. #! /bin/bash
  2. #判断是否具有 root 权限
  3. root_need() {
  4. if [[ $EUID -ne 0 ]]; then
  5. echo "Error:This script must be run as root!" 1>&2
  6. exit 1
  7. fi
  8. }
  9. #检查系统分支及版本(主要是:分支->>版本>>决定命令格式)
  10. check_release() {
  11. if uname -a | grep el7 ; then
  12. release="centos7"
  13. elif uname -a | grep el6 ; then
  14. release="centos6"
  15. yum install ipset -y
  16. elif cat /etc/issue |grep -i ubuntu ; then
  17. release="ubuntu"
  18. apt install ipset -y
  19. fi
  20. }
  21. #安装必要的软件(wget),并下载中国 IP 网段文件(最后将局域网地址也放进去)
  22. get_china_ip() {
  23. #安装必要的软件(wget)
  24. rpm --help >/dev/null 2>&1 && rpm -qa |grep wget >/dev/null 2>&1 ||yum install -y wget ipset >/dev/null 2>&1
  25. dpkg --help >/dev/null 2>&1 && dpkg -l |grep wget >/dev/null 2>&1 ||apt-get install wget ipset -y >/dev/null 2>&1
  26. #该文件由 IPIP 维护更新,大约一月一次更新(也可以用我放在国内的存储的版本,2018-9-8 日版)
  27. [ -f china_ip_list.txt ] && mv china_ip_list.txt china_ip_list.txt.old
  28. wget https://github.com/17mon/china_ip_list/blob/master/china_ip_list.txt
  29. cat china_ip_list.txt |grep 'js-file-line">' |awk -F'js-file-line">' '{print $2}' |awk -F'<' '{print $1}' >> china_ip.txt
  30. rm -rf china_ip_list.txt
  31. #wget https://qiniu.wsfnk.com/china_ip.txt
  32. #放行局域网地址
  33. echo "192.168.0.0/18" >> china_ip.txt
  34. echo "10.0.0.0/8" >> china_ip.txt
  35. echo "172.16.0.0/12" >> china_ip.txt
  36. }
  37. #只允许国内 IP 访问
  38. ipset_only_china() {
  39. echo "ipset create whitelist-china hash:net hashsize 10000 maxelem 1000000" > /etc/ip-black.sh
  40. for i in $( cat china_ip.txt )
  41. do
  42. echo "ipset add whitelist-china $i" >> /etc/ip-black.sh
  43. done
  44. echo "iptables -I INPUT -m set --match-set whitelist-china src -j ACCEPT" >> /etc/ip-black.sh
  45. #拒绝非国内和内网地址发起的 tcp 连接请求(tcp syn 包)(注意,只是屏蔽了入向的 tcp syn 包,该主机主动访问国外资源不用影响)
  46. echo "iptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 0 -j DROP" >> /etc/ip-black.sh
  47. #拒绝非国内和内网发起的 ping 探测(不影响本机 ping 外部主机)
  48. echo "iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j DROP" >> /etc/ip-black.sh
  49. #echo "iptables -A INPUT -j DROP" >> /etc/ip-black.sh
  50. rm -rf china_ip.txt
  51. }
  52. run_setup() {
  53. chmod +x /etc/rc.local
  54. sh /etc/ip-black.sh
  55. rm -rf /etc/ip-black.sh
  56. #下面这句主要是兼容 centos6 不能使用"-f"参数
  57. ipset save whitelist-china -f /etc/ipset.conf || ipset save whitelist-china > /etc/ipset.conf
  58. [ $release = centos7 ] && echo "ipset restore -f /etc/ipset.conf" >> /etc/rc.local
  59. [ $release = centos6 ] && echo "ipset restore < /etc/ipset.conf" >> /etc/rc.local
  60. echo "iptables -I INPUT -m set --match-set whitelist-china src -j ACCEPT" >> /etc/rc.local
  61. echo "iptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 0 -j DROP" >> /etc/rc.local
  62. echo "iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j DROP" >> /etc/rc.local
  63. #echo "iptables -A INPUT -j DROP" >> /etc/rc.local
  64. }
  65. main() {
  66. check_release
  67. get_china_ip
  68. ipset_only_china
  69. case "$release" in
  70. centos6)
  71. run_setup
  72. ;;
  73. centos7)
  74. chmod +x /etc/rc.d/rc.local
  75. run_setup
  76. ;;
  77. ubuntu)
  78. sed -i '/exit 0/d' /etc/rc.local
  79. run_setup
  80. echo "exit 0" >> /etc/rc.local
  81. ;;
  82. esac
  83. }
  84. main

如果你要排除一些 IP,允许这些 IP 作为例外继续访问,可以使用 iptables -I 命令新增 iptables 规则,或者手动添加 iptables 规则,注意要将规则放在最上面,因为 iptables 执行顺序是从上往下。

3.3 手动设置仅允许特定国家 IP 访问

手动设置和上面的一键设置方法是一样的,按照下面的命令一条一条地执行就可以了。

  1. 1、安装 ipset
  2. #Debian/Ubuntu 系统
  3. apt-get -y install ipset
  4. #CentOS 系统
  5. yum -y install ipset
  6. CentOS 7 还需要关闭 firewall 防火墙:
  7. systemctl stop firewalld.service
  8. systemctl disable firewalld.service
  9. 2、清空之前的规则
  10. #防止设置不生效,建议清空下之前的防火墙规则
  11. iptables -P INPUT ACCEPT
  12. iptables -F
  13. 3、创建新规则
  14. #创建一个名为 cnip 的规则
  15. ipset -N cnip hash:net
  16. #下载国家 IP 段,这里以中国为例,其它国家 IP 下载参考:http://www.ipdeny.com/ipblocks/
  17. wget -P . http://www.ipdeny.com/ipblocks/data/countries/cn.zone
  18. #将 IP 段添加到 cnip 规则中
  19. for i in $(cat /root/cn.zone ); do ipset -A cnip $i; done
  20. 4、设置 IP 段白名单
  21. #放行 IP 段
  22. iptables -A INPUT -p tcp -m set --match-set cnip src -j ACCEPT
  23. #关掉所有端口
  24. iptables -P INPUT DROP
  25. 这时候就只有指定国家的 IP 能访问服务器了。
  26. #如果你在国内,网站不允许被国内人访问,建议别关所有端口,这样你的 S-S-H 会上不去,我们可以只关闭 80/443 端口。
  27. #关闭指定端口,比如 80/443
  28. iptables -A INPUT -p tcp --dport 80 -j DROP
  29. iptables -A INPUT -p tcp --dport 443 -j DROP
  30. 这时候其他国家的 IP 是无法访问你服务器的 80/443 端口,等于无法访问你的网站,其它端口还是可以访问的。
  31. 5、删除规则
  32. #将参数里的-A 改成-D 就是删除规则了,如
  33. iptables -D INPUT -p tcp -m set --match-set cnip src -j ACCEPT
  34. iptables -D INPUT -p tcp --dport 443 -j DROP

四、Wordpress 屏蔽特定 IP

WordPress 插件
https://wordpress.org/plugins/wordfence/
https://wordpress.org/plugins/all-in-one-wp-security-and-firewall/
https://wordpress.org/plugins/ip-geo-block/

五、总结

网站屏蔽特定国家 IP 最简单的方法就是本文介绍的 PHP 代码,引用了淘宝 IP 库,准确度非常高,而且还可以精确到省、市,自己可以根据需要来调整。不足的地方是不支持 Https 以及仅限 PHP 运行。

实际上常用的应该是 iptables,直接以Linux防火墙的方式来阻止 IP 访问,不消耗资源,阻止得干净彻底。Nginx 的 Geo IP 模块应用范围比较广泛,结合 Nginx 你可以实现对不同的 IP 用户展现不同的内容。

本文转至:https://blog.kieng.cn/774.html

1. 本站所有资源来源于用户上传或网络,仅作为参考研究使用,如有侵权请邮件联系站长!
2. 本站积分货币获取途径以及用途的解读,想在本站混的好,请务必认真阅读!
3. 本站强烈打击盗版/破解等有损他人权益和违法作为,请各位会员支持正版!
4. 技术文章 > 网站屏蔽和阻止特定地区和国家的IP访问设置方法-PHP代码/Nginx/WordPress设置

用户评论