การดู : 0

12/04/2026 18:16น.

Golang The Series EP.137: Enterprise Security Best Practices – สร้างป้อมปราการให้ WebSocket Server

Golang The Series EP.137: Enterprise Security Best Practices – สร้างป้อมปราการให้ WebSocket Server

#Golang

#WebSocket Security

#Authentication

#Go

#CSWSH

ยินดีต้อนรับชาว Gopher ทุกท่านครับ! หลายคนอาจจะคิดว่าแค่เปลี่ยนจาก ws:// เป็น wss:// (TLS) ก็เพียงพอแล้ว แต่ในโลกความเป็นจริงนั่นเป็นเพียงการ "ล็อกประตูรั้ว" เท่านั้นครับ การทำระบบระดับ Enterprise ต้องมองให้ลึกไปถึง Application Layer, Infrastructure และการบริหารจัดการทรัพยากร เพื่อรับมือกับแฮกเกอร์ที่จ้องจะเจาะระบบของคุณตลอด 24 ชั่วโมง

วันนี้ผมสรุป 5 เสาหลักของความปลอดภัย WebSocket ในภาษา Go มาให้แบบเจาะลึกครับ

 

1. Authentication & Authorization (ด่านแรกต้องแน่น)

 

WebSocket มีจุดอ่อนคือ Browser API มาตรฐานไม่รองรับการส่ง Custom HTTP Headers ในขณะสร้างการเชื่อมต่อ (new WebSocket()) ทำให้เราส่ง Authorization: Bearer <token> แบบปกติไม่ได้

กลยุทธ์ที่แนะนำ:

  • Ticket-based Authentication (Gold Standard): 1. Client ขอ "One-time Ticket" ผ่าน REST API ปกติ (ที่มี Auth แน่นหนา)
    2. Server สร้าง Ticket ที่มีอายุสั้นมาก (เช่น 30 วินาที) เก็บไว้ใน Redis
    3. Client ส่ง Ticket นี้ผ่าน Query String มาตอนเปิด WebSocket
    4. Server ตรวจสอบ Ticket และ "เผาทิ้ง" (Delete on Read) ทันทีเพื่อป้องกัน Replay Attack
  • Periodic Re-authentication: สำหรับการเชื่อมต่อที่ค้างไว้นานหลายชั่วโมง ควรมีการส่งข้อความบังคับให้ Client ยืนยันตัวตนใหม่ (Refresh Token) ผ่านท่อ WebSocket เดิม หากทำไม่สำเร็จให้ตัดการเชื่อมต่อทันที

 

2. Origin Checking: ป้องกัน CSWSH

 

Cross-Site WebSocket Hijacking (CSWSH) คือช่องโหว่ที่น่ากลัวที่สุด แฮกเกอร์สามารถสร้างเว็บหลอกให้เหยื่อกด แล้วใช้ Browser ของเหยื่อส่ง Cookie เพื่อเปิดการเชื่อมต่อ WebSocket มายัง Server ของเราโดยที่เหยื่อไม่รู้ตัว

วิธีแก้ใน Go:

ห้ามตั้ง CheckOrigin เป็น true เด็ดขาด! คุณต้องตรวจสอบ White-list Domain อย่างเคร่งครัด

 

Go
var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        origin := r.Header.Get("Origin")
        // ใน Production ควรดึงค่ามาจาก Environment Variable
        allowedOrigins := []string{"https://superdevacademy.com", "https://app.superdev.io"}
        
        for _, o := range allowedOrigins {
            if origin == o {
                return true
            }
        }
        return false
    },
}

 

3. Payload Validation & Size Limiting (ป้องกัน OOM)

 

การส่งข้อมูลขนาดใหญ่เกินจริง หรือ JSON ที่ซ้อนกันลึกๆ (Recursive JSON) สามารถทำให้ Server เกิดอาการ Out of Memory (OOM) หรือ CPU Peak ได้

