2026年11月12日

2026年11月12日

จำกัดการเข้าถึงตามประเทศด้วย Nginx GeoIP2 และ GeoLite2

もくじ

บทความนี้เป็นฉบับปรับให้เหมาะกับท้องถิ่นจากต้นฉบับภาษาญี่ปุ่น อ่านต้นฉบับภาษาญี่ปุ่น

การจำกัดการเข้าถึงตามประเทศบน Nginx ในขั้นตอนปัจจุบัน (ณ พฤศจิกายน 2026) ทำได้โดยใช้โมดูล GeoIP2 (ngx_http_geoip2_module) ร่วมกับฐานข้อมูล GeoLite2 ของ MaxMind แล้วเก็บรหัสประเทศลงตัวแปรด้วยบล็อก geoip2 จากนั้นใช้ map ตัดสินว่าจะอนุญาตหรือปฏิเสธ ส่วนวิธีเก่าในบทความรุ่นก่อนที่สั่ง wget ไฟล์ .dat ของ GeoLite นั้นใช้ไม่ได้แล้ว เพราะยุติการแจกจ่ายข้อมูลรูปแบบดังกล่าวไปแล้ว

สรุปประเด็นสำคัญไว้ก่อน

  • โมดูลเก่า ngx_http_geoip_module (GeoIP Legacy) ใช้เริ่มต้นใหม่ไม่ได้ เพราะ MaxMind เลิกแจกจ่ายข้อมูลรูปแบบเก่าแล้ว ให้ย้ายไปใช้ GeoIP2 (รูปแบบ .mmdb)
  • GeoLite2 ใช้ฟรี แต่ต้องสมัครบัญชี MaxMind และมี License Key โดยดาวน์โหลดและอัปเดตผ่าน geoipupdate
  • ฝั่ง Nginx ให้สร้างตัวแปรอย่าง $geoip2_country_code ด้วยบล็อก geoip2 ใช้ map กำหนดค่า 0 / 1 ที่เทียบเท่า allow / deny แล้วสั่ง return 403 ใน location
  • หากเว็บไซต์อยู่หลัง CDN เช่น Cloudflare ต้องกู้คืน IP จริงของผู้เข้าชมด้วย real_ip_header ก่อน ไม่เช่นนั้นทุกคำขอจะถูกตัดสินเป็นประเทศของ CDN
  • การจำกัดตามประเทศเป็นเพียงมาตรการเสริมเพื่อลดการโจมตี และหลบเลี่ยงได้ด้วย VPN หรือตัวกลาง จึงควรใช้เฉพาะหน้าล็อกอินและหน้าผู้ดูแล ไม่ใช่ทั้งหน้าสาธารณะ
ลำดับการตั้งค่า Nginx GeoIP2: สมัคร MaxMind, ดึงฐานข้อมูลด้วย geoipupdate, โหลดโมดูล, ตัดสินด้วย geoip2 และ map, จำกัดด้วย location

ความต่างระหว่าง geoip แบบเก่ากับ GeoIP2

หัวข้อ ngx_http_geoip_module (เก่า) ngx_http_geoip2_module (GeoIP2)
รูปแบบข้อมูล GeoIP Legacy (.dat) GeoIP2 (.mmdb)
การแจกจ่ายข้อมูลฟรี สิ้นสุดแล้ว (ยุติการแจกจ่ายในปี 2019) GeoLite2 (ต้องสมัครบัญชีและมี License Key)
ไลบรารีที่ต้องใช้ libGeoIP libmaxminddb
การติดตั้งโมดูล มากับ Nginx มาตรฐาน (--with-http_geoip_module) โมดูลของบุคคลที่สาม leev/ngx_http_geoip2_module ส่วน Debian / Ubuntu มีแพ็กเกจให้
ตัวแปร กำหนดตายตัว เช่น $geoip_country_code ตั้งชื่อเองในบล็อก geoip2

หากการตั้งค่าเดิมยังใช้ geoip_country อยู่ ฐานข้อมูลจะไม่ได้รับการอัปเดตแล้ว ผลการตัดสินจึงล้าสมัย ควรถือโอกาสนี้ย้ายไปใช้ GeoIP2

ขั้นตอนที่ 1: สมัคร MaxMind และสร้าง License Key

  1. สร้างบัญชีฟรีจากหน้า GeoLite2 ของ MaxMind
  2. หลังล็อกอิน ให้ออก License Key ในหน้าจัดการบัญชี (คีย์จะแสดงเฉพาะตอนออกเท่านั้น จึงต้องจดเก็บไว้)
  3. ฐานข้อมูลที่ใช้ ถ้าต้องการแค่ระดับประเทศให้ใช้ GeoLite2-Country ถ้าต้องการถึงระดับเมืองให้ใช้ GeoLite2-City สำหรับการจำกัดตามประเทศ Country ก็เพียงพอแล้ว

