ส่งต่อพอร์ตไปยังแอปพลิเคชันในเนมสเปซเครือข่ายด้วย vpn


13

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

ฉันทำตามคำแนะนำจาก @schnouki อธิบายวิธีตั้งค่าเนมสเปซเครือข่ายและเรียกใช้ OpenVPN ภายใน

ip netns add myvpn
ip netns exec myvpn ip addr add 127.0.0.1/8 dev lo
ip netns exec myvpn ip link set lo up
ip link add vpn0 type veth peer name vpn1
ip link set vpn0 up
ip link set vpn1 netns myvpn up
ip addr add 10.200.200.1/24 dev vpn0
ip netns exec myvpn ip addr add 10.200.200.2/24 dev vpn1
ip netns exec myvpn ip route add default via 10.200.200.1 dev vpn1
iptables -A INPUT \! -i vpn0 -s 10.200.200.0/24 -j DROP
iptables -t nat -A POSTROUTING -s 10.200.200.0/24 -o en+ -j MASQUERADE
sysctl -q net.ipv4.ip_forward=1
mkdir -p /etc/netns/myvpn
echo 'nameserver 8.8.8.8' > /etc/netns/myvpn/resolv.conf

หลังจากนั้นฉันสามารถตรวจสอบ ip ภายนอกของฉันและรับผลลัพธ์ที่แตกต่างกันทั้งภายในและภายนอกเนมสเปซได้ตามที่ต้องการ:

curl -s ipv4.icanhazip.com
<my-isp-ip>
ip netns exec myvpn curl -s ipv4.icanhazip.com
<my-vpn-ip>

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

ip netns exec myvpn sudo -u <my-user> /usr/bin/deluged
ip netns exec myvpn sudo -u <my-user> /usr/bin/deluge-web -f
ps $(ip netns pids myvpn)
 PID TTY      STAT   TIME COMMAND
1468 ?        Ss     0:13 openvpn --config /etc/openvpn/myvpn/myvpn.conf
9302 ?        Sl    10:10 /usr/bin/python /usr/bin/deluged
9707 ?        S      0:37 /usr/bin/python /usr/bin/deluge-web -f

ฉันสามารถเข้าถึงเว็บอินเตอร์เฟสบนพอร์ต 8112 จากภายในเนมสเปซและจากภายนอกหากฉันระบุ IP ของ veth vpn1

ip netns exec myvpn curl -Is localhost:8112 | head -1
HTTP/1.1 200 OK
ip netns exec myvpn curl -Is 10.200.200.2:8112 | head -1
HTTP/1.1 200 OK
curl -Is 10.200.200.2:8112 | head -1
HTTP/1.1 200 OK

แต่ฉันต้องการเปลี่ยนเส้นทางพอร์ต 8112 จากเซิร์ฟเวอร์ของฉันไปยังแอปพลิเคชันในเนมสเปซ เป้าหมายคือการเปิดเบราว์เซอร์บนคอมพิวเตอร์ภายใน LAN ของฉันและรับเว็บอินเตอร์เฟสด้วยhttp: // my-server-ip: 8112 (my-server-ip เป็น ip แบบคงที่ของเซิร์ฟเวอร์ที่อินสแตนซ์เครือข่ายอินสแตนซ์)

แก้ไข: ฉันลบความพยายามในการสร้างกฎ iptables สิ่งที่ฉันพยายามจะทำอธิบายไว้ข้างต้นและคำสั่งต่อไปนี้ควรส่ง HTTP 200:

curl -I localhost:8112
curl: (7) Failed to connect to localhost port 8112: Connection refused
curl -I <my-server-ip>:8112
curl: (7) Failed to connect to <my-server-ip> port 8112: Connection refused

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

แก้ไข: tcpdump -nn -q tcp port 8112เอาท์พุทของ แปลกใจที่คำสั่งแรกจะส่งคืน HTTP 200 และคำสั่งที่สองจะยุติลงด้วยการเชื่อมต่อที่ถูกปฏิเสธ

curl -Is 10.200.200.2:8112 | head -1
listening on vpn0, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 10.200.200.1.36208 > 10.200.200.2.8112: tcp 82
IP 10.200.200.2.8112 > 10.200.200.1.36208: tcp 145

