외부에서 홈 네트워크에 접속할 수 있도록 집에서 Wireguard 서버를 실행하고 있습니다. Wireguard는 UDP를 사용하고 있습니다. 불행히도 공급자가 CG-NAT를 지원했기 때문에 예전처럼 Fritz 상자에서 IPv4 UDP 포트를 열 수 없습니다. IPv6을 사용해야 하지만 IPv6는 아직 직장에서 사용할 수 없습니다.
따라서 집에는 IPv6가 있고 직장에는 IPv4가 있지만 홈 네트워크에 연결할 방법이 없습니다.
또한 TCP 트래픽을 위한 역방향 SSH 터널을 설정할 수 있는 공용 IPv4가 있는 VPS도 있습니다. 불행하게도 SSH 터널은 TCP만 지원하며 어쨌든 TCP를 통한 VPN 연결을 수행해서는 안 됩니다. 이것이 Wireguard가 UDP만 사용하는 이유입니다.
VPN-Server VPN-Client
(UDP) | | (IPv4 UDP)
| | | not possible |
-----------|--------| <-------------------
| |
NAT CG-NAT
VPN-Server VPN-Client
(UDP) (IPv4 UDP)
| |
| |
inside agent outside agent
tunnel tunnel
|| | | ||
|| punch| punch| ||
| --------->|-------->|-------------------- |
-----------|<--------|<--------------------
| |
| |
NAT CG-NAT
외부 에이전트가 공개 IPv4를 사용하는 VPS에서 실행 중입니다.
내부 에이전트는 UDP 데이터그램을 외부 에이전트의 공용 IP 및 포트로 보냅니다. 이는 두 NAT 모두에 구멍을 뚫고, 외부 에이전트는 이러한 데이터그램을 수신하고 소스 주소 및 포트에서 데이터그램을 내부 에이전트로 다시 보내는 방법을 학습합니다. .
VPN 클라이언트는 UDP를 외부 에이전트에 보낼 수 있으며 이러한 데이터그램은 내부 에이전트로 전달되고 거기에서 VPN 서버로 전달됩니다. VPN 서버는 내부 에이전트에 응답할 수 있으며 이러한 데이터그램은 외부 에이전트로 전달되고 그곳에서 VPN 서버로 전달됩니다. VPN 클라이언트.
외부 에이전트는 클라이언트에 대해 VPN 서버로 나타나고, 내부 에이전트는 서버에 대해 VPN 클라이언트로 나타납니다.
외부에서 연결되는 모든 새 클라이언트에 대해 내부 에이전트의 터널과 새 소켓을 사용하므로 여러 클라이언트 연결이 가능합니다. 따라서 서버에는 내부 에이전트의 호스트에서 여러 클라이언트가 실행 중인 것처럼 나타납니다.
두 시스템 모두에서 코드를 복제하거나 압축을 풀고 빌드합니다. 최소한 make와 gcc가 필요합니다. 소스 디렉토리를 입력하고 명령을 사용하십시오
$ make
성공적으로 빌드되면 동일한 폴더에 바이너리 udp-tunnel
이 생성됩니다. 이제 터미널에서 직접 시작하여(물론 올바른 옵션을 사용하여) 몇 가지 빠른 테스트를 수행하거나 makefile의 도움으로 설치할 수 있습니다.
컴파일된 바이너리 udp-tunnel
명령줄에 전달하는 옵션에 따라 내부 에이전트 또는 외부 에이전트로 작동할 수 있습니다.
예를 들어 VPN 서버가 UDP 1234에서 수신 대기하고 있으며 localhost(내부 에이전트와 동일)에서 실행되고 외부 시스템이 jump.example.com이고 UDP 포트 9999에서 수신 대기하기를 원한다고 가정합니다.
내부 호스트에서는 다음으로 시작합니다.
$ ./udp-tunnel -s localhost:1234 -o jump.example.com:9999
외부 호스트에서는 다음과 같이 시작합니다.
$ ./udp-tunnel -l 9999
makefile에는 3개의 설치 대상이 포함되어 있습니다. 바이너리만 설치하려면 install
, systemd 서비스 파일도 설치하려면 install-outside
및 install-inside
. 후자의 두 가지가 제대로 작동하려면 변수를 전달해야 합니다.
점프 호스트에 외부 에이전트를 설치하려면(포트 9999를 원한다고 가정) 다음 명령을 실행합니다.
$ sudo make install-outside listen=9999
그러면 /usr/local/bin/
에 바이너리가 설치되고 포트 9999를 사용하여 외부 에이전트 모드에서 시작하는 데 필요한 명령이 포함된 systemd 서비스 파일이 /etc/systemd/system/
에 설치됩니다.
내부 머신에 내부 에이전트를 설치하려면 다음 명령을 사용하십시오(예를 들어 VPN 서버가 localhost:1234이고 점프 호스트가 jump.example.com이라고 가정).
$ sudo make install-inside service=localhost:1234 outside=jump.example.com:9999
그러면 바이너리가 /usr/local/bin/
에 다시 설치되고 systemd 장치 파일이 /etc/systemd/system/
에 설치됩니다.
이 시점에서 바이너리가 어떻게 사용되는지 확인하고 옵션이 올바른지 확인하기 위해 시스템 단위 파일을 빠르게 살펴볼 수 있습니다. 옵션은 위의 빠른 테스트에서 설명한 것과 같아야 합니다.
systemd 파일이 설치되고 올바른지 확인한 후에는 아직 자동 시작이 활성화되지 않았으므로 해당 파일을 활성화하고 시작해야 합니다. Inside 머신에서:
$ sudo systemctl enable udp-tunnel-inside.service
$ sudo systemctl start udp-tunnel-inside.service
그리고 외부 기계에서
$ sudo systemctl enable udp-tunnel-outside.service
$ sudo systemctl start udp-tunnel-outside.service
암호화가 없습니다. 패킷은 있는 그대로 전달되며, 터널링하는 서비스가 무엇이든 자체적으로 데이터를 보호하거나 암호화하는 방법을 알고 있다고 가정합니다. 일반적으로 VPN 연결의 경우입니다.
또한 공격자는 외부 에이전트를 혼란스럽게 하고 터널을 자신의 시스템으로 전환하여 서비스 중단을 초래하기 위해 내부 에이전트의 연결 유지 패킷을 스푸핑하려고 할 수 있습니다. 이러한 매우 간단한 공격을 방지하기 위해 Keepalive 데이터그램은 해시 기반 메시지 인증 코드로 인증될 수 있습니다. 이 기능을 활성화하려면 양쪽 터널 끝에서 -k 옵션을 사용하여 사전 공유 비밀번호를 사용할 수 있습니다.
내부 호스트에서는 다음과 같이 사용합니다.
$ ./udp-tunnel -s localhost:1234 -o jump.example.com:9999 -k mysecretpassword
외부 호스트에서는 다음과 같이 시작합니다.
$ ./udp-tunnel -l 9999 -k mysecretpassword
위의 설치 단계가 성공적으로 작동하면 양쪽 끝에서 시스템 파일을 수동으로 편집하고 -k 옵션을 추가한 다음 양쪽 끝에서 다시 로드하고 다시 시작할 수 있습니다.
그러면 Keepalive 메시지에는 이 비밀번호와 단순 재생 공격을 방지하기 위해 정확히 한 번만 사용할 수 있는 엄격하게 증가하는 nonce에 대한 SHA-256이 포함됩니다.
두 에이전트 모두 연결 목록을 유지 관리하며 각 연결은 해당 특정 클라이언트 연결과 관련된 소켓 주소 및 소켓 핸들을 저장합니다.
시작 시 내부 에이전트는 외부 에이전트로 나가는 터널을 시작하고 이를 사용되지 않은 것으로 표시한 다음 이를 통해 연결 유지 패킷을 보냅니다. 외부 에이전트는 이러한 패킷을 보고 소스 주소와 함께 이 터널을 자체 연결 목록에 추가합니다. Keepalive 패킷은 nonce와 인증 코드로 서명되므로 스푸핑되거나 재생할 수 없습니다.
클라이언트가 연결되면 외부 에이전트는 사용되지 않은 예비 터널로 클라이언트 데이터를 보내고, 내부 에이전트는 이를 확인하고 터널을 활성으로 표시하고 서비스와 통신하기 위한 소켓을 생성하고 데이터를 양방향으로 전달합니다. 그런 다음 다음 수신 클라이언트를 준비하기 위해 또 다른 새로운 나가는 예비 터널을 즉시 생성합니다.
새 예비 터널이 외부 에이전트에 도착하면 자체 연결 목록에 추가되어 다음 연결 클라이언트에 즉시 서비스를 제공할 수 있습니다.
이 시점에서 두 에이전트 모두 목록에 2개의 터널이 있습니다. 하나는 활성 상태이고 다른 하나는 다음 클라이언트 연결을 기다리는 예비 터널입니다.
비활성 시간 초과는 데드 터널(과거에 활성으로 표시되었지만 한동안 클라이언트 데이터가 없는 터널)이 삭제되고 해당 소켓이 닫히도록 합니다. 내부 에이전트는 오랫동안 전달된 데이터의 부족을 감지하고 자체 목록에서 이를 제거하고 소켓을 닫습니다. 그런 다음 얼마 후 외부 에이전트는 이 연결에 대해 더 이상 도착하는 Keepalive가 없음을 감지하고 자체 목록에서 제거합니다. 목록도요.
이 코드는 아직 매우 실험적이므로 적어도 아직은 이를 기반으로 수백만 달러 규모의 사업을 시작하지 마세요. 그것은 나에게 완벽하게 목적을 달성하지만 서버가 충돌하고 불타고 폭발할 수 있습니다. 당신은 경고를 받았습니다.