คู่มือเกมแลค › ต้นเหตุของการส่งซ้ำใน TCP
การส่งซ้ำคำขอเชื่อมต่อ (SYN) SYN retransmission on connect
ID สาเหตุ rt-syn · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), อินฟราเครือข่าย (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
เปิดการ์ดในฉบับหลักที่มีภาพและการทดลอง →
ถ้าคำขอเชื่อมต่อหายไปเพราะคิวรอเชื่อมต่อ (backlog) ล้นหรือถูกไฟร์วอลล์บล็อก OS ฝั่งไคลเอนต์จะส่งใหม่ โดยเริ่มหลัง 1 วินาทีและเว้นช่วงห่างขึ้นเรื่อย ๆ
ทำไม การเชื่อมต่อทะลักทันทีหลังปิดปรับปรุงจนคิวรอเชื่อมต่อของเซิร์ฟเวอร์ล้น หรือไฟร์วอลล์/ระบบป้องกัน DDoS ทิ้ง SYN → ผลคือ OS ฝั่งไคลเอนต์ส่ง SYN ซ้ำตามช่วงที่กำหนด โดยเริ่มหลัง 1 วินาที (Linux รุ่นเก่า 1 วินาที → 2 วินาที → 4 วินาที) → บนหน้าจอ หลังกดปุ่มเชื่อมต่อ ช้าไปเป็นวินาทีพอดี ๆ เช่น 1 วินาที, 3 วินาที และถ้าล้มเหลวต่อเนื่องจะเข้าเกมไม่ได้หรือโหลดไม่จบ
- อาการ
- เข้าเกมไม่ได้/โหลดไม่จบ
- ปัจจัย
- แพ็กเก็ตหาย
- ใครเจอ
- ทั้งเซิร์ฟเวอร์, บางพื้นที่/บาง ISP
- เกิดเมื่อไร
- หลังล็อกอิน/หลังปิดปรับปรุง
- ผู้รับผิดชอบ
- ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา), อินฟราเครือข่าย (ทีมอินฟรา), พัฒนาไคลเอนต์ (ทีมพัฒนาเกม)
- งานฝั่งทีมพัฒนาเกม
- เซิร์ฟเวอร์: เพิ่มอาร์กิวเมนต์ backlog ของ listen (พร้อมกับ somaxconn), ทำให้เซิร์ฟเวอร์เกมเรียก accept ได้ทัน, ใช้ระบบคิวล็อกอิน ไคลเอนต์: ยืดช่วงเวลาลองเชื่อมต่อใหม่ (สุ่มกระจาย)
- งานฝั่งทีมอินฟรา
- เครื่องเซิร์ฟเวอร์/OS: ตรวจคิวรอเชื่อมต่อของเซิร์ฟเวอร์ล้นจาก TcpExtListenOverflows และ TcpExtListenDrops ใน nstat และคำเตือน “Possible SYN flooding” ใน log, เพิ่ม somaxconn (พร้อมกับอาร์กิวเมนต์ของ listen), ใช้ SYN cookie เครือข่าย: ผ่อนการจำกัด SYN ของไฟร์วอลล์และระบบป้องกัน DDoS
- ตัวเลขที่ควรรู้
- SYN ที่ส่งซ้ำครั้งแรกของ Linux (รวมถึง Android) อยู่ที่ 1 วินาที เคอร์เนลรุ่นเก่าหลังจากนั้นจะเพิ่มช่วงห่างเป็นสองเท่าและส่งซ้ำที่วินาทีที่ 1, 3, 7, 15 … ส่วนตั้งแต่ 6.5 ขึ้นไปจะส่งซ้ำห้าครั้งที่ 1, 2, 3, 4, 5 วินาที แล้วจึงเพิ่มเป็นสองเท่า (7, 11, 19 วินาที …) ตามค่า tcp_syn_linear_timeouts=4 มือถือ Android จำนวนมากยังใช้เคอร์เนลตอนวางจำหน่ายแม้จะอัปเดต OS แล้ว จึงอาจต่างกันไปตามเครื่องแม้เป็น Android เวอร์ชันเดียวกัน ไม่ว่าแบบไหน ถ้าล้มเหลวทั้งหมดจะเลิกหลังประมาณ 2 นาที Windows เริ่มเพิ่มจาก 1 วินาทีหรือ 3 วินาที แล้วแต่เวอร์ชันและการตั้งค่า และส่งซ้ำแค่ 2–4 ครั้ง จึงเลิกภายใน 20–30 วินาที (ดูค่าของ PC เครื่องนั้นได้จาก Max SYN Retransmissions ใน netsh int tcp show global)
- บนกราฟ
- พุ่งทันทีหลังเปิดเซิร์ฟ/ปิดปรับปรุง · จำนวนครั้งที่พยายามเชื่อมต่อ, จำนวนครั้งที่คิวรอเชื่อมต่อล้น
- จุดที่ต้องดู
- TcpExtListenOverflows และ TcpExtListenDrops ใน nstat ของเซิร์ฟเวอร์ กับคำเตือน “Possible SYN flooding on port” ใน dmesg และใช้ ss -lnt ดูว่า Recv-Q ของซ็อกเก็ตที่รอเชื่อมต่อ (จำนวนการเชื่อมต่อที่รอ accept) ชน Send-Q (ขีดจำกัด backlog) หรือไม่ ตรวจจาก capture ฝั่งเซิร์ฟเวอร์ว่า SYN มาถึงหรือไม่ และเซิร์ฟเวอร์ส่ง SYN-ACK กลับหรือไม่
- สัญญาณว่าใช่
- ช่วงที่การเชื่อมต่อทะลักทันทีหลังปิดปรับปรุง TcpExtListenOverflows เพิ่มขึ้นและ Recv-Q ติดเพดาน Send-Q ใน capture เห็น SYN จากไคลเอนต์เดิมมาซ้ำเป็นช่วงห่างระดับวินาที แต่เซิร์ฟเวอร์ไม่ตอบ
- สัญญาณว่าไม่ใช่
- SYN ไม่มาถึงเซิร์ฟเวอร์และตัวนับของเซิร์ฟเวอร์ก็ไม่ขยับ: ไฟร์วอลล์หรือระบบป้องกัน DDoS ด้านหน้าทิ้งไป ให้ดูการจำกัด SYN และ log การดรอปของอุปกรณ์นั้น ถ้าเซิร์ฟเวอร์ส่ง SYN-ACK แล้วแต่ยังเชื่อมต่อช้า น่าจะเป็นแพ็กเก็ตหายในทิศทางขากลับ
- วิธีตรวจ
- ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง
- include/net/tcp.h Linux kernel
RTO แรก TCP_TIMEOUT_INIT = 1 วินาที (ค่าเริ่มต้นตาม RFC 6298) - RFC 6298: Computing TCP's Retransmission Timer IETF
RTO เริ่มต้น 1 วินาที เพิ่มเป็นสองเท่าทุกครั้งที่ส่งซ้ำ - IP Sysctl Linux kernel
tcp_syn_retries ค่าเริ่มต้น 6, tcp_syn_linear_timeouts ค่าเริ่มต้น 4 (SYN RTO 1, 1, 1, 1, 1, 2, 4 …), ส่งซ้ำครั้งสุดท้ายที่ 67 วินาทีและเลิกที่ 131 วินาที, somaxconn ค่าเริ่มต้น 4096, tcp_syncookies ค่าเริ่มต้น 1 - tcp: make the first N SYN RTO backoffs linear Linux kernel
commit ที่เปลี่ยนการส่ง SYN ซ้ำช่วงแรกให้เว้นช่วงคงที่ ตั้งแต่ Linux 6.5 (ค่าเริ่มต้น 4 ตามแบบของ macOS และ iOS) - Android common kernels Android (Google)
รองรับ common kernel 5.10–6.18 ไปพร้อมกัน และใช้เคอร์เนลของแพลตฟอร์มก่อนหน้า (เช่น android14-6.1) กับการวางจำหน่ายหรืออัปเกรดเครื่อง Android รุ่นใหม่ได้ - TcpMaxConnectRetransmissions Microsoft
ค่าเริ่มต้นของ Windows รุ่นเก่า: ส่ง SYN ซ้ำ 2 ครั้ง รอครั้งแรก 3 วินาทีแล้วเพิ่มเป็นสองเท่า หลังครั้งสุดท้ายรออีกสองเท่าแล้วเลิก (3+6+12=21 วินาที) - TCP/IP connectivity issues troubleshooting Microsoft
จำนวนครั้งที่ส่ง SYN ซ้ำต่างกันไปตาม OS ตรวจได้จาก Max SYN Retransmissions ใน netsh int tcp show global - listen(2) — Linux manual page Linux man-pages
อาร์กิวเมนต์ backlog ของ listen ถูกตัดตาม somaxconn (ค่าเริ่มต้น 4096 ตั้งแต่ Linux 5.4 ก่อนหน้านั้น 128) - SNMP counter Linux kernel
เมื่อคิว accept เต็ม SYN จะถูกทิ้ง และ TcpExtListenOverflows กับ TcpExtListenDrops เพิ่มขึ้นพร้อมกัน, TcpExtTCPSynRetrans - net/ipv4/tcp_input.c Linux kernel
ข้อความ log “Possible SYN flooding on port …” - net/ipv4/tcp_diag.c Linux kernel
สำหรับซ็อกเก็ตที่รอเชื่อมต่อ Recv-Q ใน ss คือจำนวนการเชื่อมต่อที่รอ accept และ Send-Q คือขีดจำกัด backlog
สาเหตุที่ควรดูประกอบ
ชั้นเดียวกัน: ต้นเหตุของการส่งซ้ำใน TCP
สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (เข้าเกมไม่ได้/โหลดไม่จบ)
ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง