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

เกริ่นนำ: ทำไมพร็อกซี่ตัวเดียวกันถึงให้บริการสองโหมด และนี่ไม่ใช่การตลาด

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

HTTP Proxy พูดภาษา HTTP มันรับ HTTP request อ่านเข้าใจว่าคุณอยากได้อะไร แล้วไปดึงทรัพยากรมาให้เอง มันแคชได้ เพิ่มเฮดเดอร์ได้ ตอบด้วยรหัสสถานะได้ สำหรับสิ่งที่ ไม่ใช่ HTTP มันมีท่าไม้ตายตัวเดียว: เมธอด CONNECT ที่เปลี่ยนมันให้กลายเป็นท่อโง่ ๆ

SOCKS5 ไม่รู้จักด้วยซ้ำว่า HTTP คืออะไร มันเป็นโปรโตคอลระดับเซสชัน: ไคลเอนต์บอกว่า "เชื่อมฉันกับโฮสต์นี้และพอร์ตนี้" พร็อกซี่ก็เปิด TCP connection แล้วจากจุดนั้นก็แค่ย้ายไบต์ไปกลับ มันไม่สนใจว่าข้างในคือ TLS, IMAP, SSH, โปรโตคอลฐานข้อมูล หรือฟอร์แมตไบนารีที่คุณคิดขึ้นเอง

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

สิ่งที่คุณจะได้จากบทความนี้:

  • คำขอไปยัง HTTP proxy มีหน้าตาอย่างไรในระดับข้อความ และต่างจากคำขอปกติไปยังเว็บไซต์อย่างไร
  • พร็อกซี่มองเห็นอะไรและแก้ไขอะไรได้บ้างในโหมด HTTP ใส
  • เมธอด CONNECT ทำงานอย่างไร และตัวกลางยังมองเห็นอะไรหลังสร้างทันเนล
  • แฮนด์เชคระดับไบต์ของ SOCKS5, สคีมาการยืนยันตัวตน และที่อยู่ ATYP สามแบบ
  • ทำไมการเลือกระหว่างโดเมนกับ IP ในคำขอ SOCKS5 ถึงส่งผลต่อ geolocation และความเป็นส่วนตัวของ DNS
  • เปรียบเทียบโปรโตคอลที่ไม่ใช่ HTTP, UDP, โอเวอร์เฮด, การแคช และการล็อก
  • ตาราง "งาน, โปรโตคอล, เพราะอะไร" และวิเคราะห์ความเข้ากันได้ในไคลเอนต์และไลบรารียอดนิยม

กลไกของคำสั่ง UDP ASSOCIATE และความต่างระหว่างสคีมา socks5 กับ socks5h ใน curl และ Python เราจะไม่ลงลึกในที่นี้ เพราะมีบทความเฉพาะแยกต่างหากในบล็อก Proxeon และจะมีลิงก์อ้างอิงในจุดที่เกี่ยวข้อง

พื้นฐาน: พร็อกซี่อยู่ในสแต็กเครือข่ายตรงไหน

เพื่อให้การคุยเรื่องโปรโตคอลมีความหมาย เรามาตกลงเรื่องคำศัพท์กันก่อน มีไม่กี่คำ

สามฝ่ายและสองการเชื่อมต่อ

ในทุกแผนผังที่มีพร็อกซี่ จะมีสามฝ่าย: ไคลเอนต์ (เบราว์เซอร์ สคริปต์ โปรแกรมอีเมลของคุณ) พร็อกซี่เซิร์ฟเวอร์ (ตัวกลาง) และ เซิร์ฟเวอร์ปลายทาง (origin) ระหว่างพวกเขามี TCP connection อิสระสองเส้น เส้นแรก: ไคลเอนต์ไปพร็อกซี่ เส้นที่สอง: พร็อกซี่ไปเซิร์ฟเวอร์ปลายทาง เซิร์ฟเวอร์ปลายทางเห็นแค่เส้นที่สอง และเห็นแค่ไอพีของพร็อกซี่

ทุกอย่างที่เราคุยในบทความนี้เกี่ยวกับเส้นแรกเท่านั้น ความต่างระหว่าง HTTP และ SOCKS5 อยู่ตรงนั้น ส่วนเส้นที่สองในทั้งสองกรณีเหมือนกัน: TCP ธรรมดาจากพร็อกซี่ไปโฮสต์ปลายทาง

ระดับของโมเดล และทำไมมันสำคัญ

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

ถ้าพูดในศัพท์ของโมเดลเครือข่าย HTTP proxy ทำงานที่ ชั้นแอปพลิเคชัน: เข้าใจความหมายของคำขอ SOCKS5 ทำงานที่ ชั้นเซสชัน: ใช้งานด้วยแนวคิด "โฮสต์", "พอร์ต", "การเชื่อมต่อ" และไม่ขึ้นไปสูงกว่านั้น

การแปลงชื่อเกิดขึ้นที่ไหน

แนวคิดอีกอันที่ร้อยเรียงผ่านทั้งบทความ: การแปลง DNS เมื่อคุณเข้าถึง example.com ต้องมีใครสักคนแปลงชื่อเป็นไอพี อาจเป็นไคลเอนต์ของคุณแปลงในเครื่อง หรือพร็อกซี่แปลงฝั่งตัวเอง สิ่งนี้กำหนดว่าคุณใช้โครงสร้าง DNS ของใคร จะได้คำตอบระดับภูมิภาคแบบไหนจาก CDN และข้อมูลโดเมนที่คุณเข้าถึงรั่วไปในเครือข่ายท้องถิ่นหรือไม่ จำจุดนี้ไว้ มันจะโผล่ทั้งในส่วน HTTP และส่วน SOCKS5

การยืนยันตัวตน

ทั้ง HTTP proxy และ SOCKS5 ตรวจสอบล็อกอินและรหัสผ่านได้ แต่ทำต่างกัน HTTP ใช้เฮดเดอร์ Proxy-Authorization และรหัสตอบกลับ 407 ส่วน SOCKS5 ใช้โปรโตคอลย่อยแยกต่างหากที่มีหมายเลขเมธอด 0x02 ยังมีทางเลือกที่ไม่ขึ้นกับโปรโตคอล: การยืนยันตัวตนด้วยไอพีของไคลเอนต์ เมื่อพร็อกซี่ปล่อยให้ทุกคนที่มาจากที่อยู่ที่อนุญาตไว้ล่วงหน้าเข้ามา ใน Proxeon มีทั้งสองแบบ และการเลือกส่งผลต่อความง่ายในการเชื่อมต่อไคลเอนต์ที่ไม่สามารถส่งข้อมูลรับรองได้

HTTP Proxy: คำขอแบบ absolute URI พร็อกซี่เห็นอะไรและแก้ไขอะไรได้

คำขอ HTTP ปกติไปยังเว็บไซต์มีหน้าตาแบบนี้:

GET /catalog/items?page=2 HTTP/1.1
Host: shop.example

สังเกตดู: ในบรรทัดคำขอมีแค่พาธ โฮสต์ถูกส่งในเฮดเดอร์แยก ฟอร์แมตนี้เรียกว่า origin-form เมื่อไคลเอนต์รู้ว่ากำลังคุยกับพร็อกซี่ ไม่ใช่กับเว็บไซต์ มันจะเปลี่ยนฟอร์แมตเป็น absolute-form: ใส่ URI เต็มลงในบรรทัดคำขอ

GET http://shop.example/catalog/items?page=2 HTTP/1.1
Host: shop.example
Proxy-Authorization: Basic dXNlcjpwYXNz
User-Agent: my-parser/1.0
Accept: text/html

ทำไมต้องใส่โฮสต์ซ้ำ? ในทางประวัติศาสตร์ absolute form เกิดก่อนเฮดเดอร์ Host และเป็นวิธีเดียวที่จะบอกพร็อกซี่ว่าต้องไปที่ไหน มาตรฐาน HTTP/1.1 สมัยใหม่กำหนดให้พร็อกซี่ต้องรับ absolute form ได้ และให้ไคลเอนต์ที่คุยกับพร็อกซี่ใช้รูปแบบนี้ ส่วนเฮดเดอร์ Host ยังคงเก็บไว้เพื่อความเข้ากันได้และเพื่อส่งต่อให้เซิร์ฟเวอร์ปลายทาง ซึ่งพร็อกซี่จะส่งคำขอในรูป origin-form

HTTP proxy มองเห็นอะไร

