คู่มือเกมแลค › ต้นเหตุของการส่งซ้ำใน TCP
ไฟร์วอลล์/connection tracking ทิ้งแพ็กเก็ต Stateful firewall / conntrack drops
ID สาเหตุ rt-stateful-fw · ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
เปิดการ์ดในฉบับหลักที่มีภาพและการทดลอง →
ไฟร์วอลล์หรือ connection tracking ของ Linux (conntrack คือฟังก์ชันที่บันทึกการเชื่อมต่อที่ผ่านลงในตาราง) จะทิ้งแพ็กเก็ตเมื่อตารางเต็ม หรือเมื่อตัดสินว่าสถานะการเชื่อมต่อไม่ถูกต้อง
ทำไม ตาราง connection tracking เต็ม (table full) หรือเส้นทางขาไปกับขากลับต่างกันจนผ่านไฟร์วอลล์แค่ทิศทางเดียว (asymmetric routing) → ผลคือ ไฟร์วอลล์มองว่าเป็นแพ็กเก็ตของ “การเชื่อมต่อที่ไม่รู้จัก” หรือ “sequence number ที่อยู่นอกช่วง window” แล้วทิ้ง → บนหน้าจอ ถ้าตารางเต็ม การเชื่อมต่อใหม่จะถูกบล็อก, ถ้าเส้นทางเหลื่อมกัน เฉพาะคนที่ใช้เส้นทางนั้นจะส่งซ้ำวนไปจนหลุด
- อาการ
- ค้าง, หลุด, เข้าเกมไม่ได้/โหลดไม่จบ
- ปัจจัย
- แพ็กเก็ตหาย
- ใครเจอ
- ทั้งเซิร์ฟเวอร์, บางพื้นที่/บาง ISP
- เกิดเมื่อไร
- ตอนคนแห่มารวมกัน, หลังล็อกอิน/หลังปิดปรับปรุง, สุ่มเป็นครั้งคราว
- ผู้รับผิดชอบ
- ผู้รับผิดชอบหลัก อินฟราเครือข่าย (ทีมอินฟรา) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
- งานฝั่งทีมพัฒนาเกม
- เซิร์ฟเวอร์: เผื่อกรณีตารางเต็มด้วยการคุมการเชื่อมต่อที่ทะลักเข้ามาผ่านระบบคิวล็อกอิน, ใช้การเชื่อมต่อซ้ำเพื่อไม่ให้เปิดปิดการเชื่อมต่อสั้น ๆ ซ้ำไปมา (รวมถึงการเรียกระหว่างเซิร์ฟเวอร์), ปิดการเชื่อมต่อที่ heartbeat ขาดไปก่อน ไคลเอนต์: เมื่อเชื่อมต่อไม่สำเร็จหรือหลุด ให้ยืดช่วงเวลาลองใหม่ขึ้นเรื่อย ๆ และสุ่มกระจาย (เพื่อไม่ให้กลับมาทะลักพร้อมกันตอนตารางเต็ม)
- งานฝั่งทีมอินฟรา
- เครือข่าย: เพิ่มขนาดตาราง connection tracking ของไฟร์วอลล์, เอาพอร์ตเกมออกจาก connection tracking, ปรับ routing ให้ขาไปและขากลับผ่านไฟร์วอลล์ตัวเดียวกัน, ตรวจการตั้งค่าการตรวจ TCP window ของไฟร์วอลล์ เครื่องเซิร์ฟเวอร์/OS: เพิ่มขนาดตารางของ Linux (nf_conntrack_max), เอาพอร์ตเกมออกจาก connection tracking (NOTRACK), ตรวจการตั้งค่าการตรวจ TCP window (nf_conntrack_tcp_be_liberal), ถ้าเป็น AWS ตรวจ conntrack_allowance_exceeded ด้วย
- ตัวเลขที่ควรรู้
- ขีดจำกัดเริ่มต้นของ conntrack ใน Linux (nf_conntrack_max) อยู่ที่หลายหมื่นถึงหลายแสนรายการ ขึ้นกับหน่วยความจำ เมื่อจำนวนปัจจุบัน (nf_conntrack_count) ชนขีดจำกัด จะมี log “nf_conntrack: table full, dropping packet”
- บนกราฟ
- ชนเพดานแล้วแบนราบ · จำนวนรายการ conntrack (nf_conntrack_count), จำนวนการเชื่อมต่อใหม่ที่ล้มเหลว
- จุดที่ต้องดู
- เซิร์ฟเวอร์ Linux ดู nf_conntrack_count กับ nf_conntrack_max, “nf_conntrack: table full, dropping packet” ใน dmesg, drop และ invalid ใน /proc/net/stat/nf_conntrack (หนึ่งบรรทัดต่อคอร์, เลขฐาน 16) ไฟร์วอลล์ดูการใช้ตารางเซสชันและ log การดรอป AWS ดู conntrack_allowance_exceeded ใน ethtool -S
- สัญญาณว่าใช่
- จำนวนรายการแบนราบที่ขีดจำกัด และในเวลาเดียวกัน log table full กับ drop หรือ conntrack_allowance_exceeded เพิ่มขึ้น ถ้าเป็นเส้นทางไม่สมมาตร ขีดจำกัดยังเหลือ แต่ invalid และ log การดรอปของไฟร์วอลล์เพิ่มขึ้นในการเชื่อมต่อของเส้นทางหนึ่ง
- สัญญาณว่าไม่ใช่
- จำนวนรายการยังห่างจากขีดจำกัด และ invalid กับ log การดรอปก็ไม่ขยับ: เป็นสาเหตุอื่น ถ้าตารางยังเหลือที่แต่ CPU หรือจำนวนแพ็กเก็ตต่อวินาทีของไฟร์วอลล์เต็ม น่าจะเป็น “อุปกรณ์กลางทางเกินขีดความสามารถ”
- วิธีตรวจ
- ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง
- Netfilter Conntrack Sysfs variables Linux kernel
ค่าเริ่มต้นของ nf_conntrack_max เท่ากับจำนวน hash bucket (หน่วยความจำ÷16384, 1,024–262,144), จำนวนปัจจุบันคือ nf_conntrack_count, nf_conntrack_tcp_be_liberal ทำให้นับเป็น INVALID เฉพาะ RST ที่อยู่นอก window - net/netfilter/nf_conntrack_core.c Linux kernel
เมื่อตารางเต็มจะเขียน log “nf_conntrack: table full, dropping packet” แล้วทิ้ง (สถิติ drop เพิ่ม) แพ็กเก็ตที่ไม่ตรงกับสถานะการเชื่อมต่อจะทำให้สถิติ invalid เพิ่ม - iptables-extensions(8) — Linux manual page netfilter
ยกเว้นจาก connection tracking ด้วย CT --notrack ในตาราง raw - Amazon EC2 security group connection tracking AWS
ถ้าเกินขีดจำกัดจำนวนการเชื่อมต่อที่ติดตามได้ของแต่ละอินสแตนซ์ แพ็กเก็ตจะถูกทิ้ง ตรวจได้จาก conntrack_allowance_exceeded พร้อมคำแนะนำให้หลีกเลี่ยงเส้นทางไม่สมมาตร - net/netfilter/nf_conntrack_standalone.c Linux kernel
/proc/net/stat/nf_conntrack มีหนึ่งบรรทัดต่อคอร์ เป็นเลขฐาน 16 และมีคอลัมน์ entries, invalid, insert_failed, drop, early_drop ฯลฯ
สาเหตุที่ควรดูประกอบ
ชั้นเดียวกัน: ต้นเหตุของการส่งซ้ำใน TCP
สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (ค้าง)
ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง