我使用NGINX根据客户的地理位置控制对我网站的访问。我选择使用外部GeoIP服务,而不是GeoIP模块,因为我发现它更灵活地满足我的需求。然而,我面临的问题是,对于基于其GeoIP国家/地区而被阻止的请求,NGINX访问日志中没有填充与GeoIP相关的变量。
以下是我的NGINX配置的相关部分:
server {
server_name mydomain.com;
access_log /var/log/nginx/mydomain.access.log with_geoip;
error_log /var/log/nginx/mydomain.error.log;
server_tokens off;
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
location = @geoip {
internal;
proxy_pass http://geoip-service:8080/;
proxy_set_header X-Geoip-Address $remote_addr;
}
location / {
error_page 403 = @denied;
auth_request @geoip;
auth_request_set $geoip_country $upstream_http_x_geoip_country;
auth_request_set $geoip_stateprov $upstream_http_x_geoip_stateprov;
auth_request_set $geoip_city $upstream_http_x_geoip_city;
auth_request_set $geoip_latitude $upstream_http_x_geoip_latitude;
auth_request_set $geoip_longitude $upstream_http_x_geoip_longitude;
auth_request_set $geoip_continent $upstream_http_x_geoip_continent;
auth_request_set $geoip_timezone $upstream_http_x_geoip_timezone;
auth_request_set $geoip_asn $upstream_http_x_geoip_asn;
auth_request_set $geoip_asnorganization $upstream_http_x_geoip_asnorganization;
if ($geoip_country != 'US') {
return 403;
}
proxy_pass http://my-backend;
}
location @denied {
return 403;
}
}
使用上述配置,访问日志会正确记录允许请求的GeoIP变量。当我提出绕过访问控制逻辑的请求时,即以下部分
if ($geoip_country != 'US') {
return 403;
}
我已经确认GeoIP服务通过设置调试端点正确地返回了预期的头。
然而,当我取消注释这一部分时,由于GeoIP变量总是被视为空,请求被阻止(返回403)。在日志中,我可以看到未填充的,显示为“-”。
[IP_ADDRESS] | - | [2024-04-04T07:55:53+00:00] | "GET / HTTP/1.1" | 403 | 548 | "-" | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36" | "-" | "-" | "-" | "-" | "-" | "-" | "-" | "-" | "-" | "-"
我正在寻找如何确保GeoIP变量填充在所有请求的访问日志中的见解或解决方案,无论这些请求是被允许还是被阻止。由于nginx-GeoIP模块的复杂性和我的设置的特定需求,我不喜欢使用它。
此外,这是我的日志配置:
log_format with_geoip '$remote_addr | $remote_user | \[$time_iso8601\] | "$request" | ' '$status | $body_bytes_sent | "$http_referer" | ' '"$http_user_agent" | "$http_x_forwarded_for" | ' '"$geoip_country" | "$geoip_stateprov" | "$geoip_city" | ' '"$geoip_latitude" | "$geoip_longitude" | "$geoip_continent" | ' '"$geoip_timezone" | "$geoip_asn" | "$geoip_asnorganization"';
由于我的应用程序有一个单独的nginx,这个nginx路由到这个应用程序,所以我可以通过将geoap头传递给这个内部nginx并更改内部nginxs配置来按区域拒绝allow请求。
但我需要一个更干净的解决方案,我想把这两个nginx的问题分开。内部仅用于路由,外部仅用于访问管理&ssl等。
如有任何建议或建议,我们将不胜感激!