ในโหมดใส (ไม่มีการเข้ารหัสระหว่างไคลเอนต์กับเว็บปลายทาง) พร็อกซี่เห็นทุกอย่างที่มีในคำขอและคำตอบ:

  • เมธอด, URL เต็ม รวมถึง query parameter
  • เฮดเดอร์คำขอทั้งหมด: User-Agent, Cookie, Authorization, Referer
  • บอดี้คำขอทั้งหมด: ฟอร์ม, JSON, ไฟล์ที่อัปโหลด
  • สถานะการตอบกลับ, เฮดเดอร์คำตอบ และบอดี้คำตอบ

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

HTTP proxy แก้ไขอะไรได้

มาตรฐานแบ่งเฮดเดอร์เป็น end-to-end และ hop-by-hop เฮดเดอร์แบบ hop-by-hop เกี่ยวข้องกับการเชื่อมต่อหนึ่งครั้ง และพร็อกซี่ต้องลบออกก่อนส่งต่อ ได้แก่ Connection, Keep-Alive, Proxy-Authorization, Proxy-Authenticate, TE, Trailer, Transfer-Encoding, Upgrade นี่คือเหตุผลที่ล็อกอินและรหัสผ่านพร็อกซี่ของคุณไม่ลอยไปยังเว็บปลายทาง: เฮดเดอร์ Proxy-Authorization ถูกถอดออกที่พร็อกซี่ตามมาตรฐาน

นอกจากล้างเฮดเดอร์ที่บังคับ พร็อกซี่ยังทำได้อีก:

  • เพิ่มเฮดเดอร์ Via พร้อมชื่อและเวอร์ชันโปรโตคอลของตัวเอง มาตรฐานกำหนดให้ทำ แต่ในทางปฏิบัติพร็อกซี่แบบไม่ระบุตัวตนมักไม่ใส่
  • เพิ่ม X-Forwarded-For พร้อมไอพีจริงของไคลเอนต์ พร็อกซี่องค์กรมักทำ และพร็อกซี่ที่คุณซื้อมาใช้งานกับทรัพยากรภายนอกไม่ควรทำเด็ดขาด
  • ตอบกลับจาก แคช ของตัวเองโดยไม่แตะเซิร์ฟเวอร์ปลายทาง ถ้าคำตอบถูกทำเครื่องหมายว่าแคชได้
  • เปลี่ยนการเข้ารหัสบอดี้ เพิ่มหรือถอดการบีบอัด เขียนลิงก์ใหม่ใน HTML
  • ปฏิเสธคำขอด้วยคำตอบของตัวเอง เช่น 403 หรือ 407

คำตอบ 407 Proxy Authentication Required สมควรพูดถึงแยก ถ้าพร็อกซี่ต้องการการยืนยันตัวตนและไคลเอนต์ไม่ได้ส่งมา พร็อกซี่จะตอบด้วยรหัส 407 และเฮดเดอร์ Proxy-Authenticate ที่ระบุสคีมาที่รองรับ ไคลเอนต์ที่ดีจะส่งคำขอซ้ำพร้อม Proxy-Authorization ไคลเอนต์ที่แย่จะโชว์ข้อผิดพลาดให้ผู้ใช้แบบไม่รู้เรื่อง นี่คือปัญหาที่พบบ่อยเวลาตั้งค่า: แอป "มองไม่เห็นพร็อกซี่" ทั้งที่จริงมันแค่จัดการ 407 ไม่เป็น

ลองทำจริง

วิธีง่ายที่สุดที่จะเห็นทั้งหมดนี้ด้วยตาตัวเอง: curl พร้อมคีย์ -v

curl -v -x http://user:pass@gate.proxeon.net:8080 http://httpbin.org/get

ในเอาต์พุตคุณจะเห็นบรรทัดแบบ GET http://httpbin.org/get HTTP/1.1 และเฮดเดอร์ Proxy-Authorization นี่แหละคือ absolute form

คำขอเดียวกันเขียนมือผ่านซ็อกเก็ตใน Python เพื่อไม่ให้เหลือความลึกลับ:

import socket, base64

creds = base64.b64encode(b"user:pass").decode()
req = (
"GET http://httpbin.org/get HTTP/1.1\r\n"
"Host: httpbin.org\r\n"
f"Proxy-Authorization: Basic {creds}\r\n"
"Connection: close\r\n\r\n"
)
s = socket.create_connection(("gate.proxeon.net", 8080))
s.sendall(req.encode())
print(s.recv(65535).decode(errors="replace"))

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

ชื่อถูกแปลงที่ไหนในโหมด HTTP

ใน absolute form ไคลเอนต์ส่งชื่อโฮสต์ให้พร็อกซี่ตามเดิม พร็อกซี่เป็นคนแปลง ไคลเอนต์ไม่จำเป็นต้องรู้ไอพีของเซิร์ฟเวอร์ปลายทาง และไม่มีการส่ง DNS query ในเครื่อง สะดวกดี แต่นำเราไปสู่ข้อจำกัดสำคัญ: สคีมาที่อธิบายมานี้ใช้ได้กับ HTTP ที่ไม่เข้ารหัสเท่านั้น สำหรับ HTTPS นั้น absolute form ไร้ประโยชน์ เพราะ TLS ต้องถูกสร้างระหว่างไคลเอนต์กับเซิร์ฟเวอร์ปลายทาง และพร็อกซี่ไม่สามารถแทรกกลางได้โดยไม่ทำลายเซอร์ติฟิเคต นี่คือเหตุผลที่ CONNECT ถูกคิดขึ้นมา

เมธอด CONNECT: เปลี่ยน HTTP proxy ให้เป็นทันเนล TCP

CONNECT เป็นเมธอด HTTP ที่ขอให้พร็อกซี่ไม่ส่งต่อคำขอ แต่สร้าง TCP connection กับโฮสต์และพอร์ตที่ระบุ แล้วกลายเป็นท่อใส คำขอมีหน้าตาแบบนี้:

CONNECT shop.example:443 HTTP/1.1
Host: shop.example:443
Proxy-Authorization: Basic dXNlcjpwYXNz
Proxy-Connection: Keep-Alive

สังเกตฟอร์แมตของเป้าหมาย: มีแค่โฮสต์กับพอร์ต ไม่มีสคีมาและพาธ นี่คือ authority-form ของคำขอ ฟอร์แมตที่สามถัดจาก origin-form และ absolute-form

ถ้าพร็อกซี่ตกลง มันจะตอบ:

HTTP/1.1 200 Connection established

ข้อความหลังรหัสจะเป็นอะไรก็ได้ ไคลเอนต์ดูแค่ 2xx จากจุดนี้ HTTP จบลง ทุกอย่างที่ไคลเอนต์เขียนลงซ็อกเก็ต พร็อกซี่จะส่งต่อไปยังเซิร์ฟเวอร์ปลายทางแบบไบต์ต่อไบต์ และกลับกัน ไคลเอนต์เริ่ม TLS handshake ในซ็อกเก็ตนี้เลย ราวกับเชื่อมต่อกับเซิร์ฟเวอร์โดยตรง

ตัวกลางเห็นอะไรหลัง CONNECT

ตรงนี้คือส่วนที่น่าสนใจที่สุด พร็อกซี่ที่เพิ่งเคยเห็นทุกอย่างกลับตาบอดทันที หลัง CONNECT สำเร็จ พร็อกซี่รู้แค่:

  • ชื่อโฮสต์และพอร์ต จากบรรทัด CONNECT นี่คือข้อมูลเชิงความหมายเดียวที่มันได้รับ
  • เวลา ที่เริ่มและปิดการเชื่อมต่อ
  • ปริมาณ ไบต์ที่ส่งไปกลับทั้งสองทาง
  • เนื้อหาของ TLS ClientHello ถ้าข้างในทันเนลเป็น TLS: ตรงนั้นมี SNI (ชื่อเซิร์ฟเวอร์) ส่งแบบเปิดเผย รายการ cipher ที่รองรับ และส่วนขยาย ส่วนขยาย Encrypted Client Hello สมัยใหม่ซ่อน SNI ได้ด้วย แต่การรองรับยังไม่แพร่หลาย
  • ไม่มีอะไรจากชั้น HTTP: ไม่มี URL ไม่มีเฮดเดอร์ ไม่มีคุกกี้ ไม่มีบอดี้

พูดอีกแบบ หลัง CONNECT HTTP proxy เห็นเท่ากับ SOCKS5 เป๊ะ โฮสต์ พอร์ต ไทม์มิ่ง ปริมาณ ความต่างในการมองเห็นระหว่างสองโปรโตคอลมีอยู่แค่กับ HTTP ที่ไม่เข้ารหัส ซึ่งในปี 2026 เหลือน้อยมากในงานจริง

