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>

응용 프로그램이 시작되었습니다.이 예제에서는 deluge를 사용하고 있습니다. 웹 인터페이스를 사용하여 여러 가지 응용 프로그램을 시도하여 특정 문제가 아닌지 확인했습니다.

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

veth vpn1의 ip를 지정하면 네임 스페이스 내에서 또는 외부에서 포트 8112의 웹 인터페이스에 액세스 할 수 있습니다.

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 규칙을 시도하고 좋은 척도를 위해 MASQUERADE를 던졌지 만, 내가하고있는 일을 모르기 때문에 내 시도는 쓸모가 없습니다. 어쩌면 누군가이 구성을 정리하는 데 도움이 될 수 있습니다.

편집 :의 tcpdump 출력 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 자신은 일반적인 iptables TCP 프록시를 설명하는 데비안 관리 기사 를 지적했습니다 . 당면한 문제에 적용되는 스크립트는 다음과 같습니다.

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

불행히도, veth 인터페이스 사이의 트래픽은 탈취되었고 다른 일은 발생하지 않았습니다. 그러나 @schnouki는 socatTCP 프록시로 사용하도록 제안했으며 이는 완벽하게 작동합니다.

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 인터페이스를 통과하는 동안 이상한 포트 셔플 링을 아직 이해하지 못했지만 이제는 문제가 해결되었습니다.


면책 조항 : 나는 veth장치에 대한 경험이 전혀 없습니다 (이것은 매우 흥미 롭습니다 ... ;-)). 당신은 사용해 본 적이 tcpdump들어오는 패킷이 얼마나 멀리 확인하기 위해? 경우 tcpdump -i veth0아무것도 표시되지 않습니다 다음 tcpdumo -i lo필요할 수 있습니다.
Hauke ​​Laging

나는 tcpdump와의 비 - 자세한 정보 출력 추가
pskiebe

답변:


9

나는 항상 iptables 리디렉션에 문제가있었습니다 (아마도 내 잘못, 그것이 가능하다고 확신합니다). 그러나 귀하와 같은 경우 iptables없이 사용자 영역에서 IMO를 수행하는 것이 더 쉽습니다.

기본적으로 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를 사용하고 싶다면 데비안 관리 사이트 에 안내서가 있습니다. 그러나 여전히 socatIPv4를 IPv6로 프록시 처리하거나 SSL을 제거하여 오래된 Java 프로그램이 보안 서비스에 연결할 수 있도록하는 등 고급 기능을 선호 합니다 ...

그러나 Deluge의 모든 연결은 실제 클라이언트 IP 대신 서버 IP에서 연결됩니다. 이를 피하려면 원래 클라이언트 IP를 프록시 헤더의 프록시 요청에 추가하는 실제 HTTP 리버스 프록시를 사용해야합니다.


1
오늘은 진짜 너 덕분이다! 나는 결코 오지 않았고 socatiptables로 지금 시도했던 것과 정확히 일치합니다. 여러 응용 프로그램을 테스트했으며 모두 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

메인 네임 스페이스와 네트워크 네임 스페이스를 상호 연결하면 항상 귀찮게됩니다. 일반적으로 네임 스페이스를 만드는 이유는 네임 스페이스를 분리하기 때문입니다. 상호 연결을 생성하는 네임 스페이스로 달성하려는 목표에 따라 이러한 목적을 달성 할 수 없습니다.

그러나 고립되어 있어도 편의상 네트워크를 통해 찌르기를 원합니다.

이 솔루션을 사용하면 격리를 유지하고 일부 연결을 어쨌든 전달할 수 있습니다. 하나의 포트를 전달하기 위해 두 네트워크 네임 스페이스간에 해당 네트워크를 모두 만들 필요는 없습니다. 연결을 허용 할 네임 스페이스에서이를 실행하십시오. ip netns exec작동하려면 루트로 실행해야합니다 .

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

