Nginx 实现屏蔽境外IP访问

方式一 指定IP

  • 在nginx目录下创建blockips.conf 并添加

deny 42.200.167.4;

  • 其中 42.200.167.4为屏蔽的ip地址
  • 在nginx.conf中任何server{ ... }前 添加 include /etc/nginx/blockips.conf;
  • 刷新配置 systemctl reload nginx

方式二 通过GeoIP禁止国外IP访问

  • 检查一下nginx是否编译了GeoIP模块

nginx -V

  • 出现 --with-http_geoip_module 说明nginx已经编译了GeoIP模块

  • 没有GeoIP 模块 手动添加

# ./configure --prefix=/usr/local/webserver/nginx-1.6.2 --with-http_stub_status_module --with-http_ssl_module --with-pcre=/usr/local/pcre-4-27/pcre-8.35 --with-http_geoip_module
# make
# make install
  • /usr/local/webserver/nginx-1.6.2 为nginx目录

接下来我们安装GeoIP数据库

  • 乌班图安装办法

apt-get install geoip-database libgeoip1

  • CentOS安装办法

yum -y install geoip-devel

mv /usr/share/GeoIP/GeoIP.dat /usr/share/GeoIP/GeoIP.dat_bak

cd /usr/share/GeoIP/
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
gunzip GeoIP.dat.gz
  • 配置nginx.conf文件

vi /etc/nginx/nginx.conf

  • 将下面的内容添加进 http {} 区域,并且要放在任何 include 语句之前。
geoip_country /usr/share/GeoIP/GeoIP.dat;
map $geoip_country_code $allowed_country {
default yes;
FK no;
FM no;
EH no;
}
  • 上面这些语句是除了 FK,FM,EH这三个地区的用户允许其它地区的用户访问。
  • 也可以只允许部分地区用户访问,如下:
geoip_country /usr/share/GeoIP/GeoIP.dat;
map $geoip_country_code $allowed_country {
default no;
FK yes;
FM yes;
EH yes;
}
  • 上面这些语句是除了 FK,FM,EH这三个地区的用户其它地区的用户都不允许访问。
  • 上面的语句只是设置了一个 $allowed_country 变量,要最终实现禁止设置的地区用户访问,我们要对 $allowed_country 变量进行判断处理。
  • 在 server {} (网站代理的server)区域里添加以下内容:
if ($allowed_country = no) {
return 403;
}
// 或者
 if ($geoip_country_code != "CN") { // 只允许中国IP访问
   return 500 "error";
}
  • 也可以针对某个特定url进行限制:
location /special {
 if ($allowd_country = no) {
  return 403;
 }
}
  • 关于我个人的nginx配置是
geoip_country /usr/share/GeoIP/GeoIP.dat;
map $geoip_country_code $allowed_country {
 default no;
 CN yes;
}
  • 网站里面配置(网站代理的server)的是
if ($allowed_country = no) {
 return 402;
}
  • 除了中国以外的IP ,访问都会返回 402
    这个模块需要geo数据库和读取数据库的库文件。

Get the free database of geo_city

wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz

Get the free database of geo_coundty

wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz

Get the libgeoip. In debian you can do like this:

sudo apt-get install libgeoip-dev

In other systems, you can download the source and compile it youself.

wget http://geolite.maxmind.com/download/geoip/api/c/GeoIP.tar.gz

实战

http {

    log_format geoip_log '$remote_addr - $remote_user [$time_local] '
                         '"$request" $status $body_bytes_sent '
                         '"$http_referer" "$http_user_agent" '
                         '"$http_x_forwarded_for" '
                         'Country: $geoip_country_code '
                         'CountryName: $geoip_country_name';

    # 使用 geoip 地址库,需要下载geoip.dat 地址库并且nginx已安装--with-http_geoip_module模块
	geoip_country /usr/local/nginx/geoip.dat;
	map $geoip_country_code $allowed_access {
	 default 0;
	 CN 1;
	}

    #方式二 使用 geo 指定白名单;
	geo $allowlist {
	    default 0;
	    include /usr/local/nginx/allowlist.conf;
	}
	# allowlist.conf 白名单格式如下
	# 1.0.1.0/24 1;
    # 1.0.2.0/23 1;
    # 1.0.8.0/21 1;
    # 42.50.0.0/16 1;
	
    server {
    
    	listen 443 ssl http2;
    	server_name xxxx.com;
    
    	ssl_certificate /home/ssl/xxx.com.pem;
    	ssl_certificate_key /home/ssl/xxx.com.key;
    	ssl_session_timeout 5m;
    	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    	ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    	ssl_prefer_server_ciphers on;
    
        # 测试日志,会记录$geoip_country_code,如果是中国区域访问,日志中会记录 Country: CN
        access_log /home/.nginx/logs/access_geoip.log geoip_log;
        
        # 指定只允许中国IP能访问,这个判断必须放在 server 里
        if ($geoip_country_code != "CN") {
          return 500 "error";
        }
        
        # 或者,如果不在白名单IP中直接返回444,这个判断必须放在 server 里
		#if ( $allowlist = 0 ) {
		#    return 444;
		#}
        
        # 测试访问
        location /debug {
           add_header Content-Type text/plain;
           return 200 "Country: $geoip_country_code";
        }
    }
}

TCP geoip方式

  • 如果需要--with-stream_geoip_module模块可以添加到上面的编译脚本中,此模块可用于TCP协议转发区域IP限制,如下
stream {
    geoip_country /usr/local/nginx/geoip.dat;
    
    server {
        listen 3306;
        
        if ($geoip_country_code != "CN") {
            return "";
        }
        
        proxy_pass 192.168.1.100:3306;
    }
}

TCP 白名单方式

// 需要跟 http {} 同级,而不是配置 http {}里面
stream {
    log_format simple '$remote_addr:$remote_port '
                        '[$time_iso8601] '
                        '$protocol $status ';

    # 导入包含中国 IP 列表
    #include /usr/local/nginx/china_ips_dynamic.conf;
    # 这里只是验证,所有只指定一个IP段,生产环境可以使用include方式导入多个
    allow 119.41.0.0/16;

    deny all;

    upstream iot_demo {
        server 127.0.0.1:8882;
    }

    server {
        listen 8881;
        proxy_pass iot_demo;
        proxy_timeout 3s;
        proxy_responses 1;
        access_log /home/.nginx/logs/tcp_access.log simple;
    }
}

获取中国白名单脚本

#!/bin/bash
# 从网上获取中国 IP 列表并生成 nginx 配置
# 下载最新的中国 IP 列表
curl -s https://www.ipdeny.com/ipblocks/data/countries/cn.zone | \
awk '{print "allow " $1 ";"}' > ./china_ips_dynamic.conf

# 添加 deny all
echo "deny all;" >> ./china_ips_dynamic.conf
posted @ 2025-04-09 11:47  程序员の奇妙冒险  阅读(568)  评论(0)    收藏  举报