CONNECT ไม่จำเป็นต้องนำไปสู่ HTTPS

ความเข้าใจผิดที่พบบ่อย: CONNECT ใช้แค่กับ HTTPS จริง ๆ มาตรฐานไม่ได้จำกัดเนื้อหาในทันเนล ผ่าน CONNECT เชื่อมต่อไปยัง IMAP server พอร์ต 993, SSH พอร์ต 22, หรือ TCP service ใดก็ได้ คำถามเดียวคือคอนฟิกของพร็อกซี่อนุญาตหรือไม่ พร็อกซี่สาธารณะและองค์กรจำนวนมากอนุญาต CONNECT เฉพาะพอร์ต 443 และบางครั้ง 80 เพื่อป้องกันการใช้งานในทางที่ผิด Proxeon อนุญาต CONNECT บนพอร์ตใดก็ได้ แต่ถ้าซอฟต์แวร์ของคุณรองรับ SOCKS5 สำหรับโปรโตคอลที่ไม่ใช่ HTTP มันก็ยังเป็นตัวเลือกที่เป็นธรรมชาติกว่า ดังที่จะกล่าวถึงด้านล่าง

ตัวอย่าง: TLS ผ่าน CONNECT เขียนมือ

เครื่องมือ openssl ผ่าน HTTP proxy ได้เอง:

openssl s_client -proxy gate.proxeon.net:8080 -connect shop.example:443 -servername shop.example

และนี่คือหน้าตาใน Python ด้วยไลบรารีมาตรฐาน ไม่ต้องพึ่งพาไลบรารีภายนอก:

import http.client, ssl

conn = http.client.HTTPSConnection("gate.proxeon.net", 8080,
 context=ssl.create_default_context())
conn.set_tunnel("shop.example", 443,
headers={"Proxy-Authorization": "Basic dXNlcjpwYXNz"})
conn.request("GET", "/")
resp = conn.getresponse()
print(resp.status, resp.getheader("server"))

เมธอด set_tunnel ทำตามที่อธิบายข้างต้นเป๊ะ: ส่ง CONNECT รอ 200 แล้วห่อซ็อกเก็ตด้วย TLS สังเกตว่า TLS context ตรวจเซอร์ติฟิเคตของ shop.example ไม่ใช่พร็อกซี่ พร็อกซี่ในสคีมานี้ไม่สามารถสลับเซอร์ติฟิเคตได้โดยไม่ทำให้ไคลเอนต์เจอ error

CONNECT ใน HTTP/2 และ HTTP/3

ใน HTTP/2 เมธอด CONNECT ยังมีอยู่ แต่ทำงานภายใน connection เดียวที่ multiplex แล้ว: แต่ละทันเนลเป็น stream แยก ทำให้ถือทันเนลหลายสิบผ่าน TCP connection เดียวไปพร็อกซี่ได้ และประหยัด handshake ส่วน CONNECT แบบขยาย (มี pseudo-header :protocol) ใช้กับ WebSocket บน HTTP/2 ใน HTTP/3 บนพื้นฐาน QUIC มีสเปก CONNECT-UDP ที่ในทางทฤษฎีอนุญาตให้ทันเนล UDP ผ่าน HTTP proxy ได้ แต่ในไลบรารีไคลเอนต์ยังเป็นของแปลก และในทางปฏิบัติ ถ้าคุณต้องการ UDP ผ่านพร็อกซี่ คุณจะมองไปที่ SOCKS5

สิ่งที่ CONNECT ทำไม่ได้

  • แคช: เนื้อหาในทันเนลทึบแสง
  • แก้ไขเฮดเดอร์: มองไม่เห็นตั้งแต่แรก
  • Multiplex หลายโฮสต์เป้าหมายผ่านทันเนลเดียวใน HTTP/1.1: หนึ่ง CONNECT เท่ากับหนึ่ง TCP connection
  • ส่ง UDP ใน HTTP/1.1 และ HTTP/2

SOCKS5: แฮนด์เชค การยืนยันตัวตน และ ATYP

SOCKS5 ระบุใน RFC 1928 และสคีมาการยืนยันตัวตนด้วยล็อกอินรหัสผ่านใน RFC 1929 สเปกทั้งสองรวมกันไม่กี่หน้า และนี่คือข้อดีอย่างหนึ่งของโปรโตคอล: เขียนใหม่จากศูนย์ไม่ยาก ทำให้มี implementation เยอะและตีความไม่ค่อยต่างกัน

SOCKS5 เป็นโปรโตคอลไบนารี ไม่มีข้อความ มีแค่ไบต์ในโครงสร้างตายตัว มาดูการแลกเปลี่ยนเต็มรูปแบบของคำสั่ง CONNECT

ขั้นที่ 1: ทักทายและเลือกเมธอดยืนยันตัวตน

ไคลเอนต์ส่งเวอร์ชันและรายการเมธอดที่รองรับ:

05 02 00 02
VER=5 NMETHODS=2 METHODS: 00 (ไม่มี auth), 02 (ล็อกอิน/รหัสผ่าน)

เซิร์ฟเวอร์เลือกหนึ่งเมธอดแล้วตอบสองไบต์:

05 02
VER=5 METHOD=02 (เซิร์ฟเวอร์ต้องการล็อกอิน/รหัสผ่าน)

ถ้าเซิร์ฟเวอร์ตอบ 05 FF หมายความว่า "ไม่มีเมธอดที่เสนอมาตัวไหนใช้ได้" และไคลเอนต์ต้องปิดการเชื่อมต่อ นี่คือหน้าตาในระดับไบต์ของสถานการณ์ที่คุณลืมใส่รหัสผ่าน แต่พร็อกซี่ Proxeon ตั้งไว้ให้ต้องล็อกอิน

ขั้นที่ 2: ยืนยันตัวตนตาม RFC 1929

ถ้าเลือกเมธอด 02 ไคลเอนต์ส่ง:

01 04 75 73 65 72 04 70 61 73 73
VER=1 ULEN=4 UNAME="user" PLEN=4 PASSWD="pass"

สังเกต: เวอร์ชันของโปรโตคอลย่อยตรงนี้คือ 01 ไม่ใช่ 05 นี่คือแหล่งข้อผิดพลาดที่พบบ่อยในไคลเอนต์ที่เขียนเอง เซิร์ฟเวอร์ตอบ:

01 00
VER=1 STATUS=00 (สำเร็จ; ค่าอื่นหมายถึงปฏิเสธ)

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

ขั้นที่ 3: คำขอเชื่อมต่อ

ตอนนี้คือข้อความที่สำคัญที่สุด:

05 01 00 03 0C 73 68 6F 70 2E 65 78 61 6D 70 6C 65 01 BB
VER=5 CMD=01 (CONNECT) RSV=00 ATYP=03 (โดเมน)
LEN=12 ADDR="shop.example" PORT=0x01BB (443)

ฟิลด์ CMD รับสามค่า: 01 CONNECT (เปิด TCP connection ขาออก), 02 BIND (รอรับ connection ขาเข้า แทบไม่ใช้), 03 UDP ASSOCIATE (สร้าง UDP relay) กลไก UDP ASSOCIATE และข้อควรระวังเราแกะไว้ในบทความแยก เรื่อง UDP ใน SOCKS5 ที่นี่แค่ยืนยันว่า: นี่คือโปรโตคอลเดียวจากสองตัวที่มี UDP ในตัว

ATYP: โดเมนกับ IP

ฟิลด์ ATYP กำหนดว่าไคลเอนต์ส่งที่อยู่ปลายทางมาในรูปแบบไหน:

  • 0x01 IPv4: 4 ไบต์ถัดมาคือที่อยู่
  • 0x03 ชื่อโดเมน: หนึ่งไบต์บอกความยาว ตามด้วยชื่อโดยไม่มี null ต่อท้าย
  • 0x04 IPv6: 16 ไบต์ถัดมาคือที่อยู่

ฟังดูเป็นรายละเอียดทางเทคนิค แต่จริง ๆ นี่คือหนึ่งในการตัดสินใจที่สำคัญที่สุดที่ไคลเอนต์ทำ และนี่คือเหตุผล