curl -Is <my-server-ip>:8112 | head -1
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
IP <my-server-ip>.58228 > <my-server-ip>.8112: tcp 0
IP <my-server-ip>.8112 > <my-server-ip>.58228: tcp 0

แก้ไข: @schnouki ตัวเองชี้ให้ฉันไปบทความ Debian บริหารอธิบาย iptables ทั่วไปพร็อกซี่ นำไปใช้กับปัญหาที่เกิดขึ้นสคริปต์ของพวกเขาจะมีลักษณะเช่นนี้:

YourIP=<my-server-ip>
YourPort=8112
TargetIP=10.200.200.2
TargetPort=8112

iptables -t nat -A PREROUTING --dst $YourIP -p tcp --dport $YourPort -j DNAT \
--to-destination $TargetIP:$TargetPort
iptables -t nat -A POSTROUTING -p tcp --dst $TargetIP --dport $TargetPort -j SNAT \
--to-source $YourIP
iptables -t nat -A OUTPUT --dst $YourIP -p tcp --dport $YourPort -j DNAT \
--to-destination $TargetIP:$TargetPort

น่าเสียดายที่การรับส่งข้อมูลระหว่างส่วนต่อข้อมูลสัตวแพทย์ได้ยึดและไม่มีอะไรเกิดขึ้น อย่างไรก็ตาม @schnouki ยังแนะนำให้ใช้socatเป็นพร็อกซี TCP และทำงานได้อย่างสมบูรณ์

curl -Is <my-server-ip>:8112 | head -1
IP 10.200.200.1.43384 > 10.200.200.2.8112: tcp 913
IP 10.200.200.2.8112 > 10.200.200.1.43384: tcp 1495

ฉันยังไม่เข้าใจถึงการสลับพอร์ตแปลก ๆ ในขณะที่ทราฟฟิกข้ามผ่านส่วนต่อประสานสัตวแพทย์ แต่ปัญหาของฉันได้รับการแก้ไขแล้ว


ข้อจำกัดความรับผิดชอบ: ฉันไม่มีประสบการณ์กับvethอุปกรณ์เลย (พบว่าน่าสนใจมากแม้ว่า ... ;-)) คุณเคยใช้tcpdumpในการตรวจสอบว่าแพ็คเก็ตขาเข้าได้รับมานานแค่ไหนแล้วหรือยัง? หากtcpdump -i veth0ไม่แสดงสิ่งใดtcpdumo -i loอาจจำเป็น
Hauke ​​Laging

ฉันได้เพิ่มเอาต์พุตที่ไม่ใช่ verbose ของ tcpdump
pskiebe

คำตอบ:


9

ฉันเคยมีปัญหากับการเปลี่ยนเส้นทาง iptables (อาจเป็นความผิดของฉันฉันค่อนข้างแน่ใจว่ามันเป็นไปได้) แต่สำหรับกรณีของคุณ IMO ง่ายกว่าที่จะทำในพื้นที่ผู้ใช้โดยไม่มี iptables

โดยทั่วไปคุณต้องมี daemon ในเวิร์กสเปซ "default" ที่รับฟังบนพอร์ต TCP 8112 และเปลี่ยนเส้นทางปริมาณการใช้งานทั้งหมดเป็น 10.200.200.2 พอร์ต 8112 ดังนั้นจึงเป็น TCP พร็อกซีแบบธรรมดา

นี่คือวิธีการทำกับsocat :

socat tcp-listen:8112,reuseaddr,fork tcp-connect:10.200.200.2:8112

( forkตัวเลือกที่จำเป็นเพื่อหลีกเลี่ยงsocatการหยุดหลังจากการเชื่อมต่อพร็อกซี่แรกถูกปิด)

แก้ไข : เพิ่มreuseaddrตามที่แนะนำในความคิดเห็น

หากคุณต้องการทำกับ iptables อย่างแน่นอนมีคำแนะนำเกี่ยวกับเว็บไซต์Debian Administration แต่ฉันยังคงต้องการsocatสิ่งที่ล้ำสมัยมากกว่าเช่น proxying IPv4 ถึง IPv6 หรือการแยก SSL เพื่ออนุญาตให้โปรแกรม Java เก่าเชื่อมต่อกับบริการที่ปลอดภัย ...

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