Best Practices:

  • Hard Limit on Message Size: ใช้ SetReadLimit เพื่อตัดการเชื่อมต่อทันทีหากส่งข้อมูลเกินขนาดที่กำหนด
  • Strict Schema Validation: ใช้ Struct Tags หรือ Library อย่าง go-playground/validator เพื่อเช็คว่าข้อมูลที่ส่งมามีฟิลด์ที่ถูกต้องและไม่มีค่าที่อันตราย (Injection)

 

Go
func (c *Client) readPump() {
    // จำกัดขนาดไว้ที่ 4KB เท่านั้นสำหรับข้อความแชท
    c.conn.SetReadLimit(4096) 
    
    // ตั้งค่า Deadline เพื่อป้องกัน Slowloris Attack (การเปิดท่อค้างแต่ไม่ส่งข้อมูล)
    c.conn.SetReadDeadline(time.Now().Add(pongWait))
    // ...
}

 

4. Connection Rate Limiting & DoS Protection

 

WebSocket เป็นระบบที่ Stateful การเปิดท่อทิ้งไว้ 100,000 ท่อ กินทรัพยากรมากกว่าการทำ 100,000 HTTP Requests มหาศาล

การป้องกัน:

  • Concurrent Connection Limit per User: จำกัดให้ 1 User ID หรือ 1 IP สามารถเปิดได้ไม่เกิน X Connection (เช่น 5 ท่อ) เพื่อป้องกันการจอง Resource จนเต็ม (Connection Exhaustion)
  • Distributed Rate Limiting: ใช้ Redis ในการเก็บจำนวนการเชื่อมต่อปัจจุบันข้ามหลายๆ Instance (ตามที่คุยใน EP.130)
  • Aggressive Idle Timeout: หากไม่มีการส่งข้อมูลหรือ Ping/Pong ภายในเวลาที่กำหนด ให้ปิดการเชื่อมต่อทันทีเพื่อคืน RAM

 

5. Secure Infrastructure & Deep Defense

 

ความปลอดภัยไม่ได้จบที่ตัว Code แต่ต้องรวมไปถึงสภาพแวดล้อมที่รันระบบด้วย:

  • TLS 1.3 & Strong Ciphers: ปิดโปรโตคอลเก่าอย่าง TLS 1.0/1.1 และใช้เฉพาะ Cipher Suites ที่มีความปลอดภัยสูง
  • Message-level Encryption: ในกรณีที่ข้อมูลมีความไวสูง (เช่น ระบบธนาคาร) ควรมีการเข้ารหัส Payload อีกชั้นก่อนส่งผ่าน WebSocket เพื่อป้องกันกรณีที่ TLS ถูกถอดรหัส (SSL Stripping)
  • Non-Root Containers: รันแอป Go ใน Docker ด้วย USER nonroot เพื่อลดสิทธิ์ในการเข้าถึงระบบหากแอปถูกเจาะ
  • WAF (Web Application Firewall): เลือกใช้ WAF ที่มีความสามารถในการทำ Protocol Validation เพื่อตรวจจับ Packet WebSocket ที่ผิดปกติ

 


 

สรุป

 

ความปลอดภัยในระดับ Enterprise ไม่ใช่เรื่องของการ "ติ๊กถูก" ตาม Checklists แต่คือการวางแผน Defense in Depth (การป้องกันหลายชั้น) ตั้งแต่การคัดกรองคนเข้า (Auth), การตรวจสอบของที่ถือมา (Payload), และการรักษาพื้นที่ (Resource Management) ภาษา Go ช่วยเราได้มากเรื่อง Type-safety แต่การมีระเบียบวินัยในการจัดการ Security จะทำให้ระบบของคุณเป็น "ป้อมปราการ" ที่ไม่มีวันพังครับ

ในตอนหน้า (EP.138): เราจะพักเรื่องความปลอดภัย แล้วกลับมาโฟกัสที่ความเร็วสะใจกับเรื่อง Monitoring Latency & Performance Optimization — จะรีดประสิทธิภาพ WebSocket ให้เร็วระดับ Millisecond และลดอาการ "Lag" ต้องปรับจูนตรงไหนบ้าง! ห้ามพลาดครับ