ถ้าไคลเอนต์ใช้ ATYP=0x01 หรือ 0x04 หมายความว่ามัน แปลง DNS เองแล้ว ก่อนส่งคำขอ เครื่องของคุณไปถาม DNS server ของตัวเอง ได้ที่อยู่มา แล้วส่งไอพีสำเร็จรูปให้พร็อกซี่ ผลที่ตามมา:

  • DNS query ออกผ่านเครือข่ายท้องถิ่นของคุณ และผู้ให้บริการหรือผู้ดูแลระบบเห็นได้
  • คุณได้ไอพีที่ DNS ตอบสำหรับ ภูมิภาคของคุณ สำหรับเว็บที่มี CDN หมายความว่าพร็อกซี่ที่อยู่คนละประเทศจะไปแตะ edge server ที่ "ผิดที่" ทำให้การเชื่อมต่อช้าลงและดูผิดปกติ
  • ถ้าเครื่องคุณไม่มี IPv6 คุณจะไม่ได้รับ AAAA record และใช้เส้นทาง IPv6 ของพร็อกซี่ไม่ได้ แม้มันจะมีก็ตาม
  • ถ้า DNS ในเครือข่ายคุณทำงานไม่มาตรฐาน พร็อกซี่จะได้ที่อยู่ผิด และคุณจะเสียเวลาไล่หาสาเหตุ

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

จะบังคับไคลเอนต์ให้ส่งโดเมนได้อย่างไร? ขึ้นกับไคลเอนต์ ใน curl และไลบรารี Python เรื่องนี้ขึ้นกับการเลือกสคีมา socks5 กับ socks5h และนี่คือหัวข้อของบทความแยก ที่นี่สำคัญคือเข้าใจเหตุผล: ตัวอักษร h หมายถึง "hostname" และเปิดใช้ ATYP=0x03 ถ้าไม่มี ไลบรารีจะแปลงชื่อในเครื่อง

ขั้นที่ 4: คำตอบจากเซิร์ฟเวอร์

05 00 00 01 C0 A8 01 0A 1F 90
VER=5 REP=00 (สำเร็จ) RSV=00 ATYP=01 BND.ADDR=192.168.1.10 BND.PORT=8080

ฟิลด์ REP มีรหัสผลลัพธ์ มีประโยชน์ที่จะรู้ทั้งหมดเวลาดีบัก:

  • 00 สำเร็จ
  • 01 ข้อผิดพลาดทั่วไปของเซิร์ฟเวอร์
  • 02 การเชื่อมต่อถูกห้ามตามกฎ
  • 03 เครือข่ายไปไม่ถึง
  • 04 โฮสต์ไปไม่ถึง
  • 05 การเชื่อมต่อถูกปฏิเสธโดยเซิร์ฟเวอร์ปลายทาง
  • 06 TTL หมดอายุ
  • 07 คำสั่งไม่รองรับ
  • 08 ชนิดที่อยู่ไม่รองรับ

รหัส 08 พบได้ใน implementation เก่าหรือแบบง่ายที่ไม่รองรับ ATYP=0x03 หรือ IPv6 Proxeon รองรับที่อยู่ทั้งสามแบบ

ทำไม SOCKS5 ถึงไม่แยกวิเคราะห์เนื้อหา

หลังตอบ REP=00 โปรโตคอล SOCKS5 ก็จบลง ทุกอย่างที่ไคลเอนต์เขียนต่อ พร็อกซี่ก็ย้ายไปยัง connection ปลายทางโดยไม่วิเคราะห์ นี่ไม่ใช่ข้อจำกัดของการ implement แต่เป็นคุณสมบัติของการออกแบบ SOCKS5 ไม่มีแนวคิด "คำขอ" ไม่มีแนวคิด "เฮดเดอร์" มันไม่รู้ว่า HTTP, IMAP หรือ TLS คืออะไร มีคนบอกที่อยู่กับพอร์ต มันก็ต่อท่อสองท่อเข้าด้วยกัน

จากตรงนี้มีผลในทางปฏิบัติหลายอย่าง:

  • SOCKS5 แคชไม่ได้: มันไม่เข้าใจว่าคำตอบหนึ่งจบตรงไหนและอีกอันเริ่มตรงไหน
  • SOCKS5 เพิ่มเฮดเดอร์หรือเปลี่ยนเนื้อหาไม่ได้ ทำได้มากสุดคือปิด connection
  • SOCKS5 กรองตาม URL ไม่ได้ กรองได้แค่โฮสต์กับพอร์ต
  • SOCKS5 ทำงานกับโปรโตคอล TCP ใดก็ได้เท่าเทียมกัน รวมถึงอันที่คุณเพิ่งคิดขึ้นเมื่อวาน

แฮนด์เชค SOCKS5 เต็มรูปแบบใน Python

import socket, struct

def socks5_connect(proxy, user, pwd, host, port):
s = socket.create_connection(proxy)
s.sendall(b"\x05\x02\x00\x02")
ver, method = s.recv(2)
if method == 0x02:
u, p = user.encode(), pwd.encode()
s.sendall(b"\x01" + bytes([len(u)]) + u + bytes([len(p)]) + p)
if s.recv(2)[1] != 0:
raise RuntimeError("auth failed")
elif method != 0x00:
raise RuntimeError("no acceptable auth method")
h = host.encode()
s.sendall(b"\x05\x01\x00\x03" + bytes([len(h)]) + h + struct.pack("!H", port))
reply = s.recv(4)
if reply[1] != 0:
raise RuntimeError(f"connect failed, REP={reply[1]}")
atyp = reply[3]
s.recv({1: 4, 4: 16}.get(atyp, 0) if atyp != 3 else s.recv(1)[0])
s.recv(2)
return s

sock = socks5_connect(("gate.proxeon.net", 1080), "user", "pass", "shop.example", 443)
# ต่อไปห่อ sock ด้วย ssl.wrap_socket หรือส่งให้โปรโตคอลใดก็ได้

สามสิบบรรทัด คุณก็มีไคลเอนต์ SOCKS5 ที่ใช้งานได้ ส่งโดเมน (ATYP=0x03) และปล่อยให้พร็อกซี่แปลง DNS ความเรียบง่ายนี้เองที่ทำให้ SOCKS5 กลายเป็นมาตรฐานโดยพฤตินัยสำหรับการเข้าถึงแบบเขียนโปรแกรมได้

เปรียบเทียบตามเกณฑ์: ใครชนะตรงไหน

ตอนนี้ที่กลไกของทั้งสองโปรโตคอลถูกแกะถึงไบต์แล้ว การเปรียบเทียบก็เลิกเป็นเรื่องรสนิยม และกลายเป็นรายการความต่างที่วัดได้

โปรโตคอลที่ไม่ใช่ HTTP

SOCKS5 ทำงานกับโปรโตคอล TCP ใดก็ได้ตามมาตรฐาน: คำสั่ง CONNECT โฮสต์ พอร์ต จบ HTTP proxy ก็ผ่าน CONNECT ได้ แต่มีข้อแม้: ไคลเอนต์ต้องส่ง CONNECT สำหรับทราฟฟิกที่ไม่ใช่ HTTP ได้ (โปรแกรมอีเมลทำได้ เครื่องมือ CLI ส่วนใหญ่ไม่ได้) และพร็อกซี่ต้องอนุญาตพอร์ตที่ต้องการ ผู้ชนะ: SOCKS5

UDP

SOCKS5 มี UDP ASSOCIATE HTTP proxy ในเวอร์ชัน 1.1 และ 2 ไม่มีอะไรเลย ส่วน CONNECT-UDP จาก HTTP/3 แทบไม่มีไคลเอนต์รองรับ ถ้างานรวมถึง DNS query ตรง ๆ, QUIC, โปรโตคอลเสียง, ทราฟฟิกเกม ไม่มีทางเลือกอื่น ผู้ชนะ: SOCKS5 โดยมีข้อแม้ว่าไม่ใช่พร็อกซี่ SOCKS5 ทุกตัวเปิด UDP โปรดตรวจสอบเอกสารของแพ็กเกจ

โอเวอร์เฮดในการสร้างการเชื่อมต่อ

นับเป็น round-trip (RTT) ระหว่างไคลเอนต์กับพร็อกซี่ เหนือ TCP handshake เอง:

  • HTTP proxy โหมดใส ไม่มี auth: 0 RTT เพิ่ม คำขอออกทันที
  • HTTP CONNECT พร้อม auth ในคำขอแรก: 1 RTT (CONNECT, ตอบ 200)
  • SOCKS5 ไม่มี auth: 2 RTT (ทักทาย, คำขอ)
  • SOCKS5 มีล็อกอินรหัสผ่าน: 3 RTT (ทักทาย, ยืนยันตัวตน, คำขอ)

