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.29.4 --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.29.4 为nginx目录
接下来我们安装GeoIP数据库
Ubuntu安装办法:
apt-get install geoip-database libgeoip1
CentOS安装办法:
yum -y install geoip-devel
安装完成之后,GeoIP数据库会被安装在 /usr/share/GeoIP/GeoIP.dat。这个GeoIP.dat是GeoIP数据库文件,使用apt-get命令安装的话这个文件不是最新的,我们可以从 http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz 这里下载最新的GeoIP数据库文件。
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;
}
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 yourself.
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
实战
使用ip+自定义页面,阻止非中国ip访问
- 配合白名单ip使用
nginx配置
#引用允许中国ip段规则,注释后配置的反向代理将无效
include /www/server/ip/*.conf;
error_page 403 /banip.html;
location = /banip.html {
root /www/server/nginx/html/;
internal;
allow all; # 关键!必须添加
}
deny all;
使用自定义403页面banip.html
<html>
<head>
<title>Access Restricted</title>
<meta charset="UTF-8">
</head>
<body>
<center>
<h1>Access Restricted</h1>
<p>We're sorry, but this website is only available to users within China. Access from international IP addresses has been restricted.</p>
</center>
<hr>
<center>awesome server</center>
</body>
</html>