วิธีการส่งต่อพอร์ตจาก ip หนึ่งไปยัง ip อื่นในเครือข่ายเดียวกัน


77

ผมอยากจะทำบางอย่างในNAT iptablesเพื่อให้ทุกแพ็กเก็ตที่จะมาถึง192.168.12.87และพอร์ต80จะถูกส่งต่อไปยังท่าเรือ192.168.12.7780

วิธีการทำเช่นนี้กับ iptables?

หรือ

มีวิธีอื่นอีกไหมในการบรรลุเป้าหมายเดียวกัน?


@ Matewlfe ด้วยเหตุผลบางอย่างฉันต้องส่งคำขอ Apache ทั้งหมดจาก (192.168.12.87) ไปยัง (192.168.12.77)
เสาร์ที่

1
@ Matthllfe ฉันมีเซิร์ฟเวอร์การผลิตสองแห่ง มีการเชื่อมต่อหนึ่งกับที่อยู่ IP สาธารณะคงที่ เนื่องจากปัญหาการเชื่อมต่อบางอย่างฉันไม่สามารถเชื่อมต่อกับฐานข้อมูลและระบบอื่น ๆ192.168.12.87ได้ 192.168.12.77ดังนั้นฉันจึงต้องส่งต่อทุกการร้องขอไปยัง
เสาร์ที่

@lain iptablesผมไม่คุ้นเคยกับ และฉันเห็นตัวอย่าง แต่ดูเหมือนว่าจะต้องมีสองอีเธอร์เน็ต Link: revsys.com/writings/quicktips/nat.html
นั่ง

คุณสามารถใช้โหมดพร็อกซี่ในเว็บเซิร์ฟเวอร์เพื่อส่งคำขอไปที่ 192.168.12.77 จาก 192.168.12.87 (หากเว็บเซิร์ฟเวอร์ของคุณรองรับ)
krisFR

คำตอบ:


75

กฎเหล่านี้ควรใช้งานได้สมมติว่าiptablesทำงานบนเซิร์ฟเวอร์192.168.12.87:

#!/bin/sh

echo 1 > /proc/sys/net/ipv4/ip_forward

iptables -F
iptables -t nat -F
iptables -X

iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.12.77:80
iptables -t nat -A POSTROUTING -p tcp -d 192.168.12.77 --dport 80 -j SNAT --to-source 192.168.12.87

คุณต้องรับส่งข้อมูลขาเข้าของ DNAT ที่พอร์ต 80 แต่คุณจะต้องใช้ SNAT ในการรับส่งข้อมูลกลับ


ทางเลือก (และวิธีการที่ดีที่สุด IMHO):

ขึ้นอยู่กับว่าเว็บเซิร์ฟเวอร์ของคุณคืออะไร (Apache, NGinx) คุณควรพิจารณา HTTP Proxy บนเซิร์ฟเวอร์หน้า (192.168.12.87):


ทำงานตราบใดที่ ufw ถูกปิดใช้งานแม้ว่าพอร์ตจะอนุญาตให้ใช้ใน ufw แต่ถ้าเปิดใช้งาน ufw สิ่งที่ส่งต่อนี้จะไม่ทำงานมีความคิดใด ๆ
Sudhir N

1
สุดยอดคำถามพร้อมคำตอบที่ดี การใช้งานกรณีอื่นที่มีประโยชน์คือถ้าคุณต้องการเปลี่ยนเส้นทางการรับส่งข้อมูลทั้งหมดที่เข้ามาในบริการหนึ่งชั่วคราวเช่น squid ไปยัง ip / พอร์ตอื่นเพื่อทำการบำรุงรักษาบริการเดิมโดยไม่จำเป็นต้องกำหนดค่าไคลเอนต์ทั้งหมด! มีประโยชน์มาก!
PF4Public

3
"แต่คุณจะต้อง SNAT ปริมาณข้อมูลคืน" -> คุณช่วยชีวิตฉันไว้ ขอขอบคุณ
obayhan

วิธีนี้ไม่ได้ผลสำหรับฉัน ฉันต้องส่งต่อจาก eth0 ไปยังเครือข่ายเสมือน (virb0) ซึ่งใช้โดยผู้เยี่ยมชม KVM ฉันพยายามเพิ่มตัวเลือก -i และ -o แต่ -o ไม่ได้รับอนุญาตให้กำหนดค่าล่วงหน้า ข้อเสนอแนะใด ๆ
สูญหายใน

ระวังด้วยวิธีนี้ ฉันไม่สามารถเข้าถึงเครื่องระยะไกลได้ในขณะนี้
Sören

28

เหตุผลที่ชัดเจนดูเหมือนiptables -t nat -A PREROUTING -d 192.168.12.87 -p tcp --dport 80 -j DNAT --to-destination 192.168.12.77จะไม่ทำงานเป็นวิธีการที่แพ็กเก็ตกลับจะถูกกำหนดเส้นทาง

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

