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

เริ่มจากมุมมองของไคลเอนต์

ไคลเอนต์ในตัวอย่างนี้อยู่ในพูล VPN 10.62.0.0/24 และเชื่อมต่อกับ 10.62.0.1 บนพอร์ต 8080 ที่อยู่ดังกล่าวเป็นของเกตเวย์เอง แพ็กเก็ตจึงมาถึงเคอร์เนลของเกตเวย์ไม่ใช่เพื่อนร่วมเครือข่ายอื่น หลังเกตเวย์คือ LAN 172.21.4.0/24 เกตเวย์ถือ 172.21.4.10 และอุปกรณ์ที่ให้บริการ HTTP จริงคือ 172.21.4.40

ที่อยู่ที่เป็นของเพื่อน VPN อื่นใช้แทนที่อยู่บริการของเกตเวย์ไม่ได้ หากไคลเอนต์เชื่อมต่อกับที่อยู่ของเพื่อน ไม่มีกฎของเกตเวย์เข้ามาเกี่ยวข้องเลย และการเดินเรื่องทั้งหมดนี้เป็นกรณีที่ผิด

จำกัดขอบเขตการแปลปลายทางอย่างตั้งใจ

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

iptables -t nat -A PREROUTING -i tun0 -s 10.62.0.0/24 -d 10.62.0.1 -p tcp --dport 8080 -j DNAT --to-destination 172.21.4.40:80

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

ให้ขอบเขตการส่งต่อสอดคล้องกัน

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

iptables -A FORWARD -i tun0 -o lan0 -d 172.21.4.40 -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

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

อุปกรณ์ต้องตอบกลับให้ได้สักทางหนึ่ง

หลังการแปล อุปกรณ์เห็นต้นทางใน 10.62.0.0/24 คำตอบของมันไปยังเกตเวย์เริ่มต้น ซึ่งเป็นเราเตอร์ LAN ไม่ใช่เกตเวย์ VPN เว้นแต่มีอะไรบอกเป็นอย่างอื่น สองวิธีแก้ปัญหานี้ได้ และทั้งสองไม่เทียบเท่ากัน เส้นทางบนอุปกรณ์หรือบนเราเตอร์ LAN ส่ง 10.62.0.0/24 ไปยัง 172.21.4.10 โดยคงต้นทางของไคลเอนต์ ส่วนการแปลต้นทางแบบจำกัดกลับซ่อนไคลเอนต์ไว้หลังที่อยู่ LAN ของเกตเวย์

ip route add 10.62.0.0/24 via 172.21.4.10 dev eth1
iptables -t nat -A POSTROUTING -s 10.62.0.0/24 -d 172.21.4.40 -o lan0 -p tcp --dport 80 -j SNAT --to-source 172.21.4.10

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

อย่าทดสอบจากเกตเวย์เอง

คำขอที่สร้างบนเกตเวย์ไปยัง 10.62.0.1 ออกผ่านเชน OUTPUT ไม่ใช่ PREROUTING ขาเข้า ความล้มเหลวหรือความสำเร็จของมันไม่ได้บอกอะไรเกี่ยวกับกฎที่หันไปทางไคลเอนต์ และนั่นคือวิธีที่ผู้คนสรุปว่ากฎที่ทำงานอยู่เสีย

conntrack -L | grep 172.21.4.40
tcpdump -ni any 'port 8080 or port 80'

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

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