สถานการณ์ที่คุ้นเคย: คุณตั้งค่า proxy, เบราว์เซอร์เปิดเว็บไซต์ได้, parser เก็บข้อมูลได้, ทุกอย่างดูสมบูรณ์แบบ แต่แล้วคุณเริ่มวิดีโอคอล และคู่สนทนาไม่ได้ยินคุณ หรือคุณเข้าเกมออนไลน์ และแมตช์ไม่เชื่อมต่อ หรือคุณเปิดแชทเสียง และมันเงียบ Proxy ทำงานใช่ไหม? ทำงาน แต่มีบางอย่างพังในระดับลึก และแทบเป็นไปไม่ได้ที่จะเข้าใจโดยไม่มีความรู้เกี่ยวกับ transport

สาเหตุเกือบจะเหมือนกันเสมอ: proxy ของคุณไม่ให้ผ่าน traffic UDP และนี่ไม่ใช่ความเสียหาย แต่เป็นคุณสมบัติพื้นฐาน Proxy บางประเภทสามารถทำงานกับ UDP ได้ตามมาตรฐาน บางประเภทไม่สามารถทำได้เลย ความแตกต่างระหว่างสองโลกนี้กำหนดว่า คุณจะสามารถสื่อสารจริงบนอินเทอร์เน็ตได้ หรือแค่โหลดหน้าเว็บเท่านั้น

ในคู่มือนี้ เราจะเจาะลึกหัวข้อตั้งแต่พื้นฐานจนถึงเครื่องมือตรวจสอบเชิงปฏิบัติ คุณจะได้เรียนรู้ว่าคำสั่ง UDP ASSOCIATE ในโปรโตคอล SOCKS5 ทำงานอย่างไร, เหตุใด HTTP Proxy ผ่านเมธอด CONNECT จึงไม่สามารถส่งดาตาแกรมได้จริง, สิ่งที่เสียหายเมื่อผู้ใช้ไม่มี UDP และวิธีตรวจสอบ proxy ใด ๆ ด้วยตัวเองในเวลาเพียงไม่กี่นาทีว่า รองรับ UDP จริงหรือไม่ เราจะพูดถึงเฉพาะ transport เท่านั้น: ไม่มีการวิเคราะห์การเลือกระหว่างประเภท proxy และไม่มีคำแนะนำในการตั้งค่าแอปพลิเคชันเฉพาะ

พื้นฐาน: TCP เทียบกับ UDP, ดาตาแกรม และระดับการทำงานของ Proxy

เพื่อให้เข้าใจว่าเหตุใด UDP จึงดื้อดึงในโครงสร้างพื้นฐานของ proxy เราต้องย้อนกลับไปยังแนวคิดพื้นฐานของ transport layer อย่ากลัว: เราจะอธิบายด้วยอุปมาอุปไมยง่าย ๆ

โปรโตคอล transport สองแบบ สองปรัชญา

บนอินเทอร์เน็ต ข้อมูลถูกส่งผ่านโปรโตคอล transport หลักสองแบบ: TCP (Transmission Control Protocol) และ UDP (User Datagram Protocol) ทั้งคู่ทำงานบน IP แต่มีพฤติกรรมแตกต่างกันอย่างสิ้นเชิง

TCP เปรียบเหมือนการสนทนาทางโทรศัพท์ที่ต้องมีการยืนยันตลอดเวลา ก่อนเริ่มส่งข้อมูล ทั้งสองฝ่ายจะสร้างการเชื่อมต่อผ่านขั้นตอน handshake แต่ละแพ็กเก็ตที่ส่งไปจะได้รับการยืนยันจากผู้รับ ถ้ามีอะไรสูญหาย ก็จะส่งซ้ำ ลำดับแพ็กเก็ตได้รับการรับประกัน เป็นสตรีมที่เชื่อถือได้ เรียงตามลำดับ แต่ค่อนข้างช้า TCP เหมาะสำหรับการโหลดหน้าเว็บ ดาวน์โหลดไฟล์ ส่งอีเมล ในทุกที่ที่ข้อมูลทุกส่วนและลำดับที่ถูกต้องมีความสำคัญ

UDP เปรียบเหมือนการส่งไปรษณียบัตรโดยไม่มีการแจ้งเตือนการส่ง คุณโยน ดาตาแกรม ลงในเครือข่ายและไม่รอการยืนยัน ไม่มีการสร้างการเชื่อมต่อ ไม่มีการรับประกันการส่ง ไม่มีการรับประกันลำดับ แพ็กเก็ตอาจสูญหาย มาซ้ำ หรือสลับลำดับ และโปรโตคอลก็ไม่ใส่ใจ ฟังดูเป็นข้อเสีย? เฉพาะเมื่อมองแวบแรก ความเรียบง่ายนี้เองที่ทำให้ UDP มีข้อได้เปรียบหลัก: ความเร็วและความหน่วงต่ำที่สุด

ดาตาแกรมคืออะไร

ดาตาแกรม คือข้อมูลส่วนอิสระใน UDP แตกต่างจาก TCP ที่ข้อมูลไหลเป็นสตรีมไบต์ต่อเนื่อง ใน UDP แต่ละแพ็กเก็ตจะสมบูรณ์ในตัวเอง มันประกอบด้วยที่อยู่ปลายทาง พอร์ต และ payload ดาตาแกรมไม่รู้อะไรเกี่ยวกับดาตาแกรมที่ส่งก่อนหรือหลัง มันเหมือนจดหมายแยกแต่ละฉบับโดยไม่มีเลขลำดับในการติดต่อกัน

ทำไมสิ่งนี้ถึงสำคัญสำหรับหัวข้อของเรา? เพราะ proxy ที่สามารถส่งต่อสตรีม TCP ต่อเนื่องได้ ไม่จำเป็นต้องสามารถส่งต่อดาตาแกรม UDP ที่แยกอิสระได้ มันเป็นงานที่แตกต่างกันโดยพื้นฐานในแง่ของการใช้งาน

Proxy อาศัยอยู่ตรงไหนในห่วงโซ่

ลองนึกภาพโมเดลเครือข่ายเป็นชั้น ๆ ของอาคาร ชั้นล่างสุดคือการส่งสัญญาณทางกายภาพและการกำหนดที่อยู่ IP ถัดขึ้นมาคือ transport layer ที่มี TCP และ UDP สูงขึ้นไปคือ application layer ที่มี HTTP, DNS, โปรโตคอลการโทร

Proxy server เป็นตัวกลางที่อยู่ระหว่างคุณและทรัพยากรเป้าหมาย แต่มันทำงานในระดับไหน ขึ้นอยู่กับประเภทของ proxy และนี่คือจุดเริ่มต้นของสิ่งที่น่าสนใจ

  • HTTP proxy เดิมทีเข้าใจ application layer HTTP มันอ่านคำขอ HTTP, เห็น header, สามารถแก้ไขและแคชได้ มันคือ proxy ที่ออกแบบมาสำหรับโปรโตคอล application เฉพาะที่ทำงานบน TCP
  • SOCKS proxy ทำงานต่ำกว่า ใกล้กับ transport layer มันไม่สนใจเนื้อหาของโปรโตคอล application แต่เพียงส่งต่อการเชื่อมต่อ นั่นเป็นเหตุผลที่ SOCKS มีความยืดหยุ่นมากกว่า: ไม่สำคัญว่าคุณจะส่ง HTTP หรืออะไรที่แปลกใหม่

ความแตกต่างในระดับการทำงานนี้คือรากของเรื่องทั้งหมด HTTP proxy ถูกจำกัดอยู่ในโลกของ HTTP บน TCP SOCKS5 ถูกออกแบบมาให้เป็นตัวกลาง transport สากล และนั่นคือเหตุผลที่กลไกการส่ง UDP ถูกเพิ่มเข้าไปในสเปค

เจาะลึก: SOCKS5 ส่ง UDP อย่างไร

โปรโตคอล SOCKS5 ถูกอธิบายในมาตรฐาน RFC 1928 มันเป็นโปรโตคอลที่กะทัดรัดและสง่างาม การเข้าใจตรรกะของมันมีประโยชน์สำหรับทุกคนที่ทำงานกับ proxy อย่างจริงจัง มาวิเคราะห์คำสั่งและการส่ง UDP แบบพิเศษกัน

สามคำสั่งของ SOCKS5: CONNECT, BIND, UDP ASSOCIATE