1
คุณทำให้วันนี้ดี! ฉันไม่เคยเจอsocatและมันก็ทำสิ่งที่ฉันพยายามจะทำกับ iptables ได้สักพักแล้ว ฉันทดสอบแอพพลิเคชั่นหลายตัวและพวกมันทำงานได้อย่างไร้ที่ติโดยเชื่อมต่อกับโลกภายนอกผ่านทาง tun0 ในขณะที่ยังคงให้การเข้าถึงเว็บอินเตอร์เฟสผ่าน veth1
pskiebe

1
หลังจากทำการทดสอบฉันเพิ่มreuseaddrธง สิ่งนี้จะช่วยป้องกันport already in useข้อผิดพลาดเมื่อเริ่มต้นและหยุด socat อย่างรวดเร็ว:socat -4 TCP-LISTEN:8112,reuseaddr,fork TCP:10.200.200.2:8112
pskiebe

8

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

แต่ถึงอย่างนั้นฉันก็ยังต้องการที่จะสะกิดมันผ่านเครือข่ายเพื่อความสะดวก

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

socat tcp-listen:8112,fork,reuseaddr \
  exec:'ip netns exec myvpn socat STDIO tcp-connect\:127.0.0.1\:8112',nofork

มันฟังสำหรับการเชื่อมต่อเครือข่ายใน namespace หนึ่งที่คุณเรียกใช้บนพอร์ต 8112 แล้วลูกค้าที่เชื่อมต่อได้รับexecการเรียกใช้ip netns exec myvpn ...ในการดำเนินการส่วนที่เหลือภายในmyvpnnamespace เครือข่ายแล้วเมื่อภายในmyvpnnamespace socatเครือข่ายจะสร้างการเชื่อมต่อที่สองอีกครั้งกับอีก


ทำงานอย่างมีเสน่ห์
ประมาณ

เนื่องจากฉันไม่ได้มีประสบการณ์เกี่ยวกับการจัดการ linux มากเกินไปและทำให้ฉันเสียเวลาในการค้นหา: โปรดหลีกเลี่ยง:อักขระทั้งสองตัวในเครื่องหมายคำพูดเดี่ยวมิฉะนั้นคุณอาจพบข้อผิดพลาด... wrong number of parameters (2 instead of 1)(2 หรือ 3) เป็นอย่างอื่น: ใช้งานได้ดี! ขอบคุณมาก!
Igor

2

สำหรับน้ำท่วมนี่คือทางออกของฉัน ไม่จำเป็นต้อง iptables นี่คือขั้นตอน:

  1. เริ่มอุโมงค์ openvpn ของคุณ
  2. สร้างเนมสเปซและนำอุโมงค์ openvpn ของคุณไปที่นั่น:
ip netns เพิ่ม $ NS
# รอให้ TUN ขึ้นมา
ในขณะที่ [[$ (เส้นทาง ip | grep $ TUN | wc -l) == 0]]; นอนหลับ 1 เสร็จแล้ว
MY_IP = $ (ip addr แสดง $ TUN | grep inet | cut -d '' -f6 | cut -d '/' -f1)
# วิธีที่คุณดึง IP ของเกตเวย์อาจแตกต่างกันสำหรับการเชื่อมต่อ openvpn ของคุณ
GATEWAY_IP = $ MY_IP
# คุม $ TUN (อินเทอร์เฟซ VPN) ของฉันไว้ในเนมสเปซ
ip link ตั้งค่า $ TUN netns $ NS
# นำอินเทอร์เฟซขึ้นกับซับเน็ต (เทียบเท่ากับเซิร์ฟเวอร์ VPN ที่ฉันมอบให้)
ip netns เรียกใช้ $ NS ifconfig $ TUN $ MY_IP / 24 ขึ้นไป
# นำลูปแบ็คขึ้น
ip netns exec $ NS ifconfig แท้จริง 127.0.0.1/8 ขึ้นไป
# ตั้งค่าเกตเวย์ระยะไกล (ที่อยู่ IP pointtopoint VPN ของคุณ)
ip netns exec เส้นทาง $ NS เพิ่มค่าเริ่มต้น gw $ GATEWAY_IP
  1. สร้างการเชื่อมต่อ veth ระหว่าง namespace เริ่มต้นของคุณและที่คุณสร้างขึ้น:
# ตั้งค่าอินเตอร์เฟสสัตวแพทย์สำหรับการสื่อสารระหว่างเนมสเปซ
ip link เพิ่ม veth0 ประเภท veth เพียร์ชื่อ veth1
# ย้าย veth ที่สองไปยังเนมสเปซของคุณ
ip link set veth1 netns $ NS
# ให้ IP จากช่วง IP ที่ไม่ได้ใช้จนถึงอันดับแรก
ifconfig veth0 10.1.1.1/24 ขึ้นไป
# และอันที่สอง
ip netns เรียกใช้ $ NS ifconfig veth1 10.1.1.2/24 ขึ้นไป
# TODO: ตั้งค่าบริดจ์ระหว่าง veth1 และ eth interface เพื่อให้สามารถสื่อสารกับ LAN ได้
# ตั้งค่าไคลเอนต์ DNS ip netns จะเลียนแบบ /etc/resolv.conf โดยใช้ไฟล์นี้:
mkdir -p / etc / netns / $ NS
echo "nameserver 8.8.4.4"> /etc/netns/$NS/resolv.conf
  1. เรียกใช้ deluged ของคุณใน $ NS และ deluge-web ของคุณในเนมสเปซเริ่มต้นของคุณ ชี้ deluge-web ไปที่ 10.1.1.2 ที่อยู่ IP veth ซึ่ง deluged จะรับฟังการเชื่อมต่อ

Voila! คุณได้รับการรักษาความปลอดภัยที่ซ่อนอยู่หลัง VPN ในขณะที่น้ำท่วมเว็บของคุณสามารถเข้าถึงได้อย่างอิสระบนเครือข่ายภายในบ้านของคุณ


2

@ คำตอบของ AndrDevEK นั้นมีประโยชน์ socatเพื่อขยายความว่าคุณอาจไม่ต้องการที่จะติดตั้ง ในกรณีนี้คุณสามารถบรรลุสิ่งเดียวกันด้วยการตั้งค่าพอร์ตส่งต่อ SSH ที่ซับซ้อนเล็กน้อย โดยเฉพาะคุณสมบัติการส่งต่อพอร์ตไปยัง / จากซ็อกเก็ต unix-domain มีประโยชน์ที่นี่เนื่องจากซ็อกเก็ต unix-domain ทำงานโดยไม่ขึ้นกับเนมสเปซเครือข่าย:

sudo ip netns exec myvpn su -c "ssh -N -L /tmp/myunixsock:localhost:8112 localhost" $USER &
ssh_pid1=$!
ssh -N -L localhost:8112:/tmp/myunixsock localhost &
ssh_pid2=$!

ทำความสะอาด:

sudo kill $ssh_pid1
kill $ssh_pid2
rm /tmp/myunixsock

อันแรกssh -N -Lเริ่มต้นภายใน myvpn เนมสเปซ สิ่งนี้จะสร้างซ็อกเก็ตยูนิกซ์โดเมน/tmp/myunixsockและฟังมัน การเชื่อมต่อขาเข้าจะถูกส่งต่อไปยัง localhost: 8112 (ภายใน myvpn namespace) ที่สองssh -N -Lเริ่มต้นใน namespace เริ่มต้น สิ่งนี้จะสร้างพอร์ต TCP ที่รับฟังและส่งต่อการเชื่อมต่อขาเข้าไปยังซ็อกเก็ต unix-domain

ควรสังเกตว่าเพื่อให้สิ่งนี้สามารถทำงานได้sshภายในเนมสเปซเครือข่ายของคุณจะต้องใช้งานได้หากยังไม่ได้ดำเนินการ (และการดำเนินการ pubkey ที่ไม่มีรหัสผ่านจะเป็นประโยชน์):

sudo ip netns exec myvpn ip link set up dev lo
sudo ip netns exec myvpn /usr/sbin/sshd -o PidFile=/run/sshd-myvpn.pid
ssh-copy-id localhost
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.