
다소 초보적인 질문일 수도 있지만...
나는 Ubuntu 18.04.3 LTS를 사용하고 있으며VPN몇 가지 응용 프로그램에 사용하고 싶습니다. 체크아웃했어요namespaced-openvpn
그리고 그것은 작동합니다! 주의할 점은 관리 목적으로 이 애플리케이션에 로컬로 연결할 수 없다는 것입니다.
VPN 터널 내부의 특정 포트를 로컬 호스트로 전달하는 방법이 있습니까?VPN 터널이 다른 목적으로 이를 사용하여 너무 많은 정보를 유출하지 않고 있습니까?
내가 이미 할 수 있는 일:
- 달리다
namespaced-openvpn
-스크립트:sudo ./namespaced-openvpn --namespace vpn --config /etc/openvpn/vpn-xxxxx.ovpn
- 네트워크 네임스페이스 내에서 애플리케이션을 실행합니다.
sudo ip netns exec vpn application
내가 달성하고 싶은 것:
1234
실제 로컬 호스트(enp3s0
이더넷 어댑터) 에서 VPN 터널(예: 포트) 내부에서 시작된 애플리케이션에 연결합니다.- 내 LAN에 있는 다른 컴퓨터에서 액세스할 수 있도록 이 포트를 전달합니다.
답변1
몇 년이 지났지만, 제가 지난 며칠 동안 그랬더라면 좋았을 것처럼 누군가가 이 문제를 접하게 될 경우를 대비해 말이죠.
누군가에게 도움이 되기를 바랍니다.
첫째, 여기에 모든 것을 실행하는 작업의 90%를 수행하는 네임스페이스 VPN이 있습니다.
https://github.com/slingamn/namespaced-openvpn
그리고 여기에 무슨 일이 왜 이루어지고 있는지 이해하지 못했음에도 불구하고 나에게 많은 도움이 된 것과 거의 똑같은 질문에 대한 답변이 있습니다. https://unix.stackexchange.com/questions/391193/how-to-forward-traffic-between-linux-network-namespaces
나는 검색에서 찾은 정보의 일부를 사용하여 많은 시행착오 끝에 내가 이해하게 된 내용을 설명하려고 노력할 것입니다.
(서비스가 실행 중인 PC가 아닌) 서비스로 연결을 전달하는 데 가장 관련성이 높은 부분은 다음과 같습니다(PREROUTING 뒤에 느낌표가 표시됨).
iptables -t nat -A PREROUTING ! -s 10.0.0.0/24 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
여기서는 10.0.0.0/24
전달하고 싶지 않은 IP 범위가 할당되었음을 나타냅니다. 이는 주로 서브넷을 사용하여 액세스할 수 있는 모든 서비스가 자체적으로 다시 라우팅되는
라우팅 루프를 방지하기 위한 것입니다 . --dport 80은 포트 80 IE 웹 서버 연결을 찾는 패킷만 전달하는 것입니다. 서버가 실행 중인 네임스페이스 내부로 이동된 veth 인터페이스입니다. 이렇게 하면 서브넷이 아닌 포트 80 서비스를 찾는 패킷이 대상 IP를 . 예: 아마도 서버가 있는 네임스페이스 내부의 인터페이스 가 될 것입니다.10.0.0.0/24
10.0.0.2
10.0.0.0/24
10.0.0.2
192.168.1.200:80
10.0.0.2:80
여러 네임스페이스에서 여러 VPN 터널을 실행하고 있습니다. iptables에 PREROUTING 규칙을 추가하지 않으면 LAN의 PC 외부에서 리소스에 액세스할 수 없습니다.
자신의 PC에서 액세스하려면 다음과 같은 규칙을 추가해야 합니다.
iptables --table nat --append OUTPUT --destination 192.168.1.2 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
따라서 서버가 있는 PC에서 브라우저에 입력하면 192.168.1.2
서버에 액세스하기 위해 10.0.0.2
대신 라우팅됩니다.
내 설정의 일부를 설명하려고 노력할 것입니다 ...
네임스페이스 예시:ip netns add ns_example
veth 쌍을 만듭니다. 한 쪽은 루트/일반 네임스페이스(저는 이것을 이라고 부름)에 유지되고 host
, 다른 쪽은 VPN이 있는 네임스페이스로 이동합니다.
ip link add dev ihost type veth peer name ivpn
veth 쌍의 VPN 측을 대상 네임스페이스로 이동합니다.
ip link set dev ivpn netns ns_example
생성한 veth 쌍에 IP를 할당합니다.
범위가 아닌 정확한 IP만 할당하고 싶기 때문에 /32를 사용합니다. 그렇지 않으면 장치를 UP할 때 일부 경로가 내 ip route
테이블에 자동으로 삽입되어 다른 네임스페이스에 대한 라우팅이 엉망이 됩니다.
호스트 측에 할당합니다.
ip addr add 10.0.0.1/32 dev ihost
네임스페이스로 이동된 VPN 측에 할당하려면 명령 앞에 ..를 접두어로 붙여야 합니다.
ip netns exec TARGET_NAMESPACE
따라서 VPN 측에 IP를 할당하려면 다음을 수행하십시오.
ip netns exec ns_example ip addr add 10.0.0.2/32 dev ivpn
이제 인터페이스를 불러오세요.
ip link set dev ihost up
ip netns exec ns_example ip link set dev ivpn up
여기서는 경로와 iptables를 추가하여 이들 사이에 트래픽 흐름을 만듭니다.
루트 네임스페이스에서 VPN 측( )에 도달하려면 10.0.0.2
ihost 인터페이스를 사용하고 소스 주소를 루트 네임스페이스 측( 10.0.0.1
)에 다시 씁니다.
ip route add 10.0.0.2/32 dev ihost src 10.0.0.1
VPN 네임스페이스 내에서 완전히 동일한 작업을 수행하되 반대 관점에서 수행합니다.
ip netns exec ns_example ip route add 10.0.0.1/32 dev ivpn src 10.0.0.2
iptables
이제 유사한 작업 과 별개 이지만 수행하는 동일한 작업을 추가합니다 ip route
.
모든 패킷은 10.0.0.2
소스 주소를 다시 작성하게 됩니다.10.0.0.1
iptables --table nat --append POSTROUTING --destination 10.0.0.2/32 --jump SNAT --to-source 10.0.0.1
똑같지만 관점이 반대이고 네임스페이스 내부도 다릅니다.
ip netns exec ns_example iptables --table nat --append POSTROUTING --destination 10.0.0.1/32 --jump SNAT --to-source 10.0.0.2
내가 올바르게 이해했다면 소스 주소 다시 쓰기는 패킷이 네임스페이스에서 다시 나가는 방법을 알고 있는지 확인하는 것이며 그 반대의 경우도 마찬가지입니다.
예를 들어, 포트 8080의 네임스페이스에 있는 토렌트 webui에 액세스하려면 다음을 수행합니다.
내 LAN IP로 이동하는 모든 패킷(예: 브라우저에 입력 192.168.1.2:8080
) 내 토렌트 클라이언트가 실행 중인 네임스페이스에 대상을 다시 작성합니다(예: 10.0.0.2
).
iptables --table nat --append OUTPUT --destination 192.168.1.2/32 --protocol tcp --match tcp --dport 8080 --jump DNAT --to-destination 10.0.0.2
이 규칙은 특히 포트 8080만 전달하며 이 규칙은 서비스가 실행 중인 PC에서 서비스에 액세스하기 위한 것입니다. 네트워크에 액세스하는 다른 모든 PC에는 192.168.1.2:8080
답변 상단에서 언급한 PREROUTING 규칙이 필요합니다(--dport 80을 --dport 8080 또는 필요한 포트/프로토콜로 변경하면 됩니다).
이 방법과 네임스페이스-vpn.py 스크립트를 사용하는 사람들을 위한 것입니다. VPN을 재설정해야 하는 경우 문제가 발생할 수 있습니다. 네임스페이스 VPN은 루프백 인터페이스가 아닌 대상 네임스페이스 내부의 인터페이스를 감지하면 예외를 발생시킵니다 lo
.
다음은 내 대상 네임스페이스가 이미 존재하고 내 veth 쌍이 있을 때 spaced-vpn.py를 사용할 때 예외를 발생시키는 부분입니다.
if os.path.exists(os.path.join('/var/run/netns', namespace)):
adapters = _adapter_names(namespace)
if adapters != [b'lo']:
LOG.error('Namespace %s already has adapters %s, exiting.' % (namespace, adapters))
raise Exception
다음은 제가 사용한 수정 예입니다.
allowed_adapters = [b'lo', b'ivpn']
if os.path.exists(os.path.join('/var/run/netns', namespace)):
adapters = _adapter_names(namespace)
# Iterate and ensure all are in allowed list
for a in adapters:
if not a.split(b'@')[0] in allowed_adapters:
LOG.error('Namespace %s has non-whitelisted adapters %s, exiting.' % (namespace, adapters))
raise Exception
`def setup_namespace(namespace)` 함수 하단에 이미 존재할 것으로 예상되는 각 인터페이스에 대해 이와 같은 호출을 추가했는지 확인하세요. LO를 장치 이름으로 바꾸십시오.
subprocess.check_call(_enter_namespace_cmd(namespace) + [IP_CMD, 'link', 'set', 'LO', 'up'])
예:
subprocess.check_call(_enter_namespace_cmd(namespace) + [IP_CMD, 'link', 'set', 'ivpn', 'up'])
VPN 인터페이스에 연결된 비트토렌트 클라이언트를 실행하는 사람들의 경우 어떤 이유로든 클라이언트가 무작위로 연결을 멈추는 문제가 발생할 수 있습니다. 예를 들어, 아침에 일어나서 보니 아름다운 다운로드가 모두 떠난 지 10분 후에 정지되어 있었습니다.
나는 이 문제가 VPN 소프트웨어 IE openvpn 때문에 발생한다고 생각합니다. 어떤 이유로든(오류, 핑 재시작 등) VPN 공급자에 다시 연결하고 새 IP 주소가 할당되기 때문입니다. 구성을 재설정하려면 VPN 인터페이스를 잠시 동안 오프라인으로 전환해야 할 수 있으며 이로 인해 클라이언트에 결함이 발생합니다(qBittorrent는 확실히 이 작업을 수행합니다). 제가 조사하기 시작한 "수정"은 VPN 인터페이스가 새 IP 주소를 수신하거나 어떤 이유로든 오프라인 상태가 되는 경우를 감지하는 스크립트를 작성하는 것입니다. 스크립트는 토렌트 클라이언트를 정상적으로(중요: 무언가 손상/파일 시스템 오류를 방지하기 위해 적절하게) 종료한 다음 다시 시작해야 합니다. 아직 작동하는 스크립트가 없지만 이것이 이 문제를 해결하는 데 적합한 벡터인 것 같습니다.
답변2
좋아요. 이 질문은 누군가가 실제로 대답하기에는 너무 복잡한 것 같습니다. 또는 이전에 답변을 받았지만 아무도 대답하려고 하지 않는 것 같습니다.
어쨌든: 나는 하루 더 작업했고 응용 프로그램의 웹 인터페이스에 대해 하나의 포트만 노출하는 데 관심이 있기 때문에 다음을 사용하는 것이 좋겠다고 생각했습니다.socat
. 그래서 나는 그랬다.
네임스페이스-openvpn 연결을 생성하고 해당 네트워크 네임스페이스 내에서 애플리케이션을 시작한 후 전용 터미널에서 다음 명령을 실행했습니다.
sudo socat tcp-listen:PORT-TO-FORWARD-TO,fork,reuseaddr exec:'ip netns exec vpn socat STDIO tcp-connect\:127.0.0.1\:PORT-TO-LISTEN-TO',nofork
노트:
PORT-TO-FORWARD-TO
포트가 전달되기를 원하는 포트입니다(루트 네트워크 네임스페이스에서).PORT-TO-LISTEN-TO
루트 네임스페이스에 노출하려는 애플리케이션의 포트입니다.127.0.0.1
실제 localhost-IP를 사용해야 했습니다(localhost
제대로 해결되지 않는 것 같아서 이름이나 이름이 아님).:
작은따옴표 안에 있는 이중점 문자( )를 이스케이프 처리하세요.- 이로 인해 DNS 누출이 발생하는지 확실하지 않습니다. 내가 확인한 바에 따르면 그렇지 않지만 테스트 방법을 모르기 때문에 확신할 수 없습니다.
남은 작업:
- 애플리케이션을 시작하고 시작 시 포트를 전달하기 위해 모든 명령을 자동화합니다. 현재는 필요하지 않지만, 방법을 알게 되면 여기에 추가하겠습니다.