หลังจากที่ client เชื่อมต่อกับ SOCKS5 server และผ่านขั้นตอนการตรวจสอบสิทธิ์ มันจะส่งคำขอพร้อมหนึ่งในสามคำสั่ง แต่ละคำสั่งกำหนดประเภทการทำงานที่ต้องการ

  • CONNECT (รหัส 0x01) เป็นคำสั่งที่พบบ่อยที่สุด มันบอก proxy: สร้างการเชื่อมต่อ TCP ขาออกไปยังที่อยู่และพอร์ตที่ระบุให้ฉัน จากนั้นส่งต่อไบต์ทั้งสองทิศทาง นี่คือคำสั่งที่เบราว์เซอร์ของคุณใช้เมื่อเข้าถึงอินเทอร์เน็ตผ่าน SOCKS5 99% ของ traffic ในชีวิตประจำวันผ่าน CONNECT
  • BIND (รหัส 0x02) เป็นคำสั่งสำหรับการเชื่อมต่อขาเข้า มันจำเป็นสำหรับโปรโตคอลเช่น FTP แบบคลาสสิกที่ server เริ่มต้นการเชื่อมต่อกลับไปยัง client เอง Proxy จะเปิดพอร์ตรอรับและรอการเชื่อมต่อขาเข้า ปัจจุบัน BIND ถูกใช้น้อย
  • UDP ASSOCIATE (รหัส 0x03) เป็นดาวเด่นของบทสนทนาของเรา คำสั่งนี้สร้าง association สำหรับการส่งดาตาแกรม UDP ผ่าน proxy มันคือสิ่งที่ทำให้ SOCKS5 ทำงานกับเสียง วิดีโอ เกม QUIC และ DNS บน UDP

UDP ASSOCIATE ทำงานภายในอย่างไร

นี่คือจุดที่มีเทคนิคทางสถาปัตยกรรมที่สวยงามซึ่งมักทำให้เกิดความเข้าใจผิด คำสั่ง UDP ASSOCIATE ถูกส่งผ่าน การเชื่อมต่อ TCP ใช่ คุณไม่ได้ยินผิด: เพื่อเริ่มส่ง UDP client จะสร้างการเชื่อมต่อ TCP สำหรับควบคุมกับ proxy และส่งคำสั่งผ่านมัน

ทำไมต้องมีการเชื่อมต่อ TCP สำหรับควบคุมหากเราต้องการส่ง UDP? มีหลายสาเหตุ และมันชาญฉลาดในทางปฏิบัติ

  1. การตรวจสอบสิทธิ์และการเจรจาพารามิเตอร์จะทำผ่าน TCP ได้อย่างน่าเชื่อถือ UDP ไม่เหมาะสำหรับสิ่งนี้เพราะไม่น่าเชื่อถือ
  2. การเชื่อมต่อ TCP สำหรับควบคุมทำหน้าที่เป็นตัวบ่งชี้ว่า UDP association ยังมีชีวิตอยู่ ตราบใดที่การเชื่อมต่อ TCP ยังเปิดอยู่ UDP association ก็ยังทำงาน ทันทีที่ client ปิดการเชื่อมต่อ TCP สำหรับควบคุม proxy ต้องปล่อยทรัพยากรทันทีและหยุดการส่งต่อดาตาแกรม นี่เป็นวิธีจัดการอายุการใช้งานที่สง่างาม

หลังจากได้รับคำสั่ง UDP ASSOCIATE proxy server จะจัดสรร relay-port พิเศษสำหรับ UDP และแจ้งที่อยู่และหมายเลขพอร์ตให้ client ทราบในคำตอบ client จะส่งดาตาแกรมไปที่ relay-port นี้ และ proxy จะส่งต่อต่อไปยังเป้าหมายและส่งคำตอบกลับมา

บทบาทของ relay-port และที่อยู่ผูกพัน

ในคำตอบของ UDP ASSOCIATE server จะส่งคืนฟิลด์ BND.ADDR และ BND.PORT นี่คือที่อยู่และพอร์ตที่ client ต้องส่งดาตาแกรม UDP ของตนเพื่อถ่ายทอด ประเด็นสำคัญ: ที่อยู่ในคำตอบอาจแตกต่างจากที่อยู่ที่ client เชื่อมต่อด้วย TCP client ที่มีคุณภาพควรตีความที่อยู่นี้อย่างถูกต้อง โดยเฉพาะเมื่อ server ส่งคืนที่อยู่ศูนย์ ซึ่งหมายถึงให้ใช้โฮสต์เดียวกับการเชื่อมต่อควบคุม

ในขั้นตอนนี้เองที่หลายการใช้งานสะดุด การจัดการ BND.ADDR ที่ไม่ถูกต้องทำให้ client ส่งดาตาแกรมไปผิดที่ และการส่ง UDP ก็เงียบไม่ทำงาน ทั้งที่ทางการ association ถูกตั้งค่าแล้ว

รูปแบบการห่อหุ้มดาตาแกรม UDP ใน SOCKS5

ไม่สามารถส่งดาตาแกรม UDP ไปที่ relay-port แบบเปล่า ๆ ได้ Proxy ต้องรู้ว่าจะส่งต่อไปที่ไหน ดังนั้นดาตาแกรม UDP แต่ละอันที่ client ส่งไปที่ relay-port จะถูกห่อหุ้มด้วย header พิเศษของ SOCKS5 มาวิเคราะห์ฟิลด์ต่าง ๆ เพราะการเข้าใจโครงสร้างนี้คือสิ่งที่แยกคนที่รู้จริงออกจากคนอื่น

header การห่อหุ้ม UDP ประกอบด้วยฟิลด์ดังนี้:

  • RSV (2 ไบต์) ฟิลด์สำรอง เติมด้วยศูนย์เสมอ ไว้ใช้ในอนาคต แต่ยังไม่ถูกใช้งาน
  • FRAG (1 ไบต์) หมายเลข fragment ฟิลด์นี้มีไว้สำหรับการแบ่งส่วนดาตาแกรมขนาดใหญ่ ค่า 0 หมายถึงดาตาแกรมเป็นอิสระและไม่ถูกแบ่งส่วน ในทางปฏิบัติ การแบ่งส่วน UDP ผ่าน SOCKS5 แทบไม่มีใคร implement และเซิร์ฟเวอร์และ client ส่วนใหญ่ทำงานกับ FRAG เท่ากับศูนย์เท่านั้น
  • ATYP (1 ไบต์) ประเภทที่อยู่ปลายทาง อาจเป็น 0x01 สำหรับ IPv4, 0x03 สำหรับชื่อโดเมน, 0x04 สำหรับ IPv6 ฟิลด์นี้บอก proxy ว่าจะอ่านฟิลด์ที่อยู่ถัดไปในรูปแบบใด
  • DST.ADDR (ความยาวแปรผัน) ที่อยู่ปลายทางของดาตาแกรม ความยาวขึ้นอยู่กับ ATYP: 4 ไบต์สำหรับ IPv4, 16 ไบต์สำหรับ IPv6, สำหรับชื่อโดเมน ไบต์แรกจะกำหนดความยาว ตามด้วยชื่อ
  • DST.PORT (2 ไบต์) พอร์ตปลายทางในลำดับไบต์ของเครือข่าย
  • DATA payload จริง นั่นคือดาตาแกรม UDP ดั้งเดิมของแอปพลิเคชัน

เมื่อ proxy ได้รับดาตาแกรมที่ห่อหุ้มนี้ที่ relay-port มันจะถอด header SOCKS5 อ่านที่อยู่และพอร์ตปลายทาง และส่ง payload ที่สะอาดไปยังปลายทางเป็นแพ็กเก็ต UDP ปกติ เมื่อคำตอบมา proxy จะทำตรงกันข้าม: ห่อหุ้มดาตาแกรมตอบกลับด้วย header เดียวกันแล้วส่งไปยัง client ที่ relay-port

สังเกตความสง่างามของรูปแบบนี้ Client ไม่เคยสื่อสารกับเป้าหมายโดยตรงผ่าน UDP ทุกอย่างผ่าน relay-port ของ proxy และ header การห่อหุ้มทำหน้าที่เป็นป้ายที่อยู่ มันเป็นวิธีที่เชื่อถือได้และเป็นมาตรฐานในการขนส่งดาตาแกรมที่แยกกันผ่านตัวกลาง

ทำไมฟิลด์ FRAG ถึงตายเป็นส่วนใหญ่

ควรพูดถึงการแบ่งส่วนแยกต่างหาก ในทางทฤษฎี SOCKS5 อนุญาตให้แบ่งดาตาแกรม UDP ขนาดใหญ่ออกเป็น fragment และประกอบกลับที่ proxy ในทางปฏิบัติ สิ่งนี้สร้างความซับซ้อนมหาศาล: ต้องบัฟเฟอร์ fragment จัดการ timeout การประกอบ ป้องกันการโจมตี ดังนั้นการใช้งานส่วนใหญ่จึงกำหนดให้ FRAG เท่ากับศูนย์และทิ้งส่วนอื่นทิ้ง สำหรับแอปพลิเคชัน นั่นหมายความว่า: ดาตาแกรมต้องพอดีในแพ็กเก็ตเดียว โชคดีที่โปรโตคอลจริงส่วนใหญ่ที่ใช้ UDP ก็ทำงานกับดาตาแกรมขนาดเล็กอยู่แล้ว

เหตุใด HTTP และ HTTPS Proxy ผ่าน CONNECT จึงไม่สามารถส่ง UDP

