DTLS를 기반으로 하는 매우 간단한 IP 터널입니다.
강력한 암호화가 필요하지 않다면 더 가벼운 utun을 사용하는 것을 고려해 볼 수 있습니까?
go install github.com/taoso/dtun/cmd/dtun
# 服务端
dtun -key foo
# 客户端
dtun -connect addr:port -key foo
고려해야 할 몇 가지 요소에 대한 간단한 목록은 다음과 같습니다.
안정적이고 신뢰할 수 있는 전송 계층 데이터 암호화를 달성하는 것은 쉽지 않기 때문에 항상 TLS를 기본 프로토콜로 사용해 왔습니다.
TLS는 TCP를 사용하며, 암호화된 데이터도 상당 부분 TCP 데이터입니다. 이와 같이 상위 계층 데이터 패킷을 전송하려면 내부 및 외부 TCP 연결을 확인해야 합니다. 이러한 종류의 TCP over TCP의 구현 문제는 작지 않습니다. 자세한 내용은 http://sites.inka.de/~bigred/devel/tcp-tcp.html을 참조하세요.
따라서 UDP 전송을 사용하는 것이 가장 좋습니다. 당연히 암호화에는 DTLS가 사용됩니다. 현재 DTLS는 1.3을 지원하지 않으며 go 언어도 공식적으로 지원하지 않습니다. 이 타사 구현 https://github.com/pion/dtls만 사용할 수 있습니다.
TLS이든 DTLS이든 일반적으로 인증서를 생성해야 합니다. 이 프로세스는 이제 무료이지만 구성하기가 여전히 복잡합니다. 또한 인증서는 암호화 문제만 해결하고 인증 문제는 해결하지 않습니다. 일반적으로 클라이언트만 서버 인증서를 확인합니다. 서버가 클라이언트 인증서를 확인하도록 할 수도 있지만 이는 너무 번거롭습니다.
또한 DTLS는 비연결형이므로 TCP 연결과 같은 연결을 생성할 때만 인증을 수행할 수 없습니다.
따라서 DTLS 핸드셰이크 중에 양쪽 끝의 인증을 동시에 완료하는 것이 가장 좋습니다. 그래서 PSK(Pre-Shared Key) 모드를 선택합니다. 이중 엔드 인증을 완료하려면 -key
사용하여 양쪽 끝에서 마스터 키를 지정하기만 하면 됩니다. 클라이언트가 PSK를 모르면 DTLS 세션을 설정할 수 없습니다.
또한 PSK는 힌트 매개변수도 지정해야 합니다. 간단히 PSK라는 이름으로 생각하시면 됩니다. DTLS가 연결되어 있지 않아 클라이언트가 오프라인 상태인지 확인하기 어렵습니다. 나는 각 클라이언트마다 고유한 힌트 매개변수를 갖기로 결정했습니다. 서버는 힌트를 위해 tun 장치를 할당합니다. 클라이언트 연결이 끊어졌다가 다시 연결되면 여러 tun 장치가 생성되지 않습니다. 하지만 동일한 hinit의 클라이언트가 동시에 로그인할 수 없다는 부작용이 있습니다.
macos를 지원하기 위해 tun 장치는 지점간 모드로만 설정할 수 있습니다. 투명한 라우팅 및 전달을 수행하려면 아래 그림을 보십시오.
pc <-----------> router <====== dtun ======> pc2 <---------> www
10.0.0.2/16 10.0.0.1/16 10.1.0.1/16 10.1.0.2/16
PC에서 보낸 패킷이 라우터를 통해 PC2로 전달된 후 외부 네트워크로 전달되기를 바랍니다. 일반적으로 NAT는 라우터에서 한 번, 그 다음에는 pc2에서 한 번 수행됩니다. 이것의 장점은 pc2가 라우터에 대한 PC의 네트워크 구성을 알 필요가 없다는 것입니다. 그러나 단점도 분명합니다. 두 가지 nat가 있습니다. 라우터의 성능은 일반적으로 강하지 않으므로 NAT는 최대한 피하는 것이 좋습니다.
그래서 내 계획은 PC가 있는 네트워크 세그먼트 10.0.0.0/16을 pc2에 직접 푸시하고 pc2에 경로를 추가하는 것입니다.
ip route add 10.0.0.0/16 via 10.1.0.1
이러한 방식으로 라우터는 패킷을 pc에서 pc2로 그대로 전달할 수 있으며 pc2에서는 NAT를 한 번만 수행하면 됩니다.
때로는 라우팅 화이트리스트를 지정해야 할 때도 있습니다. 화이트리스트에 있는 네트워크 세그먼트의 기본 경로를 사용하고 나머지는 터널을 통해 전달합니다.
먼저 라우터에 화이트리스트 경로를 추가하고 다음 홉을 라우터의 기본 경로로 설정할 수 있습니다. 그런 다음 pc2의 공용 IP를 지정하여 라우터의 기본 경로(핵심!)를 사용합니다. 마지막으로 추가됨
ip route add 0.0.0.0/1 via 10.1.0.2
ip route add 128.0.0.0/1 via 10.1.0.2
여기서 0.0.0.0/1
및 128.0.0.1/1
은 전체 네트워크 세그먼트에만 적용됩니다. 효과는 기본값과 동일하지만 기본 경로를 덮어쓰지는 않습니다. 터널이 비정상적으로 폐쇄되면 관련 경로가 모두 자동으로 삭제되므로 매우 안정적입니다.
이를 스크립트로 작성하고 -up
매개변수를 사용하여 실행할 수 있습니다. 내 스크립트는 다음과 같습니다.
#! /bin/sh
# curl -S https://cdn.jsdelivr.net/gh/misakaio/chnroutes2@master/chnroutes.txt|grep -v '#'|xargs -I % ip route add % via $DEFAULT_GW 2>/dev/null
VPN_IP= $( ping your-server-name -c 1 | grep from | cut -d ' ' -f4 | cut -d: -f1 )
DEFAULT_GW= $( ip route | grep default | cut -d ' ' -f3 )
ip route add $VPN_IP /32 via $DEFAULT_GW
ip route add 0.0.0.0/1 via $PEER_IP
ip route add 128.0.0.0/1 via $PEER_IP