เงื่อนไขการใช้งาน (GeoLite2 End User License Agreement) มีข้อกำหนดเกี่ยวกับการแจกจ่ายต่อและการแสดงข้อมูล หากใช้ตัดสินบนเซิร์ฟเวอร์ภายในองค์กรก็ถือว่าอยู่ในขอบเขตปกติ แต่ควรอ่านเงื่อนไขอีกครั้งตอนสมัคร

ขั้นตอนที่ 2: ดึงและอัปเดตฐานข้อมูลด้วย geoipupdate

GeoLite2 ได้รับการอัปเดตเป็นระยะ จึงไม่ควรดาวน์โหลดด้วยมือ แต่ให้ใช้ geoipupdate (เอกสารของ geoipupdate)

# Debian / Ubuntu
sudo apt install geoipupdate

# ตระกูล RHEL (AlmaLinux / Rocky Linux) ติดตั้งจาก EPEL
sudo dnf install geoipupdate

ระบุ Account ID และ License Key ในไฟล์ตั้งค่า /etc/GeoIP.conf

AccountID 123456
LicenseKey คีย์ที่ออกให้
EditionIDs GeoLite2-Country
# ที่เก็บไฟล์ใช้ค่าเริ่มต้นของแพ็กเกจ (Debian / Ubuntu คือ /var/lib/GeoIP ส่วนดิสโทรอื่นมักเป็น /usr/share/GeoIP)
# หากต้องการเปลี่ยน ให้ระบุ DatabaseDirectory /var/lib/GeoIP
sudo geoipupdate -v
ls -l /var/lib/GeoIP/   # หากมี GeoLite2-Country.mmdb แสดงว่าสำเร็จ

แพ็กเกจ geoipupdate ที่ติดตั้งผ่านตัวจัดการแพ็กเกจมักตั้งให้รันเป็นระยะด้วย systemd timer หรือ cron อยู่แล้ว (ตรวจสอบได้ด้วย systemctl list-timers | grep geoip) หากไม่มี ให้เพิ่ม cron ที่รันสัปดาห์ละครั้งโดยประมาณ

ขั้นตอนที่ 3: ติดตั้งโมดูล GeoIP2 ให้ Nginx

Debian / Ubuntu (Nginx จาก apt)

sudo apt install libnginx-mod-http-geoip2
ls /etc/nginx/modules-enabled/   # จะมีไฟล์ 50-mod-http-geoip2.conf วางอยู่
nginx -t

Nginx จากแพ็กเกจของ nginx.org หรือที่คอมไพล์จากซอร์ส

ติดตั้ง libmaxminddb ก่อน แล้วคอมไพล์ dynamic module จากซอร์สของ Nginx เวอร์ชันเดียวกับที่รันอยู่

sudo apt install libmaxminddb-dev   # ตระกูล RHEL ใช้ libmaxminddb-devel
cd /usr/local/src
git clone https://github.com/leev/ngx_http_geoip2_module
curl -LO https://nginx.org/download/nginx-1.26.3.tar.gz   # ให้ตรงกับเวอร์ชันจาก nginx -v
tar xzf nginx-1.26.3.tar.gz && cd nginx-1.26.3
./configure --with-compat --add-dynamic-module=../ngx_http_geoip2_module
make modules
sudo cp objs/ngx_http_geoip2_module.so /etc/nginx/modules/

โหลดโมดูลที่ส่วนบนสุดของ nginx.conf (หากใช้แพ็กเกจของดิสโทร ระบบจะวางให้โดยอัตโนมัติ)

load_module modules/ngx_http_geoip2_module.so;

ขั้นตอนที่ 4: เก็บรหัสประเทศลงตัวแปรและกำหนดการอนุญาต/ปฏิเสธ

เขียนในบล็อก http โดยเก็บรหัสประเทศลงตัวแปรด้วยบล็อก geoip2 แล้วใช้ map กำหนดให้ประเทศที่อนุญาตเป็น 1 และประเทศอื่นเป็น 0

http {
    geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 60m;
        $geoip2_country_code country iso_code;
    }

    # ประเทศที่อนุญาตให้เข้าหน้าผู้ดูแล (รหัส 2 ตัวอักษรตาม ISO 3166-1)
    map $geoip2_country_code $admin_allowed {
        default 0;
        JP      1;
        ""      1;   # กรณีตัดสินไม่ได้ (เช่น IP ส่วนตัว) ให้อนุญาต หากต้องการปฏิเสธให้ใช้ 0
    }
}

