เกตเวย์สาธารณะเครื่องหนึ่งรัน WireGuard บน UDP 51820, SSH บน 22 และแอปพลิเคชันหนึ่งที่ต้องเข้าถึงได้จากอินเทอร์เน็ตอยู่แล้ว กฎที่ดูน่าดึงดูดส่งต่อทุกพอร์ตไปยัง peer แล้วประกาศว่างานเสร็จ บนเกตเวย์ WireGuard กฎนั้นอาจจับการรับส่งของอุโมงค์เองและล็อกคุณออกจากเครื่องที่ยุติอุโมงค์ การเผยแพร่คือการตัดสินใจเรื่องเส้นทางที่มีข้อยกเว้นสำหรับระนาบควบคุม ไม่ใช่บรรทัด DNAT บรรทัดเดียว

ทางเข้าสาธารณะหรือทางเข้าอุโมงค์ เลือกอย่างใดอย่างหนึ่ง

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

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

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

พอร์ตเดียวเข้า backend เดียวออก

ใช้พอร์ตสาธารณะหนึ่งพอร์ตและบริการ backend หนึ่งบริการ ในตัวอย่างนี้ eth0 ถือที่อยู่สาธารณะ 198.51.100.20 ที่อยู่อุโมงค์ของเกตเวย์คือ 10.200.0.1 และ peer รันแอปพลิเคชันบน 10.200.0.7 TCP สาธารณะ 9443 ถูกแมปไปยัง TCP 8443 ของ peer

iptables -t nat -A PREROUTING -i eth0 -d 198.51.100.20 -p tcp --dport 9443 -j DNAT --to-destination 10.200.0.7:8443
iptables -t nat -A POSTROUTING -o wg0 -d 10.200.0.7 -p tcp --dport 8443 -m conntrack --ctorigdst 198.51.100.20 --ctorigdstport 9443 -j SNAT --to-source 10.200.0.1

กฎ SNAT ตรงกับ backend ที่ถูกแปลแล้วและปลายทางสาธารณะดั้งเดิม ดังนั้นการเชื่อมต่ออื่นไปยังบริการ backend เดียวกันจึงอยู่นอกการแมปนี้ มันยังซ่อนที่อยู่ของผู้มาเยือนจาก peer และนั่นคือการแลกเปลี่ยนที่ทำให้เส้นทางกลับแบบกำหนดเส้นทางที่รักษาต้นทางกลายเป็นงานออกแบบแยก เอกสารอ้างอิงส่วนขยาย iptables อธิบายทั้งสองเป้าหมายและตัวเลือกการจับคู่

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

peer ต้องยอมรับการเชื่อมต่อบริการจากที่อยู่อุโมงค์ของเกตเวย์และส่งการตอบกลับกลับผ่านอุโมงค์ AllowedIPs ของมันต้องอนุญาตต้นทางที่มันได้รับจริง ซึ่งภายใต้การแปลต้นทางคือที่อยู่อุโมงค์ของเกตเวย์ และรายการ 0.0.0.0/0 แบบกว้างบนทุก peer ไม่จำเป็นสำหรับการออกแบบนี้ สิ่งที่ทำให้ทราฟฟิกขากลับหลุดคือ peer ที่รายการของมันละเว้นที่อยู่นั้น หรือการออกแบบที่รักษาต้นทางซึ่งส่งต่อที่อยู่ของผู้มาเยือนเองแทน ดังนั้นจงตรวจสอบต้นทางที่ peer เห็นจริง ไม่ใช่ต้นทางในกฎของคุณ

เก็บ listener ของเกตเวย์เองไว้นอกกฎ

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

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

หากต้องการส่งต่อแบบกว้างจริง ๆ ให้จองพอร์ตควบคุมไว้ก่อนกฎที่จับทุกอย่าง หรือใช้ที่อยู่สาธารณะแยกสำหรับการเผยแพร่ ตัวเลือกที่สองสะอาดกว่าเพราะที่อยู่ควบคุมรักษานโยบายของตัวเองไว้ แต่ผู้ให้บริการต้องส่งมอบที่อยู่นั้น การเพิ่มระเบียน DNS ไม่ได้จัดสรรที่อยู่ให้

การส่งต่อ TCP และ UDP แบบกว้างก็ไม่ใช่ทุกโปรโตคอล ICMP, IPv6, ข้อป้อนกลับ path-MTU และการรับส่ง VPN ชั้นนอกต้องการนโยบายของตัวเอง และกฎที่ครอบ TCP กับ UDP ปล่อยกรณีเหล่านั้นให้เชนเริ่มต้น

เลือกรูปแบบก่อนเขียนกฎ

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

ModelWhat it protectsCostUse when
Narrow port forwardEvery other listener, including the VPNOne rule per serviceFew services, stable ports
Catch-all with reserved portsPorts named in the exception listRule order becomes criticalMany services and disciplined review
Separate public addressControl address fully isolatedProvider must supply the addressHigh-value publication
VPN-only accessNo public entry at allVisitors need the tunnelAdmin interfaces and internal tools

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

พิสูจน์ทั้งการเผยแพร่และเส้นทางควบคุม

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

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

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