ในแง่ไบต์ ความต่างกลับกัน: SOCKS5 handshake เต็มรูปแบบพร้อม auth ใช้ประมาณ 40 ไบต์ ส่วน CONNECT พร้อมเฮดเดอร์ Host, Proxy-Authorization และ User-Agent กิน 150 ไบต์ขึ้นไปได้สบาย แต่ในงานจริง RTT เป็นตัวตัดสิน ไม่ใช่ไบต์ เมื่อดีเลย์ไปพร็อกซี่ 50 ms SOCKS5 พร้อม auth เพิ่ม 150 ms ต่อ connection ใหม่ เทียบกับ 50 ms ของ CONNECT ถ้าไคลเอนต์ใช้ connection ซ้ำ (keep-alive, pool) นี่คือจ่ายครั้งเดียว ถ้าทุกคำขอเปิดซ็อกเก็ตใหม่ ความต่างก็สะสม ผู้ชนะในแง่ RTT: HTTP วิธีลดช่องว่างสำหรับ SOCKS5: การยืนยันตัวตนด้วยไอพี ซึ่งตัดออกหนึ่ง RTT

การแคช

มีแค่ HTTP proxy ในโหมดใส ไม่ใช่ CONNECT ไม่ใช่ SOCKS5 และแคชได้แค่ทราฟฟิกที่ไม่เข้ารหัส ซึ่งทุกวันนี้มีน้อย เกณฑ์นี้จึงจากที่เป็นตัวตัดสินกลายเป็นเรื่องเฉพาะทาง ใช้ได้กับระบบบิลด์ภายใน, มิเรอร์แพ็กเกจ, คำขอซ้ำไปยัง API ที่ไม่มี TLS ในขอบเขตที่เชื่อถือได้ ผู้ชนะ: HTTP แต่ขอบเขตแคบ

การล็อก

จุดนี้มักเข้าใจผิด คำถามคือพร็อกซี่บันทึกอะไรในล็อกได้ในแต่ละโหมด?

  • HTTP ใส: URL เต็ม, เมธอด, เฮดเดอร์, และถ้าต้องการบอดี้; สถานะการตอบกลับ; ปริมาณ
  • HTTP CONNECT: โฮสต์และพอร์ตจากบรรทัด CONNECT; เวลา; ปริมาณ; และถ้าต้องการ SNI จาก ClientHello
  • SOCKS5 กับ ATYP=0x03: ชื่อโดเมนและพอร์ต; เวลา; ปริมาณ; และถ้าต้องการ SNI
  • SOCKS5 กับ ATYP=0x01/0x04: แค่ IP และพอร์ต; พร็อกซี่ไม่รู้โดเมน; เวลา; ปริมาณ; SNI

สำหรับทราฟฟิกที่เข้ารหัส CONNECT กับ SOCKS5 ให้การมองเห็นเท่ากับตัวกลาง ความต่างเกิดขึ้นเฉพาะจุดที่ไคลเอนต์ SOCKS5 ส่ง IP แทนโดเมน ซึ่งตอนนั้นพร็อกซี่รู้น้อยกว่ารู้อีก แต่เซิร์ฟเวอร์ปลายทางก็จะได้คำขอจาก "ผิดภูมิภาค" ด้วย ดูหัวข้อ ATYP เสมอ เท่ากันโดยมีข้อแม้

การวินิจฉัยข้อผิดพลาด

HTTP proxy ตอบด้วยรหัสที่มนุษย์อ่านออก: 407 บอกเรื่อง auth, 403 บอกเรื่องห้าม, 502 บอกปลายทางเข้าไม่ถึง, 504 บอก timeout บาง implementation ใส่บอดี้คำอธิบายมาด้วย SOCKS5 ตอบแค่ไบต์ REP ตัวเดียว และไม่ใช่ทุกไลบรารีจะแปลเป็นข้อความที่เข้าใจได้ เวลาดีบักในสภาพแวดล้อมที่ไม่คุ้น HTTP proxy วินิจฉัยง่ายกว่า ผู้ชนะ: HTTP

Multiplexing

HTTP/2 proxy ทำได้: ลาก CONNECT tunnel หลายอันผ่าน connection เดียว SOCKS5 ต้องมี TCP connection แยกต่อหนึ่งเป้าหมาย สำหรับไคลเอนต์ที่มี connection ขนานกันหลายร้อย นี่ลดภาระบนสแต็กเครือข่ายและพร็อกซี่ได้ชัดเจน แต่การรองรับ HTTP/2 ไปพร็อกซี่ในไคลเอนต์ยังกระจัดกระจาย ผู้ชนะตามทฤษฎี: HTTP ในทางปฏิบัติเท่ากัน

ความเป็นไปได้ในการแทรกแซงทราฟฟิก

HTTP proxy ในโหมดใสแก้ได้ทุกอย่าง ในโหมด CONNECT และ SOCKS5 ทำได้แค่ตัด connection สำหรับไคลเอนต์ที่ต้องการความมั่นใจว่าทราฟฟิกไม่ถูกแก้ SOCKS5 หรือ CONNECT ที่มี TLS ข้างในดีที่สุด ผู้ชนะในแง่ความคาดเดาได้: SOCKS5

การยืนยันตัวตน

ทั้งคู่มีล็อกอินรหัสผ่าน HTTP ยังรองรับสคีมา Digest, NTLM, Negotiate ซึ่งสำคัญในสภาพแวดล้อมองค์กร SOCKS5 ในทางทฤษฎีมีเมธอด GSSAPI แต่ในพร็อกซี่เชิงพาณิชย์แทบไม่เจอ สำหรับการใช้งานกับบริการอย่าง Proxeon ไม่มีผล เพราะใช้ Basic หรือ whitelist IP

จะเลือกอะไรตามงาน: ตาราง

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

งานโปรโตคอลที่แนะนำเพราะอะไร
เบราว์เซอร์สำหรับทำงานมือหรือทดสอบHTTP (พร้อม CONNECT สำหรับ HTTPS)เบราว์เซอร์ทั้งหมดรองรับ HTTP proxy พร้อม auth ผ่านการตั้งค่าระบบหรือส่วนขยาย; ส่วน SOCKS5 พร้อมล็อกอินในเบราว์เซอร์ตระกูล Chromium ผ่านระบบทำไม่ได้ ต้องใช้ auth ด้วยไอพีเท่านั้น
ไคลเอนต์ HTTP, parser, ตัวเก็บข้อมูล ใน Python, Node.js, GoSOCKS5 พร้อมส่งโดเมน (ATYP=0x03)การแปลง DNS ฝั่งพร็อกซี่ให้ที่อยู่ระดับภูมิภาคของ CDN ที่ถูกต้อง ไลบรารีรองรับทั้งสองโหมด และ SOCKS5 ไม่มีความเสี่ยงที่จะแทรกแซงเฮดเดอร์
Parser ที่มี connection สั้นจำนวนมากโดยไม่มี keep-aliveHTTP CONNECT หรือ SOCKS5 พร้อม auth ด้วยไอพีทุก RTT ของ handshake คูณด้วยจำนวน connection; CONNECT ประหยัด 1-2 RTT เทียบกับ SOCKS5 พร้อมรหัสผ่าน
โปรแกรมอีเมล (IMAP, SMTP, POP3)SOCKS5โปรโตคอลอีเมลไม่ใช่ HTTP; ไคลเอนต์เดสก์ท็อปรองรับ SOCKS5 โดยตรง ขณะที่ผ่าน HTTP proxy ต้องใช้ CONNECT บนพอร์ตที่ไม่มาตรฐาน
SSH, ไคลเอนต์ฐานข้อมูล, RDP, โปรโตคอล TCP ใด ๆSOCKS5รองรับใน OpenSSH ผ่าน ProxyCommand หรือ wrapper ที่เข้ากับ ProxyJump ในไคลเอนต์ฐานข้อมูลส่วนใหญ่มีในตัว; HTTP CONNECT ใช้ไม่ได้ทุกที่
แอปที่ใช้ UDP: ไคลเอนต์ DNS, QUIC, เสียงSOCKS5 พร้อม UDP ASSOCIATEโปรโตคอลเดียวจากสองตัวที่มี UDP ในสเปก
พร็อกซี่แคชสำหรับบิลด์ภายในและมิเรอร์แพ็กเกจผ่าน HTTPHTTP ใสมีแค่ตัวนี้ที่เข้าใจความหมายของคำตอบและแคชได้
แอปองค์กรที่รองรับแค่พร็อกซี่ระบบ WindowsHTTPWinHTTP และการตั้งค่าระบบ Windows ทำงานกับ HTTP proxy; การรองรับ SOCKS ตรงนั้นจำกัดและไม่มี auth
แอปมือถือ Android หรือ iOS ในสภาพแวดล้อมทดสอบHTTPการตั้งค่า Wi-Fi ของทั้งสองแพลตฟอร์มรองรับแค่ HTTP proxy; SOCKS5 ต้องมีตัวพร็อกซี่ไฟร์ระดับแอป
ซอฟต์แวร์ของตัวเองที่ทำงานกับซ็อกเก็ตตรง ๆSOCKS5Implementation 30 บรรทัด ฟอร์แมตไบนารีไม่ต้อง parser รองรับโปรโตคอลใดก็ได้ข้างบน ควบคุมจุดแปลง DNS ได้ชัดเจน
เครื่องมือบรรทัดคำสั่ง: curl, wget, gitHTTP สำหรับ wget; SOCKS5 หรือ HTTP สำหรับ curl และ gitwget ไม่รองรับ SOCKS เลย; curl และ git รองรับทั้งสองโหมด
มอนิเตอร์ความพร้อมใช้งานเว็บจากต่างภูมิภาคSOCKS5 พร้อม ATYP=0x03ต้องการให้ DNS 変換มาจากภูมิภาคของพร็อกซี่ ไม่งั้นก็ตรวจ edge server ผิดตัว
ดีบักเวลามีอะไรเสียและไม่รู้ว่าอะไรHTTPรหัส 407, 403, 502, 504 เข้าใจง่ายกว่าไบต์ REP และ curl -v โชว์บทสนทนาทั้งหมดกับพร็อกซี่

อัลกอริทึมเลือกในสี่ขั้น

  1. ระบุโปรโตคอลข้างใน ถ้าไม่ใช่ HTTP หรือ HTTPS เลือก SOCKS5 ไม่ต้องคิดมาก
  2. ตรวจว่าไคลเอนต์ทำอะไรได้ เปิดเอกสารค้นคำสำคัญ socks5, proxy, CONNECT ถ้าไม่มี SOCKS5 หรือมีแต่ไม่มี auth ทางเลือกก็ถูกกำหนดให้แล้ว
  3. ตัดสินว่าโดเมนควรถูกแปลงที่ไหน ถ้าภูมิภาคสำคัญ (CDN, เนื้อหาตามพื้นที่, มอนิเตอร์) ใช้ SOCKS5 พร้อมส่งโดเมน หรือ HTTP CONNECT: ทั้งสองกรณีพร็อกซี่เป็นคนแปลง
  4. ประเมินโปรไฟล์การเชื่อมต่อ connection สั้นจำนวนมากโดยไม่มีพูล: ดู RTT ของ handshake เลือก HTTP CONNECT หรือเปิด auth ด้วยไอพี

ความเข้ากันได้ในไคลเอนต์และไลบรารียอดนิยม

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

curl

รองรับทุกอย่าง สคีมาในพารามิเตอร์ -x หรือในตัวแปรสภาพแวดล้อม: http://, https:// (TLS ไปถึงพร็อกซี่เอง), socks4://, socks4a://, socks5://, socks5h:// ความต่างระหว่าง socks5 กับ socks5h อธิบายในบทความแยก ที่นี่จำไว้ว่า: ต้องการให้พร็อกซี่แปลง DNS ต้องใช้ socks5h

curl -x socks5h://user:pass@gate.proxeon.net:1080 https://shop.example/
curl -x http://user:pass@gate.proxeon.net:8080 https://shop.example/

ตัวแปรสภาพแวดล้อม http_proxy, https_proxy, all_proxy ถูกอ่านอัตโนมัติ; all_proxy รับสคีมา SOCKS ได้ด้วย

wget

รองรับแค่ HTTP proxy ไม่รองรับ SOCKS ในรูปแบบใดเลย ถ้าต้องการ wget ผ่าน SOCKS5 ต้องใช้ตัวพร็อกซี่ไฟร์ระดับระบบ

Python: requests

HTTP proxy ใช้ได้ทันที สำหรับ SOCKS5 ต้องติดตั้งแพ็กเกจเพิ่ม PySocks (ติดตั้งเป็น requests[socks])

import requests

proxies = {
"http": "socks5h://user:pass@gate.proxeon.net:1080",
"https": "socks5h://user:pass@gate.proxeon.net:1080",
}
r = requests.get("https://shop.example/api/items", proxies=proxies, timeout=15)
print(r.status_code, r.headers.get("cf-ray"))

สำหรับ HTTPS ผ่าน HTTP proxy requests ใช้ CONNECT อัตโนมัติ สำหรับ HTTP ผ่าน HTTP proxy ใช้ absolute form

Python: httpx

HTTP proxy ใช้ได้ทันที SOCKS5 ผ่านแพ็กเกจ socksio (httpx[socks]) สคีมา socks5:// ใน httpx ส่งโดเมนให้พร็อกซี่ รองรับ async ทำให้สะดวกสำหรับงานขนาน

import httpx, asyncio

async def main():
async with httpx.AsyncClient(proxy="socks5://user:pass@gate.proxeon.net:1080") as c:
r = await c.get("https://shop.example/")
print(r.status_code)

asyncio.run(main())

Python: aiohttp

HTTP proxy รองรับในตัว SOCKS5 ผ่านแพ็กเกจ aiohttp-socks ด้วยคลาส ProxyConnector ที่พารามิเตอร์ rdns ควบคุมจุดแปลง DNS

Node.js: fetch และ undici

fetch ในตัวของ Node.js ใช้ undici ซึ่งมี ProxyAgent สำหรับ HTTP proxy สำหรับ SOCKS5 ใช้ agent แยกจากระบบนิเวศ เช่น socks-proxy-agent สำหรับโมดูล http/https

import { ProxyAgent, fetch } from "undici";

const agent = new ProxyAgent({
 uri: "http://gate.proxeon.net:8080",
 token: "Basic " + Buffer.from("user:pass").toString("base64"),
});
const res = await fetch("https://shop.example/", { dispatcher: agent });
console.log(res.status);

Go

net/http มาตรฐานรองรับ HTTP proxy ผ่าน Transport.Proxy และตัวแปรสภาพแวดล้อม ตั้งแต่ Go 1.13 สคีมา socks5:// ใน HTTP_PROXY ก็ถูกไลบรารีมาตรฐานรับด้วย สำหรับการควบคุมละเอียดใช้แพ็กเกจ golang.org/x/net/proxy

package main

import (
"fmt"
"net/http"
"net/url"
)

func main() {
u, _ := url.Parse("socks5://user:pass@gate.proxeon.net:1080")
tr := &http.Transport{Proxy: http.ProxyURL(u)}
client := &http.Client{Transport: tr}
resp, err := client.Get("https://shop.example/")
if err != nil {
panic(err)
}
fmt.Println(resp.Status)
}

ใน Go สคีมา socks5 ส่งโดเมนให้พร็อกซี่: ไม่มีการแปลงในเครื่อง

Java

HTTP proxy ผ่านพร็อพเพอร์ตีระบบ http.proxyHost, https.proxyHost หรือออบเจกต์ Proxy ชนิด Type.HTTP SOCKS ผ่าน socksProxyHost และ Proxy.Type.SOCKS การยืนยันตัวตนผ่านคลาส Authenticator ตั้งแต่ JDK 8u111 สคีมา Basic สำหรับ HTTPS ผ่าน CONNECT ถูกปิดโดยพร็อพเพอร์ตี jdk.http.auth.tunneling.disabledSchemes โดยค่าเริ่มต้น ต้องล้างค่ามัน ไม่งั้นจะเจอ 407 โดยไม่มีคำอธิบาย นี่คือสาเหตุที่พบบ่อยที่สุดในการติดต่อฝ่ายสนับสนุน

.NET

HttpClient กับ SocketsHttpHandler รองรับ HTTP proxy ผ่าน WebProxy การรองรับ SOCKS4, SOCKS4a และ SOCKS5 ปรากฏใน .NET 6 และเปิดใช้ด้วย WebProxy ที่มีที่อยู่แบบ socks5://host:port

เบราว์เซอร์

เบราว์เซอร์ตระกูล Chromium ใช้การตั้งค่าพร็อกซี่ระบบหรือแฟล็ก --proxy-server HTTP proxy พร้อม auth ใช้ได้: เบราว์เซอร์จะโชว์ไดอะล็อกล็อกอิน SOCKS5 ผ่านการตั้งค่าระบบใช้ได้โดยไม่มี auth ส่งล็อกอินรหัสผ่านไม่ได้ สำหรับ SOCKS5 พร้อมรหัสผ่านต้องใช้ส่วนขยายที่มี API proxy หรือ auth ด้วยไอพี Firefox มีการตั้งค่าพร็อกซี่ของตัวเอง รองรับ SOCKS5 และมีออปชัน "Proxy DNS when using SOCKS v5" ที่เปิด ATYP=0x03 ส่วน auth สำหรับ SOCKS5 ใน Firefox ก็ไม่มีในตัวเช่นกัน

