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

กฎ DNAT เขียนปลายทางใหม่แล้วหยุดอยู่แค่นั้น

บนเกตเวย์ Linux การเผยแพร่บริการหมายถึงกฎในเชน PREROUTING ของตาราง nat หรือสิ่งที่เทียบเท่าใน nftables กฎจะจับคู่ที่อยู่และพอร์ตสาธารณะ จากนั้นเขียนปลายทางใหม่เป็นที่อยู่ส่วนตัวของแอปพลิเคชัน ที่อยู่ต้นทาง พอร์ตต้นทาง และเพย์โหลดยังคงเดิม และ conntrack บันทึกการแมปไว้เพื่อให้คำตอบถูกเขียนกลับตอนออก พฤติกรรมนี้คือรูปแบบการแปลที่อยู่แบบดั้งเดิมที่อธิบายใน RFC 3022

sudo iptables -t nat -A PREROUTING -d 203.0.113.10 -p tcp --dport 443 \
  -j DNAT --to-destination 10.20.30.40:443
sudo iptables -t nat -L PREROUTING -n -v
sudo conntrack -L -p tcp --dport 443

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

กฎยังกำหนดโหมดความล้มเหลวที่คุณจะพบในภายหลัง ถ้าเกตเวย์ส่งต่อแต่โฮสต์ของแอปพลิเคชันไม่มี เส้นทางกลับไปยังไคลเอนต์ คำตอบจะออกไปพร้อมต้นทางผิดและการจับมือจะหยุดชะงัก ถ้ากฎที่สองตรงก่อน ลำดับจะเป็นตัวกำหนดผลลัพธ์ และ iptables -t nat -L -n -v แสดงตัวนับที่พิสูจน์ว่ากฎใดรับแพ็กเก็ตไป

อุโมงค์ห่อแพ็กเก็ตก่อนที่ตัวรับฟังจะเห็น

VPN ไม่เผยแพร่แอปพลิเคชันเลย ไคลเอนต์สร้างแพ็กเก็ตชั้นนอกที่จ่าหน้าถึงที่อยู่สาธารณะของเกตเวย์ เข้ารหัสแพ็กเก็ตชั้นในไว้ข้างใน และเกตเวย์ถอดรหัสแล้วส่งแพ็กเก็ตชั้นในไปยังปลายทางส่วนตัว ด้วย WireGuard การขนส่งชั้นนอกเป็น UDP โดยปกติอยู่บนพอร์ตสูง ด้วย OpenVPN บน TCP 443 แพ็กเก็ตชั้นนอกดูเหมือน TLS สำหรับทุกสิ่งที่เฝ้าดูเส้นทาง

ภายในอุโมงค์ แพ็กเก็ตชั้นในยังคงใช้ที่อยู่ส่วนตัว คือที่อยู่ tunnel ของไคลเอนต์ สมมติว่า 10.8.0.6 และแอปพลิเคชันที่ 10.20.30.40 ดังนั้นตัวรับฟังจึงเห็นต้นทางจากพูลของอุโมงค์ และไคลเอนต์ทุกคนใช้เกตเวย์นั้นเป็นฮอปถัดไป บันทึกการเข้าถึงหลัง VPN มักแสดงเกตเวย์แทนผู้ใช้ด้วยเหตุผลนี้ เว้นแต่เกตเวย์จะเก็บต้นทางเดิมไว้

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

ip route get 10.20.30.40
ping -M do -s 1400 10.20.30.40
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
  -j TCPMSS --clamp-mss-to-pmtu

การเปิดเผยถูกตัดสินที่ทางเข้า ไม่ใช่ที่การเข้ารหัส

ทั้งสองแบบจบที่ตัวรับฟัง TLS ตัวเดียวกัน จึงสืบทอดใบรับรองเดียวกัน เวอร์ชันโปรโตคอลเดียวกัน และการเข้าสู่ระบบของแอปพลิเคชันเดียวกัน สิ่งที่เปลี่ยนคือใครได้รับอนุญาตให้เริ่มการจับมือ ในการส่งต่อแบบสาธารณะ โฮสต์ใดก็ตามที่เข้าถึง 203.0.113.10:443 จะได้การจับมือ TCP และ TLS ClientHello ก่อนที่การอนุญาตของแอปพลิเคชันจะถูกตรวจด้วยซ้ำ ในการเข้าถึงผ่านอุโมงค์เท่านั้น ตัวรับฟังเข้าถึงได้เฉพาะจากที่อยู่ที่เกตเวย์ส่งเข้าไปในอุโมงค์ และ SYN ของคนแปลกหน้าจะตายที่ นโยบายของเกตเวย์

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

ตรวจสอบตัวรับฟังและนโยบายแยกกัน เพราะอย่างใดอย่างหนึ่งอาจกว้างกว่าที่คุณคิด:

sudo ss -ltnp 'sport = :443'
sudo nft list ruleset
openssl s_client -connect 203.0.113.10:443 -servername files.example.com </dev/null

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

วัดเส้นทาง ไม่ใช่วัดป้ายชื่อ

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

curl -sS -o /dev/null -w '%{time_connect} %{time_appconnect} %{time_total}\n' \
  https://files.example.com/report.pdf
mtr -rwc 20 203.0.113.10
mtr -rwc 20 10.20.30.40

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

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

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

บทความที่เกี่ยวข้อง