ปิด HTTP/3 บน NGINX เพื่อลดความเสี่ยง CVE-2026-95101 และทดสอบก่อน–หลัง
หากใช้ NGINX เป็น reverse proxy และเปิด HTTP/3 อยู่ เราสามารถปิด HTTP/3 ชั่วคราวเพื่อลดความเสี่ยงจาก CVE-2026-95101 ระหว่างรออัปเดตแพ็กเกจได้ โดยยังเปิด HTTPS ผ่าน TCP ให้เว็บไซต์ใช้งานต่อไป บทความนี้จะพาตรวจ config ปิดตัวรับ QUIC และทดสอบก่อน–หลังให้เห็นว่าค่าที่เปลี่ยนมีผลจริง
ตรวจข้อมูลวันที่ 28 ตุลาคม 2026 ภาพเป็นแผนภาพประกอบ ส่วนผลทดสอบด้านล่างเป็นเกณฑ์ที่คาดหวัง ไม่ใช่ผลจากเซิร์ฟเวอร์ของผู้เขียน
ช่องโหว่นี้เกี่ยวกับอะไร
CVE-2026-95101 อยู่ในส่วน HTTP/3 ของ NGINX เมื่อใช้ร่วมกับ proxy_request_buffering ผู้โจมตีที่ไม่ต้องล็อกอินอาจแทรกข้อมูลใน request ที่ส่งต่อให้ backend ได้ ตาม ประกาศของ Red Hat วิธีลดความเสี่ยงที่ระบุไว้คือปิด HTTP/3 หรือใช้ proxy_request_buffering off; ในส่วนที่เกี่ยวข้อง
ตัวอย่างนี้เลือกปิด HTTP/3 เพื่อทดสอบผลจากการเชื่อมต่อได้ชัดเจน และใช้ NGINX บน Linux ที่จัดการ service ด้วย systemd หากรันใน container ให้ตรวจและ reload config ของ NGINX ภายใน container ที่ให้บริการจริง
ตรวจ config และเก็บผลก่อนแก้
ดูเวอร์ชันและ config รวมไฟล์ที่ถูก include ด้วยคำสั่ง
nginx -v
sudo nginx -T
มองหาบรรทัด listen ที่มี quic รวมถึงทุก virtual host ทั้ง IPv4, IPv6 และพอร์ตอื่นที่เปิดไว้ เช่น
listen 443 quic reuseport;
listen [::]:443 quic reuseport;
ตรวจด้วยว่ามี proxy_pass และ proxy_request_buffering ในส่วนที่รับ HTTP/3 หรือไม่ อย่าตัดสินจากไฟล์เดียว เพราะค่าจริงอาจอยู่ใน conf.d หรือ sites-enabled ส่วน nginx -T แสดง config บนดิสก์ ยังไม่ยืนยันว่า process ที่ทำงานอยู่โหลด config ชุดนั้นแล้ว ตาม คู่มือคำสั่ง NGINX
ที่เครื่องทดสอบ ให้ตรวจว่า curl รองรับ HTTP/3 โดยมองหาคำว่า HTTP3 ใน Features
curl -V
จากนั้นทดสอบตรงไปยัง NGINX โดยเปลี่ยน example.com เป็นโดเมนจริง และ 203.0.113.10 เป็น IP ของเครื่องต้นทาง คำสั่ง --resolve ช่วยเลือก IP โดยยังใช้ชื่อโดเมนเดิมสำหรับ TLS และ virtual host
curl --noproxy '*' --http3-only \
--resolve example.com:443:203.0.113.10 \
--max-time 10 -v \
https://example.com/
ก่อนแก้ควรเชื่อมต่อ HTTP/3 ได้ หากไม่ได้ตั้งแต่แรก ต้องตรวจ curl, UDP firewall และเส้นทางเครือข่ายก่อน เพราะจะยังเปรียบเทียบผลก่อน–หลังไม่ได้ ไม่ต้องเปิด HTTP/3 เพิ่มบนเครื่องที่ปิดอยู่แล้วเพื่อทำการทดสอบ
ใช้ --http3-only เพื่อบังคับ HTTP/3 โดยไม่ fallback ไป HTTP รุ่นอื่น ตาม คู่มือ curl ถ้า curl แจ้งว่าไม่รองรับ option หรือ HTTP/3 นั่นเป็นข้อจำกัดของเครื่องทดสอบ ไม่ใช่หลักฐานว่าเซิร์ฟเวอร์ปิด HTTP/3 แล้ว
ปิดตัวรับ QUIC
สำรองไฟล์ config ที่จะเปลี่ยน แล้วแก้ใน server เดิม ตัวอย่างก่อนแก้
listen 443 ssl;
listen 443 quic reuseport;
listen [::]:443 quic reuseport;
เปลี่ยนเป็น
listen 443 ssl;
# listen 443 quic reuseport;
# listen [::]:443 quic reuseport;
คงบรรทัด HTTPS ผ่าน TCP เดิมทั้งหมดไว้ รวมถึง IPv6 หากมี และปิดบรรทัด QUIC ให้ครบทุก virtual host ที่เกี่ยวข้อง อย่าเพียงลบคำว่า quic ออกจากบรรทัดแล้วปล่อย option ที่เหลือไว้
นำการประกาศ Alt-Svc ที่โฆษณา h3 ออกด้วย เช่น
add_header Alt-Svc 'h3=":443"; ma=86400';
หาก header มาจาก backend หรือ proxy อีกชั้น ต้องปรับที่จุดนั้นด้วย การลบ Alt-Svc อย่างเดียวไม่ได้ปิดตัวรับ QUIC ดูตัวอย่างความสัมพันธ์ของ listen กับ header นี้ใน เอกสาร HTTP/3 ของ NGINX
ตรวจแล้ว reload
ตรวจ syntax ก่อน
sudo nginx -t
เมื่อผ่านแล้วจึง reload จากนั้นตรวจสถานะและ log รันทีละคำสั่งและหยุดตรวจสาเหตุหากมี error
sudo systemctl reload nginx
sudo systemctl status nginx --no-pager
sudo journalctl -u nginx --since "5 minutes ago" --no-pager
ดู error log ของ NGINX ตามตำแหน่งที่ตั้งไว้ด้วย หากนำ config ใหม่มาใช้ไม่ได้ NGINX อาจยังทำงานด้วย config เดิม และ worker เดิมอาจยังระบายงานที่ค้างอยู่ระหว่าง graceful reload ตาม เอกสารการ reload ของ NGINX
ทดสอบหลังแก้
รันคำสั่ง HTTP/3 เดิมอีกครั้งจากเครื่องและเครือข่ายเดิม
curl --noproxy '*' --http3-only \
--resolve example.com:443:203.0.113.10 \
--max-time 10 -v \
https://example.com/
จากนั้นทดสอบ HTTPS ผ่าน HTTP/1.1
curl --noproxy '*' --http1.1 \
--resolve example.com:443:203.0.113.10 \
--max-time 10 -v \
https://example.com/
ตรวจ UDP listener บนเซิร์ฟเวอร์เพิ่ม หากเดิมใช้พอร์ต 443
sudo ss -lunp 'sport = :443'
| สิ่งที่ตรวจ | ผลที่ต้องการหลังปิด HTTP/3 |
|---|---|
| การเชื่อมต่อ HTTP/3 ใหม่ | เชื่อมต่อไม่สำเร็จ หลังจากก่อนแก้เคยสำเร็จ |
| HTTPS ผ่าน HTTP/1.1 | ได้ status และเนื้อหาตามปกติของเว็บไซต์ |
| Config และ UDP listener | ไม่เหลือตัวรับ QUIC ของ NGINX ที่ต้องการปิด |
| การ reload | ไม่พบข้อผิดพลาดในการนำ config ใหม่มาใช้ |
หากมีหลายเครื่อง หลายพอร์ต หรือ IPv6 ให้ตรวจทุกปลายทางด้วย หากอยู่หลัง CDN ให้ทดสอบตรง origin เพราะ HTTP/3 ของ CDN อาจยังเปิดอยู่ได้แม้ปิดที่ NGINX แล้ว
ผล timeout อย่างเดียวไม่พอจะยืนยันการปิด HTTP/3 ต้องดูผลก่อนแก้ config และ listener ประกอบกัน การตรวจนี้ยืนยันการปิดเส้นทาง HTTP/3 ไม่ใช่การทดสอบ exploit หรือการยืนยันว่าบั๊กใน binary ถูกแก้แล้ว
หากจำเป็นต้องคง HTTP/3 ไว้
อีกทางเลือกตามประกาศคือกำหนดค่าต่อไปนี้ในส่วนที่ได้รับผลกระทบ โดยตรวจทุก location ว่าไม่มีค่า on เปิดกลับมา
proxy_request_buffering off;
อย่าสับสนกับ proxy_buffering ซึ่งเป็นการ buffer response การปิด request buffering เปลี่ยนวิธีส่ง request body ไป backend และเมื่อเริ่มส่ง body แล้วจะลองส่ง request ไป upstream ตัวอื่นไม่ได้ จึงต้องทดสอบงาน upload และ backend ตาม เอกสาร proxy_request_buffering
ถ้าเลือกวิธีนี้ HTTP/3 ควรยังเชื่อมต่อได้ การใช้ curl ปกติจึงไม่ยืนยันว่าแก้ช่องโหว่แล้ว ต้องตรวจขอบเขต config การ reload และทดสอบการรับ body ของระบบเพิ่มเติม
อัปเดตแพ็กเกจเพื่อแก้ตัวบั๊ก
NGINX upstream แก้ CVE-2026-95101 ในสาย stable ตั้งแต่ 1.30.6 และสาย mainline ตั้งแต่ 1.31.7 ตาม NGINX Security Advisories ให้อัปเดตตามแหล่งแพ็กเกจที่ใช้อยู่และตรวจโมดูลที่ติดตั้งร่วมกัน
หากใช้ Ubuntu ให้ตรวจ USN-8955-1 ซึ่งระบุว่า CVE นี้กระทบแพ็กเกจใน Ubuntu 26.04 LTS และ 26.10 สำหรับประกาศชุดนี้ อย่าใช้ช่วงเวอร์ชัน upstream ตัดสินแพ็กเกจ Ubuntu โดยตรง เพราะดิสโทรอาจนำแพตช์มาใส่ในรุ่นเดิมได้
หลังอัปเดตต้องตรวจว่า process ใช้ binary ใหม่แล้ว การ reload config อย่างเดียวไม่โหลด executable ใหม่ หากใช้ systemctl restart nginx ให้จัดช่วงเวลาที่รับผลกระทบจากการหยุดและเริ่ม service ได้ แล้วตรวจ config, log และเว็บไซต์อีกครั้งก่อนพิจารณาเปิด HTTP/3 กลับ