กฎของพอร์ต 80 และ 443 ไม่ได้พาเบราว์เซอร์ผ่าน VPN
การจับคู่พอร์ตเลือกโฟลว์ TCP ไม่ใช่เบราว์เซอร์ HTTP/3 ทำงานบน UDP, DNS อาจไปคนละเส้นทาง และตัวอัปเดตก็ตรงกับกฎเดียวกับที่คุณเขียน
มีคนขอให้เบราว์เซอร์ใช้ทันเนล และคำตอบกลับมาเป็นกฎไฟร์วอลล์ที่ตรงกับพอร์ตปลายทาง 80 และ 443 มันดูแม่นยำและไม่ใช่ การจับคู่พอร์ตเลือกแพ็กเก็ตตามส่วนหัวการขนส่ง ไม่ใช่ตามโปรแกรมที่เปิดซ็อกเก็ต และการท่องเว็บสมัยใหม่ไม่ได้จำกัดอยู่ที่สองพอร์ตนั้นบน TCP กฎนี้จะพลาดทราฟฟิกบางส่วนที่คุณตั้งใจจะรวมไว้และจับทราฟฟิกที่คุณไม่เคยคิดจะแตะ ก่อนเขียนมัน จงตัดสินใจว่าคุณต้องการขอบเขตใดจากสามขอบเขตที่ต่างกันจริง ๆ
กฎนี้อธิบายชั้นการขนส่ง ไม่ใช่แอปพลิเคชัน
บน Linux การจับคู่พอร์ตปลายทางตรวจดูส่วนหัว TCP และไม่มีอะไรเหนือขึ้นไป การทำเครื่องหมายแพ็กเก็ตเหล่านั้นและนำทางด้วยเส้นทางนโยบายทำงานตรงตามที่เอกสารระบุ และกลไกเหล่านี้ไม่รู้ว่าสิ่งที่บรรทุกมาหมายถึงอะไรหรือโปรเซสใดส่งมันมา เครื่องหมายคือตัวเลขที่ติดอยู่กับแพ็กเก็ต ไม่ใช่ตัวตนที่ติดอยู่กับแอปพลิเคชัน
nft add rule inet mangle output tcp dport { 80, 443 } meta mark set 0x1
ip rule add fwmark 0x1 table 100
ip route add default dev wg0 table 100
ผลลัพธ์สองอย่างตามมาทันที ตัวอัปเดตซอฟต์แวร์ที่ติดต่อ TCP 443 ได้รับการปฏิบัติเช่นเดียวกับเบราว์เซอร์ ซึ่งอาจจะโอเคหรืออาจเป็นการหยุดชะงักที่รอรอบอัปเดตถัดไป และบริการเว็บที่เผยแพร่บนพอร์ตอื่นโดยเจตนา เช่น 8443 จะหลุดออกจากกฎทั้งหมด ทั้งที่ยังเป็นทราฟฟิกเว็บที่ผู้ใช้สนใจ
ตัวเลขเป็นตัวเลือกที่ชอบด้วยกฎหมายเมื่อข้อกำหนดนั้นเกี่ยวกับพอร์ตเหล่านั้นจริง ๆ พวกมันกลายเป็นเรื่องแต่งเมื่อตั๋วเขียนว่า «เบราว์เซอร์» และมีการใช้งานช่วงพอร์ตในชุดกฎ ช่องว่างนั้นไม่ใช่รายละเอียดของการเขียนเอกสาร มันคือความแตกต่างระหว่างกฎที่คุณป้องกันได้ในการทบทวนกับกฎที่ไม่มีใครทดสอบได้
HTTP/3 แอบออกจากกฎ TCP ของคุณ
HTTP/3 ทำงานบน QUIC และ QUIC ถูกบรรทุกใน UDP กฎที่ตรงกับ TCP เท่านั้นมองไม่เห็น ดังนั้นเบราว์เซอร์เดียวกันที่ผ่านหน้าทดสอบของคุณสามารถส่งคำขอในภายหลังผ่าน UDP และข้ามทันเนลได้โดยไม่มีใครเปลี่ยนการตั้งค่า RFC 9114 อธิบาย HTTP/3 ว่าเป็นโปรโตคอลที่อิง QUIC และ QUIC ใช้ UDP ที่มีพอร์ตเริ่มต้น 443 ในการติดตั้งทั่วไป
ไม่ว่าเบราว์เซอร์ที่กำหนดจะลอง HTTP/3 หรือไม่นั้นขึ้นอยู่กับการกำหนดค่า ไซต์ และการพยายามครั้งก่อนสำเร็จหรือไม่ นั่นทำให้มันเป็นสิ่งที่ให้เหตุผลจากความจำได้ไม่ดี ถามเครื่องมือแทน:
curl --http3 -sS -o /dev/null -w '%{http_version} %{time_total}\n' https://example.com
ss -tunp | grep -E ':443\b'
บรรทัด curl พิมพ์เวอร์ชันที่เจรจาได้ ดังนั้น 3 ยืนยันว่าใช้เส้นทาง UDP แล้ว รายการซ็อกเก็ตแสดงว่าการเชื่อมต่อนั้นผูกกับอินเทอร์เฟซของทันเนลหรือของจริง หาก curl ที่คุณสร้างไม่มี HTTP/3 แฟล็กจะล้มเหลวอย่างดังแทนที่จะถอยกลับอย่างเงียบ ๆ ซึ่งเป็นความเมตตาเล็ก ๆ ของมันเอง
DNS คือการตัดสินใจแยกต่างหากที่คุณต้องทำ
กฎพอร์ตสำหรับทราฟฟิกเว็บไม่พูดอะไรเกี่ยวกับการแปลงชื่อ เบราว์เซอร์อาจใช้ตัวแปลงของระบบ ตัวแปลงที่กำหนดค่าไว้ในเบราว์เซอร์ หรือตัวที่การเชื่อมต่อล่าสุดผลักเข้ามา แต่ละตัวอาจส่งคำถามผ่านเส้นทางที่ต่างจากที่กฎของคุณเลือก ซึ่งสร้างการแยกแบบคลาสสิก: หน้าเว็บโหลด ชื่อถูกแปลงในที่ที่คุณไม่คาดคิด และไซต์ภายในแปลงเป็นที่อยู่สาธารณะหรือไม่แปลงเลย
ตัดสินใจอย่างชัดเจน หากชื่อภายในต้องแปลงผ่านทันเนล ตัวแปลงต้องอยู่ข้างใน และชุดกฎต้องอนุญาต DNS ไปยังตัวแปลงนั้นพร้อมกันคำถามอื่นไว้นอก หากเบราว์เซอร์ใช้ DNS over HTTPS ไปยังผู้ให้บริการสาธารณะ คำถามจะข้ามตัวแปลงของคุณทั้งหมดและกฎพอร์ตช่วยไม่ได้ เขียนตัวเลือกนั้นไว้ในบันทึกการเปลี่ยนแปลงเดียวกับกฎเส้นทาง เพราะคนที่แก้ปัญหาความล้มเหลวครั้งถัดไปจะอ่านทั้งสองอย่างพร้อมกัน
จากนั้นตรวจสอบด้วยตัวแปลงไม่ใช่ด้วยหน้าเว็บ:
resolvectl query intranet.example.internal
resolvectl status | grep -A3 'Current DNS Server'
คำตอบที่หายไปคือปัญหาในการแปลงชื่อ แม้ข้อความแสดงข้อผิดพลาดของเบราว์เซอร์จะโทษเครือข่าย ความล้มเหลวทั้งสองนี้ดูเหมือนกันสำหรับผู้ใช้และเป็นตั๋วที่ต่างกันโดยสิ้นเชิง
สามขอบเขต สามกลไกที่ต่างกัน
ความสับสนส่วนใหญ่หายไปเมื่อคุณตั้งชื่อขอบเขตที่ต้องการ พวกมันใช้แทนกันไม่ได้ และแต่ละอันมีโหมดความล้มเหลวที่ต่างกันเมื่อทันเนลล่ม
| What you actually want | Mechanism that fits | What it does not cover |
|---|---|---|
| These transport ports use this exit | Firewall mark plus policy route | Applications, HTTP/3 over UDP, DNS |
| This browsing session stays separate | Application-aware VPN, or a separate network namespace plus a proxy | Other applications in the same session |
| Only these private sites are reachable | Destination-based routes with private DNS | Public sites on the same address family |
โปรไฟล์เบราว์เซอร์แยกเป็นกับดักในแถวกลาง มันแยกคุกกี้และประวัติ และไม่เปลี่ยนอะไรในตารางเส้นทางของโฮสต์ ดังนั้นทั้งสองโปรไฟล์ไปเส้นทางเดียวกัน การแยกต้องอาศัยสิ่งที่เคอร์เนลบังคับ ซึ่งหมายถึงเนมสเปซ คอนเทนเนอร์ หรือแอปพลิเคชันที่มีอินเทอร์เฟซทันเนลของตัวเอง
ไม่ว่าแถวใดจะใช้ได้ จงเขียนว่าเกิดอะไรขึ้นเมื่อทันเนลล่ม เส้นทางที่อิงเครื่องหมายซึ่งหายไปพร้อมอินเทอร์เฟซมักถอยกลับไปยังเส้นทางเริ่มต้นของจริง ซึ่งเป็นพฤติกรรม fail-open นั่นอาจยอมรับได้สำหรับการท่องเว็บและยอมรับไม่ได้สำหรับอย่างอื่น และมันเป็นการตัดสินใจ ไม่ใช่รายละเอียดการใช้งาน
ทดสอบโฟลว์ที่คุณอ้างว่าครอบคลุม
การทดสอบการยอมรับต้องเป็นไปตามขอบเขตที่คุณเขียนไว้ ไม่ใช่หมายเลขพอร์ตที่สะดวก เลือกหนึ่งโฟลว์ที่ต้องผ่านทันเนล หนึ่งที่ไม่ควร และหนึ่งที่ใช้การขนส่งที่คุณไม่ได้คิดถึง:
ip route get 203.0.113.40
curl -sS -o /dev/null -w 'v4 %{http_version} %{remote_ip}\n' https://example.com
nft list ruleset | grep -A2 'dport'
การค้นหาเส้นทางบอกคุณว่าปลายทางใช้อินเทอร์เฟซใดจริง ๆ และนั่นคือข้อเท็จจริงที่รายงานส่วนใหญ่ระบุผิด บรรทัด curl ยืนยันเวอร์ชันที่เจรจาและตระกูลที่อยู่ การทิ้งชุดกฎจับกฎที่คุณเพิ่มระหว่างการทดสอบและลืมจำกัด และนั่นคือวิธีที่เครื่องหมายชั่วคราวกลายเป็นการกำหนดเส้นทาง fail-open ถาวร
บันทึกผลลัพธ์ทั้งสามพร้อมตราเวลาและเก็บไว้กับการเปลี่ยนแปลง เมื่อมีคนรายงานในภายหลังว่า «VPN ทำให้อินทราเน็ตพัง» ความแตกต่างระหว่างขอบเขตที่ตั้งใจและที่ใช้งานจริงจะปรากฏในบันทึกนั้น และการแก้ไขจะเป็นการเปลี่ยนกฎไม่ใช่การโต้เถียง