포트 8112에서 실행하는 한 네트워크 네임 스페이스의 연결을 수신 한 다음 연결된 클라이언트는 네트워크 네임 스페이스 내부의 나머지 exec를 실행 ip netns exec myvpn ...하기 위해 실행 된 myvpn다음 myvpn네트워크 네임 스페이스 내부에서 다른 연결을 다시 생성합니다 socat.


매력처럼
대략적인 번호

리눅스 관리에 익숙하지 않아서 알아내는 데 시간이 걸렸습니다. :작은 따옴표 안에 두 문자를 모두 피하십시오. 그렇지 않으면 ... wrong number of parameters (2 instead of 1)(2 또는 3) 오류가 발생할 수 있습니다 . 그렇지 않으면 : 잘 작동합니다! 큰 감사합니다!
Igor

2

대홍수 여기 내 솔루션이 있습니다. iptables가 필요 없습니다. 단계는 다음과 같습니다.

  1. openvpn 터널을 시작하십시오
  2. 네임 스페이스를 만들고 openvpn 터널을 거기에 가져 오십시오.
ip netns는 $ NS를 추가합니다
# TUN이 올 때까지 기다리십시오
[[$ (ip route | grep $ TUN | wc -l) == 0]]; 잠을 1; 끝난
MY_IP = $ (ip addr show $ TUN | grep inet | cut -d ''-f6 | cut -d '/'-f1)
# openvpn 연결에 따라 게이트웨이 IP를 추출하는 방법이 다를 수 있습니다
GATEWAY_IP = $ MY_IP
# 네임 스페이스에 $ TUN (VPN 인터페이스)을 감금
IP 링크 세트 $ TUN netns $ NS
# 서브넷으로 인터페이스를 가져옵니다 (VPN 서버가 제공 한 것과 동일)
ip netns exec $ NS ifconfig $ TUN $ MY_IP / 24 up
# 루프백을 가져 오십시오
ip netns exec $ NS ifconfig lo 127.0.0.1/8 이상
# 원격 게이트웨이 설정 (포인트 투 포인트 VPN IP 주소)
ip netns exec $ NS route 기본 gw $ GATEWAY_IP 추가
  1. 기본 네임 스페이스와 생성 한 네임 스페이스 사이에 연결을 설정하십시오.
# 네임 스페이스 간 통신을위한 veth 인터페이스 설정
IP 링크 추가 veth0 유형 veth 피어 이름 veth1
# 두 번째 veth를 네임 스페이스로 이동
IP 링크 세트 veth1 netns $ NS
# 사용하지 않은 IP 범위에서 첫 번째 정맥까지 IP를 제공
ifconfig veth0 10.1.1.1/24 이상
# 그리고 두번째
ip netns exec $ NS ifconfig veth1 10.1.1.2/24 up
# TODO : veth1과 eth 인터페이스 사이에 브릿지를 설정하여 LAN과 통신 할 수 있도록합니다.
# DNS 클라이언트를 설정합니다. ip netns는이 파일을 사용하여 /etc/resolv.conf를 에뮬레이트합니다.
mkdir -p / etc / netns / $ NS
echo "nameserver 8.8.4.4"> /etc/netns/$NS/resolv.conf
  1. 기본 네임 스페이스에서 $ NS에서 델러 지 및 deluge-web을 실행하십시오. deluge-web을 10.1.1.2 veth IP 주소로 지정하십시오. 여기서 deluged는 해당 연결을 수신 대기합니다.

짜잔! 홈 네트워크에서 델지 웹에 자유롭게 액세스 할 수있는 동안 VPN 뒤에 안전하게 보호됩니다


2

@AndrDevEK의 답변이 유용합니다. 이를 확장하기 위해 설치하지 않을 수 있습니다 socat. 이 경우 약간 복잡한 SSH 포트 포워드 설정으로 동일한 작업을 수행 할 수 있습니다. 유닉스 도메인 소켓은 네트워크 네임 스페이스와 독립적으로 작동하기 때문에 특히 유닉스 도메인 소켓과의 포트 포워딩 기능은 유용합니다.

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 네임 스페이스 내부)로 전달됩니다. 두 번째 ssh -N -L는 기본 네임 스페이스에서 시작됩니다. 이것은 청취 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.