มีสามวิธีในการแก้ปัญหานี้

  1. ในโฮสต์แรกไม่เพียง แต่ทำ DNAT แต่ยังทำ SNAT เพื่อให้ทราฟฟิกที่ส่งคืนจะถูกส่งกลับผ่านโฮสต์แรก กฎอาจมีลักษณะเหมือนiptables -t NAT -A POSTROUTING -d 192.168.12.77 -p tcp --dport 80 -j SNAT --to-source 192.168.12.87
  2. รับแรงบันดาลใจจากการทำโหลดบาลานซ์ DSR และ DNAT แพ็กเก็ตที่เลเยอร์ Ethernet แทนที่จะเป็นที่เลเยอร์ IP โดยการแทนที่ MAC ปลายทางของแพ็กเก็ตด้วย MAC ของ 192.168.12.77 และส่งไปยังอีเธอร์เน็ตโดยไม่ต้องสัมผัสเลเยอร์ IP จากนั้น 192.168.12.77 อาจมี 192.168.12.87 ตั้งค่าบนอินเทอร์เฟซแบบจำลองและทำให้สามารถยุติการเชื่อมต่อ TCP ได้ กับเซิร์ฟเวอร์ IP ที่ลูกค้ารู้จัก
  3. ใช้โซลูชันไร้เดียงสา (แต่ไม่ทำงาน) บนโฮสต์แรก จากนั้นจัดการแพ็กเก็ตคืนบนโฮสต์ที่สองโดยทำ SNAT กับทราฟฟิกที่ส่งคืน กฎอาจมีลักษณะเช่นiptables -t nat -A OUTPUT -p tcp --sport 80 -j SNAT --to-source 192.168.12.87

แต่ละวิธีแก้ปัญหาทั้งสามนั้นมีข้อเสียดังนั้นคุณต้องพิจารณาอย่างรอบคอบหากคุณต้องการส่งต่อโดยเฉพาะอย่างยิ่ง

  1. การใช้ SNAT จะสูญเสีย IP ของไคลเอ็นต์ดังนั้นโฮสต์หมายเลข 2 จะคิดว่าการเชื่อมต่อทั้งหมดมาจาก 192.168.12.87 นอกจากนี้คุณจะใช้แบนด์วิดท์ผ่านหมายเลขโฮสต์ 1 สำหรับแพ็กเก็ตตอบกลับทั้งหมดซึ่งจะใช้เส้นทางตรงมากขึ้นด้วยวิธีการอื่น
  2. วิธี DSR จะหยุดการสื่อสารอื่น ๆ ทั้งหมดระหว่างสองโหนด วิธี DSR นั้นจะเหมาะสมก็ต่อเมื่อที่อยู่เซิร์ฟเวอร์ไม่ใช่ IP หลักของโฮสต์ใด ๆ แต่ละโฮสต์ต้องมี IP หลักซึ่งไม่ใช่ IP DSR
  3. การใช้การติดตามการเชื่อมต่อกับโฮสต์หนึ่งเพื่อแปลในทิศทางเดียวและการติดตามการเชื่อมต่อกับโฮสต์อื่นเพื่อแปลในทิศทางอื่นนั้นน่าเกลียดและมีหลายวิธีที่อาจแตกหักได้ ตัวอย่างเช่นถ้าหมายเลขพอร์ตถูกแก้ไขโดย NAT บนโฮสต์ใด ๆ ไม่มีวิธีการสร้างใหม่ การติดตามการเชื่อมต่อนั้นจะทำงานได้อย่างถูกต้องหากแพ็กเก็ตแรกที่เห็นคือ SYN-ACK แทนที่จะเป็น ACK

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

คุณยังสามารถเลือกที่จะลืม NAT ทั้งหมดและไม่พยายามแก้ไขปัญหาในเลเยอร์ MAC หรือ IP คุณสามารถไปจนถึงเลเยอร์ HTTP และค้นหาวิธีแก้ไขที่นั่น ในกรณีนั้นการแก้ปัญหาที่คุณจะพบคือ HTTP proxy หากคุณติดตั้งพร็อกซี HTTP ใน 192.168.12.87 และกำหนดค่าอย่างเหมาะสมคุณสามารถส่งต่อคำขอไปที่ 192.168.12.77 และส่งต่อคำตอบกลับ นอกจากนี้ยังสามารถแทรกส่วนหัว X-Forwarded-For เพื่อรักษา IP ไคลเอ็นต์ดั้งเดิม เซิร์ฟเวอร์บน 192.168.12.77 ต้องถูกกำหนดค่าเพื่อเชื่อถือส่วนหัว X-Forwarded-For จาก 192.168.12.87


ฉันประหลาดใจ-j MASQUERADEไม่ได้กล่าวถึงที่นี่; ไม่ใช่วิธีการปกติของ DNAT ใช่ไหม
remram

3
@remram ฉันพูดSNATแทนMASQUERADEเพราะนั่นคือสิ่งที่เอกสารพูด ถ้อยคำที่แน่นอนในเอกสารประกอบคือ:It should only be used with dynamically assigned IP (dialup) connections: if you have a static IP address, you should use the SNAT target.
kasperd
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.