ตอนนี้เรามาถึงคำถามที่ทำให้เกิดความเข้าใจผิดมากที่สุด ผู้คนมักคิดว่า: ถ้า HTTPS proxy สามารถทำ tunnel traffic ที่เข้ารหัสผ่านเมธอด CONNECT ได้ แสดงว่ามันเป็นสากลและควรจะรองรับ UDP ได้ นี่คือความผิดพลาด และเราจะอธิบายว่าทำไมมันถึงเป็นไปไม่ได้โดยพื้นฐาน

เมธอด CONNECT ใน HTTP Proxy ทำงานอย่างไร

เมื่อเบราว์เซอร์เข้าเว็บไซต์ที่ปลอดภัยผ่าน HTTP proxy มันไม่สามารถส่งคำขอ HTTP ตรง ๆ ได้เพราะเนื้อหาถูกเข้ารหัส แต่จะส่งคำสั่งพิเศษ CONNECT ไปยัง proxy พร้อมระบุโฮสต์และพอร์ต Proxy จะสร้าง การเชื่อมต่อ TCP ไปยังโฮสต์นั้น และหลังจากสำเร็จก็ตอบกลับด้วยสถานะการสร้าง tunnel จากนั้น proxy ก็แค่ส่งต่อไบต์ระหว่าง client และ server ทั้งสองทิศทาง โดยไม่สนใจเนื้อหา

คำสำคัญที่นี่คือ TCP เมธอด CONNECT ตามสเปคของมันสร้าง TCP tunnel เท่านั้น มันเปิดการเชื่อมต่อ TCP แบบสตรีมและเชื่อมสองสตรีมไบต์เข้าด้วยกัน ในนิยามของ CONNECT ไม่มีกลไกใดสำหรับการทำงานกับดาตาแกรม

สามสาเหตุพื้นฐานของความไม่เข้ากัน

มาวิเคราะห์เป็นข้อ ๆ ว่าทำไมนี่ไม่ใช่ข้อบกพร่องทางเทคนิค แต่เป็นความเป็นไปไม่ได้ในเชิงแนวคิด

  1. CONNECT ผูกติดกับโมเดลสตรีม HTTP เป็นโปรโตคอลบน TCP เมธอด CONNECT สืบทอดธรรมชาติแบบสตรีมนี้ มันสามารถเชื่อมต่อสองสตรีม TCP แต่ UDP ไม่ใช่สตรีม แต่เป็นชุดของดาตาแกรมอิสระ ไม่มีความสอดคล้องระหว่างกัน ไม่สามารถยัดดาตาแกรมที่แตกต่างกันหลายอันที่มีที่อยู่ปลายทางต่างกันเข้าไปใน TCP tunnel เดียวโดยไม่มีโปรโตคอลการห่อหุ้มเพิ่มเติม ซึ่ง HTTP CONNECT ไม่มี
  2. ไม่มีกลไกกำหนดที่อยู่ดาตาแกรม ใน UDP แต่ละดาตาแกรมสามารถไปยังที่อยู่และพอร์ตของตัวเอง แอปพลิเคชันเสียงอาจสื่อสารกับเซิร์ฟเวอร์หลายตัวพร้อมกัน TCP tunnel ของ CONNECT เชื่อมต่อคุณกับที่อยู่เดียวที่ระบุตอนสร้าง tunnel มันไม่มีฟิลด์สำหรับระบุที่อยู่ปลายทางของแต่ละดาตาแกรม ต่างจาก SOCKS5 ที่มี header การห่อหุ้ม DST.ADDR และ DST.PORT
  3. ไม่มี relay-port สำหรับ UDP SOCKS5 จัดสรร relay-port UDP แยกต่างหากและแจ้งให้ client ทราบ HTTP proxy ไม่มีกลไกดังกล่าวเลย สถาปัตยกรรมของมันไม่ได้ออกแบบมาให้เปิด UDP socket ฝั่ง server เพื่อถ่ายทอด โค้ดของ HTTP proxy ทำงานกับการเชื่อมต่อ TCP และการเพิ่ม UDP เข้าไปก็เหมือนกับการเขียนโปรโตคอลใหม่ทั้งหมด

ข้อสรุปที่ควรจำไว้ตลอดไป

HTTP และ HTTPS proxy ไม่รองรับ UDP ไม่ใช่เพราะนักพัฒนาขี้เกียจ แต่เพราะโปรโตคอลของพวกเขาสร้างขึ้นบน TCP เท่านั้น เมธอด CONNECT คือ TCP tunnel และจบ หากคุณต้องการ UDP ผ่าน proxy ทางมาตรฐานเดียวคือ SOCKS5 ที่รองรับคำสั่ง UDP ASSOCIATE ไม่มี HTTP proxy ใด ไม่ว่าจะทันสมัยแค่ไหน ก็จะไม่ส่งต่อเสียง วิดีโอ หรือ traffic เกมผ่าน UDP ให้คุณ

สิ่งที่เสียหายเมื่อไม่มี UDP: แผนที่อาการทั้งหมด

ตอนนี้ถึงส่วนที่ใช้ได้จริงแล้ว มาวิเคราะห์ว่าเทคโนโลยีใดบ้างที่พึ่งพา UDP และอาการเสียหายที่ผู้ใช้ทั่วไปมองเห็น ซึ่งจะช่วยให้คุณวินิจฉัยปัญหาได้ทันทีจากอาการ

WebRTC และชุด STUN/TURN

WebRTC เป็นเทคโนโลยีเรียลไทม์ที่เป็นพื้นฐานของวิดีโอคอลในเบราว์เซอร์ แชทเสียง การแชร์หน้าจอ และบริการประชุมมากมาย การส่งสตรีมมีเดียนั้นใช้ UDP เพราะสำหรับการสนทนาสด ความเร็วสำคัญกว่าการรับประกันการส่งทุกแพ็กเก็ต การสูญเสียแพ็กเก็ตเล็กน้อยในเสียงแทบจะสังเกตไม่เห็น แต่ความหน่วงจากการส่ง TCP ซ้ำจะทำลายคุณภาพ

ในการสร้างการเชื่อมต่อ WebRTC ใช้โปรโตคอล STUN และ TURN STUN ช่วยค้นหาที่อยู่ภายนอกของคุณหลัง NAT ส่วน TURN ทำหน้าที่เป็นรีเลย์เมื่อไม่สามารถเชื่อมต่อโดยตรงได้ ทั้ง STUN และสตรีมมีเดียโดยค่าเริ่มต้นจะใช้ UDP

อาการที่ผู้ใช้เห็น: สายดูเหมือนจะเชื่อมต่อ มีไฟแสดงการโทร แต่คู่สนทนาไม่ได้ยินหรือเห็นคุณ หรือการสื่อสารเป็นทางเดียว บางครั้งสายหลุดหลังจากไม่กี่วินาที อินเทอร์เฟซเว็บทำงาน แชททำงาน แต่เสียงและภาพไม่มา นี่คือสัญญาณคลาสสิกของ UDP ที่ถูกบล็อก

QUIC และ HTTP/3 ที่ถอยไปใช้ TCP

QUIC เป็นโปรโตคอล transport สมัยใหม่ที่สร้างบน UDP มันใช้กับ HTTP/3 ซึ่งเป็นเวอร์ชันล่าสุดของโปรโตคอลเว็บ QUIC ให้การสร้างการเชื่อมต่อที่เร็วกว่าและจัดการกับการสูญเสียแพ็กเก็ตได้ดีกว่า TCP แบบคลาสสิก ภายในปี 2026 ส่วนใหญ่ของเว็บไซต์และบริการขนาดใหญ่รองรับ HTTP/3 แล้ว

เมื่อ UDP ไม่พร้อมใช้งาน จะเกิดสิ่งที่น่าสนใจ: แอปพลิเคชันหรือเบราว์เซอร์มักจะถอยไปใช้ HTTP/2 หรือ HTTP/1.1 บน TCP นี่เป็นกลไกการทนต่อความผิดพลาดที่ออกแบบไว้

อาการที่ผู้ใช้เห็น: ส่วนใหญ่ไม่มีความเสียหายชัดเจน เว็บไซต์เปิดได้ แต่คุณสูญเสียข้อดีของ QUIC: การเชื่อมต่อช้าลง, เครือข่ายไม่เสถียรอาจเกิดอาการกระตุก ผู้สังเกตที่มีประสบการณ์จะสังเกตว่า HTTP/3 ไม่พร้อมใช้งานแม้เซิร์ฟเวอร์จะรองรับ สำหรับคนส่วนใหญ่ นี่คือการเสื่อมสภาพที่ซ่อนเร้น ไม่ใช่ความล้มเหลวที่ชัดเจน

DNS ที่พอร์ต 53 ผ่าน UDP

การสอบถาม DNS แบบคลาสสิกนั้นใช้ UDP ที่พอร์ต 53 เป็นประเพณี มันรวดเร็วและมีประสิทธิภาพสำหรับการสอบถามชื่อสั้น ๆ

