เพิ่ม Security Headers ใน Nginx เพื่อลดความเสี่ยงบน Browser
ตั้งค่า CSP, HSTS, X-Content-Type-Options, frame protection, Referrer-Policy และ Permissions-Policy พร้อม rollout แบบ report-only และตรวจ header หลัง deploy

ภาพรวม
เว็บโหลดไวอย่างเดียวไม่พอ แต่ถ้า header ความปลอดภัยหายไป เว็บที่ดูปกติอาจเปิดช่องให้โดนโจมตีแบบเงียบๆ ได้ 🔐
หลายระบบพังไม่ได้พังจากโค้ดตรงๆ แต่พังจาก browser ถูกหลอกให้เชื่อสิ่งที่ไม่ควรเชื่อ 🌐
ถ้าใช้ Nginx อยู่ มี Security Headers บางตัวที่ควรใส่แทบทุกเว็บตั้งแต่วันแรก 🛡️
Headers พวกนี้ช่วยลดความเสี่ยงจาก XSS, clickjacking, MIME sniffing, ข้อมูลรั่วผ่าน referrer และการบังคับใช้ HTTPS 🚨
ตัวที่ควรเริ่มใส่ก่อนมีประมาณนี้
- X-Content-Type-Options: nosniff สั่ง browser ไม่ให้เดาประเภทไฟล์เอง ลดปัญหาการตีความไฟล์ผิดประเภท โดยเฉพาะ JS และ CSS 🧩
Nginx ตัวอย่าง add_header X-Content-Type-Options "nosniff" always;
- X-Frame-Options: SAMEORIGIN กันเว็บเราถูกฝังใน iframe จากโดเมนอื่น ช่วยลดความเสี่ยง clickjacking 🖼️
Nginx ตัวอย่าง add_header X-Frame-Options "SAMEORIGIN" always;
- Referrer-Policy: strict-origin-when-cross-origin ช่วยคุมว่าตอนผู้ใช้กดลิงก์ออกจากเว็บ browser จะส่งข้อมูล referer ไปมากแค่ไหน 🔎
ค่านี้ถือว่าสมดุลดี ยังพอใช้วิเคราะห์ทราฟฟิกได้ แต่ไม่หลุด path เต็มๆ ไปเว็บปลายทาง
Nginx ตัวอย่าง add_header Referrer-Policy "strict-origin-when-cross-origin" always;
- Permissions-Policy ปิดสิทธิ์ฟีเจอร์ browser ที่เว็บส่วนใหญ่ไม่ได้ใช้ เช่น กล้อง ไมค์ ตำแหน่ง ที่อาจโดนเรียกโดยไม่จำเป็น 🎙️
Nginx ตัวอย่าง add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
- Content-Security-Policy ตัวนี้สำคัญมาก และแรงที่สุดในชุดนี้ ใช้กำหนดว่า script, style, image, font โหลดจากที่ไหนได้บ้าง 🧠
ตัวอย่างเริ่มต้นแบบปลอดภัยกว่าค่า default add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline' https:; font-src 'self' data: https:; connect-src 'self' https:; frame-ancestors 'self'; base-uri 'self'; form-action 'self'" always;
จุดที่หลายคนไม่รู้ CSP ที่ดีไม่ควรหยุดแค่ copy ไปวาง เพราะถ้าเว็บใช้ analytics, CDN, third-party widget หรือ frontend build tool หลายตัว ค่าอาจพังทันที ⚙️
แนวทางที่ปลอดภัยกว่า เริ่มจาก Content-Security-Policy-Report-Only ก่อน ให้ browser รายงานสิ่งที่จะโดนบล็อก โดยยังไม่บล็อกจริง 📊
- Strict-Transport-Security ถ้าเว็บเปิด HTTPS พร้อมใช้งานจริงแล้ว header นี้จะบังคับให้ browser ใช้ HTTPS ตลอด 🔒
Nginx ตัวอย่าง add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
สำคัญมาก ห้ามเปิด HSTS ถ้ายังมี subdomain ที่รองรับแต่ HTTP อย่างเดียว เพราะผู้ใช้จะเข้าไม่ได้ทันที
ชุดเริ่มต้นที่หลายเว็บใช้ได้
add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ถ้าจะใส่ CSP ควรทดสอบกับ staging ก่อนเสมอ 🧪 โดยเฉพาะเว็บที่มี React, Vue, analytics, ads, payment gateway หรือโหลด asset จากหลายแหล่ง
อีกเรื่องที่คนพลาดบ่อย add_header ของ Nginx บางเคสจะไม่ติดใน response บางประเภท การใส่ always; ช่วยให้ header ถูกส่งออกไปสม่ำเสมอมากขึ้น ✅
และถ้า config ซ้อนหลายชั้น เช่น http, server, location ควรเช็ก inheritance ให้ดี เพราะ header อาจหายโดยไม่รู้ตัว
วิธีเช็กเร็วๆ หลัง deploy ใช้ curl -I https://yourdomain.com หรือเปิด DevTools แล้วดูแท็บ Network ก็ได้ 🧰
Security headers ไม่ได้ทำให้เว็บปลอดภัย 100% แต่เป็นเกราะชั้นต้นที่ต้นทุนต่ำและได้ผลจริง โดยเฉพาะเว็บองค์กร เว็บ SaaS หลังบ้าน และระบบที่มีการล็อกอิน 👨💻
ถ้าเว็บยังไม่มีชุดนี้ การเพิ่มไม่กี่บรรทัดใน Nginx อาจลดความเสี่ยงได้มากกว่าที่คิด 🚀
งาน infra ที่ดี ไม่ใช่แค่ทำให้ระบบรันได้ แต่ต้องทำให้รันแบบไว้ใจได้ด้วย ✨
แนวทางนำไปใช้
- นำแนวคิดจากโพสต์นี้ไปทดลองกับงานจริงของคุณ
- แยกเป็นขั้นตอนเล็ก ๆ แล้วทำทีละส่วน
- บันทึกผลลัพธ์และสิ่งที่เรียนรู้เพื่อต่อยอด
สรุป
ตั้งค่า CSP, HSTS, X-Content-Type-Options, frame protection, Referrer-Policy และ Permissions-Policy พร้อม rollout แบบ report-only และตรวจ header หลัง deploy