โปรแกรมอีเมล

Thunderbird ใช้การตั้งค่าพร็อกซี่คล้าย Firefox และรองรับ SOCKS5 สำหรับ IMAP และ SMTP โปรแกรมอีเมลเดสก์ท็อปอื่น ๆ หลายตัวมีส่วนตั้งค่า SOCKS5 ในบัญชีของตัวเอง ผ่าน HTTP proxy อีเมลจะใช้ได้เฉพาะเมื่อไคลเอนต์ส่ง CONNECT ไปยังพอร์ต 993 และ 465 ได้ ซึ่งพบน้อย

ตัวพร็อกซี่ไฟร์ระดับระบบ

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

เช็กลิสต์ความเข้ากันได้

  • ไคลเอนต์รองรับ SOCKS5 ไหม? ส่งล็อกอินรหัสผ่านใน SOCKS5 ได้ไหม?
  • ไคลเอนต์แปลงโดเมนเองหรือส่งให้พร็อกซี่? มีการตั้งค่า remote DNS ไหม?
  • ไคลเอนต์จัดการ 407 ถูกต้องและส่งคำขอซ้ำพร้อม auth ไหม?
  • ไคลเอนต์ใช้ CONNECT สำหรับ HTTPS หรือพยายามส่ง absolute URI ที่มีสคีมา https (บางไลบรารีเก่าทำ และมันใช้ไม่ได้)?
  • ไคลเอนต์ใช้ connection ไปพร็อกซี่ซ้ำ หรือเปิดใหม่ทุกคำขอ?

เคสจากประสบการณ์วิศวกรรม

ตัวเลขด้านล่างเป็นค่าปกติของสถานการณ์ที่อธิบาย ให้เข้าใจขนาดของผลกระทบ ไม่ใช่ผลลัพธ์ที่รับประกันได้

เคส 1: มอนิเตอร์หน้าร้านจากต่างภูมิภาค

ทีมติดตามความพร้อมใช้งานและราคาบนหน้าร้านของตัวเองในภูมิภาคต่าง ๆ ผ่านพร็อกซี่จากหลายประเทศ ใช้ Python และ requests กับสคีมา socks5:// เป็นครั้งคราวเมตริกโชว์ราคา "ผิด" สำหรับภูมิภาค ทั้งที่หน้าร้านทำงานถูกต้อง สาเหตุ: ไลบรารีแปลงโดเมนในเครื่อง ที่ประเทศสำนักงาน แล้วส่งไอพีของ edge server CDN ให้พร็อกซี่ พร็อกซี่จากอีกประเทศก็เชื่อมกับที่อยู่นั้นตรง ๆ และ CDN ก็ให้เนื้อหาตามภูมิภาคที่มันอนุมานจากโหนดของตัวเอง ไม่ใช่จากไอพีไคลเอนต์ การเปลี่ยนสคีมาเป็น socks5h ย้ายการแปลง DNS ไปที่พร็อกซี่ สัดส่วนการวัดที่ผิดปกติลดลงแทบเหลือศูนย์ และเวลาตอบกลับมัธยฐานลดลงประมาณหนึ่งในสาม เพราะพร็อกซี่เริ่มไปยังโหนด CDN ที่ใกล้ตัวเองที่สุด

เคส 2: ฝูงตัวเก็บข้อมูลที่ใช้ connection สั้น

บริการรวบรวมราคาเปิดเผยทำงานถึงหลายแสนคำขอต่อวันผ่าน SOCKS5 พร้อมล็อกอินรหัสผ่าน โดยเปิด connection ใหม่ทุกคำขอ การโปรไฟล์โชว์ว่าสาม RTT ของ handshake ต่อ connection ที่ดีเลย์ไปพร็อกซี่ประมาณ 40 ms ให้โอเวอร์เฮด 120 ms ต่อคำขอ ประมาณหนึ่งในสี่ของเวลาทั้งหมด สองการเปลี่ยนแปลง: เปิดพูล connection ในไคลเอนต์ HTTP และเปลี่ยนไปใช้ auth ด้วยไอพี ตัดออกหนึ่ง RTT เวลารวมในการไล่รายการลดลงประมาณ 30 เปอร์เซ็นต์โดยไม่เปลี่ยนจำนวนพร็อกซี่ โปรโตคอลยังเป็น SOCKS5 เพราะเปลี่ยนเป็น HTTP CONNECT จะได้กำไรน้อยกว่าการทำพูล

เคส 3: กล่องอีเมลและ IMAP

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

เคส 4: แอป Java และ 407 ปริศนา

ผู้รวมระบบขององค์กรกำลังเชื่อมบริการ Java กับ API ภายนอกผ่าน HTTP proxy พร้อม Basic auth พร็อกซี่ตอบ 407 อย่างสม่ำเสมอ แม้ข้อมูลรับรองถูกต้อง และ curl ด้วยพารามิเตอร์เดียวกันก็ทำงานได้ สาเหตุ: ตั้งแต่การอัปเดต JDK บางเวอร์ชัน Basic auth สำหรับ CONNECT tunnel ถูกปิดโดยค่าเริ่มต้น แฟล็ก JVM ตัวเดียวที่ล้าง jdk.http.auth.tunneling.disabledSchemes แก้ปัญหาได้ นี่คือจุดที่ HTTP proxy ตอบรหัสอ่านออกมีประโยชน์: รหัส 407 ชี้ทิศทางการค้นหาทันที ขณะที่ SOCKS5 ในสถานการณ์เดียวกันจะตอบ 05 FF และถ้าไม่เข้าใจโปรโตคอลก็คงเข้าใจยากกว่า

ความเข้าใจผิดที่พบบ่อย

  • "SOCKS5 ปลอดภัยกว่า HTTP proxy" สำหรับทราฟฟิกที่เข้ารหัส ทั้งสองให้การมองเห็นเท่ากับตัวกลาง: โฮสต์ พอร์ต ไทม์มิ่ง ปริมาณ SNI ความปลอดภัยของเนื้อหามาจาก TLS ไม่ใช่จากโปรโตคอลพร็อกซี่ ความต่างมีแค่กับ HTTP ที่ไม่เข้ารหัส ซึ่ง HTTP proxy โหมดใสเห็นทุกอย่าง
  • "HTTP proxy ใช้กับ HTTPS ไม่ได้" ใช้ได้ผ่าน CONNECT นี่คือกลไกมาตรฐานที่ใช้กันทั่ว นี่คือวิธีที่เบราว์เซอร์ทั้งหมดเข้าถึงเว็บ HTTPS ผ่านพร็อกซี่องค์กร
  • "SOCKS5 เร็วกว่าเพราะเป็นไบนารี" ในการสร้าง connection SOCKS5 พร้อม auth ใช้ RTT มากกว่า HTTP CONNECT ในการส่งข้อมูลทั้งสองไม่เพิ่มอะไร: หลัง handshake มันคือท่อ TCP เปล่า ๆ ในทั้งสองกรณี ความเร็วขึ้นกับช่องทางของพร็อกซี่ ไม่ใช่โปรโตคอล
  • "CONNECT ใช้แค่พอร์ต 443" มาตรฐานไม่ได้จำกัดพอร์ต คอนฟิกของพร็อกซี่แต่ละตัวต่างหากที่จำกัด
  • "SOCKS5 แปลงโดเมนที่พร็อกซี่เสมอ" เฉพาะเมื่อไคลเอนต์ส่ง ATYP=0x03 ไลบรารีหลายตัวแปลงในเครื่องโดยค่าเริ่มต้นและส่ง IP
  • "HTTP proxy เพิ่ม X-Forwarded-For เสมอและเปิดเผยไอพีของฉัน" นั่นคือพฤติกรรมของคอนฟิกองค์กรเฉพาะ ไม่ใช่คุณสมบัติโปรโตคอล พร็อกซี่เชิงพาณิชย์ไม่เพิ่มเฮดเดอร์แบบนั้น และในโหมด CONNECT ก็เพิ่มไม่ได้ทางกายภาพ
  • "พร็อกซี่เห็นรหัสผ่านพร็อกซี่ของฉันแบบเปิด ก็เห็นรหัสผ่านเว็บด้วย" รหัสผ่านพร็อกซี่ถูกส่งให้พร็อกซี่ และตามมาตรฐานไม่ถูกส่งต่อ รหัสผ่านเว็บในทันเนล TLS พร็อกซี่มองไม่เห็น
  • "ในเมื่อ SOCKS5 ไม่แยกวิเคราะห์เนื้อหา ก็จำกัดมันไม่ได้" พร็อกซี่จำกัดตามโฮสต์ปลายทาง พอร์ต ปริมาณ ความเร็ว และจำนวน connection ได้ แค่จำกัดตาม URL ไม่ได้
  • "พอร์ต HTTP และ SOCKS5 ของผู้ให้บริการเดียวกันคือเซิร์ฟเวอร์คนละตัว" โดยทั่วไปเป็นเซิร์ฟเวอร์เดียวและไอพีขาออกเดียว ต่างกันแค่โปรโตคอลขาเข้า ใน Proxeon ก็เป็นแบบนั้น
  • "SOCKS5 พร้อมรหัสผ่านในเบราว์เซอร์ตั้งค่าเหมือน HTTP" ไม่ การตั้งค่าระบบของ Chromium และ Firefox ไม่ส่งข้อมูลรับรองใน SOCKS5 ต้องใช้ auth ด้วยไอพีหรือส่วนขยาย