ที่นี่มีรายละเอียดที่ขึ้นอยู่กับว่าแอปพลิเคชันแก้ไขชื่ออย่างไร หากการแก้ไขเกิดขึ้นที่ฝั่ง proxy ปัญหาอาจไม่มี แต่ถ้าแอปพลิเคชันต้องการส่งคำขอ DNS UDP ผ่าน proxy เอง และ UDP ไม่รองรับ การแก้ไขจะล้มเหลว

อาการที่ผู้ใช้เห็น: ชื่อเว็บไซต์ไม่ถูกแก้ไข แอปพลิเคชันแจ้งว่าไม่พบโฮสต์แม้อินเทอร์เน็ตจะทำงาน บางครั้งมีความหน่วงเมื่อระบบพยายามใช้ UDP ไม่ได้รับคำตอบ แล้วเปลี่ยนไปใช้ DNS แบบ TCP

VoIP และการสื่อสารด้วยเสียง

VoIP คือการส่งเสียงผ่านอินเทอร์เน็ต โปรโตคอลเสียงเกือบทั้งหมดใช้ UDP สำหรับการส่งเสียงเพราะความหน่วงเป็นสิ่งสำคัญ การสนทนาสดเป็นไปไม่ได้ถ้าทุกแพ็กเก็ตรอการยืนยัน

อาการที่ผู้ใช้เห็น: สายเชื่อมต่อแต่ไม่มีเสียง เสียงขาดหรือล่าช้ามาก ได้ยินทางเดียว มีเสียงโลหะ หลุดหลังจากไม่กี่วินาทีของการสนทนา ทั้งหมดนี้เป็นสัญญาณของปัญหากับ UDP transport

เกมออนไลน์

เกมเครือข่ายหลายเกม โดยเฉพาะเกมยิงมุมมองบุคคลที่หนึ่งและเกมแข่งขัน ใช้ UDP สำหรับส่งสถานะของโลกในเกม เหตุผลก็เหมือนเดิม: ความหน่วงสำคัญกว่าการรับประกันการส่ง แพ็กเก็ตตำแหน่งผู้เล่นที่ล้าสมัยไร้ประโยชน์ ควรได้รับข้อมูลล่าสุดดีกว่า

อาการที่ผู้ใช้เห็น: เกมไม่เชื่อมต่อกับแมตช์ ค้างที่หน้าจอเชื่อมต่อ หลุดเพราะ timeout หรือเชื่อมต่อได้แต่เล่นกระตุก ตัวละครเทเลพอร์ต การกระทำไม่ถูกลงทะเบียน เมนูและร้านค้าอาจทำงานได้เพราะมักใช้ HTTP บน TCP

Torrent และ P2P

โปรโตคอล P2P จำนวนมากใช้ UDP สำหรับการแลกเปลี่ยนข้อมูลควบคุมและการส่งข้อมูลอย่างจริงจัง หากไม่มี UDP ฟังก์ชันการทำงานจะลดลง: กลไกการค้นหาโหนดและการส่งข้อมูลบางส่วนไม่ทำงาน

อาการที่ผู้ใช้เห็น: การทำงานช้าลง ปัญหาในการค้นหาแหล่งที่มา ฟังก์ชันไม่สมบูรณ์

ตารางสรุปการพึ่งพา UDP ของสถานการณ์ต่าง ๆ

ด้านล่างคือตารางที่ใช้ได้จริงที่ควรบันทึกไว้ มันจะบอกคุณทันทีว่าควรคาดหวังอะไรในแต่ละสถานการณ์

  • วิดีโอคอลและวิดีโอแชท ใช้ UDP: ใช่ สำคัญมาก หากไม่รองรับ UDP: สายเชื่อมต่อได้ทางภาพแต่ไม่มีเสียงและวิดีโอ การสื่อสารทางเดียวหรือหลุด ฟังก์ชันหลักไม่ทำงาน
  • เกมออนไลน์ ใช้ UDP: ใช่ สำหรับเกมแข่งขันส่วนใหญ่ หากไม่รองรับ UDP: ไม่เชื่อมต่อแมตช์, timeout, กระตุก, เทเลพอร์ต การเล่นเกมเป็นไปไม่ได้หรือเสื่อมสภาพอย่างมาก
  • การสอบถาม DNS ใช้ UDP: ใช่ DNS คลาสสิกที่พอร์ต 53 หากไม่รองรับ UDP: อาจมีปัญหาการแก้ไขชื่อหรือหน่วง ถ้าแก้ไขที่ฝั่ง proxy อาจไม่มีปัญหา
  • QUIC และ HTTP/3 ใช้ UDP: ใช่ สร้างบน UDP ทั้งหมด หากไม่รองรับ UDP: ถอยไปใช้ TCP HTTP/2 อย่างไม่รู้ตัว เสียความเร็วและข้อดี แต่เว็บไซต์ยังเปิดได้
  • Torrent และ P2P ใช้ UDP: ใช่ สำหรับหลายกลไก หากไม่รองรับ UDP: ฟังก์ชันเสื่อม ปัญหาการค้นหาแหล่งและการส่งข้อมูล
  • การ parse และ web scraping ทั่วไป ใช้ UDP: ไม่ ปกติใช้ TCP ผ่าน HTTP ล้วน ๆ หากไม่รองรับ UDP: ทุกอย่างทำงานปกติ ไม่จำเป็นต้องใช้ UDP
  • การโทร VoIP ใช้ UDP: ใช่ สำหรับสตรีมเสียง หากไม่รองรับ UDP: ไม่มีเสียง หลุด หน่วง ได้ยินทางเดียว

สังเกตบรรทัดสุดท้าย สำหรับงานคลาสสิกเช่นการ parse หรือการท่องเว็บทั่วไป ไม่จำเป็นต้องใช้ UDP เลย นั่นคือเหตุผลที่หลายคนใช้ proxy โดยไม่มี UDP เป็นเวลาหลายปีโดยไม่รู้ถึงข้อจำกัด จนกระทั่งเจอการโทรหรือเกม

การตรวจสอบเชิงปฏิบัติ: จะรู้ได้อย่างไรว่า proxy รองรับ UDP

ถึงเวลาเครื่องมือแล้ว เราจะอธิบายหลายวิธีตรวจสอบ ตั้งแต่ง่ายไปจนถึงขั้นสูง และอธิบายว่าทำไมวิธีที่นิยมมักทำให้เข้าใจผิด

ทำไม curl ตรวจสอบได้แค่ TCP

หลายคนลองตรวจสอบ proxy ด้วยคำสั่ง curl ผ่าน socks5-hostname ไปยังเว็บไซต์บางแห่ง ถ้าคำขอผ่านก็สรุปว่า proxy ทำงาน แสดงว่า UDP ก็ทำงานด้วย นี่คือกับดัก

ความจริงคือ คำขอ HTTP ผ่าน curl ใช้ TCP คำสั่งที่มีแฟล็ก socks5-hostname ตรวจสอบว่า SOCKS5 proxy สามารถ执行คำสั่ง CONNECT และแก้ไขชื่อได้ที่ฝั่งตัวเอง แต่ CONNECT คือ TCP ความสำเร็จของการตรวจสอบนี้บอกแค่ว่า TCP ผ่าน proxy ทำงานได้ มันไม่ได้บอกอะไรเกี่ยวกับการรองรับ UDP ASSOCIATE

จำกฎเหล็กนี้: การตรวจสอบด้วยเครื่องมือ TCP ไม่ได้ตรวจสอบ UDP ในการตรวจสอบ UDP คุณต้องเริ่มคำสั่ง UDP ASSOCIATE อย่างชัดเจนและพยายามส่งดาตาแกรม

วิธีที่ 1: สคริปต์ Python ผ่าน socket

