Ubuntu 22.04 Nginx GeoIP 地理阻擋

Ubuntu 22.04 Nginx GeoIP Geographic Blocking

在現代網路安全架構中,基於地理位置的存取控制是一項重要的防禦機制。透過 GeoIP 技術,我們可以根據訪客的 IP 位址判斷其地理位置,進而實施國家或城市級別的存取限制。本文將詳細介紹如何在 Ubuntu 22.04 上配置 Nginx 與 GeoIP2 模組,實現精細的地理阻擋功能。

GeoIP 模組介紹

GeoIP 是一種將 IP 位址對應到地理位置的技術。Nginx 支援兩種 GeoIP 模組:

傳統 GeoIP 模組 (ngx_http_geoip_module)

這是 Nginx 內建的模組,使用 MaxMind 的舊版 GeoIP Legacy 資料庫格式(.dat 檔案)。然而,MaxMind 已於 2019 年停止更新 Legacy 資料庫,因此不建議在新專案中使用。

GeoIP2 模組 (ngx_http_geoip2_module)

這是第三方開發的模組,支援 MaxMind 的新版 GeoIP2 資料庫格式(.mmdb 檔案)。GeoIP2 提供更精確的地理資訊和更好的效能,是目前推薦的解決方案。

GeoIP2 的優勢:

  • 更精確的地理位置資料
  • 支援 IPv6
  • 更快的查詢速度
  • 持續更新的資料庫
  • 支援更多地理資訊欄位(城市、郵遞區號、時區等)

MaxMind GeoIP2 資料庫

MaxMind 提供兩種類型的 GeoIP2 資料庫:

GeoLite2(免費版)

  • GeoLite2-Country:國家級別的地理資訊
  • GeoLite2-City:城市級別的地理資訊
  • GeoLite2-ASN:自治系統編號資訊

GeoIP2(付費版)

提供更高的準確度和更頻繁的更新,適合商業應用。

註冊 MaxMind 帳號

要下載 GeoLite2 資料庫,首先需要註冊 MaxMind 帳號:

  1. 前往 MaxMind 官網
  2. 完成註冊流程
  3. 登入後,前往 AccountManage License Keys
  4. 點擊 Generate New License Key
  5. 記下產生的 License Key,稍後設定自動更新時會用到

ngx_http_geoip2_module 安裝

方法一:使用預編譯的 Nginx 套件

Ubuntu 22.04 可以透過第三方 PPA 安裝已編譯 GeoIP2 模組的 Nginx:

1
2
3
4
5
6
7
8
9
# 安裝必要的工具
sudo apt update
sudo apt install -y software-properties-common

# 新增 Nginx 官方 PPA(包含額外模組)
sudo add-apt-repository -y ppa:ondrej/nginx

# 安裝 Nginx 和 GeoIP2 模組
sudo apt install -y nginx libnginx-mod-http-geoip2

方法二:從原始碼編譯

如果需要更多控制權或使用自訂配置,可以從原始碼編譯:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 安裝編譯所需的依賴套件
sudo apt update
sudo apt install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev \
    libssl-dev libgd-dev libgeoip-dev libmaxminddb-dev git

# 下載 ngx_http_geoip2_module
cd /usr/local/src
sudo git clone https://github.com/leev/ngx_http_geoip2_module.git

# 下載 Nginx 原始碼(請根據需要調整版本號)
NGINX_VERSION="1.24.0"
sudo wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz
sudo tar -xzf nginx-${NGINX_VERSION}.tar.gz
cd nginx-${NGINX_VERSION}

# 查看現有 Nginx 的編譯參數(如果已安裝)
nginx -V

# 編譯 Nginx(加入 GeoIP2 模組)
sudo ./configure \
    --prefix=/etc/nginx \
    --sbin-path=/usr/sbin/nginx \
    --modules-path=/usr/lib64/nginx/modules \
    --conf-path=/etc/nginx/nginx.conf \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --pid-path=/var/run/nginx.pid \
    --lock-path=/var/run/nginx.lock \
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-http_realip_module \
    --with-http_gzip_static_module \
    --add-dynamic-module=/usr/local/src/ngx_http_geoip2_module

sudo make
sudo make install

安裝 libmaxminddb 函式庫

無論使用哪種安裝方式,都需要安裝 libmaxminddb:

1
sudo apt install -y libmaxminddb0 libmaxminddb-dev mmdb-bin

下載 GeoLite2 資料庫

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 建立資料庫目錄
sudo mkdir -p /usr/share/GeoIP

# 使用 wget 下載(需替換為您的 License Key)
LICENSE_KEY="YOUR_LICENSE_KEY"

# 下載國家資料庫
sudo wget -O /tmp/GeoLite2-Country.tar.gz \
    "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=${LICENSE_KEY}&suffix=tar.gz"

# 下載城市資料庫
sudo wget -O /tmp/GeoLite2-City.tar.gz \
    "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=${LICENSE_KEY}&suffix=tar.gz"

# 解壓縮並移動檔案
sudo tar -xzf /tmp/GeoLite2-Country.tar.gz -C /tmp
sudo tar -xzf /tmp/GeoLite2-City.tar.gz -C /tmp
sudo mv /tmp/GeoLite2-Country_*/GeoLite2-Country.mmdb /usr/share/GeoIP/
sudo mv /tmp/GeoLite2-City_*/GeoLite2-City.mmdb /usr/share/GeoIP/

# 設定適當的權限
sudo chmod 644 /usr/share/GeoIP/*.mmdb

驗證模組載入

確認 GeoIP2 模組已正確載入:

1
2
3
4
5
# 檢查 Nginx 模組
nginx -V 2>&1 | grep -o 'geoip2'

# 或者查看動態模組
ls -la /usr/lib/nginx/modules/ | grep geoip2

國家級存取控制

基本配置

在 Nginx 配置檔中設定國家級存取控制:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# /etc/nginx/nginx.conf

load_module modules/ngx_http_geoip2_module.so;

http {
    # 載入 GeoIP2 國家資料庫
    geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 60m;
        $geoip2_metadata_country_build metadata build_epoch;
        $geoip2_data_country_code country iso_code;
        $geoip2_data_country_name country names en;
    }

    # 定義允許的國家(使用 map 指令)
    map $geoip2_data_country_code $allowed_country {
        default no;
        TW yes;  # 台灣
        JP yes;  # 日本
        US yes;  # 美國
        SG yes;  # 新加坡
    }

    # 其他 http 區塊配置...
}

網站配置範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# /etc/nginx/sites-available/example.com

server {
    listen 80;
    listen [::]:80;
    server_name example.com;

    # 國家級存取控制
    if ($allowed_country = no) {
        return 403;
    }

    # 或者使用自訂錯誤頁面
    # error_page 403 /blocked.html;

    location / {
        root /var/www/html;
        index index.html;
    }

    # 記錄存取者的地理資訊
    access_log /var/log/nginx/access.log combined;
}

阻擋特定國家

如果您想阻擋特定國家而非允許特定國家:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 定義要阻擋的國家
map $geoip2_data_country_code $blocked_country {
    default no;
    CN yes;  # 中國
    RU yes;  # 俄羅斯
    KP yes;  # 北韓
}

server {
    listen 80;
    server_name example.com;

    if ($blocked_country = yes) {
        return 403;
    }

    # 其他配置...
}

自訂 403 錯誤頁面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
server {
    listen 80;
    server_name example.com;

    error_page 403 /403.html;

    location = /403.html {
        root /var/www/error;
        internal;
    }

    if ($allowed_country = no) {
        return 403;
    }

    # 其他配置...
}

建立自訂錯誤頁面:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
sudo mkdir -p /var/www/error
sudo tee /var/www/error/403.html << 'EOF'
<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>存取被拒絕</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f5f5f5;
        }
        .container {
            text-align: center;
            padding: 40px;
            background: white;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        h1 { color: #e74c3c; }
        p { color: #666; }
    </style>
</head>
<body>
    <div class="container">
        <h1>403 - 存取被拒絕</h1>
        <p>抱歉,您所在的地區無法存取本網站。</p>
        <p>Access Denied: Your region is not allowed to access this website.</p>
    </div>
</body>
</html>
EOF

城市級細粒度控制

配置城市資料庫

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# /etc/nginx/nginx.conf

http {
    # 載入城市資料庫
    geoip2 /usr/share/GeoIP/GeoLite2-City.mmdb {
        auto_reload 60m;
        $geoip2_data_city_name city names en;
        $geoip2_data_postal_code postal code;
        $geoip2_data_latitude location latitude;
        $geoip2_data_longitude location longitude;
        $geoip2_data_state_name subdivisions 0 names en;
        $geoip2_data_state_code subdivisions 0 iso_code;
        $geoip2_data_continent_code continent code;
        $geoip2_data_country_code country iso_code;
    }

    # 根據城市進行控制
    map $geoip2_data_city_name $allowed_city {
        default yes;
        "Beijing" no;
        "Shanghai" no;
        "Moscow" no;
    }

    # 其他配置...
}

結合國家和城市的複合規則

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 建立複合條件變數
map "$geoip2_data_country_code:$geoip2_data_state_code" $geo_access {
    default deny;
    "TW:~.*" allow;        # 允許台灣所有地區
    "JP:13" allow;         # 允許日本東京都
    "US:CA" allow;         # 允許美國加州
    "US:NY" allow;         # 允許美國紐約州
}

server {
    listen 80;
    server_name example.com;

    if ($geo_access = deny) {
        return 403;
    }

    # 其他配置...
}

根據地理位置進行內容導向

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 根據國家導向不同的後端伺服器
upstream backend_tw {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
}

upstream backend_default {
    server 10.0.2.10:8080;
    server 10.0.2.11:8080;
}

map $geoip2_data_country_code $backend_server {
    default backend_default;
    TW backend_tw;
    HK backend_tw;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://$backend_server;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-GeoIP-Country $geoip2_data_country_code;
        proxy_set_header X-GeoIP-City $geoip2_data_city_name;
    }
}

在日誌中記錄地理資訊

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 自訂日誌格式,包含地理資訊
log_format geoip '$remote_addr - $remote_user [$time_local] '
                 '"$request" $status $body_bytes_sent '
                 '"$http_referer" "$http_user_agent" '
                 'country=$geoip2_data_country_code '
                 'city="$geoip2_data_city_name" '
                 'state="$geoip2_data_state_name"';

server {
    listen 80;
    server_name example.com;

    access_log /var/log/nginx/access_geo.log geoip;

    # 其他配置...
}

自動資料庫更新

MaxMind 每週更新 GeoLite2 資料庫,因此建議設定自動更新機制。

安裝 geoipupdate 工具

1
2
3
4
# 下載最新版本的 geoipupdate
GEOIPUPDATE_VERSION="6.0.0"
wget https://github.com/maxmind/geoipupdate/releases/download/v${GEOIPUPDATE_VERSION}/geoipupdate_${GEOIPUPDATE_VERSION}_linux_amd64.deb
sudo dpkg -i geoipupdate_${GEOIPUPDATE_VERSION}_linux_amd64.deb

配置 geoipupdate

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
sudo tee /etc/GeoIP.conf << EOF
# GeoIP.conf - Configuration file for geoipupdate
# https://dev.maxmind.com/geoip/updating-databases

AccountID YOUR_ACCOUNT_ID
LicenseKey YOUR_LICENSE_KEY
EditionIDs GeoLite2-Country GeoLite2-City GeoLite2-ASN

# 資料庫存放目錄
DatabaseDirectory /usr/share/GeoIP

# 鎖定檔案位置
LockFile /tmp/geoipupdate.lock
EOF

# 設定適當的權限
sudo chmod 600 /etc/GeoIP.conf

測試更新

1
2
# 手動執行更新
sudo geoipupdate -v

設定 Cron 排程

1
2
# 編輯 root 的 crontab
sudo crontab -e

加入以下內容:

1
2
# 每週三和週六凌晨 3:00 更新 GeoIP 資料庫
0 3 * * 3,6 /usr/bin/geoipupdate -v >> /var/log/geoipupdate.log 2>&1 && /usr/sbin/nginx -s reload

使用 Systemd Timer(推薦)

建立 systemd service:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
sudo tee /etc/systemd/system/geoipupdate.service << 'EOF'
[Unit]
Description=GeoIP Database Updater
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/geoipupdate -v
ExecStartPost=/usr/sbin/nginx -s reload
User=root
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

建立 systemd timer:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
sudo tee /etc/systemd/system/geoipupdate.timer << 'EOF'
[Unit]
Description=Run GeoIP Database Updater weekly

[Timer]
OnCalendar=Wed,Sat 03:00:00
RandomizedDelaySec=3600
Persistent=true

[Install]
WantedBy=timers.target
EOF

啟用 timer:

1
2
3
4
5
6
sudo systemctl daemon-reload
sudo systemctl enable geoipupdate.timer
sudo systemctl start geoipupdate.timer

# 檢查 timer 狀態
sudo systemctl list-timers | grep geoip

與 fail2ban 整合

將 GeoIP 與 fail2ban 整合,可以實現更強大的安全防護。

安裝 fail2ban

1
sudo apt install -y fail2ban

建立 GeoIP 過濾器

1
2
3
4
5
6
7
sudo tee /etc/fail2ban/filter.d/nginx-geoip.conf << 'EOF'
[Definition]
# 匹配被 GeoIP 阻擋的請求(403 狀態碼)
failregex = ^<HOST> .* "(GET|POST|HEAD|PUT|DELETE|OPTIONS|PATCH).*" 403 .* country=(?!TW|JP|US|SG)

ignoreregex =
EOF

配置 fail2ban jail

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
sudo tee /etc/fail2ban/jail.d/nginx-geoip.conf << 'EOF'
[nginx-geoip]
enabled = true
port = http,https
filter = nginx-geoip
logpath = /var/log/nginx/access_geo.log
maxretry = 5
findtime = 300
bantime = 86400
action = iptables-multiport[name=nginx-geoip, port="http,https", protocol=tcp]
EOF

進階:動態更新阻擋清單

建立腳本,根據攻擊來源國家動態調整阻擋規則:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
sudo tee /usr/local/bin/geoip-analyzer.sh << 'EOF'
#!/bin/bash

# GeoIP 攻擊分析腳本
LOG_FILE="/var/log/nginx/access_geo.log"
THRESHOLD=1000
ALERT_EMAIL="admin@example.com"

# 分析過去 24 小時內的 403 錯誤
declare -A country_count

while IFS= read -r line; do
    if [[ $line =~ country=([A-Z]{2}) ]]; then
        country="${BASH_REMATCH[1]}"
        if [[ $line =~ "\" 403 " ]]; then
            ((country_count[$country]++))
        fi
    fi
done < <(grep "$(date -d '1 day ago' '+%d/%b/%Y')" "$LOG_FILE")

# 檢查是否有國家超過閾值
for country in "${!country_count[@]}"; do
    if [[ ${country_count[$country]} -gt $THRESHOLD ]]; then
        echo "警告: $country 有 ${country_count[$country]} 次被阻擋的請求" | \
            mail -s "GeoIP 警報: 大量來自 $country 的請求" "$ALERT_EMAIL"
    fi
done
EOF

sudo chmod +x /usr/local/bin/geoip-analyzer.sh

設定每日執行:

1
echo "0 6 * * * /usr/local/bin/geoip-analyzer.sh" | sudo tee -a /etc/crontab

fail2ban 與 GeoIP 複合規則

1
2
3
4
5
6
7
8
sudo tee /etc/fail2ban/filter.d/nginx-geoip-bruteforce.conf << 'EOF'
[Definition]
# 針對登入頁面的暴力破解,結合 GeoIP
failregex = ^<HOST> .* "POST /login.*" (401|403) .* country=(?!TW)

ignoreregex =
datepattern = %%d/%%b/%%Y:%%H:%%M:%%S %%z
EOF

效能考量與最佳實務

1. 資料庫載入優化

GeoIP2 模組會將資料庫載入記憶體,因此需要考慮記憶體使用:

1
2
3
4
5
# 使用 auto_reload 減少手動重載需求
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
    auto_reload 60m;  # 每 60 分鐘檢查資料庫更新
    $geoip2_data_country_code country iso_code;
}

2. 快取配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 使用 proxy_cache 減少重複查詢
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=geo_cache:10m inactive=60m;

server {
    location / {
        proxy_cache geo_cache;
        proxy_cache_key "$geoip2_data_country_code$request_uri";
        proxy_cache_valid 200 10m;
        proxy_pass http://backend;
    }
}

3. 使用 map 指令優化

map 指令在配置載入時只會評估一次,比在每個請求中使用 if 更有效率:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 推薦:使用 map
map $geoip2_data_country_code $geo_block {
    default 0;
    CN 1;
    RU 1;
}

server {
    if ($geo_block) {
        return 403;
    }
}

4. 處理 CDN 和反向代理

當網站使用 CDN 或位於反向代理後方時,需要正確取得真實 IP:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 設定信任的代理 IP 範圍
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from 103.21.244.0/22;   # Cloudflare
set_real_ip_from 103.22.200.0/22;   # Cloudflare
set_real_ip_from 103.31.4.0/22;     # Cloudflare
# ... 更多 Cloudflare IP 範圍

real_ip_header X-Forwarded-For;
real_ip_recursive on;

# GeoIP 將使用真實 IP 進行查詢
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
    $geoip2_data_country_code source=$remote_addr country iso_code;
}

5. 監控與日誌分析

建立監控腳本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
sudo tee /usr/local/bin/geoip-stats.sh << 'EOF'
#!/bin/bash

# GeoIP 統計分析腳本
LOG_FILE="/var/log/nginx/access_geo.log"

echo "=== GeoIP 存取統計 ==="
echo ""
echo "過去 24 小時各國家存取次數 (前 20 名):"
grep "$(date -d '1 day ago' '+%d/%b/%Y')" "$LOG_FILE" | \
    grep -oP 'country=\K[A-Z]{2}' | \
    sort | uniq -c | sort -rn | head -20

echo ""
echo "過去 24 小時被阻擋的請求 (前 10 名國家):"
grep "$(date -d '1 day ago' '+%d/%b/%Y')" "$LOG_FILE" | \
    grep '" 403 ' | \
    grep -oP 'country=\K[A-Z]{2}' | \
    sort | uniq -c | sort -rn | head -10
EOF

sudo chmod +x /usr/local/bin/geoip-stats.sh

6. 安全性最佳實務

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 完整的安全配置範例
http {
    # GeoIP2 配置
    geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 60m;
        $geoip2_data_country_code country iso_code;
    }

    # 允許的國家
    map $geoip2_data_country_code $allowed_country {
        default no;
        TW yes;
        JP yes;
        US yes;
        SG yes;
        HK yes;
    }

    # 速率限制
    limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;

    server {
        listen 80;
        listen 443 ssl http2;
        server_name example.com;

        # SSL 配置
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

        # 地理阻擋
        if ($allowed_country = no) {
            return 403;
        }

        # 一般請求速率限制
        limit_req zone=general burst=20 nodelay;

        location /login {
            # 登入頁面更嚴格的速率限制
            limit_req zone=login burst=5 nodelay;
            proxy_pass http://backend;
        }

        location / {
            proxy_pass http://backend;
        }
    }
}

7. 測試配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 檢查 Nginx 配置語法
sudo nginx -t

# 查看 GeoIP 模組是否正確載入
sudo nginx -V 2>&1 | grep geoip2

# 測試特定 IP 的地理位置
mmdblookup --file /usr/share/GeoIP/GeoLite2-Country.mmdb --ip 8.8.8.8

# 重新載入配置
sudo systemctl reload nginx

8. 故障排除

常見問題與解決方案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 問題:GeoIP 變數為空
# 解決:檢查資料庫路徑和權限
ls -la /usr/share/GeoIP/
sudo chmod 644 /usr/share/GeoIP/*.mmdb

# 問題:模組載入失敗
# 解決:確認模組路徑正確
ls -la /usr/lib/nginx/modules/ngx_http_geoip2_module.so

# 問題:某些 IP 無法正確識別
# 解決:更新資料庫
sudo geoipupdate -v

# 問題:記憶體使用過高
# 解決:只載入需要的資料庫欄位
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
    $geoip2_data_country_code country iso_code;
    # 只載入必要的欄位
}

總結

透過本文的介紹,您應該已經了解如何在 Ubuntu 22.04 上配置 Nginx GeoIP2 模組,實現基於地理位置的存取控制。主要重點包括:

  1. 選擇正確的模組:使用 ngx_http_geoip2_module 而非舊版 GeoIP 模組
  2. 資料庫管理:註冊 MaxMind 帳號並設定自動更新
  3. 靈活的規則配置:使用 map 指令實現國家級和城市級的存取控制
  4. 安全整合:結合 fail2ban 實現更全面的安全防護
  5. 效能優化:正確處理 CDN/代理環境,使用快取和監控

地理阻擋只是多層安全策略的一部分,建議搭配其他安全措施如 WAF、速率限制、SSL/TLS 等,建構完整的網站安全防護體系。

參考資源

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy