GeoIP2
GeoIP2是MaxMind提供的最新一代地理定位服务,它提供了比旧版GeoIP更高的精度和更多的数据点。GeoIP 数据库有免费版(GeoLite2)和收费版(GeoIP2),这些数据库可以提供详细的地理位置信息,如国家、地区/省、城市、邮政编码、纬度/经度、ISP、自治系统编号(ASN)等。
将GeoIP数据库集成到Nginx服务器,常见的做法是编译时使用--with-http_geoip_module
参数,然而这样编译实际上是提供了旧版GeoIP数据库格式的支持(官方称之为Legacy格式)。虽然Legacy格式曾经是行业标准,但随着技术的发展,它逐渐被功能更强大、精度更高的 GeoIP2 所替代。官方已宣布在2022年5月结束对Legacy数据库的支持,并建议用户迁移到更新的GeoIP2平台。
Nginx集成GeoIP2可以通过ngx_http_geoip2_module项目实现。
编译安装Nginx
安装依赖
为了编译一个支持stream和http/3等常用功能的Nginx,需要先行安装如下依赖:
sudo apt-get install openssl libssl-dev \
libpcre3 libpcre3-dev \
zlib1g-dev \
libxml2 libxml2-dev libxslt-dev \
libgd-dev \
libgeoip1 libgeoip-dev
进一步地,安装geoip相关的库:
sudo apt-get install libmaxminddb0 libmaxminddb-dev mmdb-bin
编译安装
首先下载ngx_http_geoip2_module源码到服务器,并解压。
然后下载Nginx-1.27.4源码到服务器并解压,切换到configure文件所在目录下(cd nginx-1.27.4/
):
./configure --with-debug \
--with-pcre-jit \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_auth_request_module \
--with-http_v2_module \
--with-http_v3_module \
--with-http_dav_module \
--with-http_slice_module \
--with-threads \
--with-http_addition_module \
--with-http_geoip_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_image_filter_module \
--with-http_sub_module \
--with-http_xslt_module \
--with-stream \
--with-stream_ssl_module \
--with-mail \
--with-mail_ssl_module \
--with-stream_ssl_preread_module \
--add-module=/home/src/ngx_http_geoip2_module-3.4/
注意上面的最后一行指向ngx_http_geoip2_module
所在的目录。最后编译安装。
make && make install
也可以同时调用更多的内核参与这个过程,这也会消耗更多的内存,如:
make -j4 && make install
Nginx会被默认安装在/usr/local/nginx/
目录下
创建如下软连接
ln -s /usr/local/nginx/sbin/nginx /usr/sbin/nginx
之后即可正常使用nginx -V
和nginx -s reload
等命令。
应用实战
场景——对于站点s.221.ltd
上的静态资源,来自中国大陆的访问直接提供资源,中国大陆以外的访问重定向到static.colorfulstage.cn
站点下的同一路径资源(实际应用中,后者可能是CDN域名或专门用于提供地区特供资源)。基于此,同样可以实现屏蔽特定地区访问的功能(简单粗暴地return 403;
)。
配置文件
为方便管理,在/usr/local/nginx/conf/
目录下创建conf.d
和 modules-enabled
文件夹,并把/usr/local/nginx/conf/nginx.conf
中的内容替换为如下内容,重要修改有以下几点:
http
中的include conf.d/*.conf;
和最外层的include modules-enabled/*.conf;
- 在
http{}
中加入server_tokens off;
,以此隐藏错误页的服务器信息 - log_format和access_log,quic需要用到
- [可选]禁用了远古TLS协议,仅启用TLSv1.2和1.3
- 基于GeoIP2提供了访客IP属地的判定
user root root;
worker_processes auto;
include modules-enabled/*.conf;
events {
worker_connections 1024;
}
http {
log_format quic '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$http3"';
access_log logs/access.log quic;
include mime.types;
charset utf-8;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
gzip on;
# Sets a gzip compression level of a response. Acceptable values are in the range from 1 to 9.
gzip_comp_level 6;
gzip_types text/css text/xml application/javascript;
# Disable gzip for legacy IEs.
gzip_disable "MSIE [1-6]\.";
# 选择支持vary header;改选项可以让前端的缓存服务器缓存经过gzip压缩的页面; 这个可以不写,表示在传送数据时,给客户端说明我使用了gzip压缩
gzip_vary on;
# with geoip-2
geoip2 /home/geoip-2/GeoLite2-Country.mmdb {
$geoip2_data_country_code country iso_code;
}
map $geoip2_data_country_code $is_china {
default 0;
CN 1;
}
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
include conf.d/*.conf;
server_tokens off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
}
在conf.d/
目录下创建static-file.conf
,并写入以下内容:
server {
listen 443 ssl;
server_name s.221.ltd;
ssl_certificate crts/221.ltd/fullchain.pem;
ssl_certificate_key crts/221.ltd/key.pem;
http2 on;
add_header Strict-Transport-Security "max-age=31536000;includeSubDomains;preload";
proxy_hide_header X-Powered-By;
add_header 'Access-Control-Allow-Origin' '*';
if ($is_china = 0) {
return 301 https://static.colorfulstage.cn$request_uri;
}
location / {
alias /var/www/html/static/;
client_max_body_size 512m;
autoindex on;
try_files $uri $uri/ =404;
valid_referers none 221.ltd *.221.ltd;
if ($invalid_referer) {
return 403;
}
}
}
server {
listen 443 ssl;
server_name static.colorfulstage.cn;
ssl_certificate crts/colorfulstage.cn/fullchain.pem;
ssl_certificate_key crts/colorfulstage.cn/key.pem;
http2 on;
add_header Strict-Transport-Security "max-age=31536000;includeSubDomains;preload";
proxy_hide_header X-Powered-By;
add_header 'Access-Control-Allow-Origin' '*';
location / {
alias /var/www/html/static/;
client_max_body_size 512m;
autoindex off;
try_files $uri $uri/ =404;
}
}
添加Systemd守护进程
控制台执行vim /usr/lib/systemd/system/nginx.service
并写入以下内容
[Unit]
Description=nginx service
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true
Restart=on-failure
RestartSec=10s
[Install]
WantedBy=multi-user.target
输入:wq
保存,之后配置开启自启动
systemctl enable nginx
启动Nginx服务
service nginx start
查看服务状态
service nginx status
编译安装Nginx到此结束。
使用XFF模拟测试
设置X-Forwarded-For
头来模拟源站ip地址测试。
使用8.8.8.8
来模拟海外ip的访问,可以看到发生了跳转并由跳转后的Cloudflare CDN提供了资源。
Comments NOTHING