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

by Qi

/ 2019-03-05 18:08

有不少的朋友搭建了外贸站的朋友想要限制自己的网站不让国内的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插件。如果你在网站建设的过程总是被各种恶意攻击所困扰,可以试试以下方法:

  1. 五条关于使用免费VPS控制面板的安全建议-不让黑客有可趁之机
  2. WordPress开启Nginx fastcgi_cache缓存加速方法-Nginx配置实例
  3. 十个你可能不知道的CloudFlare免费CDN加速技巧-SSLDDOSCache

一、PHP代码屏蔽特定IP

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

<?php  /**   *   * test.php(屏蔽国家IP)   *   */    $verification = '美国';//需要屏蔽国家的IP  function get_client_ip() {                  $ip = $_SERVER['REMOTE_ADDR'];                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'])) {                       $ip = $_SERVER['HTTP_X_REAL_FORWARDED_FOR'];                  }                     elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match('/^([0-9]{1,3}.){3}[0-9]{1,3}$/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {                        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];                  }                     elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {                      $ip = $_SERVER['HTTP_CLIENT_IP'];                  }                     return $ip;               }  $ip = get_client_ip();//获取访客IP  $antecedents = $_SERVER['HTTP_REFERER'];//访客来路地址  $result = file_get_contents("http://ip.taobao.com/service/getIpInfo.php?ip=".$ip);//IP数据库来自淘宝。  $address = json_decode($result,true);  //判断访客是否属于美国,是否来自百度,是否来自谷歌  if($address['data']['country'] == $verification && strpos($antecedents, 'baidu') === false && strpos($antecedents, 'google') === false){          sleep(10);//设置一个10秒等待。          header('HTTP/1.1 503 Service Temporarily Unavailable');          header('Status: 503 Service Temporarily Unavailable');          header('Retry-After: 3600000');          exit;  }      /****** 如果需要阻止某一个省份的IP访问,使用以下代码*********/      <?php  /**   *   * test.php(屏蔽地方IP)   *   */    $verification = '江西省';//需要屏蔽省份的IP  function get_client_ip() {                  $ip = $_SERVER['REMOTE_ADDR'];                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'])) {                       $ip = $_SERVER['HTTP_X_REAL_FORWARDED_FOR'];                  }                     elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match('/^([0-9]{1,3}.){3}[0-9]{1,3}$/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {                        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];                  }                     elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {                      $ip = $_SERVER['HTTP_CLIENT_IP'];                  }                     return $ip;               }  $ip = get_client_ip();//获取访客IP  $antecedents = $_SERVER['HTTP_REFERER'];//访客来路地址  $result = file_get_contents("http://ip.taobao.com/service/getIpInfo.php?ip=".$ip);//IP数据库来自淘宝。  $address = json_decode($result,true);  //判断访客是否属于江西省,是否来自百度,是否来自谷歌  if($address['data']['region'] == $verification && strpos($antecedents, 'baidu') === false && strpos($antecedents, 'google') === false){    sleep(99999999);//设置一个999999秒的等待。    Header("HTTP/1.1 204 No Content");    exit;  }

二、Nginx-ngx_http_geoip_module模块

IP库下载:

  1. 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面板,可以采用以下命令:

#安装geoip库  yum -y install epel-release  yum -y install geoip-devel      #先查看一下本机的Nginx配置情况  [root@cs ~]# nginx -V  nginx version: nginx/1.14.2  built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)   built with OpenSSL 1.0.2l  25 May 2017  TLS SNI support enabled  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    #开始下载Nginx,这里用的是1.15.1,你也可以下载其它的版本  wget http://nginx.org/download/nginx-1.15.1.tar.gz  tar -xzvf nginx-1.15.1.tar.gz  cd nginx-1.15.1    #下面的命令只是在上面的Nginx -v得到的配置详情后加上了--with-http_geoip_module,目的是为了保持原来的配置不变同时又增加新的模块    ./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    #只编译不安装  make

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

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

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

安装Nginx-ngx_http_geoip_module模块

到你的宝塔面板点击Nginx,修改配置文件,加入以下代码:

geoip_country /usr/share/GeoIP/GeoIP.dat;

操作如下图:

网站屏蔽和阻止特定IP修改配置

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

#返回403 502 404等错误  location / {  default_type text/html;  charset utf-8;  if ($geoip_country_code = CN) {  return 403;  }  }  #导向另一个网站目录  location / {  default_type text/html;  charset utf-8;  if ($geoip_country_code = CN) {  root /home/www/wzfou.com-cn/;  }  }

这是添加网站配置。

网站屏蔽和阻止IP设置页面

最后效果如下:

网站屏蔽和阻止特定IP成功效果

2.2  仅允许指定国家IP访问

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

 # 引入IP库           geoip_country /usr/share/GeoIP/GeoIP.dat;    geoip_city /usr/share/GeoIP/GeoLiteCity.dat;       map $geoip_country_code $allowed_country {                  default no;                  CN yes;          }        # 在配置中阻止IP          if ($allowed_country = no) {                  return 403;          }

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

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

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

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

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

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

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

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

网站屏蔽指定国家的IP

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

网站屏蔽选择一个代码

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

网站屏蔽解封IP

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

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

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

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

