Category: reference
HTTP Security Headers — ป้องกันเว็บด้วย Headers
รายการ HTTP security headers ที่ควรตั้งค่าสำหรับเว็บใดก็ตาม ครอบคลุม CSP, HSTS, X-Frame-Options, Permissions-Policy และวิธีตั้งค่าใน Astro + Railway
สารบัญ
ทำไม Security Headers สำคัญ
Browser รองรับ headers ที่ป้องกันการโจมตีหลายรูปแบบ แต่ถ้าไม่ตั้งค่า server จะไม่ส่งมาให้ browser — ทำให้เว็บเสี่ยงโดยไม่จำเป็น:
- XSS (Cross-Site Scripting) — script จากแหล่งไม่ทราบที่รันใน browser ผู้ใช้
- Clickjacking — เว็บอื่นฝัง site ในกรอบ
<iframe>เพื่อหลอก user - MITM (Man-in-the-Middle) — ดักจับ HTTP traffic ก่อน upgrade เป็น HTTPS
Headers ที่สำคัญ
Content-Security-Policy (CSP)
ควบคุมว่า browser จะโหลด resource จากที่ไหนได้บ้าง:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data:; object-src 'none'
| Directive | ความหมาย |
|---|---|
default-src 'self' | โหลดได้เฉพาะจาก origin เดียวกัน (fallback) |
script-src 'self' | JS จาก origin เดียวเท่านั้น — บล็อก inline script |
style-src 'unsafe-inline' | อนุญาต inline CSS (จำเป็นสำหรับ Astro) |
object-src 'none' | บล็อก Flash และ plugins ทั้งหมด |
frame-ancestors 'none' | ห้ามฝังใน iframe |
Strict-Transport-Security (HSTS)
บังคับให้ browser ใช้ HTTPS เสมอ ไม่มีทาง fallback ไป HTTP:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age=31536000— จำ 1 ปีincludeSubDomains— ครอบคลุม subdomain ทั้งหมดpreload— รวมอยู่ใน browser preload list
X-Frame-Options
ป้องกัน clickjacking:
X-Frame-Options: DENY
หรือใช้ CSP frame-ancestors แทน (ยืดหยุ่นกว่า):
Content-Security-Policy: frame-ancestors 'none'
X-Content-Type-Options
ป้องกัน MIME sniffing:
X-Content-Type-Options: nosniff
Browser จะไม่เดา content type — ต้องใช้ MIME type ที่ server ส่งมาเท่านั้น
Referrer-Policy
ควบคุม referrer header ที่ส่งไปเมื่อคลิก external link:
Referrer-Policy: strict-origin-when-cross-origin
ส่ง full URL เมื่อ navigate ภายใน origin เดียวกัน แต่ส่งเฉพาะ origin เมื่อออกไป site อื่น
Permissions-Policy
ควบคุมการเข้าถึง browser features:
Permissions-Policy: camera=(), microphone=(), geolocation=(), interest-cohort=()
ปิด camera, microphone, location, และ FLoC ทั้งหมด — เว็บ content ไม่ต้องการ feature เหล่านี้
ตั้งค่าใน Railway (railway.json)
{
"$schema": "https://railway.app/railway.schema.json",
"build": {
"builder": "NIXPACKS"
},
"deploy": {
"startCommand": "node server.js",
"headers": {
"/*": {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"Referrer-Policy": "strict-origin-when-cross-origin",
"Permissions-Policy": "camera=(), microphone=(), geolocation=()",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains"
}
}
}
}
ตั้งค่าผ่าน _headers file (Netlify / Cloudflare Pages)
/*
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data:; object-src 'none'
ทดสอบ Headers
เครื่องมือที่ใช้ตรวจสอบ:
- securityheaders.com — ใส่ URL แล้วได้ grade และรายการปัญหา
- Mozilla Observatory — วิเคราะห์ละเอียดกว่า พร้อมคำแนะนำ
curl -I https://panupongws.com— ดู response headers โดยตรง
สำหรับ static site ทั่วไป เป้าหมายคือ Grade A บน securityheaders.com โดยไม่ทำให้ฟีเจอร์ปกติพัง