FAQ

เซิร์ฟเวอร์ปลายทางรู้ได้ไหมว่าฉันมาผ่าน HTTP proxy หรือ SOCKS5?

ไม่ เซิร์ฟเวอร์ปลายทางเห็นแค่ connection ที่สอง จากพร็อกซี่มาหาตัวเอง และในทั้งสองกรณีมันคือ TCP ธรรมดาจากไอพีของพร็อกซี่ ข้อยกเว้นเดียว: HTTP proxy โหมดใสที่เพิ่มเฮดเดอร์ Via หรือ X-Forwarded-For ในโหมด CONNECT และ SOCKS5 เป็นไปไม่ได้

ถ้าฉันใช้ HTTP proxy กับ HTTPS พร็อกซี่แอบดูหรือแก้เนื้อหาได้ไหม?

ได้เฉพาะถ้ามันทำ TLS interception พร้อมสลับเซอร์ติฟิเคต และตอนนั้นไคลเอนต์จะเจอ error การตรวจสอบเซอร์ติฟิเคต เว้นแต่คุณติดตั้ง root certificate ของพร็อกซี่ไว้เองด้วยมือ ในการทำงานปกติหลัง CONNECT พร็อกซี่เห็นแค่สตรีมที่เข้ารหัส และอ่านหรือแก้เนื้อหาไม่ได้

ทำไม SOCKS5 พร้อมรหัสผ่านใช้ใน Chrome ไม่ได้ แต่ HTTP proxy พร้อมรหัสผ่านใช้ได้?

สแต็กเครือข่ายของ Chromium รองรับไดอะล็อก auth สำหรับ HTTP proxy ผ่านกลไก 407 แต่ไม่ได้ implement เมธอด 0x02 จาก RFC 1929 สำหรับ SOCKS5 นี่คือการตัดสินใจของนักพัฒนาเบราว์เซอร์ ไม่ใช่ข้อจำกัดโปรโตคอล ทางแก้: auth ด้วยไอพีในแดชบอร์ด Proxeon หรือส่วนขยายที่จัดการพร็อกซี่ผ่าน API

ถ้าพร็อกซี่ตอบ REP=05 ใน SOCKS5 ต้องทำอย่างไร?

รหัส 05 หมายถึงเซิร์ฟเวอร์ปลายทางปฏิเสธ TCP connection: พอร์ตปิด บริการไม่ทำงาน หรือไฟร์วอลล์ปลายทางบล็อกไอพีพร็อกซี่ ตรวจว่าส่งพอร์ตถูก และลองที่อยู่พร็อกซี่อื่น ตัวพร็อกซี่เองทำงานถูก ปัญหาอยู่ที่ครึ่งหลังของเส้นทาง

ความต่างระหว่าง REP=02 ใน SOCKS5 กับ 403 ของ HTTP proxy คืออะไร?

ในเชิงความหมายเหมือนกัน: พร็อกซี่ปฏิเสธสร้าง connection ตามกฎของตัวเอง ปกติหมายถึงพอร์ตหรือโฮสต์ปลายทางถูกห้ามตามนโยบายพร็อกซี่ HTTP proxy บางครั้งมีคำอธิบายในบอดี้ 403 ส่วน SOCKS5 มีแค่ไบต์

ใช้ล็อกอินรหัสผ่านเดียวกันกับพอร์ต HTTP และ SOCKS5 ได้ไหม?

ใน Proxeon ได้: บัญชีใช้ร่วมกัน ต่างกันแค่พอร์ตและโปรโตคอล เวลาเปลี่ยนโปรโตคอลไม่ต้องเปลี่ยนข้อมูลรับรอง

จะรู้ได้อย่างไรว่าไคลเอนต์แปลงโดเมนในเครื่องหรือที่พร็อกซี่?

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

ควรใช้ HTTP/2 ไปพร็อกซี่ถ้าไลบรารีรองรับไหม?

ถ้าคุณมี connection ขนานจำนวนมากไปยังเป้าหมายต่าง ๆ และไคลเอนต์ multiplex CONNECT stream จริง จะได้ผลชัดเจน: TCP connection น้อยลง handshake น้อยลง แต่การรองรับความสามารถนี้ในไคลเอนต์และพร็อกซี่เซิร์ฟเวอร์ยังไม่สม่ำเสมอ ตรวจเอกสารไคลเอนต์ของคุณ และสอบถามว่าแพ็กเกจของคุณรองรับ HTTP/2 ขาเข้าหรือไม่

ทำไม HTTP proxy ถึงใช้ absolute URI ถ้ามีเฮดเดอร์ Host?

มาตรฐาน HTTP/1.1 กำหนดให้ไคลเอนต์ใช้ absolute form เมื่อคุยกับพร็อกซี่ เพื่อให้พร็อกซี่เข้าใจชัดเจนว่าคำขอต้องถูกส่งต่อ ไม่ใช่ประมวลผลในเครื่อง เฮดเดอร์ Host ยังเก็บไว้เพราะพร็อกซี่จะส่งคำขอให้เซิร์ฟเวอร์ปลายทางใน origin-form และ Host จำเป็นตรงนั้น การซ้ำกันนี้คือราคาของความเข้ากันได้

สำหรับ scraping อะไรสำคัญกว่า: HTTP หรือ SOCKS5?

สำหรับเป้าหมาย HTTPS ไม่มีความต่างในการมองเห็น ความต่างอยู่ที่พฤติกรรมไลบรารี ถ้าไลบรารีทำงานกับ SOCKS5 ได้ดีและส่งโดเมน ใช้ SOCKS5: เสี่ยงน้อยกว่าที่จะแทรกแซงเฮดเดอร์และให้การแปลง DNS ตามภูมิภาคที่ถูกต้อง ถ้าไลบรารีกับ SOCKS5 งอแง หรือคุณมี connection สั้นจำนวนมากโดยไม่มีพูล HTTP CONNECT ก็ไม่ได้แย่กว่า คำแนะนำหลัก: อย่าเปิด connection ใหม่ไปพร็อกซี่ทุกคำขอ แพงกว่าการเลือกโปรโตคอลใด ๆ

สรุป

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

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

ทำอะไรต่อตอนนี้

  1. ระบุโปรโตคอลข้างในงานของคุณ ไม่ใช่ HTTP: ไป SOCKS5 ทันที
  2. ตรวจเอกสารไคลเอนต์เรื่องการรองรับ SOCKS5 พร้อม auth และออปชัน remote resolution
  3. ถ้าทำงานกับทรัพยากรที่ผูกกับภูมิภาค ให้แน่ใจว่าโดเมนถูกส่งไปพร็อกซี่: socks5h, remote DNS, ATYP=0x03 หรือ HTTP CONNECT
  4. เปิดพูล connection หรือ keep-alive ไปพร็อกซี่ นี่ให้ผลมากกว่าการเปลี่ยนโปรโตคอลใด ๆ
  5. ถ้าไคลเอนต์ส่งล็อกอินใน SOCKS5 ไม่ได้ ตั้งค่า auth ด้วยไอพีในแดชบอร์ด Proxeon
  6. เวลาดีบัก เริ่มจาก curl -v: มันจะโชว์บทสนทนาทั้งหมดกับพร็อกซี่และแยกปัญหาไคลเอนต์ออกจากปัญหาเครือข่ายทันที

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