#! /bin/bash  #判断是否具有root权限  root_need() {      if [[ $EUID -ne 0 ]]; then          echo "Error:This script must be run as root!" 1>&2          exit 1      fi  }    #检查系统分支及版本(主要是:分支->>版本>>决定命令格式)  check_release() {      if uname -a | grep el7  ; then          release="centos7"      elif uname -a | grep el6 ; then          release="centos6"          yum install ipset -y      elif cat /etc/issue |grep -i ubuntu ; then          release="ubuntu"          apt install ipset -y      fi  }    #安装必要的软件(wget),并下载中国IP网段文件(最后将局域网地址也放进去)  get_china_ip() {    #安装必要的软件(wget)    rpm --help >/dev/null 2>&1 && rpm -qa |grep wget >/dev/null 2>&1 ||yum install -y wget ipset >/dev/null 2>&1     dpkg --help >/dev/null 2>&1 && dpkg -l |grep wget >/dev/null 2>&1 ||apt-get install wget ipset -y >/dev/null 2>&1      #该文件由IPIP维护更新,大约一月一次更新(也可以用我放在国内的存储的版本,2018-9-8日版)    [ -f china_ip_list.txt ] && mv china_ip_list.txt china_ip_list.txt.old    wget https://github.com/17mon/china_ip_list/blob/master/china_ip_list.txt    cat china_ip_list.txt |grep 'js-file-line">' |awk -F'js-file-line">' '{print $2}' |awk -F'<' '{print $1}' >> china_ip.txt    rm -rf china_ip_list.txt    #wget https://qiniu.wsfnk.com/china_ip.txt      #放行局域网地址    echo "192.168.0.0/18" >> china_ip.txt    echo "10.0.0.0/8" >> china_ip.txt    echo "172.16.0.0/12" >> china_ip.txt  }    #只允许国内IP访问  ipset_only_china() {    echo "ipset create whitelist-china hash:net hashsize 10000 maxelem 1000000" > /etc/ip-black.sh    for i in $( cat china_ip.txt )    do          	echo "ipset add whitelist-china $i" >> /etc/ip-black.sh    done    echo "iptables -I INPUT -m set --match-set whitelist-china src -j ACCEPT" >> /etc/ip-black.sh    #拒绝非国内和内网地址发起的tcp连接请求(tcp syn 包)(注意,只是屏蔽了入向的tcp syn包,该主机主动访问国外资源不用影响)    echo "iptables  -A INPUT -p tcp --syn -m connlimit --connlimit-above 0 -j DROP" >> /etc/ip-black.sh    #拒绝非国内和内网发起的ping探测(不影响本机ping外部主机)    echo "iptables  -A INPUT -p icmp -m icmp --icmp-type 8 -j DROP" >> /etc/ip-black.sh    #echo "iptables -A INPUT -j DROP" >> /etc/ip-black.sh    rm -rf china_ip.txt  }    run_setup() {    chmod +x /etc/rc.local    sh /etc/ip-black.sh    rm -rf /etc/ip-black.sh    #下面这句主要是兼容centos6不能使用"-f"参数    ipset save whitelist-china -f /etc/ipset.conf || ipset save whitelist-china > /etc/ipset.conf    [ $release = centos7 ] && echo "ipset restore -f /etc/ipset.conf" >> /etc/rc.local    [ $release = centos6 ] && echo "ipset restore < /etc/ipset.conf" >> /etc/rc.local    echo "iptables -I INPUT -m set --match-set whitelist-china src -j ACCEPT" >> /etc/rc.local    echo "iptables  -A INPUT -p tcp --syn -m connlimit --connlimit-above 0 -j DROP" >> /etc/rc.local    echo "iptables  -A INPUT -p icmp -m icmp --icmp-type 8 -j DROP" >> /etc/rc.local    #echo "iptables -A INPUT -j DROP" >> /etc/rc.local  }    main() {    check_release    get_china_ip    ipset_only_china    case "$release" in  centos6)    run_setup    ;;  centos7)    chmod +x /etc/rc.d/rc.local    run_setup    ;;  ubuntu)    sed -i '/exit 0/d' /etc/rc.local    run_setup    echo "exit 0" >> /etc/rc.local    ;;  esac  }  main

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

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

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

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

四、Wordpress屏蔽特定IP

WordPress插件

  1. https://wordpress.org/plugins/wordfence/
  2. https://wordpress.org/plugins/all-in-one-wp-security-and-firewall/
  3. https://wordpress.org/plugins/ip-geo-block/

上面三个Wordpress安全插件都带有屏蔽IP访问的设置,可以根据IP的来源、国家、范围和域名等进行屏蔽。(点击放大)

Wordpress网站屏蔽IP

IP Geo Block稍微专业一些,除了可以屏蔽特定的IP地址,还可以对不同的IP地址访问不同的页面进行屏蔽或者阻止,功能非常强大。(点击放大)

网站屏蔽安装插件

五、总结

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

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

文章出自:挖站否 https://wzfou.com/zuzhi-ip/,内容参考来自 wsfnk.commoeratsRat’s Bloglala.im 版权所有。本站文章除注明出处外,皆为作者原创文章,可自由引用,但请注明来源。

分享到:

Shared via Inoreader