Access Control Lists (ACL) หรือรายการควบคุมการเข้าถึงเป็นเครื่องมือสำคัญในการจัดการและควบคุมสิทธิ์การเข้าถึง web server ใน Nginx ผ่านการระบุว่าใครสามารถเข้าถึงทรัพยากรใดได้บ้าง และใครไม่ได้รับอนุญาต การใช้ ACL อย่างถูกต้องช่วยเพิ่มระดับความปลอดภัย (security) ของ web application และป้องกันการเข้าถึงที่ไม่ได้รับอนุญาต
ในบทความนี้ เราจะศึกษาวิธีการกำหนด Access Control Lists ใน Nginx ตั้งแต่พื้นฐาน ได้แก่ การใช้ directive allow และ deny การควบคุมตามที่อยู่ IP subnet-based access control จนถึงเทคนิคขั้นสูง เช่น geo module map-based control การป้องกันพื้นที่ admin และการรวมกับ Basic Authentication
ACL คืออะไรใน Nginx
Access Control Lists (ACL) เป็นกลไกที่ใช้ในการกำหนดกฎการเข้าถึง (access rules) ของ web server โดยอนุญาต (allow) หรือปฏิเสธ (deny) การร้องขอ (request) จากที่อยู่ IP ที่ระบุ ACL ช่วยให้เราสามารถ:
- จำกัดการเข้าถึงพื้นที่ที่ไวต่อความปลอดภัย เช่น admin panel
- อนุญาตให้เฉพาะ IP address ที่เชื่อถือได้เข้าถึง
- ปิดกั้นการเข้าถึงจากประเทศหรือภูมิภาคที่ไม่ต้องการ
- ควบคุมการเข้าถึง API endpoints
- เพิ่มความปลอดภัยในชั้น network level
Allow และ Deny Directives
ใน Nginx เราใช้ directive allow และ deny เพื่อกำหนดกฎการเข้าถึง Nginx ประเมินกฎเหล่านี้จากบนลงล่าง (sequential order) และหยุดที่กฎแรกที่ตรงกัน
ตัวอย่างพื้นฐาน
server {
listen 80;
server_name example.com;
# อนุญาต IP 192.168.1.100
allow 192.168.1.100;
# ปฏิเสธ IP ทั้งหมดที่ไม่อยู่ในรายการ allow
deny all;
location / {
root /var/www/html;
index index.html;
}
}
การควบคุมการเข้าถึงตามที่อยู่ IP Address
การควบคุมตามที่อยู่ IP คือวิธีพื้นฐานที่สุดในการจัดการ ACL ในสถานการณ์จริง เราสามารถระบุ IP address เดี่ยวหรือหลาย IP ที่อนุญาตให้เข้าถึง
server {
listen 80;
server_name example.com;
location /admin {
# อนุญาตเฉพาะ IP ที่ระบุ
allow 192.168.1.100;
allow 192.168.1.101;
allow 10.0.0.50;
# ปฏิเสธ IP ที่เหลือทั้งหมด
deny all;
root /var/www/html;
index index.html;
}
}
ในตัวอย่างนี้ เฉพาะ IP 192.168.1.100, 192.168.1.101 และ 10.0.0.50 เท่านั้นที่สามารถเข้าถึง /admin path ส่วน IP อื่น ๆ จะได้รับ 403 Forbidden error
Subnet-Based Access Control
แทนที่จะระบุ IP แต่ละตัว เราสามารถใช้ CIDR notation เพื่อระบุ subnet ทั้งหมดได้ วิธีนี้มีประโยชน์เมื่อต้องการอนุญาตให้เข้าถึงจากเครือข่ายทั้งหมด
server {
listen 80;
server_name example.com;
location /api {
# อนุญาตเซ็บเน็ตทั้งหมด 192.168.1.0/24
allow 192.168.1.0/24;
# อนุญาต 10.0.0.0/8 network
allow 10.0.0.0/8;
# อนุญาต IPv6
allow 2001:db8::/32;
# ปฏิเสธอื่น ๆ
deny all;
proxy_pass http://backend;
}
}
CIDR notation ช่วยให้การกำหนดกฎ ACL มีความยืดหยุ่นและสะดวกขึ้น ตัวอย่างเช่น 192.168.1.0/24 แสดงเซ็บเน็ตที่มี IP ตั้งแต่ 192.168.1.1 ถึง 192.168.1.254
การรวมกฎ Allow/Deny
ในหลาย ๆ กรณี เราต้องการผสมผสาน allow และ deny rules เพื่อให้ได้ผลลัพธ์ที่ต้องการ เมื่อ Nginx ประเมินกฎ มันจะหยุดที่กฎแรกที่ตรงกับ request
server {
listen 80;
server_name example.com;
location /sensitive {
# ปฏิเสธ IP สีดำ (blacklist)
deny 192.168.1.200;
deny 192.168.1.201;
# อนุญาตเฉพาะเซ็บเน็ต
allow 192.168.0.0/16;
allow 10.0.0.0/8;
# ปฏิเสธส่วนที่เหลือ
deny all;
root /var/www/html;
}
}
Geo Module สำหรับ Advanced ACL
geo module เป็นเครื่องมือขั้นสูงที่ช่วยให้สามารถควบคุมการเข้าถึงตามตำแหน่งทางภูมิศาสตร์ โดยแม็พที่อยู่ IP กับตัวแปร geo ที่สามารถใช้ในกฎอื่น ๆ ได้
geo $country {
default ZZ;
192.168.1.0/24 US;
192.168.2.0/24 TH;
10.0.0.0/8 SG;
2001:db8::/32 JP;
}
server {
listen 80;
server_name example.com;
location /content {
# อนุญาตเฉพาะประเทศที่ระบุ
if ($country = TH) {
return 200;
}
if ($country = SG) {
return 200;
}
# ปฏิเสธอื่น ๆ
return 403;
}
}
geo module มีประโยชน์มากเมื่อต้องการจัดการการเข้าถึงตามภูมิศาสตร์ อย่างไรก็ตาม ต้องคำนึงว่าอาจต้องปรับปรุงฐานข้อมูล IP geolocation เป็นระยะ ๆ
Map-Based Access Control
Module map ช่วยให้สามารถสร้างตัวแปร conditionally โดยอิงจาก IP address หรือตัวแปร request อื่น ๆ วิธีนี้ให้ความยืดหยุ่นมากขึ้นในการจัดการ ACL ที่ซับซ้อน
map $remote_addr $access_level {
default blocked;
192.168.1.100 admin;
192.168.1.101 admin;
192.168.1.0/24 user;
10.0.0.0/8 user;
}
server {
listen 80;
server_name example.com;
location /admin {
if ($access_level != admin) {
return 403;
}
root /var/www/html;
}
location /public {
if ($access_level = blocked) {
return 403;
}
root /var/www/html;
}
}
การป้องกันพื้นที่ Admin
พื้นที่ admin เป็นเป้าหมายของการโจมตี (attack) บ่อยครั้ง ดังนั้นจึงจำเป็นต้องป้องกันให้มาก ๆ โดยการ restrict ACL ให้เข้าถึงจาก IP ที่เชื่อถือได้เท่านั้น
server {
listen 80;
server_name example.com;
# ป้องกัน WordPress admin
location /wp-admin/ {
# อนุญาตเฉพาะ office IP และ specific VPN
allow 203.150.200.100; # Office
allow 203.150.200.0/24; # Office network
# ปฏิเสธอื่น ๆ
deny all;
proxy_pass http://backend;
}
# ป้องกัน login page
location /wp-login.php {
allow 203.150.200.100;
allow 203.150.200.0/24;
deny all;
proxy_pass http://backend;
}
location / {
proxy_pass http://backend;
}
}
ควรรวมการ restrict IP กับการใช้ strong password, two-factor authentication และการเปลี่ยน default login URL เพื่อเพิ่มความปลอดภัยเพิ่มเติม
การรวม ACL กับ Basic Authentication
สำหรับความปลอดภัยที่มากขึ้น เราสามารถรวม IP-based ACL กับ HTTP Basic Authentication ได้ วิธีนี้เพิ่มชั้นป้องกันเพิ่มเติม
server {
listen 80;
server_name example.com;
location /api {
# IP whitelist check
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
# Basic authentication
auth_basic "Restricted API Access";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://backend;
}
}
สร้างไฟล์ .htpasswd ด้วยคำสั่ง:
htpasswd -c /etc/nginx/.htpasswd username
การบันทึก (Logging) Denied Requests
การติดตามว่า request ใดถูก deny ช่วยให้เราตรวจจับการโจมตีและปัญหาในการเข้าถึง ใน Nginx เราสามารถกำหนด custom log สำหรับ denied requests
server {
listen 80;
server_name example.com;
# Define custom log format
log_format acl_denied '$remote_addr - [$time_local] '
'"$request" $status '
'"$http_user_agent"';
location /admin {
# Log denied requests
access_log /var/log/nginx/denied.log acl_denied if=$status=403;
allow 192.168.1.100;
deny all;
root /var/www/html;
}
}
จากนั้นสามารถตรวจสอบไฟล์ log ด้วยคำสั่ง:
tail -f /var/log/nginx/denied.log
Best Practices สำหรับ ACL ใน Nginx
- ทำให้เล็ก (Principle of Least Privilege) — อนุญาตเฉพาะ IP/subnet ที่จำเป็นเท่านั้น ไม่ควร allow ทั้งหมดแล้ว deny บางตัว
- ใช้ CIDR notation — สำหรับหลาย IP ในเซ็บเน็ตเดียวกัน ใช้ CIDR เพื่อลดความซับซ้อน
- บันทึก denied requests — ตั้ง access log สำหรับ 403 responses เพื่อติดตามการโจมตี
- ทำให้เป็นมาตรฐาน (Standardize) — ใช้ format เดียวกันและ comments ชัดเจน ให้ง่ายต่อการบำรุงรักษา
- ทดสอบหลังการเปลี่ยนแปลง — เมื่อแก้ไข ACL rules ให้ test ให้แน่ใจว่า authorized users สามารถเข้าถึงได้
- รวมกับ other security layers — ACL เพียงอย่างเดียวไม่เพียงพอ ต้องรวมกับ firewall, WAF, และ authentication mechanisms อื่น ๆ
- ตรวจสอบ IPv4 และ IPv6 — อย่าลืมระบุ IPv6 rules หากใช้ IPv6
- มีแผน backup — เมื่อให้ access บาง IP ควรมี backup IP หรือ method อื่นในกรณีฉุกเฉิน
สรุป
Access Control Lists (ACL) ใน Nginx เป็นวิธีที่มีประสิทธิภาพในการควบคุมและป้องกันการเข้าถึง web resources จากระดับ network เราได้เรียนรู้การใช้ allow และ deny directives การควบคุมตามที่อยู่ IP subnet-based access control และเทคนิคขั้นสูง เช่น geo module map-based control
การจัดการ ACL อย่างถูกต้องตามหลัก principle of least privilege จะช่วยให้ web application มีความปลอดภัยมากขึ้น ลดความเสี่ยงจากการโจมตี (attack) และการเข้าถึงที่ไม่ได้รับอนุญาต อย่างไรก็ตาม ควรจำไว้ว่า ACL เป็นเพียงหนึ่งในหลาย ๆ ชั้นของการป้องกัน ต้องรวมกับเครื่องมือและวิธีการอื่น ๆ เพื่อให้ได้ระดับความปลอดภัยที่เพียงพอ
แนะนำบริการ DE
หากคุณต้องการใช้งาน Nginx ที่มี advanced configuration รวมถึง ACL ที่ซับซ้อน DE (Dot Enterprise) มอบบริการ Cloud VPS ที่ให้ความยืดหยุ่นในการตั้งค่า web server ตามความต้องการของคุณ
นอกจากนี้ บริการ Cloud Hosting ของเรายังรองรับการกำหนด ACL และการป้องกันความปลอดภัยในระดับ advanced พร้อมด้วยการสนับสนุน technical team ที่พร้อมช่วยเหลือ คุณสามารถติดต่อเราได้ที่ https://de.co.th เพื่อรับคำปรึกษาด้านการตั้งค่า infrastructure ที่เหมาะสมกับธุรกิจของคุณ