วิธีที่โปร่งใสที่สุดในการเข้าใจและตรวจสอบ UDP ASSOCIATE คือเขียนสคริปต์ขนาดเล็กที่ทำงานกับ socket โดยตรง เราจะอธิบายตรรกะทีละขั้นตอน โดยไม่ยึดติดกับโค้ดเฉพาะ เพื่อให้คุณเข้าใจแนวคิด

  1. เปิดการเชื่อมต่อ TCP ไปยัง proxy เชื่อมต่อไปยังโฮสต์และพอร์ตของ SOCKS5 server ด้วย TCP socket ธรรมดา
  2. ผ่านขั้นตอน handshake ส่งเวอร์ชันโปรโตคอลและรายการวิธีการตรวจสอบสิทธิ์ที่รองรับ รับวิธีการที่ server เลือก ถ้าจำเป็น ให้ทำการตรวจสอบสิทธิ์ด้วยชื่อผู้ใช้และรหัสผ่าน
  3. ส่งคำสั่ง UDP ASSOCIATE สร้างคำขอด้วยเวอร์ชัน, รหัสคำสั่ง 0x03, ไบต์สำรอง และที่อยู่ โดยปกติที่อยู่และพอร์ตจะระบุเป็นศูนย์ หมายความว่า client ยังไม่รู้ว่าจะส่งดาตาแกรมจากที่อยู่ใด
  4. อ่านคำตอบจาก server นี่คือจุดสำคัญ ฟิลด์แรกหลังจากเวอร์ชันคือรหัสคำตอบ ค่า 0x00 หมายถึงสำเร็จ ถ้าคุณเห็น 0x07 นั่นคือ Command not supported แสดงว่า proxy ไม่รองรับ UDP ASSOCIATE รหัสที่ไม่ใช่ศูนย์อื่น ๆ ก็บ่งชี้ข้อผิดพลาด
  5. แยก relay-address เมื่อสำเร็จ ให้อ่าน BND.ADDR และ BND.PORT จากคำตอบ นี่คือที่อยู่และพอร์ตสำหรับส่งดาตาแกรมของคุณ
  6. ส่งดาตาแกรมทดสอบ สร้าง UDP socket, ห่อ payload ทดสอบด้วย header SOCKS5 ที่มีฟิลด์ RSV, FRAG, ATYP, DST.ADDR, DST.PORT และส่งไปที่ relay-port ควรเลือกเป้าหมายเป็นบริการสาธารณะที่ตอบกลับทาง UDP
  7. รอคำตอบ ถ้าได้รับคำตอบที่ห่อหุ้มอย่างถูกต้อง แสดงว่า UDP ผ่าน proxy ทำงานจริง ถ้าเงียบแม้รหัสคำตอบจะสำเร็จ แสดงว่า association มีอยู่แต่การส่งต่อดาตาแกรมจริงไม่ทำงาน

วิธีนี้ให้ภาพที่สมบูรณ์ คุณจะตรวจสอบแยกกันว่า server ยอมรับคำสั่ง UDP ASSOCIATE หรือไม่ และตรวจสอบแยกว่าดาตาแกรมส่งจริงหรือไม่

วิธีที่ 2: คำขอ STUN ผ่าน proxy

การทดสอบเชิงปฏิบัติที่ยอดเยี่ยมคือใช้คำขอ STUN เป็น payload STUN เป็นโปรโตคอลน้ำหนักเบา เซิร์ฟเวอร์ STUN สาธารณะตอบกลับเร็ว และการทดสอบนี้ใกล้เคียงกับสถานการณ์จริงของ WebRTC มากที่สุด

ตรรกะเหมือนกัน: สร้าง UDP association, ห่อคำขอ STUN แบบ Binding Request ด้วย header การห่อหุ้ม SOCKS5, ส่งไปที่ relay-port พร้อมที่อยู่ของเซิร์ฟเวอร์ STUN สาธารณะ ถ้าได้รับคำตอบ STUN ที่มีที่อยู่ภายนอกของคุณ แสดงว่าเส้นทาง UDP ผ่าน proxy ทำงานสมบูรณ์ รวมถึงการส่งสองทิศทาง นี่คือการทดสอบที่น่าเชื่อถือที่สุดสำหรับสถานการณ์เรียลไทม์

วิธีที่ 3: dig ผ่าน proxy สำหรับ DNS ทาง UDP

คำขอ DNS ก็เป็นการทดสอบที่ดี เพราะเป็นดาตาแกรม UDP ขนาดกะทัดรัดที่มีคำตอบที่เข้าใจได้ แนวคิดคือส่งคำขอ DNS ทาง UDP ผ่าน SOCKS5 proxy ไปยังเซิร์ฟเวอร์ DNS สาธารณะ

dig มาตรฐานไม่สามารถผ่าน SOCKS5 ทาง UDP ได้ด้วยตัวเอง จึงมักใช้ wrapper ที่ช่วยนำทาง traffic UDP ผ่าน proxy หรือ implement การห่อหุ้มด้วยตนเองตามรูปแบบที่อธิบายไว้ข้างต้น ถ้าคำตอบ DNS มา แสดงว่าช่อง UDP ทำงาน ถ้าคำขอหายไปในอากาศ แต่ TCP ทำงาน ข้อสรุปชัดเจน: UDP ไม่รองรับ

วิธีที่ 4: socat และยูทิลิตี้เสริม

ยูทิลิตี้ socat เป็นเครื่องมืออเนกประสงค์สำหรับทำงานกับ socket คุณสามารถสร้างห่วงโซ่การเปลี่ยนเส้นทาง รวมถึงการเชื่อมต่อ UDP และ SOCKS อย่างไรก็ตาม สิ่งสำคัญคือต้องเข้าใจข้อจำกัด: ไม่ใช่ทุกเวอร์ชันและโหมดของ socat ที่รองรับ UDP ASSOCIATE โดยตรง บ่อยครั้งที่ socat ถูกใช้ร่วมกับเลเยอร์กลางที่จัดการการห่อหุ้ม SOCKS5 UDP ในขณะที่ socat รับผิดชอบการเปลี่ยนเส้นทาง UDP ในเครื่อง

แนวทางปฏิบัติ: เปิดตัวรับ UDP ในเครื่อง, ส่ง traffic UDP ผ่านเลเยอร์กลางไปยัง proxy และตรวจสอบว่า payload ถึงเป้าหมายและได้รับคำตอบกลับหรือไม่ นี่เป็นแนวทางทางวิศวกรรม มีประโยชน์ในการดีบักโครงสร้างพื้นฐาน

วิธีการอ่านรหัสคำตอบ 0x07 อย่างถูกต้อง

รหัส 0x07 Command not supported เป็นสัญญาณที่ตรงไปตรงมาที่สุด มันหมายความว่า SOCKS5 server ได้รับคำสั่ง UDP ASSOCIATE ของคุณ, รู้จักมัน, แต่ตอบว่า: ฉันไม่执行คำสั่งนี้ คำตอบแบบนี้เป็นเรื่องปกติสำหรับ proxy ที่ implement เฉพาะ CONNECT

อย่างไรก็ตาม ควรระวังสถานการณ์ที่ร้ายกาจกว่า บางครั้ง server ตอบกลับด้วยรหัสสำเร็จ 0x00 ต่อคำสั่ง UDP ASSOCIATE แต่การส่งต่อดาตาแกรมจริงไม่ทำงาน สาเหตุต่างกัน: ตัวกรองเครือข่ายระหว่าง proxy และเป้าหมาย, การจัดการ relay-address ไม่ถูกต้อง, ข้อจำกัดของโฮสติ้ง ดังนั้นการตรวจสอบแค่รหัสคำตอบไม่เพียงพอ การตรวจสอบที่แท้จริงคือการส่งดาตาแกรมจากต้นทางถึงปลายทางที่สำเร็จและได้รับคำตอบ นั่นคือเหตุผลที่เราย้ำให้ใช้การทดสอบ STUN หรือ DNS ที่มีคำตอบจริง

รายการตรวจสอบการรองรับ UDP ของ proxy

  • ตรวจสอบว่าคุณกำลังทดสอบ SOCKS5 ไม่ใช่ HTTP proxy เพราะ HTTP proxy ไม่รองรับ UDP โดยนิยาม
  • สร้างการเชื่อมต่อ TCP สำหรับควบคุมและผ่านการตรวจสอบสิทธิ์
  • ส่งคำสั่ง UDP ASSOCIATE และตรวจสอบรหัสคำตอบ 0x00 ดี, 0x07 หมายถึงไม่รองรับ
  • แยกและตีความ BND.ADDR และ BND.PORT อย่างถูกต้อง โดยคำนึงถึงกรณีที่อยู่ศูนย์
  • ส่งดาตาแกรมทดสอบจริงที่ห่อหุ้มตามรูปแบบ
  • รอคำตอบที่ห่อหุ้มอย่างถูกต้อง นี่คือสิ่งเดียวที่ยืนยันว่า UDP ทำงาน
  • ทดสอบซ้ำหลายครั้งเพื่อขจัดการสูญเสียแพ็กเก็ตแบบสุ่ม

UDP ในเครือข่ายมือถือ: NAT timeout และ keepalive

หัวข้อแยกที่สำคัญมากคือพฤติกรรมของ UDP ในเครือข่ายมือถือ ที่นี่เป็นสาเหตุของการหลุดลึกลับที่ดูเหมือนอธิบายไม่ได้

ทำไม UDP session ถึงหลุดเร็วกว่า TCP

ระหว่างอุปกรณ์ของคุณกับอินเทอร์เน็ตมักจะมี NAT กลไกการแปลที่อยู่เครือข่าย NAT เก็บตารางการจับคู่ระหว่างที่อยู่ภายในและภายนอกและพอร์ต สำหรับแต่ละการเชื่อมต่อ จะมีรายการในตารางนี้ และมันมีอายุจำกัด

