VPN을 사용하여 네트워크 네임스페이스의 애플리케이션에 포트 전달

VPN을 사용하여 네트워크 네임스페이스의 애플리케이션에 포트 전달

네트워크 네임스페이스를 설정하고, 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://내 서버 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 자신이 나에게 하나를 지적했습니다.Universal 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 인터페이스를 통과할 때 이상한 포트 셔플링이 발생하는 것을 파악하지 못했지만 이제 문제가 해결되었습니다.

답변1

네트워크 네임스페이스를 기본 네임스페이스와 상호 연결하는 것은 항상 짜증스럽습니다. 제가 주로 네임스페이스를 만드는 이유는 그것이 격리되기를 원하기 때문입니다. 네임스페이스를 사용하여 달성하려는 목적에 따라 상호 연결을 생성하면 해당 목적이 무효화될 수 있습니다.

하지만 고립된 상태에서도 편의상 웹을 통해 내용을 찔러보고 싶습니다.

이 솔루션을 사용하면 격리된 상태를 유지하고 일부 연결을 전달할 수 있습니다. 두 네트워크 네임스페이스 사이에 모든 네트워크를 만들 필요는 없으며 포트만 전달하면 됩니다. 연결을 허용하려는 네임스페이스에서 이 명령을 실행합니다. 작동 하려면 루트로 실행해야 합니다 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 ...한 다음 네트워크 네임스페이스에서 다시 다른 클라이언트와 통신합니다.myvpnmyvpnsocat

또는 시스템 서비스로 실행

이것도 사용됩니다 socat.

다음 내용으로 서비스 구성 파일을 만듭니다 /etc/systemd/system/deluge-web-netns.service.

[Unit]
Description=Forwarder to deluge-web in netns
After=network-online.target
#Requires=deluge-web.service
#After=deluge-web.service

[Service]
Type=simple

ExecStart=/usr/bin/socat tcp-listen:8112,fork,reuseaddr exec:'ip netns exec vpn-netns socat STDIO "tcp-connect:127.0.0.1:8112"',nofork
#User=deluge
#Group=deluge
SyslogIdentifier=deluge-web-fwd

Restart=on-failure

# Time to wait before forcefully stopped.
TimeoutStopSec=300

[Install]
WantedBy=multi-user.target

값을 확인/수정 ExecStart=/path/to/socat하세요"실행 파일의 절대 경로입니다"요구 사항에 따라 man systemd.service.

올바른 값을 설정하고 지시문을 활성화하는 것을 고려 하십시오 Requires.After

그런 다음 명령을 활성화하고 시작하십시오.

systemctl daemon-reload
systemctl enable deluge-web-netns
systemctl start  deluge-web-netns

아니면 아래에서 실행해보세요xinetd

이것도 사용됩니다 socat.

/etc/xinetd.d/deluge-web-fwd다음과 같은 내용으로 conf 파일을 만듭니다 .

service deluge-web-vpn-netns
{
    type            = UNLISTED
    socket_type     = stream
    protocol        = tcp
    port            = 8112
    flags           = IPv4 KEEPALIVE
    wait            = no
    user            = root
    server          = /sbin/ip
    server_args     = netns exec vpn-netns socat STDIO tcp-connect:127.0.0.1:8112
}

재시작xinetd

service xinetd restart

프로그램 ncat도 와 유사하게 사용할 수 있습니다 socat.

답변2

나는 iptables 리디렉션에 문제가 있었습니다(아마도 내 잘못일 것입니다. 이것이 가능하다고 확신합니다). 하지만 귀하와 같은 경우에는 iptables 없이 사용자 공간에서 수행하는 것이 더 쉬운 것 같습니다.

기본적으로 TCP 포트 8112에서 수신 대기하고 모든 트래픽을 10.200.200.2 포트 8112로 리디렉션하는 "기본" 작업 공간에 데몬이 있어야 합니다. 따라서 이는 간단한 TCP 프록시입니다.

수행 방법은 다음과 같습니다.소캇:

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

( 이 옵션은 첫 번째 프록시 연결이 닫힌 후 중지되는 것을 fork방지하기 위해 필요합니다 .)socat

편집하다reuseaddr:댓글에 제안된 대로 추가되었습니다.

