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

สามทางเลือก และแต่ละอย่างเปลี่ยนอะไรจริง

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

What the far side needsPrefix mappingPer-host DNATRouted prefix
Users visible to its logsOnly without source NATSame conditionYes, unchanged
To start a connection toward youNo, alias is localNo, same reasonYes, both ends route
To absorb a new hostYes, arithmetic onlyNo, one rule per addressYes, it simply routes
To require no config changeYes, with source NATYes, same conditionNo, it needs a route back

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

คู่คำนำหน้า และทำไมขนาดต้องตรงกัน

NETMAP เป็นเป้าหมายของตาราง nat ที่ทำงานบนคู่คำนำหน้าที่มีความยาวเท่ากัน ข้างในไม่มีตารางต่อที่อยู่ มันตัดคำนำหน้าออก เก็บบิตโฮสต์ไว้ แล้วต่อกลับเข้ากับคำนำหน้าใหม่ นั่นคือเหตุผลที่ /24 แมปเป็น /24 และไม่เคยเป็น /25 ตำแหน่งกำหนดทิศทาง การตรงกันของปลายทางใน PREROUTING เขียนใหม่ว่าแพ็กเก็ตจะไปไหน และการตรงกันของต้นทางใน POSTROUTING เขียนใหม่ว่ามันมาจากไหน

โฮสต์ที่ 192.168.2.17 ปรากฏต่อไคลเอนต์ของคุณเป็น 10.50.1.17 และออกเต็ตสุดท้ายไม่ใช่ของประดับ มันคือตัวเลขเดียวกันทั้งสองฝั่ง พรุ่งนี้เพิ่มโฮสต์ที่ 192.168.2.40 นามแฝงของมันคือ 10.50.1.40 โดยไม่มีกฎให้แก้

ไคลเอนต์ยังต้องมีเส้นทางสำหรับช่วงนามแฝงที่ชี้ไปยังกล่องของคุณ เว้นแต่นามแฝงจะอยู่ในซับเน็ตที่พวกเขาเข้าถึงอยู่แล้ว เกตเวย์ไม่ต้องมีเส้นทางสำหรับนามแฝง เพราะการแปลปลายทางทำงานใน PREROUTING ก่อนการค้นหาเส้นทาง ต้องเปิด forwarding ด้วย ไม่อย่างนั้นเคอร์เนลจะทิ้งแพ็กเก็ตหลังการเขียนใหม่ สามคำสั่งด้านล่างคือการตั้งค่าทั้งหมดบนเกตเวย์สไตล์ Debian ที่มีไคลเอนต์บน br0 นามแฝงบน 10.50.1.0/24 และอุโมงค์บน tun0

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A PREROUTING -i br0 -d 10.50.1.0/24 -j NETMAP --to 192.168.2.0/24
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

คำตอบต้องหาเส้นทางกลับเอง

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

Masquerade ขาออกเป็นทางที่สั้นกว่า กฎเดียวใน POSTROUTING และฝั่งไกลเห็นที่อยู่อุโมงค์ของคุณ จึงไม่ต้องมีเส้นทางของตัวเอง ราคาคือผู้ใช้ทุกคนยุบเป็นที่อยู่เดียว และล็อกต่อผู้ใช้ก็ไม่มีความหมายอีก ปล่อยต้นทางไว้ไม่แตะต้องจะเก็บข้อมูลนั้นไว้ แต่แล้วไซต์ไกลต้องส่งคำตอบสำหรับช่วงไคลเอนต์กลับผ่านอุโมงค์OpenVPN เซิร์ฟเวอร์ นั่นคือ push "route 10.50.9.0 255.255.255.0" ที่ถูก push พร้อมกับ route 192.168.2.0 255.255.255.0 บรรทัด

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

conntrack -L -d 10.50.1.17
iptables -t nat -L PREROUTING -v -n

อ่านรายการทั้งสองทิศทาง tuple ต้นฉบับเก็บนามแฝงของคุณไว้ที่ปลายทาง ขณะที่ tuple คำตอบพาที่อยู่จริง ถ้าไม่มี tuple คำตอบ ปัญหาคือเส้นทางกลับ ไม่ใช่กฎ ถ้าตัวนับ PREROUTING ไม่ขยับเลย แพ็กเก็ตไม่เคยไปถึง hook นั้น

การชนกันและการค้นหาที่ทำงานก่อน

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

บนเกตเวย์ ip route get 192.168.2.17 ควรระบุอุปกรณ์อุโมงค์ bridge ภายในเครื่องหมายความว่าช่วงไกลถูกบดบังและไม่มีกฎ nat ใดแก้ได้ ถ้าเครือข่ายของคุณใช้ 192.168.2.0/24 อยู่แล้ว ให้เปลี่ยนเลขไซต์ไกลแทนการซ้อนการแมปบนการชนกัน

ทดสอบจากไคลเอนต์จริง แล้วจึงเก็บไว้

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

curl -sv http://10.50.1.17/ -o /dev/null
ss -tn dst 10.50.1.17
conntrack -L -d 10.50.1.17

การเชื่อมต่อสำเร็จสองหรือสามครั้งพิสูจน์เลขคณิต แต่ไม่บอกอะไรเกี่ยวกับความคงทนหรือวิศวกรคนต่อไป บันทึกกฎไว้ที่ที่กระบวนการบูตอ่าน ซึ่งบน Debian และ Ubuntu หมายถึง iptables-save > /etc/iptables/rules.v4 ด้วย netfilter-persistent ที่เปิดใช้งาน การแมปที่หายไปเมื่อรีบูตแย่กว่าไม่มี เพราะเหตุขัดข้องมาโดยไม่มีการเปลี่ยนแปลงล่าสุดให้โทษ

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

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