และนี่คือความแตกต่างสำคัญ สำหรับ TCP NAT มีสัญญาณเริ่มต้นและสิ้นสุดการเชื่อมต่อที่ชัดเจน: มันเห็น handshake และเห็นการปิด ดังนั้นรายการ TCP ในตาราง NAT มักมีอายุยืนยาว บางครั้งหลายสิบนาทีหรือนานกว่านั้น

สำหรับ UDP ทุกอย่างแตกต่าง UDP ไม่มีแนวคิดเรื่องการเชื่อมต่อ ดังนั้น NAT ไม่รู้ว่า session เริ่มต้นและสิ้นสุดเมื่อไหร่ มันแค่เก็บรายการไว้ตราบใดที่มี traffic ผ่าน และลบออกหลังจากช่วงเงียบ ช่วงเงียบนี้เรียกว่า UDP NAT timeout และในเครือข่ายมือถือ มันมักสั้นมาก บางครั้งเพียงไม่กี่สิบวินาที

ผลลัพธ์: หากไม่มี traffic ในช่อง UDP เป็นระยะเวลาหนึ่ง NAT จะลบรายการอย่างเงียบ ๆ ดาตาแกรมของคุณที่ตามมาจะไม่สามารถส่งกลับมาได้ และ session จะหลุด ในขณะที่การเชื่อมต่อ TCP ในสภาพเดียวกันยังคงมีชีวิตอยู่

ทำไมต้องใช้ keepalive

Keepalive คือการส่งแพ็กเก็ตขนาดเล็กเป็นประจำเพื่อให้ NAT คิดว่า session ยังทำงานอยู่และไม่ลบรายการ สำหรับ UDP keepalive มีความสำคัญเป็นพิเศษเพราะ timeout สั้น

โปรโตคอลเรียลไทม์ที่ออกแบบมาอย่างดีจะส่ง keepalive หรือแพ็กเก็ตควบคุมเป็นระยะเอง ตัวอย่างเช่น ใน WebRTC กลไกการตรวจสอบการเชื่อมต่อจะยืนยันเส้นทางอยู่เสมอ แต่ถ้าแอปพลิเคชันเงียบ และ NAT timeout สั้น การหลุดเป็นสิ่งที่หลีกเลี่ยงไม่ได้ ดังนั้นเมื่อทำงานกับ UDP ผ่าน proxy ในเครือข่ายมือถือ ควรคำนึงถึงความจำเป็นในการรักษาช่องทางให้มีชีวิต

ข้อสังเกตเชิงปฏิบัติเกี่ยวกับเครือข่ายมือถือ

  • ผู้ให้บริการมือถือมักมีนโยบายที่เข้มงวดกว่าเกี่ยวกับ UDP มากกว่า TCP เพื่อประหยัดทรัพยากร NAT
  • UDP NAT timeout อาจแตกต่างกันไปในแต่ละผู้ให้บริการและเปลี่ยนแปลงตามเวลา ดังนั้นไม่มีค่าเดียว
  • อาการของ timeout สั้น: การเชื่อมต่อทำงานได้ดีในช่วง active แต่หลุดระหว่างหยุด ตัวอย่างเช่น เมื่อคู่สนทนาเงียบในการโทร
  • การเชื่อมต่อ TCP สำหรับควบคุมของ SOCKS5 สำหรับ UDP association ก็ต้องรักษาให้มีชีวิตอยู่ด้วย ไม่เช่นนั้น proxy จะปิด association ทั้งหมด

นี่คือประเด็นละเอียดที่แยกความเข้าใจผิวเผินจากความเข้าใจลึก แม้เมื่อ proxy รองรับ UDP ASSOCIATE อย่างถูกต้อง ความไม่เสถียรอาจมาจาก NAT ของมือถือ ไม่ใช่จาก proxy เอง เมื่อวินิจฉัยการหลุด ให้คำนึงถึงปัจจัย timeout เสมอ

ข้อผิดพลาดทั่วไปเมื่อทำงานกับ UDP ผ่าน proxy

มารวบรวมความเข้าใจผิดที่พบบ่อยที่สุดไว้ในที่เดียว การหลีกเลี่ยงสิ่งเหล่านี้จะช่วยประหยัดเวลาดีบักหลายชั่วโมง

ข้อผิดพลาดที่ 1: สับสนระหว่าง socks5 และ socks5h

ในการตั้งค่าเครื่องมือหลายตัว มีสองรูปแบบการเขียน SOCKS5 โครงร่าง socks5 โดยทั่วไปหมายถึงการแก้ไขชื่อโดเมนทำในเครื่องฝั่ง client และ proxy จะได้รับที่อยู่ IP ที่พร้อมแล้ว โครงร่าง socks5h หมายถึงการแก้ไขชื่อทำที่ฝั่ง proxy server

ทำไมสิ่งนี้ถึงสำคัญ? ประการแรก การแก้ไขชื่อในเครื่องอาจรั่วไหลผ่าน DNS ปกติของคุณ ซึ่งไม่เป็นที่ต้องการสำหรับงานที่ต้องการความเป็นส่วนตัว ประการที่สอง หากเลือกรูปแบบผิด ตรรกะบางส่วนอาจทำงานไม่ตรงตามที่คาดหวัง ความสับสนระหว่าง socks5 และ socks5h ก่อให้เกิดบั๊กที่จับได้ยาก ซึ่งดูเหมือน proxy ทำงานเป็นบางครั้ง ให้เลือกอย่างมีสติเสมอว่าแก้ไขชื่อที่ไหน

ข้อผิดพลาดที่ 2: คิดว่าเป็น SOCKS5 แสดงว่า UDP ทำงาน

นี่อาจเป็นความเข้าใจผิดที่พบบ่อยที่สุดและอันตรายที่สุด มาตรฐาน SOCKS5 กำหนดให้มี คำสั่ง UDP ASSOCIATE แต่ ไม่ได้บังคับ ให้ทุกการใช้งานรองรับมัน SOCKS5 proxy จำนวนมาก implement แค่ CONNECT และ BIND และตอบกลับ UDP ASSOCIATE ด้วยรหัส 0x07

กล่าวอีกนัยหนึ่ง คำว่า SOCKS5 ไม่ใช่การรับประกัน UDP มันเป็นเพียงความเป็นไปได้ที่อาจมีหรือไม่มี การรู้แน่ชัดต้องตรวจสอบตามที่เราอธิบายไว้ อย่าเชื่อถือฉลากการตลาด จงเชื่อถือการทดสอบจริง

ข้อผิดพลาดที่ 3: ตรวจสอบ UDP ด้วยเบราว์เซอร์

บางคนพยายามตรวจสอบการรองรับ UDP โดยเปิดเว็บไซต์ผ่าน proxy ในเบราว์เซอร์ แต่เบราว์เซอร์เข้าถึงเว็บไซต์ด้วย TCP ต่อให้เว็บไซต์รองรับ HTTP/3 ผ่าน UDP ถ้า UDP ไม่พร้อมใช้งาน เบราว์เซอร์จะถอยไปใช้ TCP อย่างเงียบ ๆ และคุณจะไม่สังเกตเห็น การเปิดหน้าเว็บสำเร็จไม่ได้พิสูจน์ว่า UDP ทำงาน

ยิ่งไปกว่านั้น WebRTC ในเบราว์เซอร์มีตรรกะซับซ้อนในการเลี่ยงข้อจำกัดเครือข่าย และอาจใช้ TURN บน TCP ในบางการกำหนดค่า ซึ่งยิ่งทำให้ภาพคลุมเครือ ดังนั้นเบราว์เซอร์จึงเป็นเครื่องมือที่ไม่ดีสำหรับการตรวจสอบ UDP transport แบบบริสุทธิ์ ใช้การทดสอบ socket โดยตรง

ข้อผิดพลาดที่ 4: ละเลยการตรวจสอบจากต้นทางถึงปลายทาง

ดังที่เราเน้นย้ำแล้ว รหัส 0x00 จาก UDP ASSOCIATE ไม่เท่ากับ UDP ที่ใช้งานได้ การพึ่งพาแค่รหัสคำตอบเป็นข้อผิดพลาด ควรทำการทดสอบให้ถึงขั้นแลกเปลี่ยนดาตาแกรมจริงและได้รับคำตอบเสมอ นี่คือสิ่งที่แยกการรองรับทางการออกจากการทำงานจริง

ข้อผิดพลาดที่ 5: ไม่คำนึงถึง keepalive และ timeout

หลังจากตั้งค่า UDP ได้แล้ว มักลืม NAT timeout ทำให้ช่องทำงานตอนทดสอบ แต่หลุดระหว่างหยุดในการใช้งานจริง ควรวางกลไกการรักษาช่องให้มีชีวิตอยู่เสมอ โดยเฉพาะในเครือข่ายมือถือ

ข้อผิดพลาดที่ 6: จัดการ relay-address ไม่ถูกต้อง