iptables로 이 작업을 꼭 수행하고 싶다면 다음 가이드를 참조하세요.데비안 관리장소. 하지만 저는 여전히 socatIPv4를 IPv6로 프록시하거나 SSL을 제거하여 이전 Java 프로그램이 보안 서비스에 연결할 수 있도록 하는 것과 같은 좀 더 고급 기능을 선호합니다 .

하지만 Deluge의 모든 연결은 실제 클라이언트 IP가 아닌 서버 IP에서 비롯된다는 점에 유의하세요. 이를 방지하려면 실제 HTTP 역방향 프록시를 사용하여 HTTP 헤더의 프록시 요청에 원래 클라이언트 IP를 추가해야 합니다.

답변3

홍수의 경우 이것이 나의 해결책입니다. iptable이 필요하지 않습니다. 다음과 같이 진행하세요:

  1. OpenVPN 터널을 시작하세요
  2. 네임스페이스를 생성하고 openvpn 터널을 해당 네임스페이스로 가져옵니다.
ip netns $NS 추가
# TUN이 나타날 때까지 기다립니다
그리고 [[ $(ip Routing|grep $TUN|wc -l) == 0 ]];
MY_IP=$(IP 주소는 $TUN|grep inet|cut -d' ' -f6|cut -d'/' -f1을 표시합니다.)
# 게이트웨이 IP를 추출하는 방법은 openvpn 연결에 따라 다를 수 있습니다.
GATEWAY_IP=$MY_IP
# 내 $TUN(VPN 인터페이스)을 네임스페이스에 가두기
IP 링크 설정 $TUN netns $NS
# 인터페이스의 서브넷을 설정합니다(VPN 서버에서 제공한 서브넷과 동일).
ip netns exec $NS ifconfig $TUN $MY_IP/24 위로
# 루프백 시작
ip netns exec $NS ifconfig lo 127.0.0.1/8 위로
# 원격 게이트웨이 설정(사이트 간 VPN IP 주소)
ip netns exec $NS 라우팅은 기본 게이트웨이 $GATEWAY_IP를 추가합니다.
  1. 기본 네임스페이스와 생성한 네임스페이스 사이에 veth 연결을 설정합니다.
#네임스페이스 간 통신을 위한 veth 인터페이스 설정
IP 링크 추가 veth0 유형 veth 피어 이름 veth1
#두 번째 veth를 네임스페이스로 이동
IP 링크 설정 veth1 netns $NS
# 사용하지 않는 IP 범위의 IP를 첫 번째 veth에 제공합니다.
ifconfig veth0 10.1.1.1/24 이상
# 두번째
ip netns exec $NS ifconfig veth1 10.1.1.2/24 위로
# TODO: veth1과 eth 인터페이스 사이에 브리지를 생성하여 LAN과 통신할 수 있도록 합니다.
# DNS 클라이언트를 설정합니다. ip netns는 이 파일을 사용하여 /etc/resolv.conf를 에뮬레이트합니다:
mkdir -p /etc/netns/$NS
echo "nameserver8.8.4.4">/etc/netns/$NS/resolv.conf
  1. $NS에서 deluged를 실행하고 기본 네임스페이스에서 deluge-web을 실행합니다. Deluge-web이 Deluged가 연결을 수신할 10.1.1.2 veth IP 주소를 가리키도록 합니다.

바라보다! 홍수 네트워크는 VPN으로 보호되며 홍수 네트워크는 홈 네트워크에서 자유롭게 액세스할 수 있습니다.

답변4

@AndrDevEK의 답변이 유용합니다. 이를 확장하려면 socat. 특히 Unix 도메인 소켓을 사용하여 포트 전달하는 기능은 여기에서 매우 유용합니다. 왜냐하면 Unix 도메인 소켓은 네트워크 네임스페이스와 독립적으로 작동하기 때문입니다.

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 -Lmyvpn 네임스페이스 내에서 시작됩니다. 그러면 Unix 도메인 소켓이 생성되고 /tmp/myunixsock수신됩니다. 들어오는 연결은 localhost:8112(myvpn 네임스페이스 내)로 전달됩니다. 두 번째는 ssh -N -L기본 네임스페이스에서 시작됩니다. 그러면 수신 대기 TCP 포트가 생성되고 들어오는 연결이 Unix 도메인 소켓으로 전달됩니다.

이것이 작동하려면 ssh네트워크 네임스페이스 내부가 아직 작동하지 않는 경우 작동해야 한다는 점에 유의해야 합니다(그리고 비밀번호 없는 공개 키 작업이 도움이 됩니다).

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

관련 정보