auto_reload คือช่วงเวลาที่ Nginx จะโหลดฐานข้อมูลที่ geoipupdate แทนที่ไว้ขึ้นมาใหม่โดยไม่ต้องรีสตาร์ต

ขั้นตอนที่ 5: จำกัดเฉพาะหน้าล็อกอินและหน้าผู้ดูแลของ WordPress

ตัวอย่างนี้ไม่จำกัดหน้าสาธารณะ แต่คัดกรองตามประเทศเฉพาะ wp-login.php และ /wp-admin/ เขียนในบล็อก server

server {
    # ... การตั้งค่าเดิม ...

    location = /wp-login.php {
        if ($admin_allowed = 0) { return 403; }
        include        fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass   unix:/run/php/php8.3-fpm.sock;
    }

    location ^~ /wp-admin/ {
        if ($admin_allowed = 0) { return 403; }
        # หากปลั๊กอินภายนอกใช้ admin-ajax.php ให้อนุญาตใน location แยกต่างหาก
        location ~ \.php$ {
            include        fastcgi_params;
            fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_pass   unix:/run/php/php8.3-fpm.sock;
        }
    }
}

การใช้ if คู่กับ return เป็นรูปแบบที่ Nginx จัดการได้อย่างปลอดภัย ส่วน /wp-admin/admin-ajax.php อาจถูกเรียกโดยฟีเจอร์ของหน้าสาธารณะ (เช่น ฟอร์มหรือการเลื่อนโหลดต่อเนื่อง) ขณะที่ผู้ใช้ยังไม่ได้ล็อกอิน จึงต้องตัดสินใจให้เหมาะกับฟีเจอร์ของเว็บไซต์ว่าจะยกเว้นออกจากการจำกัดหรือไม่

การนำไปใช้และตรวจสอบ:

sudo nginx -t && sudo systemctl reload nginx

# จากประเทศของตนเอง: จะได้ 200 หรือ 302
curl -sI https://example.com/wp-login.php | head -1
# ตรวจสอบการตัดสิน (ตัวอย่างการให้แสดงรหัสประเทศในล็อก)
# log_format geo '$remote_addr $geoip2_country_code "$request" $status';

หากต้องการดูว่าจากต่างประเทศเห็นเป็นอย่างไร ให้เข้า wp-login.php ผ่าน VPN ที่มีจุดเชื่อมต่อในต่างประเทศ หรือบริการเฝ้าระวังจากนอกประเทศ แล้วตรวจว่าได้ 403

กรณีใช้ CDN (เช่น Cloudflare)

เมื่อผ่าน CDN ค่า $remote_addr จะเป็น IP ของ CDN ทำให้ทุกคนถูกตัดสินเป็นประเทศของ CDN จึงต้องกู้คืน IP จริงของผู้เข้าชมด้วย ngx_http_realip_module ก่อน (โมดูล realip)

# ตัวอย่างสำหรับ Cloudflare ให้อัปเดตรายการ IP จาก IP Ranges ทางการของ Cloudflare เป็นระยะ
set_real_ip_from 173.245.48.0/20;
# ... ระบุช่วง IP ของ Cloudflare ให้ครบทั้งหมด ...
real_ip_header   CF-Connecting-IP;

โดยค่าเริ่มต้น geoip2 จะดู $remote_addr จึงตัดสินจาก IP จริงหลังจาก realip แทนที่ค่าแล้ว นอกจากนี้ Cloudflare เองก็มีการควบคุมการเข้าถึงตามประเทศ (WAF custom rules) หากใช้ Cloudflare อยู่แล้ว การจำกัดที่ฝั่ง Cloudflare จะตั้งค่าง่ายกว่าทำบน Nginx ดูเพิ่มเติมที่ การตั้งค่า Cloudflare กับ WordPress

ข้อจำกัดของการจำกัดตามประเทศ

  • การตัดสินด้วย GeoIP เป็นการประมาณจากข้อมูลที่ลงทะเบียนไว้ของ IP address และหลบเลี่ยงได้ด้วย VPN พร็อกซี หรือการส่งต่อผ่านคลาวด์ในต่างประเทศ
  • บนเครือข่ายมือถือหรือเครือข่ายองค์กร อาจถูกตัดสินเป็นประเทศอื่นที่ไม่ตรงกับที่ตั้งจริง และอาจเกิดปัญหาในการใช้งาน เช่น ผู้ดูแลที่เดินทางไปต่างประเทศถูกบล็อก
  • ดังนั้นควรใช้การจำกัดตามประเทศเป็นมาตรการเสริมเพื่อลดการเดารหัสผ่านแบบ brute force ร่วมกับการยืนยันตัวตนสองขั้นตอน การจำกัดจำนวนครั้งที่ล็อกอิน และการป้องกัน wp-admin ด้วย Basic Authentication

