Hướng dẫn cài đặt chức năng phân luồng địa lý cho nginx dùng nginx geoip location. Nội dung bài viết sẽ bao gồm các thông tin liên quan đến nginx, geoip module và tài khoản maxmind. Mục đích là để thống kê theo khu vực, hoặc chặn theo khu vực.
Cập nhật GeoIP — Tài khoản MaxMind.
Cài đặt package geoip và các dependencies
# Arch Linux
sudo pacman -Sy geoip libmaxminddb geoipupdate
# Ubuntu
sudo add-apt-repository ppa:maxmind/ppa
sudo apt update
sudo apt install geoipupdate libmaxminddb0 libmaxminddb-dev mmdb-bin
Bạn cần tạo 1 tài khoản Maxmind để lấy gói databases. Tôi dùng gói Lite vì nó có ít thông tin nhưng miễn phí. Đăng ký tại: Đăng ký GeoLite2.
Sau khi đăng ký, bạn có thể generate license key mới trong Tài khoản MaxMind của bạn.
Sau đó mở file /etc/GeoIP.conf, Thay các thông tin YOUR_ACCOUNT_ID_HERE và YOUR_LICENSE_KEY_HERE:
sudo vi /etc/GeoIP.conf
# /etc/GeoIP.conf
# Replace YOUR_ACCOUNT_ID_HERE and YOUR_LICENSE_KEY_HERE with an active account
# ID and license key combination associated with your MaxMind account. These
# are available from https://www.maxmind.com/en/my_license_key.
AccountID YOUR_ACCOUNT_ID_HERE
LicenseKey YOUR_LICENSE_KEY_HERE
# Enter the edition IDs of the databases you would like to update.
# Multiple edition IDs are separated by spaces.
EditionIDs GeoLite2-ASN GeoLite2-City GeoLite2-Country
Bạn cũng có thể thay đổi thông tin EditionIDs, Sau đó lưu lại Sẽ trở thành như sau
# Please see https://dev.maxmind.com/geoip/geoipupdate/ for instructions
# on setting up geoipupdate, including information on how to download a
# pre-filled GeoIP.conf file.
# Replace YOUR_ACCOUNT_ID_HERE and YOUR_LICENSE_KEY_HERE with an active account
# ID and license key combination associated with your MaxMind account. These
# are available from https://www.maxmind.com/en/my_license_key.
AccountID 484914
LicenseKey fTTYsLsD6OCObTXa
# Enter the edition IDs of the databases you would like to update.
# Multiple edition IDs are separated by spaces.
EditionIDs GeoLite2-Country GeoLite2-City GeoLite2-ASN
Bạn sẽ cần thay đổi thông tin EditionIDs theo đúng như loại license của bạn. Ở đây mình chọn GeoLite2-Country GeoLite2-City GeoLite2-ASN để lấy các thông tin như: Quốc gia, thành phố và một phần thông tin của ISP (GeoLite2-ASN).
Sau đó, tiến hành cập nhật geoip database.
sudo geoipupdate
Tạo một cron để tự động cập nhật hàng ngày:
sudo crontab -e
# Run GeoIP database update all the thuesday at 02:00
0 2 * * 2 /usr/bin/geoipupdate
GeoIP2 Nginx dynamic module.
Bạn đã có database GeoIP2, giờ chỉ cần cài đặt GeoIP2 module cho Nginx (Không phải nginx plus nhé). Hãy clone github repository của module module.
git clone https://github.com/leev/ngx_http_geoip2_module.git
Bây giờ chúng ta sẽ compile nginx module. Bạn có thể tham khảo thêm tại đây
Đầu tiên kiểm tra phiên bản Nginx mà bạn đang sử dụng:
$ nginx -v
nginx version: nginx/VERSION
Download đúng phiên bản Nginx đang có. Ví dụ phiên bản hiện tại cua mình là 1.10.3
wget http://nginx.org/download/nginx-1.10.3.tar.gz
tar zxvf nginx-1.10.3.tar.gz
cd nginx-1.10.3
Cấu hình và tạo module
apt-get install libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev
./configure --with-compat --add-dynamic-module=../ngx_http_geoip2_module
make modules
Note 1: Các bạn lưu ý –with-compat chỉ sử dụng được với các phiên bản Nginx từ 1.11.5 trở lên thôi.
Sau khi hoàn tất, Copy module vào Nginx
mkdir -p /etc/nginx/modules
cp -vi objs/ngx_http_geoip2_module.so /etc/nginx/modules/
Enable module geoip2 trong nginx.conf
sudo vi /etc/nginx/nginx.conf
load_module modules/ngx_http_geoip2_module.so;
Kiểm trả cấu hình Nginx
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Issue 1: Nếu bạn gặp lỗi không load được module như sau:
nginx: [emerg] dlopen() "/usr/share/nginx/modules/ngx_http_geoip2_module.so" failed (/usr/share/nginx/modules/ngx_http_geoip2_module.so: cannot open shared object file: No such file or directory) in /etc/nginx/nginx.conf:5
nginx: configuration file /etc/nginx/nginx.conf test failed
Đơn giản bạn chỉ cần copy vào đúng thư mục mà nginx yêu cầu
sudo mkdir -p /usr/share/nginx/modules/
cd ~/nginx-1.10.3/
sudo cp -vi objs/ngx_http_geoip2_module.so /usr/share/nginx/modules/
Issue 2: Nếu bạn gặp lỗi không tương thích module như sau:
nginx: [emerg] module "/usr/share/nginx/modules/ngx_http_geoip2_module.so" is not binary compatible in /etc/nginx/nginx.conf:5
Thì bạn cần build module với các configure giống như Nginx. Trong quá trình này có thể sẽ yêu cầu cài thêm một số package:
sudo apt install libgd-dev libgeoip-dev libssl-dev libpcre++-dev libxslt1-dev
cd ~/nginx-1.10.3/
./configure --add-dynamic-module=../ngx_http_geoip2_module $(nginx -V)
make modules
sudo cp -vi objs/ngx_http_geoip2_module.so /usr/share/nginx/modules/
$(nginx -V) là lấy hết các args của Nginx, nếu bạn muốn điền trực tiếp thì nó sẽ có dạng
./configure --add-dynamic-module=../ngx_http_geoip2_module --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads
Issue 3: Nếu bị lỗi
/usr/bin/ld: objs/addon/ngx_http_geoip2_module/ngx_http_geoip2_module.o: relocation R_X86_64_PC32 against undefined symbol `ngx_http_core_module' can not be used when making a shared object; recompile with -fPIC
Hãy thử lại với -fPIC le –with-cc-opt=’-g -O2 -fPIC -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2′
./configure --add-dynamic-module=../ngx_http_geoip2_module --with-cc-opt='-g -O2 -fPIC -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads
Sau khi test ok hay khởi động lại Nginx
sudo systemctl restart nginx
Use Case 1: Giới hạn truy cập bằng GeoIP
Trong ví dụ này, chúng ta sẽ giới hạn truy cập đến server cho một số quốc giá bao gồm: Việt Nam và Singapore. Chinh sửa file /etc/nginx/nginx.conf:
load_module modules/ngx_http_geoip2_module.so;
[...]
http {
geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
$geoip2_data_country_iso_code country iso_code;
}
map $geoip2_data_country_iso_code $allowed_country {
default no;
VN yes; # Vietnam
SG yes; # Singapore
}
server {
# Block forbidden country
if ($allowed_country = no) {
return 444;
}
[...]
}
}
Sau đó bạn thử truy cập vào website từ 1 quốc gia khác, ví dụ US (Sử dụng VPN).
curl https://thich.dev curl: (92) HTTP/2 stream 0 was not closed cleanly: Unknown error code (err 1)
UseCase 2: Ghi nhận ISP nhà mạng vào nginx log
Các bạn có thể dùng GeoIP để ghi nhận lại thông tin các quốc gia, thành phố hay ISP của người dùng thông qua nginx log.
Mở /etc/nginx/nginx.conf và thêm nội dung sau:
http {
##
# Logging Settings
##
log_format main '$remote_addr - $remote_user [$time_local] "$geoip2_isp_name" "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format custom '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_x_forwarded_for" $request_id '
'$geoip2_data_country_name $geoip2_data_country_code '
'$geoip2_data_city_name [ISP:"$geoip2_isp_name"] ';
access_log /var/log/nginx/access.log custom;
error_log /var/log/nginx/error.log;
}
Kiểm tra thử kết quả trong log
"GET / HTTP/1.1" 200 6045 "https://thich.dev/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36" Vietnam VN Ho Chi Minh [ISP:"Viettel Group"]
Chúc các bạn thành công!
Nguồn:
https://medium.com/@maxime.durand.54/add-the-geoip2-module-to-nginx-f0b56e015763