ดังที่กล่าวไว้ server อาจส่งคืนที่อยู่ศูนย์ใน BND.ADDR ซึ่งหมายถึงโฮสต์เดียวกับการเชื่อมต่อควบคุม Client ที่ส่งดาตาแกรมไปยังที่อยู่ศูนย์อย่างมืดบอดจะพัง การใช้งานที่ถูกต้องจะใช้ที่อยู่ proxy จากการเชื่อมต่อ TCP รายละเอียดนี้เป็นสาเหตุของความล้มเหลวเงียบ ๆ มากมาย

เครื่องมือและทรัพยากรสำหรับการทำงานกับ UDP ผ่าน SOCKS5

มาสรุปคลังอาวุธที่ควรมีไว้ใกล้มือ

เครื่องมือวินิจฉัย

  • สคริปต์ Python ของคุณเองผ่าน socket เครื่องมือที่ยืดหยุ่นและโปร่งใสที่สุด ให้การควบคุมเต็มรูปแบบในการสร้างคำสั่ง UDP ASSOCIATE และการห่อหุ้มดาตาแกรม เหมาะสำหรับการวินิจฉัยที่แม่นยำ
  • STUN client ผ่าน proxy การทดสอบที่ดีที่สุดสำหรับสถานการณ์เรียลไทม์ คำตอบรวดเร็ว ผลลัพธ์เข้าใจง่าย ใกล้เคียงกับ WebRTC มากที่สุด
  • การทดสอบ DNS ทาง UDP กะทัดรัดและชัดเจน เหมาะสำหรับตรวจสอบการส่งต่อดาตาแกรมสั้นจากต้นทางถึงปลายทาง
  • socat และเลเยอร์กลางสำหรับการห่อหุ้ม UDP ชุดเครื่องมือทางวิศวกรรมสำหรับสร้างและดีบักห่วงโซ่การเปลี่ยนเส้นทาง UDP ผ่าน SOCKS5
  • เครื่องวิเคราะห์ traffic การสังเกตแพ็กเก็ตช่วยให้เห็นว่าดาตาแกรมถูกส่งไปที่ relay-port จริงหรือไม่ และได้รับคำตอบหรือไม่ ขาดไม่ได้เมื่อดีบักเชิงลึก

สิ่งที่ควรรู้เกี่ยวกับมาตรฐาน

เอกสารสำคัญเกี่ยวกับ SOCKS5 คือ RFC 1928 ซึ่งอธิบายคำสั่ง รูปแบบคำขอและคำตอบ และการห่อหุ้ม UDP การเข้าใจมาตรฐานนี้คือสิ่งที่แยกผู้เชี่ยวชาญจากผู้ใช้ที่เดาสุ่ม นอกจากนี้ การเข้าใจหลักการของ STUN, QUIC และการทำงานของ NAT ก็มีประโยชน์ เพราะปัญหาที่เกิดขึ้นจริงมักเกิดที่จุดเชื่อมต่อของเทคโนโลยีเหล่านี้

กรอบการตัดสินใจแบบย่อ

  1. พิจารณาว่าคุณต้องการ UDP หรือไม่ สำหรับการ parse และเว็บทั่วไป ไม่จำเป็น, สำหรับการโทร เกม เรียลไทม์ จำเป็น
  2. ถ้าต้องการ UDP ตรวจสอบว่า proxy เป็น SOCKS5 ไม่ใช่ HTTP
  3. ตรวจสอบการรองรับ UDP ASSOCIATE จริงด้วยการทดสอบจากต้นทางถึงปลายทาง ไม่ใช่จากฉลาก
  4. คำนึงถึง keepalive และ NAT timeout โดยเฉพาะในเครือข่ายมือถือ
  5. จัดการ relay-address และรูปแบบการห่อหุ้มอย่างถูกต้อง

กรณีศึกษาและผลลัพธ์การประยุกต์ใช้

มาวิเคราะห์สถานการณ์ทั่วไปที่แสดงให้เห็นว่าความรู้ด้าน transport แก้ปัญหาจริงได้อย่างไร

กรณีที่ 1: วิดีโอคอลที่เงียบ

สถานการณ์ ผู้ใช้บ่นว่าผ่าน proxy เปิดเว็บไซต์ได้ทั้งหมด แชทในการประชุมทำงาน แต่ระหว่างโทรไม่มีเสียงและวิดีโอ คู่สนทนาเห็นสัญญาณการเชื่อมต่อแต่ไม่มีการสื่อสาร

การวินิจฉัย การตรวจสอบ TCP ผ่าน proxy สำเร็จ ซึ่งทำให้สับสนในช่วงแรก จากนั้นทำการทดสอบ STUN แบบครบวงจรผ่าน UDP ASSOCIATE Server ตอบกลับคำสั่งด้วยรหัส 0x07 Command not supported

ข้อสรุป Proxy implement เฉพาะ CONNECT, ไม่รองรับ UDP เลย สตรีมมีเดีย WebRTC ผ่าน UDP ไม่ได้ จึงเงียบ วิธีแก้ในระดับ transport: ต้องการ SOCKS5 ที่รองรับ UDP ASSOCIATE จริง ยืนยันด้วยการทดสอบครบวงจร

กรณีที่ 2: การเชื่อมต่อหลุดระหว่างหยุดในเครือข่ายมือถือ

สถานการณ์ การสื่อสารด้วยเสียงผ่าน proxy ในเครือข่ายมือถือทำงานได้ดีระหว่างพูดคุย แต่เมื่อทั้งสองฝ่ายเงียบประมาณครึ่งนาที การเชื่อมต่อจะหลุด

การวินิจฉัย การทดสอบ UDP ครบวงจรสำเร็จ ดาตาแกรมไปกลับได้ แสดงว่า proxy รองรับ UDP การสังเกตพฤติกรรมพบว่าการหลุดเกิดขึ้นในช่วงที่ไม่มี traffic จริง

ข้อสรุป ผู้ร้ายคือ UDP NAT timeout สั้นของผู้ให้บริการมือถือ รายการในตาราง NAT ถูกลบระหว่างเงียบ วิธีแก้ในระดับ transport: จัดให้มี keepalive ที่รักษาช่องทางและการเชื่อมต่อ TCP สำหรับควบคุมให้มีชีวิตอยู่

กรณีที่ 3: ความมั่นใจที่ผิดพลาดจากรหัส 0x00

สถานการณ์ วิศวกรตรวจสอบ proxy โดยส่งคำสั่ง UDP ASSOCIATE ได้รหัสสำเร็จ 0x00 และประกาศว่า UDP ทำงาน แต่ผู้ใช้ยังบ่นว่าโทรไม่ทำงาน

การวินิจฉัย การตรวจสอบซ้ำไปไกลกว่ารหัสคำตอบ: ส่งดาตาแกรม STUN จริงไปที่ relay-port ไม่ได้รับคำตอบแม้รหัสจะสำเร็จ

ข้อสรุป มีการรองรับทางการ แต่การส่งต่อจริงไม่มี อาจเกิดจากการกรองระหว่าง proxy และเครือข่ายภายนอก หรือข้อผิดพลาดในการจัดการ relay-address บทเรียน: รหัส 0x00 ไม่เพียงพอ มีเพียงการส่งดาตาแกรมครบวงจรเท่านั้นที่พิสูจน์การทำงาน

กรณีที่ 4: การเสื่อมสภาพที่ซ่อนเร้นของ HTTP/3

สถานการณ์ ทุกอย่างดูเหมือนทำงาน เว็บไซต์เปิดได้ ไม่มีข้อร้องเรียน แต่ทีมสังเกตว่าการเชื่อมต่อช้ากว่าที่คาด และ HTTP/3 ไม่ถูกใช้ที่ไหน

การวินิจฉัย การตรวจสอบพบว่า UDP ผ่าน proxy ไม่ผ่าน ดังนั้น QUIC ไม่พร้อมใช้งาน และ client ถอยไปใช้ TCP อย่างเงียบ ๆ

ข้อสรุป นี่ไม่ใช่ความเสียหาย แต่เป็นการสูญเสียประสิทธิภาพที่ซ่อนเร้น การเข้าใจ transport ช่วยให้ตัดสินใจอย่างมีสติว่า QUIC สำคัญต่องานหรือไม่ และจำเป็นต้องรองรับ UDP หรือไม่

FAQ: คำถามที่พบบ่อย

เป็นไปได้ไหมที่จะส่ง UDP ผ่าน HTTP proxy ด้วยวิธีใด ๆ?

ด้วยวิธีมาตรฐานไม่มี เมธอด CONNECT ใน HTTP proxy สร้างเฉพาะ TCP tunnel และไม่มีกลไกในการกำหนดที่อยู่และส่งต่อดาตาแกรม ความพยายามใด ๆ ในการส่ง UDP ผ่าน HTTP proxy ล้วนสะดุดเพราะไม่มีโปรโตคอลที่เกี่ยวข้อง สำหรับ UDP ควรใช้ SOCKS5 กับคำสั่ง UDP ASSOCIATE นี่คือทางที่ถูกต้องและเป็นมาตรฐาน

ถ้า proxy เรียกว่า SOCKS5 แสดงว่ารองรับ UDP จริงไหม?