คำถามที่พบบ่อย

โมดูล geoip กับ geoip2 ของ Nginx ต่างกันอย่างไร

โมดูล geoip แบบเก่าอ่านข้อมูลรูปแบบ GeoIP Legacy (.dat) แต่ MaxMind เลิกแจกจ่ายรูปแบบนี้แล้ว ส่วนโมดูล geoip2 (ngx_http_geoip2_module) อ่านรูปแบบ .mmdb ปัจจุบันและใช้ข้อมูลฟรีของ GeoLite2 ได้ การตั้งค่าใหม่ให้ใช้ geoip2

GeoLite2 ใช้ฟรีหรือไม่ ต้องสมัครหรือเปล่า

ใช้ฟรี แต่ต้องสมัครบัญชี MaxMind และออก License Key ส่วนการดาวน์โหลดและอัปเดตเป็นระยะทำผ่าน geoipupdate วิธีเก่าที่ดาวน์โหลดตรงโดยไม่ใช้คีย์ใช้ไม่ได้แล้ว

จำกัดตามประเทศแล้วจะป้องกันการล็อกอินที่ไม่ชอบมาพากลของ WordPress ได้หรือไม่

ช่วยลดจำนวนการเดารหัสผ่านได้ แต่หลบเลี่ยงได้ด้วย VPN หรือการส่งต่อผ่านเซิร์ฟเวอร์ต่างประเทศ จึงไม่อาจบอกได้ว่าป้องกันได้ ควรใช้ร่วมกับการจำกัดจำนวนครั้งที่ล็อกอิน การยืนยันตัวตนสองขั้นตอน และ Basic Authentication

ใช้ Cloudflare แล้วทุกคนเป็นประเทศเดียวกันหมด

เพราะเมื่อผ่าน CDN ต้นทางของการเชื่อมต่อจะเป็น IP ของ CDN ให้กู้คืน IP จริงด้วย set_real_ip_from และ real_ip_header CF-Connecting-IP ก่อนจึงค่อยตัดสิน นอกจากนี้ยังมีวิธีจำกัดตามประเทศด้วย WAF ของ Cloudflare

ใช้ GeoLite2-City แล้วจำกัดถึงระดับเมืองได้หรือไม่

ใส่รหัสเมืองหรือภูมิภาคลงตัวแปรได้ แต่ความแม่นยำระดับเมืองต่ำกว่าระดับประเทศ จึงมีโอกาสตัดสินผิดและบล็อกผู้ใช้ที่ถูกต้อง สำหรับการควบคุมการเข้าถึง การใช้แค่ระดับประเทศปลอดภัยกว่า

สรุป

  • การจำกัดตามประเทศบน Nginx ในปัจจุบันทำด้วย GeoIP2 (ngx_http_geoip2_module + GeoLite2 .mmdb) และอัปเดตข้อมูลด้วย geoipupdate
  • เก็บรหัสประเทศลงตัวแปรด้วย geoip2 กำหนดอนุญาต/ปฏิเสธด้วย map แล้วสั่ง return 403 ใน location ของ wp-login.php และ /wp-admin/
  • หากผ่าน CDN ให้กู้คืน IP จริงก่อน และใช้การจำกัดตามประเทศเป็นมาตรการเสริมร่วมกับการยืนยันตัวตนสองขั้นตอนเป็นต้น

บทความที่เกี่ยวข้อง

อ้างอิง: ngx_http_geoip2_module (GitHub), MaxMind GeoLite2 Free Geolocation Data, MaxMind – Updating Databases (geoipupdate), Nginx ngx_http_realip_module

ประวัติการปรับปรุง: 2026-11-09 ปรับปรุงทั้งบทความ (แทนที่ขั้นตอน GeoLite แบบเก่าที่ยุติการแจกจ่ายด้วยขั้นตอนของ GeoIP2 และ geoipupdate พร้อมเพิ่มตัวอย่างการจำกัดหน้าผู้ดูแลของ WordPress และข้อควรระวังเรื่อง CDN) บทความนี้ดำเนินการโดย WordPress Hakase (บริษัทไลท์เซนด์ จำกัด)

มีคำถามเกี่ยวกับ WordPress ไหม ผู้เผยแพร่เว็บไซต์นี้อยู่ที่ญี่ปุ่นและตอบเป็นภาษาญี่ปุ่น ติดต่อ (ภาษาญี่ปุ่น)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