- วัตถุประสงค์
- 1. IP Allowlisting คืออะไร
- 2. เหมาะกับระบบแบบใด
- 3. Architecture ของ Workshop
- 4. เตรียมเครื่องมือ
- 5. สร้าง REST API ตัวอย่าง
- 6. ติดตั้ง Nginx
- 7. ตั้งค่า Nginx เป็น Reverse Proxy
- 8. จำกัด API ด้วย IP Address
- 9. อนุญาตหลาย IP
- 10. อนุญาตเป็น Network ด้วย CIDR
- 11. อนุญาต localhost
- 12. ตรวจสอบ Configuration
- 13. ทดสอบ API
- 14. ทดสอบจาก IP ที่ไม่ได้รับอนุญาต
- 15. Public API และ Private API
- 16. ใช้กับ Docker
- 17. IP Allowlisting ที่ Application Layer
- 18. ปัญหาเมื่ออยู่หลัง Reverse Proxy
- 19. X-Forwarded-For
- 20. Trusted Proxy
- 21. Static IP สำคัญอย่างไร
- 22. Dynamic IP
- 23. Firewall Layer
- 24. API Gateway
- 25. ตัวอย่าง Kong API Gateway
- 26. Defense in Depth
- 27. ตัวอย่าง Production Configuration
- 28. Workshop Challenge
- 29. Checklist ก่อนนำขึ้น Production
- 30. สรุป
การเปิด API บนอินเทอร์เน็ตโดยตรงทำให้ endpoint สามารถถูกเรียกจากแหล่งต่าง ๆ ได้ หาก API เป็นระบบภายในองค์กร, Admin API, Partner API หรือ API ที่ต้องการให้เฉพาะ Server บางเครื่องเข้าถึง การใช้ IP Allowlisting เป็นอีกชั้นหนึ่งของการควบคุมการเข้าถึงที่มีประโยชน์มาก
Workshop นี้จะทดลองสร้าง API และใช้ Nginx เป็น Reverse Proxy เพื่ออนุญาตเฉพาะ IP Address ที่กำหนดเท่านั้น
#วัตถุประสงค์
หลังจบ Workshop ผู้อ่านจะสามารถ
- อธิบายหลักการของ IP Allowlisting ได้
- จำกัดการเข้าถึง API ด้วย IP Address ได้
- ตั้งค่า Nginx ด้วย
allowและdeny - อนุญาตหลาย IP และเครือข่ายแบบ CIDR ได้
- ทดสอบ API ด้วย
curl - เข้าใจปัญหา Client IP เมื่อระบบอยู่หลัง Proxy หรือ Load Balancer
- ประยุกต์ใช้ร่วมกับ Docker และระบบ Production ได้
#1. IP Allowlisting คืออะไร
IP Allowlisting คือการกำหนดรายการ IP Address ที่ได้รับอนุญาตให้เข้าถึง Resource เช่น API
ตัวอย่างเช่น เรามี API
https://api.example.com/api/private
และต้องการให้เฉพาะเครื่องที่มี Public IP
203.0.113.10
เรียก API ได้
แนวคิดจะเป็นดังนี้
203.0.113.10
|
| Allowed
v
+-------------+
| Nginx |
| IP Allowlist|
+-------------+
|
v
+-------------+
| API |
+-------------+
ส่วน Client อื่น
198.51.100.20
|
| Denied
v
+-------------+
| Nginx |
+-------------+
|
X
403 Forbidden
IP ที่ใช้ในตัวอย่างเป็น IP สำหรับเอกสาร ควรเปลี่ยนเป็น Public IP จริงของระบบที่ต้องการอนุญาต
#2. เหมาะกับระบบแบบใด
IP Allowlisting เหมาะกับระบบ เช่น
- Internal API
- Partner API
- B2B API
- Admin API
- Webhook Endpoint ที่ทราบ Source IP
- Database Administration API
- Monitoring API
- CI/CD Server
- API ที่เรียกจาก Server-to-Server
ตัวอย่างเช่น
Partner Server
|
| Static Public IP
v
API Gateway
|
v
Private API
#3. Architecture ของ Workshop
ใน Workshop นี้จะใช้ Architecture ดังนี้
Client
|
| HTTP Request
v
+------------------+
| Nginx |
| Reverse Proxy |
| IP Allowlisting |
+------------------+
|
v
+------------------+
| REST API |
| Port 3000 |
+------------------+
Nginx จะทำหน้าที่
- รับ Request
- ตรวจสอบ Source IP
- อนุญาตเฉพาะ IP ที่กำหนด
- Forward Request ไปยัง API
#4. เตรียมเครื่องมือ
ตัวอย่างนี้สามารถทำบน Ubuntu Server หรือ Linux Server ที่มี
- Node.js
- npm
- Nginx
- curl
ตรวจสอบ Node.js
node --version
ตรวจสอบ npm
npm --version
ตรวจสอบ Nginx
nginx -v
#5. สร้าง REST API ตัวอย่าง
สร้าง Project
mkdir ip-allowlist-api
cd ip-allowlist-api
สร้าง package.json
npm init -y
ติดตั้ง Express
npm install express
สร้างไฟล์
server.js
ใส่โค้ด
const express = require("express");
const app = express();
app.get("/api/public", (req, res) => {
res.json({
message: "Public API"
});
});
app.get("/api/private", (req, res) => {
res.json({
message: "Private API",
status: "Access granted"
});
});
app.listen(3000, "127.0.0.1", () => {
console.log("API running on http://127.0.0.1:3000");
});
รัน API
node server.js
ทดสอบ
curl http://127.0.0.1:3000/api/public
ผลลัพธ์
{
"message": "Public API"
}
ทดสอบ Private API
curl http://127.0.0.1:3000/api/private
#6. ติดตั้ง Nginx
Ubuntu/Debian
sudo apt update
sudo apt install nginx -y
ตรวจสอบสถานะ
sudo systemctl status nginx
เปิดใช้งาน
sudo systemctl enable --now nginx
#7. ตั้งค่า Nginx เป็น Reverse Proxy
สร้างไฟล์
sudo nano /etc/nginx/sites-available/api
กำหนดค่า
server {
listen 80;
server_name api.example.com;
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
เปิด Site
sudo ln -s /etc/nginx/sites-available/api /etc/nginx/sites-enabled/api
ตรวจสอบ Configuration
sudo nginx -t
Reload
sudo systemctl reload nginx
#8. จำกัด API ด้วย IP Address
สมมติว่าอนุญาต IP
203.0.113.10
แก้ Configuration
location /api/private {
allow 203.0.113.10;
deny all;
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
คำสั่ง
allow 203.0.113.10;
หมายถึงอนุญาต IP ดังกล่าว
ส่วน
deny all;
หมายถึงปฏิเสธ IP อื่นทั้งหมด
#9. อนุญาตหลาย IP
ตัวอย่าง
location /api/private {
allow 203.0.113.10;
allow 203.0.113.20;
allow 203.0.113.30;
deny all;
proxy_pass http://127.0.0.1:3000;
}
Architecture
203.0.113.10 ----+
|
203.0.113.20 ----+----> Nginx ----> API
|
203.0.113.30 ----+
IP อื่น
198.51.100.20
|
X
403 Forbidden
#10. อนุญาตเป็น Network ด้วย CIDR
ถ้าต้องการอนุญาตทั้ง Network
203.0.113.0/24
สามารถกำหนด
allow 203.0.113.0/24;
deny all;
ตัวอย่าง
location /api/private {
allow 203.0.113.0/24;
deny all;
proxy_pass http://127.0.0.1:3000;
}
ดังนั้น IP ในช่วง Network ดังกล่าวจะได้รับอนุญาตตาม CIDR
#11. อนุญาต localhost
สำหรับ Development อาจอนุญาต
allow 127.0.0.1;
allow ::1;
ตัวอย่าง
location /api/private {
allow 127.0.0.1;
allow ::1;
allow 203.0.113.10;
deny all;
proxy_pass http://127.0.0.1:3000;
}
#12. ตรวจสอบ Configuration
ทุกครั้งที่แก้ Nginx ควรตรวจสอบ
sudo nginx -t
หากถูกต้องจะพบข้อความลักษณะ
syntax is ok
test is successful
จากนั้น
sudo systemctl reload nginx
#13. ทดสอบ API
จาก Client ที่ได้รับอนุญาต
curl -i http://api.example.com/api/private
ควรได้
HTTP/1.1 200 OK
พร้อม Response เช่น
{
"message": "Private API",
"status": "Access granted"
}
#14. ทดสอบจาก IP ที่ไม่ได้รับอนุญาต
curl -i http://api.example.com/api/private
จะได้
HTTP/1.1 403 Forbidden
แสดงว่า Nginx ปฏิเสธ Request ก่อนที่จะส่งไปยัง Application
#15. Public API และ Private API
เราสามารถกำหนดให้บาง API เป็น Public
location /api/public {
proxy_pass http://127.0.0.1:3000;
}
และบาง API เป็น Private
location /api/private {
allow 203.0.113.10;
deny all;
proxy_pass http://127.0.0.1:3000;
}
Architecture
+--> /api/public
| Everyone
Internet --> Nginx -+
|
+--> /api/private
|
+--> IP Allowlist
#16. ใช้กับ Docker
สมมติ API ทำงานใน Container ชื่อ
api
และใช้ Docker Compose
services:
api:
build: .
expose:
- "3000"
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- api
ไฟล์
nginx.conf
ตัวอย่าง
server {
listen 80;
location /api/public {
proxy_pass http://api:3000;
}
location /api/private {
allow 203.0.113.10;
deny all;
proxy_pass http://api:3000;
}
}
รัน
docker compose up -d
ตรวจสอบ
docker compose ps
#17. IP Allowlisting ที่ Application Layer
นอกจาก Nginx แล้ว สามารถตรวจสอบ IP ใน Application ได้เช่นกัน
ตัวอย่าง Express Middleware
const allowedIps = new Set([
"203.0.113.10",
"203.0.113.20"
]);
function ipAllowlist(req, res, next) {
const clientIp = req.ip;
if (!allowedIps.has(clientIp)) {
return res.status(403).json({
error: "Forbidden",
message: "IP address is not allowed"
});
}
next();
}
นำไปใช้
app.get(
"/api/admin",
ipAllowlist,
(req, res) => {
res.json({
message: "Admin API"
});
}
);
#18. ปัญหาเมื่ออยู่หลัง Reverse Proxy
ระบบ Production มักมี Architecture
Client
|
v
Cloudflare
|
v
Load Balancer
|
v
Nginx
|
v
Application
Application อาจเห็น IP ของ Proxy แทน Client
ตัวอย่าง
10.0.0.5
แทนที่จะเห็น
203.0.113.10
จึงต้องจัดการ Trusted Proxy อย่างถูกต้อง
#19. X-Forwarded-For
Proxy มักส่ง Header
X-Forwarded-For
ตัวอย่าง
X-Forwarded-For: 203.0.113.10
Nginx สามารถส่งต่อด้วย
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
และ
proxy_set_header X-Real-IP $remote_addr;
แต่ไม่ควรเชื่อ X-Forwarded-For จาก Client ทุกเครื่องโดยตรง เพราะ Header สามารถถูกปลอมได้
#20. Trusted Proxy
ควรกำหนดว่า Proxy ใดเป็น Trusted Proxy เท่านั้น
ตัวอย่าง Architecture
Internet
|
v
Trusted Load Balancer
|
v
Nginx
|
v
API
จากนั้น Application จึงใช้ Client IP ที่ได้รับผ่าน Trusted Proxy
#21. Static IP สำคัญอย่างไร
IP Allowlisting เหมาะกับ Client ที่มี
Static Public IP
ตัวอย่าง
Office Network
|
v
NAT Gateway
203.0.113.10
|
v
Internet
|
v
Private API
ทุกเครื่องในองค์กรออก Internet ผ่าน Public IP เดียวกัน ทำให้สามารถ Allowlist IP ของ NAT Gateway ได้
#22. Dynamic IP
ถ้า Client ใช้
- Home Internet
- Mobile Network
- Dynamic Public IP
Public IP อาจเปลี่ยนได้
ทำให้
IP Allowlist
ไม่เหมาะสมหรือจำเป็นต้องแก้ Configuration บ่อย
ในกรณีดังกล่าวควรพิจารณา
- VPN
- OAuth 2.0
- JWT
- API Key
- mTLS
- Zero Trust Network Access
#23. Firewall Layer
ถ้าระบบมี Dedicated API Server สามารถจำกัด IP ที่ Firewall ได้ด้วย
แนวคิด
Internet
|
v
Firewall
|
| allow 203.0.113.10
|
v
Nginx
|
v
API
ข้อดีคือ Request ที่ไม่ได้รับอนุญาตถูกบล็อกก่อนถึง Web Server
#24. API Gateway
ระบบ Microservices อาจใช้
Client
|
v
API Gateway
|
+-- IP Restriction
+-- Authentication
+-- Rate Limiting
+-- Logging
|
v
Microservices
ตัวอย่าง API Gateway เช่น
- Kong Gateway
- AWS API Gateway
- Google Cloud API Gateway
- Azure API Management
#25. ตัวอย่าง Kong API Gateway
Kong มี IP Restriction Plugin
ตัวอย่าง Declarative Configuration
_format_version: "3.0"
plugins:
- name: ip-restriction
config:
allow:
- 203.0.113.10
- 203.0.113.20
- 198.51.100.0/24
แนวคิด
Client
|
v
Kong Gateway
|
+-- IP Restriction
|
v
Backend API
#26. Defense in Depth
ไม่ควรใช้ IP Allowlisting เป็น Security Mechanism เพียงอย่างเดียว
ระบบ Production ควรมีหลายชั้น
Internet
|
v
Firewall / WAF
|
| IP Allowlist
v
API Gateway
|
| Rate Limiting
v
Authentication
|
| OAuth2 / JWT / API Key / mTLS
v
Application
|
| Authorization
v
Database
เรียกว่า
Defense in Depth
#27. ตัวอย่าง Production Configuration
ตัวอย่าง Nginx
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/ssl/certs/api.crt;
ssl_certificate_key /etc/ssl/private/api.key;
location /api/public {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api/private {
allow 203.0.113.10;
allow 203.0.113.20;
allow 198.51.100.0/24;
deny all;
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
#28. Workshop Challenge
ทดลองปรับระบบให้มี API
/api/public
/api/partner
/api/admin
โดยกำหนด Policy
| API | Access |
|---|---|
/api/public |
ทุก IP |
/api/partner |
Partner Network |
/api/admin |
Admin IP เท่านั้น |
ตัวอย่าง
location /api/public {
proxy_pass http://127.0.0.1:3000;
}
location /api/partner {
allow 198.51.100.0/24;
deny all;
proxy_pass http://127.0.0.1:3000;
}
location /api/admin {
allow 203.0.113.10;
deny all;
proxy_pass http://127.0.0.1:3000;
}
#29. Checklist ก่อนนำขึ้น Production
ตรวจสอบว่า
- [ ] ใช้ HTTPS
- [ ] Client มี Static Public IP
- [ ] ใช้ CIDR ที่แคบที่สุดเท่าที่จำเป็น
- [ ] มี
deny all - [ ] Backend port ไม่เปิดตรงสู่ Internet โดยไม่จำเป็น
- [ ] กำหนด Trusted Proxy ถูกต้อง
- [ ] ไม่เชื่อ
X-Forwarded-Forจากทุกแหล่ง - [ ] มี Authentication
- [ ] มี Authorization
- [ ] มี Rate Limiting
- [ ] มี Logging และ Monitoring
- [ ] มีขั้นตอนอัปเดต Allowlist เมื่อ Partner IP เปลี่ยน
- [ ] ทดสอบทั้ง Allowed IP และ Denied IP
#30. สรุป
การจำกัด API ด้วย IP Allowlisting เป็นวิธีที่เรียบง่ายและมีประสิทธิภาพสำหรับ API ที่รู้จักต้นทางแน่นอน โดยเฉพาะ Server-to-Server, Internal API และ Partner API
สำหรับระบบขนาดเล็กสามารถเริ่มจาก Nginx
location /api/private {
allow 203.0.113.10;
deny all;
proxy_pass http://127.0.0.1:3000;
}
แต่สำหรับ Production ควรออกแบบเป็นหลายชั้น
Firewall / WAF
|
v
IP Allowlisting
|
v
API Gateway
|
v
Authentication
|
v
Authorization
|
v
Application API
หลักสำคัญคือ IP Allowlisting เป็นส่วนเสริมของ API Security ไม่ใช่สิ่งทดแทน Authentication และ Authorization