ไม่ และนี่คือประเด็นสำคัญ มาตรฐานกำหนดให้มี UDP ASSOCIATE แต่ไม่บังคับให้ implement SOCKS5 proxy หลายตัวรองรับเฉพาะ CONNECT วิธีเดียวที่จะแน่ใจคือทำการทดสอบครบวงจรด้วยการส่งดาตาแกรมจริง ไม่ใช่เชื่อชื่อหรือการตลาด

ทำไม curl แสดงว่า proxy ทำงาน แต่การโทรไม่ทำงาน?

เพราะ curl ตรวจสอบ TCP ผ่านคำสั่ง CONNECT แต่การโทรใช้ UDP เป็นคนละ transport ความสำเร็จของการตรวจสอบ TCP ไม่ได้บอกอะไรเกี่ยวกับ UDP ในการตรวจสอบ UDP ต้องเริ่ม UDP ASSOCIATE และส่งดาตาแกรม เช่น คำขอ STUN แล้วรอคำตอบ

รหัสคำตอบ 0x07 เมื่อพยายาม UDP ASSOCIATE หมายถึงอะไร?

นี่คือ Command not supported Proxy ได้รับคำสั่งของคุณ รู้จักมัน แต่แจ้งว่าไม่执行 UDP ASSOCIATE ในทางปฏิบัติหมายถึง proxy ไม่สามารถส่งต่อ UDP ได้ คุณต้องใช้ proxy อื่นที่รองรับคำสั่งนี้จริง

ทำไม UDP ASSOCIATE ถึงใช้การเชื่อมต่อ TCP ในเมื่อเราส่ง UDP?

การเชื่อมต่อ TCP สำหรับควบคุมมีสองวัตถุประสงค์ ประการแรก ใช้สำหรับการตรวจสอบสิทธิ์และการเจรจาที่น่าเชื่อถือ ประการที่สอง มันกำหนดอายุของ UDP association: ตราบใดที่ TCP เปิดอยู่ association ยังทำงาน เมื่อปิด proxy จะปล่อยทรัพยากร นี่เป็นวิธีจัดการ session และทำความสะอาดที่สง่างาม

ทำไมการสื่อสาร UDP ถึงหลุดในเครือข่ายมือถือ แต่ TCP ยังคงอยู่?

เพราะลักษณะของ NAT สำหรับ TCP NAT มีสัญญาณเริ่มต้นและสิ้นสุดที่ชัดเจน รายการจึงมีอายุยืนยาว UDP ไม่มีแนวคิดเรื่องการเชื่อมต่อ NAT จึงลบรายการหลังจากช่วงเงียบสั้น ๆ ในเครือข่ายมือถือ UDP timeout สั้นเป็นพิเศษ วิธีแก้คือ keepalive เป็นระยะเพื่อรักษาช่องทางให้แอคทีฟ

สามารถตรวจสอบการรองรับ UDP ในเบราว์เซอร์ได้โดยตรงไหม?

ไม่น่าเชื่อถือ เบราว์เซอร์เข้าถึงเว็บไซต์ด้วย TCP และเมื่อ UDP ไม่พร้อมใช้งานก็จะถอยไปใช้ TCP สำหรับ QUIC อย่างเงียบ ๆ WebRTC ในเบราว์เซอร์มีตรรกะซับซ้อนและอาจใช้กลไกเลี่ยง สิ่งเหล่านี้ปกปิดสถานะ UDP จริง สำหรับการตรวจสอบบริสุทธิ์ ใช้การทดสอบ socket โดยตรง, STUN หรือ DNS ผ่าน UDP ASSOCIATE

ความแตกต่างระหว่าง socks5 กับ socks5h ในทางปฏิบัติคืออะไร?

ความแตกต่างอยู่ที่ว่าแก้ไขชื่อโดเมนที่ไหน สำหรับ socks5 ชื่อจะแก้ไขในเครื่องฝั่ง client สำหรับ socks5h แก้ไขที่ฝั่ง proxy สิ่งนี้มีผลต่อความเป็นส่วนตัวของการแก้ไขชื่อและพฤติกรรมในบางสถานการณ์ การเลือกรูปแบบอย่างมีสติช่วยหลีกเลี่ยงข้อผิดพลาดที่จับได้ยาก

จำเป็นต้อง implement การแบ่งส่วนดาตาแกรมใน SOCKS5 ไหม?

ในทางปฏิบัติไม่ ฟิลด์ FRAG ถูกกำหนดในมาตรฐาน แต่การใช้งานส่วนใหญ่ทำงานกับ FRAG เท่ากับศูนย์เท่านั้น คือไม่มีการแบ่งส่วน ดาตาแกรมต้องพอดีในแพ็กเก็ตเดียว โปรโตคอลจริงที่ใช้ UDP มักทำงานกับดาตาแกรมขนาดเล็ก จึงไม่ค่อยเกิดปัญหา

จะแยกปัญหาที่เกิดจาก proxy กับปัญหาที่เกิดจาก NAT มือถือได้อย่างไร?

ทำการทดสอบ UDP ครบวงจร ถ้าไม่ผ่านเลย และคำสั่งคืน 0x07 หรือดาตาแกรมไม่ถึง แสดงว่าปัญหาอยู่ที่ proxy ถ้าทดสอบผ่าน แต่การหลุดเกิดขึ้นเฉพาะตอนหยุดในการใช้งานจริง สาเหตุส่วนใหญ่คือ UDP NAT timeout สั้น การแยกแยะเช่นนี้จะระบุแหล่งที่มาได้แม่นยำ

บทสรุป: transport คือทุกสิ่ง

เราเดินทางจากแนวคิดพื้นฐานของ TCP และ UDP ไปจนถึงรายละเอียดของการห่อหุ้มดาตาแกรมใน SOCKS5 และ NAT timeout ที่แยบยลในเครือข่ายมือถือ มาสรุปข้อสรุปหลักที่จะเปลี่ยนคุณจากผู้ใช้ที่เดาสุ่มเป็นคนที่เข้าใจอย่างแน่ชัดว่าเกิดอะไรขึ้นในระดับ transport

ประการแรก UDP และ TCP เป็นสองโลกที่แตกต่างกัน UDP ส่งดาตาแกรมแยกกันโดยไม่มีการรับประกัน เพื่อความเร็ว และมันคือพื้นฐานของการโทร เกม QUIC และ DNS คลาสสิก Proxy ที่ส่งต่อ TCP ได้ไม่จำเป็นต้องส่งต่อ UDP

ประการที่สอง เฉพาะ SOCKS5 ผ่านคำสั่ง UDP ASSOCIATE เท่านั้นที่ให้เส้นทางมาตรฐานสำหรับ UDP กลไกสวยงาม: การเชื่อมต่อ TCP สำหรับควบคุม, relay-port แยก, และการห่อหุ้มดาตาแกรมแต่ละอันด้วย header ที่มีฟิลด์ RSV, FRAG, ATYP, DST.ADDR และ DST.PORT

ประการที่สาม HTTP และ HTTPS proxy ไม่ส่งต่อ UDP โดยหลักการ เมธอด CONNECT สร้างเฉพาะ TCP tunnel สถาปัตยกรรมไม่มีทั้งการกำหนดที่อยู่ดาตาแกรมและ relay-port

ประการที่สี่ คำว่า SOCKS5 ไม่ได้รับประกัน UDP ตรวจสอบด้วยการทดสอบครบวงจรเสมอ โดยส่งดาตาแกรมจริงและรับคำตอบ รหัส 0x00 โดยไม่มีการแลกเปลี่ยนจริงไม่พิสูจน์อะไร ส่วนรหัส 0x07 บอกอย่างตรงไปตรงมาว่าไม่รองรับ

ประการที่ห้า UDP ในเครือข่ายมือถือดื้อกว่าเพราะ NAT timeout สั้น Keepalive และการรักษาการเชื่อมต่อควบคุมให้มีชีวิตช่วยป้องกันการหลุดลึกลับระหว่างหยุด

ขั้นตอนต่อไปของคุณง่าย ๆ พิจารณาว่าคุณต้องการ UDP สำหรับงานเฉพาะหรือไม่ โดยใช้ตารางสถานการณ์ของเรา ถ้าต้องการ ตรวจสอบว่าคุณใช้ SOCKS5 และทดสอบการรองรับ UDP ASSOCIATE จริงด้วยเครื่องมือของคุณ ไม่ว่าจะเป็น STUN, DNS หรือสคริปต์ socket โดยตรง วางแผน keepalive และจัดการ relay-address อย่างถูกต้อง เมื่อทำเช่นนี้ คุณจะไม่มีวันตกอยู่ในสถานการณ์ที่ proxy ดูเหมือนทำงาน แต่การโทรเงียบอีกต่อไป ตอนนี้คุณรู้แล้วว่าต้องหาสาเหตุที่ไหนและจะแก้ไขในระดับ transport อย่างไร