WireGuard 무단 가이드: WireGuard 설정 및 구성에 대한 자세한 설명

1. 빠른 시작

일을 잘하고 싶다면, 먼저 도구를 날카롭게 만들어야 합니다! 일반적인 과정은 다음과 같습니다.

준비

현재 커널 버전 보기

uname -r #4.18.0-348.2.1.el8_5.x86_64 uname -a #Linux mir4 4.18.0-348.2.1.el8_5.x86_64 #1 SMP 2021년 11월 16일 화요일 오후 2시 42분 35초 UTC x86_64 x86_64 x86_64 GNU/Linux cat /etc/redhat-release #CentOS Linux 릴리스 8.5.2111

시스템 커널 업그레이드

dnf -y 업데이트

CentOS 8.x에 EPEL 저장소 설치

EPEL은 "Extra Packages for Enterprise Linux"의 약자로, CentOS 및 RHEL 서버에 사용할 수 있는 추가 패키지를 제공하는 무료 오픈 소스 저장소입니다. 이름에서 알 수 있듯이 EPEL 저장소는 CentOS 8 및 RHEL 8의 기본 패키지 저장소에는 없는 추가 패키지를 제공합니다.

에펠 공식 웹사이트:https://fedoraproject.org/wiki/EPEL/zh-cn

dnf search epel #epel-next-release.noarch : Enterprise Linux Next 저장소 구성을 위한 추가 패키지 #epel-release.noarch : Enterprise Linux 저장소 구성을 위한 추가 패키지 #시스템 소프트웨어 저장소에서 epel-release 버전 확인 dnf info epel-release #시스템 소프트웨어 저장소에서 epel 소스 설치 dnf install epel-release #URL을 통해 웹사이트에서 epel 소스 설치 dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm #EPEL 패키지가 이러한 저장소의 패키지에 종속될 수 있으므로 PowerTools 저장소를 활성화 dnf config-manager --set-enabled powertools #설치가 성공적으로 완료되면 저장소에 있는 패키지 수를 테스트합니다 sudo dnf --disablerepo="*" --enablerepo="epel" list 사용 가능 | wc -l

CentOS 8.x에 ELRepo 저장소 설치

ELRepo 저장소는 RedHat Enterprise(RHEL) 및 기타 RHEL 기반 Linux 배포판(CentOS, Scientific, Fedora 등)에 대한 지원을 제공하는 커뮤니티 기반 엔터프라이즈 Linux 저장소입니다.
ELRepo는 파일 시스템 드라이버, 그래픽 드라이버, 네트워크 드라이버, 사운드 카드 드라이버, 카메라 드라이버를 포함한 하드웨어 관련 소프트웨어 패키지에 중점을 둡니다.

#ELRepo 저장소의 공개 키 가져오기rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org #ELRepo 저장소의 yum 소스 설치dnf install https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm #커널 버전 확인dnf --disablerepo="*" --enablerepo="elrepo-kernel" 사용 가능한 목록

Wireguard를 설치하기 전에 서버에 eple과 ELRepo 저장소를 설치해야 합니다.

# 소프트웨어 소스 설치 후 캐시 지우기 dnf clean all # 저장소 캐시 다시 생성 yum makecache reboot

설치하다

공식 설치 참조:https://www.wireguard.com/install/

다음은 Centos8, Centos7, Ubuntu, MacOS를 포함한 여러 운영 체제에 대한 설치 방법입니다.

#CentOS8 dnf install elrepo-release epel-release dnf config-manager --set-enabled powertools dnf copr enable jdoss/wireguard dnf install wireguard-dkms wireguard-tools #CentOS7 yum install epel-release https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm yum install yum-plugin-elrepo yum install kmod-wireguard wireguard-tools # 비표준 커널을 사용하는 경우 DKMS 패키지를 설치해야 합니다. yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm curl -o /etc/yum.repos.d/jdoss-wireguard-epel-7.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-7/jdoss-wireguard-epel-7.repo yum install wireguard-dkms wireguard-tools #Ubuntu≥18.04 apt install wireguard #Ubuntu≤16.04 add-apt-repository ppa:wireguard/wireguard apt-get update apt-get install wireguard #MacOS brew install wireguard-tools

Windows 클라이언트 다운로드 주소:

  1. https://download.wireguard.com/windows-client/wireguard-amd64-0.1.1.msi
  2. https://download.wireguard.com/windows-client/wireguard-installer.exe

Android와 iOS는 앱 스토어를 통해 해당 클라이언트를 다운로드할 수 있습니다.

https://www.wireguard.com/install/#installation

릴레이 서버에서 IP 주소 전달을 활성화합니다.

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.proxy_arp = 1" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf

이 컴퓨터에서 NAT 변환을 허용하려면 iptables 규칙을 추가하세요.

iptables -A 입력 -m conntrack --ctstate 관련, 설정됨 -j 허용 iptables -A 전달 -m conntrack --ctstate 관련, 설정됨 -j 허용 iptables -A 전달 -i wg0 -o wg0 -m conntrack --ctstate 새로 만들기 -j 허용 iptables -t nat -A POSTROUTING -s 192.0.2.0/24 -o eth0 -j 매스커레이드

eth0을 실제로 사용하는 네트워크 카드 인터페이스의 이름으로 변경해야 합니다.

구성 파일 작성

구성 파일은 어떤 경로에든 배치할 수 있지만 절대 경로로 참조해야 합니다. 기본 경로는 /etc/wireguard/wg0.conf입니다.

# vi /etc/wireguard/wg0.conf 설정 파일을 생성합니다.

키 생성

개인 키 생성

wg genkey > example.key

공개 키 생성

wg 퍼브키 <예제.키> 예제.키.펍

시작 및 중지

$ wg-quick up /full/path/to/wg0.conf
$ wg-quick /full/path/to/wg0.conf 다운로드

# VPN 네트워크 인터페이스 시작/중지
$ ip 링크 설정 wg0 up
$ ip 링크 설정 wg0 다운

# VPN 네트워크 인터페이스 등록/등록 해제
$ ip 링크 추가 dev wg0 유형 wireguard
$ ip 링크 삭제 dev wg0

# 로컬 VPN 주소 등록/등록 해제
$ IP 주소 추가 dev wg0 192.0.2.3/32
$ IP 주소 삭제 dev wg0 192.0.2.3/32

# VPN 경로 추가/삭제
$ ip 경로 추가 192.0.2.3/32 dev wg0
$ ip 경로 삭제 192.0.2.3/32 dev wg0

정보 보기

인터페이스:

# 시스템 VPN 인터페이스 정보 보기
$ ip 링크 show wg0

# VPN 인터페이스 세부 정보 보기
$ wg 모두 보기
$ wg show wg0

주소:

# View VPN 인터페이스 주소
$ ip 주소 wg0 표시

라우팅

# 시스템 라우팅 테이블 보기
$ ip route show table main
$ ip route show table local

# 특정 IP로의 경로를 가져옵니다
$ ip 경로는 192.0.2.3을 얻습니다.

원클릭 설치

원클릭 설치의 경우 이 프로젝트를 참조하세요: WireGuard 설치 프로그램[3]

2. 구성 세부 정보

WireGuard는 INI를 사용합니다[4] 구성 파일 형식은 /etc/wireguard/wg0.conf입니다. 구성 파일은 어떤 경로에든 배치할 수 있지만 절대 경로로 참조해야 합니다. 기본 경로는 /etc/wireguard/wg0.conf입니다.

구성 파일 이름은 ${WireGuard 인터페이스 이름}.conf여야 합니다. 일반적으로 WireGuard 인터페이스 이름은 wg로 시작하며 0부터 시작하는 번호가 매겨지지만, 정규 표현식 ^[a-zA-Z0-9_=+.-]{1,15}$와 일치한다면 다른 이름을 사용할 수 있습니다.

wg 명령을 사용하여 VPN을 수동으로 구성할 수 있지만, 보다 강력하고 사용자 친화적인 구성 환경을 제공하고 구성 파일을 통해 구성을 관리할 수 있는 wg-quick을 사용하는 것이 일반적으로 권장됩니다.

다음은 구성 파일의 예입니다.

[인터페이스]
# 이름 = node1.example.tld
주소 = 192.0.2.3/32
청취포트 = 51820
개인키 = 로컬개인키AbcAbcAbc=
DNS = 1.1.1.1,8.8.8.8
테이블 = 12345
MTU = 1500
PreUp = /bin/example arg1 arg2 %i
PostUp = /bin/예 arg1 arg2 %i
PreDown = /bin/example arg1 arg2 %i
PostDown = /bin/example arg1 arg2 %i

[또래]
# 이름 = node2-node.example.tld
허용된 IP = 192.0.2.1/24
엔드포인트 = node1.example.tld:51820
공개키 = remotePublicKeyAbcAbcAbc=
지속적 유지 = 25

[인터페이스]

이 섹션에서는 로컬 VPN 구성을 정의합니다. 예:

  • 로컬 노드는 자체 트래픽만 라우팅하고 하나의 IP만 노출하는 클라이언트입니다.
    [인터페이스]
    # 이름 = phone.example-vpn.dev
    주소 = 192.0.2.5/32
    개인키 =
  • 로컬 노드는 다른 피어에 트래픽을 전달하고 전체 VPN 서브넷의 라우팅을 노출하는 릴레이 서버입니다.
    [인터페이스]
    # 이름 = public-server1.example-vpn.tld
    주소 = 192.0.2.1/24
    청취포트 = 51820
    개인키 =
    DNS = 1.1.1.1

① # 이름

이는 INI 구문의 표준 주석으로, 이 구성 부분이 어느 노드에 속하는지 표시하는 데 사용됩니다. WireGuard는 이 구성 부분을 완전히 무시하며 VPN 동작에 영향을 미치지 않습니다.

② 주소

로컬 노드가 라우팅해야 하는 주소 범위를 정의합니다. 일반 클라이언트인 경우 노드 자체의 단일 IP 주소(CIDR을 사용하여 지정, 예: 192.0.2.3/32)로 설정하고, 릴레이 서버인 경우 라우팅 가능한 서브넷 범위로 설정합니다.

예를 들어:

  • 일반 클라이언트는 자체 트래픽만 라우팅합니다. 주소 = 192.0.2.3/32
  • 다른 피어 노드(peers)로 트래픽을 전달할 수 있는 릴레이 서버: 주소 = 192.0.2.1/24
  • 여러 서브넷 또는 IPv6 서브넷을 지정할 수도 있습니다. 주소 = 192.0.2.1/24,2001:DB8::/64

③ 리슨포트

로컬 노드가 릴레이 서버인 경우, 이 매개변수를 통해 수신 VPN 연결을 수신 대기할 포트를 지정해야 합니다. 기본 포트 번호는 51820입니다. 일반 클라이언트에는 이 옵션이 필요하지 않습니다.

④ 개인키

로컬 노드의 개인 키는 모든 노드(릴레이 서버 포함)에 설정되어야 하며, 다른 서버와 공유할 수 없습니다.

개인 키는 wg genkey > example.key 명령을 사용하여 생성할 수 있습니다.

⑤ DNS

DHCP를 통해 클라이언트에 DNS 서버를 알립니다. 클라이언트는 여기에 지정된 DNS 서버를 사용하여 VPN 서브넷의 DNS 요청을 처리하지만, 시스템에서 이 옵션을 재정의할 수도 있습니다. 예:

  • 구성되지 않은 경우 시스템 기본 DNS가 사용됩니다.
  • 단일 DNS를 지정할 수 있습니다: DNS = 1.1.1.1
  • 여러 DNS를 지정할 수도 있습니다: DNS = 1.1.1.1,8.8.8.8

⑥ 표

VPN 서브넷에서 사용하는 라우팅 테이블을 정의합니다. 기본적으로는 설정이 필요하지 않습니다. 이 매개변수에는 주의가 필요한 두 가지 특수 값이 있습니다.

  • 테이블 = 꺼짐 : 경로 생성 비활성화
  • 테이블 = 자동(기본값) : 시스템 기본 테이블에 경로를 추가하고 기본 경로에 대한 특수 처리를 활성화합니다.

예를 들어: Table = 1234

⑦ 엠티유

피어에 연결된 MTU(최대 전송 단위)를 정의합니다. 기본적으로 설정할 필요는 없으며 일반적으로 시스템에서 자동으로 결정됩니다.

8 프리업

VPN 인터페이스를 시작하기 전에 실행할 명령입니다. 이 옵션은 여러 번 지정할 수 있으며, 지정된 순서대로 실행됩니다.

예를 들어:

  • 경로 추가: PreUp = ip rule add ipproto tcp dport 22 table 1234

⑨ 포스트업

VPN 인터페이스 시작 후 실행할 명령입니다. 이 옵션은 여러 번 지정할 수 있으며, 지정된 순서대로 실행됩니다.

예를 들어:

  • 파일이나 명령 출력에서 구성 값을 읽습니다.
    PostUp = wg set %i 개인 키 /etc/wireguard/wg0.key <(some command here)
  • 파일에 로그 줄을 추가합니다.
    PostUp = echo "$(date +%s) WireGuard 시작" >> /var/log/wireguard.log
  • WebHook 호출:
    포스트업 = 컬 https://events.example.dev/wireguard/started/?key=abcdefg
  • 경로 추가:
    PostUp = ip 규칙 추가 ipproto tcp dport 22 테이블 1234
  • 패킷 전달을 활성화하려면 iptables 규칙을 추가하세요.
    포스트업 = iptables -A 포워드 -i %i -j ACCEPT; iptables -A 포워드 -o %i -j ACCEPT; iptables -t nat -A 포스트라우팅 -o eth0 -j 매스커레이드
  • WireGuard가 피어 도메인 이름의 IP 주소를 다시 확인하도록 합니다.
    PostUp = resolvectl domain %i "~."; resolvectl dns %i 192.0.2.1; resolvectl dnssec %i yes

⑨ 프리다운

VPN 인터페이스를 중지하기 전에 실행할 명령입니다. 이 옵션은 여러 번 지정할 수 있으며, 지정된 순서대로 실행됩니다.

예를 들어:

⑪ 포스트다운

VPN 인터페이스를 중지한 후 실행할 명령입니다. 이 옵션은 여러 번 지정할 수 있으며, 지정된 순서대로 실행됩니다.

예를 들어:

  • 파일에 로그 줄을 추가합니다.
    PostDown = echo "$(date +%s) WireGuard가 다운됩니다" >> /var/log/wireguard.log
  • WebHook 호출:
    포스트다운 = 컬 https://events.example.dev/wireguard/stopping/?key=abcdefg
  • iptables 규칙을 삭제하고 패킷 전달을 끕니다.
    PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[또래]

하나 이상의 주소로 트래픽을 라우팅할 수 있는 피어를 정의하는 VPN 설정입니다. 피어는 다른 피어로 트래픽을 전달하는 릴레이 서버이거나, 공용 또는 사설 네트워크를 통해 직접 연결하는 클라이언트일 수 있습니다.

릴레이 서버는 모든 클라이언트를 피어로 정의해야 합니다. 릴레이 서버 이외의 클라이언트는 경로에 도달할 수 없기 때문에 NAT 뒤에 있는 노드를 피어로 정의할 수 없습니다. 자기 자신으로만 트래픽을 라우팅하는 클라이언트의 경우, 릴레이 서버만 피어가 되어야 하며, 다른 노드는 직접 접근 가능해야 합니다.

예를 들어, 다음 구성에서 public-server1은 릴레이 서버로 사용되고 다른 클라이언트는 직접 연결되거나 NAT 뒤에 있습니다.

  • public-server1(릴레이 서버) [피어] : public-server2, 홈 서버, 노트북, 전화
  • public-server2(직접 연결된 클라이언트) [피어] : public-server1
  • 홈 서버(클라이언트가 NAT 뒤에 있음) [피어] : public-server1, public-server2
  • 노트북(NAT 뒤의 클라이언트) [피어] : public-server1, public-server2
  • 전화(클라이언트가 NAT 뒤에 있음) [피어] : public-server1, public-server2

구성 예:

  • 피어는 자기 자신에게만 트래픽을 라우팅하는 라우팅 가능한 클라이언트입니다.
    [또래]
    # 이름 = public-server2.example-vpn.dev
    엔드포인트 = public-server2.example-vpn.dev:51820
    공개키 =
    허용된 IP = 192.0.2.2/32
  • 피어는 NAT 뒤에 있는 클라이언트로, 자기 자신에게만 트래픽을 라우팅합니다.
    [또래]
    # 이름 = home-server.example-vpn.dev
    엔드포인트 = home-server.example-vpn.dev:51820
    공개키 =
    허용된 IP = 192.0.2.3/32
  • 피어 노드는 다른 피어 노드로 트래픽을 전달하는 릴레이 서버입니다.
    [또래]
    # 이름 = public-server1.example-vpn.tld
    엔드포인트 = public-server1.example-vpn.tld:51820
    공개키 =
    #는 전체 VPN 서브넷에 대한 트래픽을 라우팅합니다.
    허용된 IP = 192.0.2.1/24
    지속적 유지 = 25

① 엔드포인트

원격 피어의 공용 네트워크 주소를 지정합니다. 피어가 NAT 뒤에 있거나 안정적인 공용 네트워크 주소가 없는 경우 이 필드는 무시됩니다. 일반적으로릴레이 서버엔드포인트는 물론, 안정적인 공용 IP를 가진 노드도 지정할 수 있습니다. 예:

  • IP로 지정:
    종점 = 123.124.125.126:51820
  • 도메인 이름으로 지정:
    엔드포인트 = public-server1.example-vpn.tld:51820

② 허용 IP

이 피어에서 허용되는 VPN 트래픽의 소스 주소 범위입니다. 이 필드는 로컬 라우팅 테이블에서 wg0에 바인딩된 IP 주소 범위로도 사용됩니다. 피어가 일반 클라이언트인 경우 노드 자체의 단일 IP로 설정하고, 피어가 릴레이 서버인 경우 라우팅 가능한 서브넷 범위로 설정합니다. , 를 사용하여 여러 IP 또는 서브넷 범위를 지정할 수 있습니다. 이 필드는 여러 번 지정할 수도 있습니다.

패킷 라우팅 방식을 결정할 때, 시스템은 먼저 가장 구체적인 경로를 선택하고, 일치하는 경로가 없으면 더 일반적인 경로를 선택합니다. 예를 들어, 192.0.2.3으로 전송된 패킷의 경우, 시스템은 먼저 주소가 192.0.2.3/32인 피어를 찾고, 피어가 없으면 주소가 192.0.2.3/32인 피어를 찾는 식으로 진행됩니다.

예를 들어:

  • 피어는 자체 트래픽만 라우팅하는 일반 클라이언트입니다.
    허용된 IP = 192.0.2.3/32
  • 피어는 다른 피어에게 트래픽을 전달하는 릴레이 서버입니다.
    허용된 IP = 192.0.2.1/24
  • 피어 노드는 외부 네트워크 트래픽과 VPN 트래픽을 포함한 모든 트래픽을 전달하는 릴레이 서버입니다. 피어 노드의 용도는 다음과 같습니다.
    허용된 IP = 0.0.0.0/0,::/0
  • 피어는 자체와 다른 피어 간의 트래픽을 라우팅하는 릴레이 서버입니다.
    허용된 IP = 192.0.2.3/32,192.0.2.4/32
  • 피어는 자체 트래픽과 자신이 속한 인트라넷의 트래픽을 라우팅할 수 있는 릴레이 서버입니다.
    허용된 IP = 192.0.2.3/32,192.168.1.1/24

③ 공개키

피어 노드(peer)의 공개 키는 모든 노드(릴레이 서버 포함)가 설정해야 합니다. 다른 피어 노드(peer)와 동일한 공개 키를 공유할 수 있습니다.

공개 키는 wg pubkey 명령을 통해 얻을 수 있습니다. <예제.키> example.key.pub , 여기서 example.key는 위에서 생성된 개인 키입니다.

예를 들어: PublicKey = somePublicKeyAbcdAbcdAbcdAbcd=

④ 지속적 Keepalive

연결이 NAT 뒤에 있는 피어에서 공용 네트워크에서 접근 가능한 피어로 이루어지는 경우, NAT 뒤에 있는 피어는 주기적으로 아웃바운드 ping 패킷을 보내 연결을 확인하고 IP가 변경되면 엔드포인트를 자동으로 업데이트해야 합니다.

예를 들어:

  • 로컬 노드가 피어 노드에 직접 연결되어 있습니다. 연결 확인이 필요하지 않으므로 이 필드는 지정할 필요가 없습니다.
  • 피어가 NAT 뒤에 있습니다. 이 필드는 지정할 필요가 없습니다. 연결을 유지하는 것은 클라이언트(연결 시작자)의 책임입니다.
  • 로컬 노드는 NAT 뒤에 있고, 피어 노드는 공용 네트워크에서 접근 가능합니다. PersistentKeepalive = 25 필드를 지정해야 합니다. 즉, 연결을 확인하기 위해 25초마다 ping을 보냅니다.

3. 고급 기능

IPv6

이전 예시에서는 주로 IPv4를 사용했지만, WireGuard는 IPv6도 지원합니다. 예를 들면 다음과 같습니다.

[인터페이스]
허용된 IP = 192.0.2.3/24, 2001:DB8::/64

[또래]
...
허용된 IP = 0.0.0.0/0, ::/0

모든 트래픽을 전달합니다

VPN 서브넷 및 공용 네트워크 트래픽을 포함하여 모든 트래픽을 VPN을 통해 전달하려면 [Peer]의 AllowedIPs에 0.0.0.0/0, ::/0을 추가해야 합니다.

IPv4 트래픽만 전달하더라도 VPN 외부로 IPv6 패킷이 유출되는 것을 방지하려면 IPv6 네트워크 세그먼트를 지정해야 합니다. 자세한 내용은 reddit.com/r/WireGuard/comments/b0m5g2/ipv6_leaks_psa_for_anyone_here_using_wireguard_to를 참조하세요.[5]

예를 들어:

[인터페이스]
# 이름 = phone.example-vpn.dev
주소 = 192.0.2.3/32
개인키 =

[또래]
# 이름 = public-server1.example-vpn.dev
공개키 =
엔드포인트 = public-server1.example-vpn.dev:51820
허용된 IP = 0.0.0.0/0, ::/0

일반적으로 VPN을 하늘로 올라가는 사다리처럼 사용할 때는 모든 트래픽만 포워딩하면 됩니다. 더 이상 설명하지 않겠습니다. 여기서 멈추세요.

NAT-to-NAT 연결

두 피어가 NAT 뒤에 있고 릴레이 서버 없이 직접 연결하려는 경우, 피어 중 적어도 한 명이 고정 공용 IP를 사용하거나 DDNS를 통해 FQDN을 동적으로 업데이트하여 안정적인 공용 네트워크 출구를 갖고 있는지 확인해야 합니다.

WebRTC 프로토콜은 두 NAT 간의 연결을 동적으로 구성할 수 있으며, 시그널링 서버를 통해 각 호스트의 IP:포트 조합을 감지할 수 있습니다. 그러나 WireGuard에는 이 기능이 없습니다. 다른 호스트를 동적으로 검색하는 시그널링 서버가 없으며, Endpoint+ListenPort를 하드코딩하고 PersistentKeepalive를 통해 연결을 유지하는 방식만 가능합니다.

NAT-to-NAT 연결의 전제 조건을 요약하면 다음과 같습니다.

  • 최소 하나 이상의 피어 노드에 고정 공인 IP가 있습니다. 두 노드 모두 고정 공인 IP가 없는 경우, DDNS를 사용하여 안정적인 도메인 이름을 유지할 수 있습니다.
  • 최소한 하나의 피어 노드가 UDP ListenPort를 지정하고, 해당 NAT 라우터는 UDP 소스 포트 무작위화를 수행할 수 없습니다. 그렇지 않으면 반환 패킷이 이전에 지정된 ListenPort로 전송되고 라우터에서 삭제되며 새로 할당된 무작위 포트로 전송되지 않습니다.
  • 모든 피어는 [피어] 구성에서 다른 피어에 대해 PersistentKeepalive를 활성화해야 연결 지속성을 유지할 수 있습니다.

의사소통을 하는 양측 모두에게,섬기는 사람NAT 라우터가 NAT 뒤의 피어 노드에 대한 전달 규칙을 지정하지 않으면 UDP 홀 펀칭이 필요합니다.

UDP 홀 펀칭의 원리:

  1. Peer1이 Peer2로 UDP 데이터 패킷을 전송하지만, Peer2의 NAT 라우터는 패킷을 누구에게 보내야 할지 모르기 때문에 패킷을 버립니다. 하지만 이는 중요하지 않습니다. 이 단계의 목적은 Peer1의 NAT 라우터가 UDP 응답을 수신하여 Peer1에게 전달할 수 있도록 하는 것입니다.
  2. Peer2가 Peer1로 UDP 데이터 패킷을 전송합니다. 이전 단계의 결과로 Peer1의 NAT 라우터는 임시 전달 규칙을 설정하여 UDP 응답을 수신할 수 있게 되었습니다. 따라서 Peer2는 해당 데이터 패킷을 수신하여 Peer1로 전달할 수 있습니다.
  3. Peer1이 Peer2에 UDP 응답을 보냅니다. 이전 단계의 효과로 인해 Peer2의 NAT 라우터는 이미 UDP 응답을 수신할 수 있으므로, 데이터 패킷을 수신하여 Peer2로 전달할 수 있습니다.

초기 패킷을 보내고, 거부한 다음, 라우터의 설정된 전달 규칙을 사용하여 응답을 받는 이러한 과정을 "UDP 홀 펀칭"이라고 합니다.

UDP 패킷을 전송할 때 라우터는 일반적으로 소스 주소/포트를 대상 주소/포트에 매핑하는 임시 규칙을 생성합니다. 대상 주소와 포트에서 반환된 UDP 패킷은 원래 소스 주소와 포트로 전달되는데, 이는 NAT 뒤에서 작동하는 대부분의 UDP 애플리케이션(예: BitTorrent, Skype 등)이 작동하는 방식입니다. 이 임시 규칙은 일정 시간 후 만료되므로 NAT 뒤의 클라이언트는 연결 지속성을 유지하기 위해 PersistentKeepalive를 통해 주기적으로 패킷을 전송해야 합니다.

두 피어가 NAT 뒤에 있는 경우 UDP 홀 펀칭이 작동하려면 두 노드가 서로에게 거의 동시에 패킷을 보내야 합니다. 즉, 양측 모두 상대방의 공개 네트워크 주소와 포트 번호를 미리 알아야 하며, 이는 wg0.conf에서 지정할 수 있습니다.

UDP 홀 펀칭의 한계

2019년 이후, 이전에 사용되었던 많은 구식 펀칭 방법들이 더 이상 효과적이지 않습니다. 과거 가장 유명했던 펀칭 방법은 pwnat입니다.[6] NAT가 개발한 새로운 홀 펀칭 방식으로, 프록시, 타사 서버, UPnP, DMZ, 스푸핑, DNS 변환 없이 NAT 내에서 P2P 통신을 구현할 수 있습니다. 원리는 매우 간단합니다.

이 문제는 클라이언트가 인터넷 상의 임의의 ICMP 홉인 것처럼 가장하여 서버가 클라이언트의 IP 주소를 획득하도록 함으로써 해결됩니다. traceroute 명령도 이 기술을 사용하여 인터넷 상의 홉을 감지합니다.

구체적으로, 서버가 시작되면 고정된 데이터를 보내기 시작합니다. ICMP 에코 요청 패킷(ICMP 에코 요청 패킷). 당연히 3.3.3.3으로부터 응답을 받을 수 없습니다. ICMP 에코 패킷하지만 3.3.3.3은 우리가 접속할 수 있는 호스트가 아니며, ICMP 에코 패킷을 보내기 위해 이 호스트인 척하고 싶지도 않습니다. 대신, pwnat 기술의 구현 원리는 클라이언트가 서버에 접속하려고 할 때, (서버 IP 주소를 알고 있는) 클라이언트가 서버로 ICMP 에코 패킷을 전송한다는 것입니다. ICMP 시간 초과 패킷(ICMP 시간 초과 패킷). 이 ICMP 패킷에는 서버가 3.3.3.3으로 보낸 원래 고정 시간 패킷이 포함되어 있습니다. ICMP 에코 요청 패킷.

왜 이렇게 할까요? 인터넷에서 ICMP 홉을 사용하는 척하고 서버에 정중하게 원래 홉을 알려줍니다. ICMP 에코 요청 패킷3.3.3.3에 도달할 수 없습니다. NAT는 스마트 장치이므로 이를 인식할 것입니다. ICMP 시간 초과 패킷서버의 데이터 패킷이 전송됩니다 ICMP 에코 요청 패킷그러면 그럴 것이다 ICMP 시간 초과 패킷클라이언트의 전체 IP 패킷 헤더를 포함하여 NAT 뒤에 있는 서버로 다시 전달하므로 서버는 클라이언트의 IP 주소를 알 수 있습니다!

현재 이러한 UDP 홀 펀칭 방식은 많은 제약을 받고 있습니다. 자세한 내용은 다음을 참조하십시오.이전 기사UDP 홀 펀칭 외에도, 하드코딩된 방법을 사용하여 두 피어 노드의 공용 네트워크 주소와 포트 번호를 지정할 수 있습니다. 이 방법은 대부분의 NAT 네트워크에 효과적입니다.

소스 포트 무작위화

모든 피어가 엄격한 UDP 소스 포트 무작위화를 사용하는 NAT(대부분의 셀룰러 네트워크) 뒤에 있는 경우, NAT 간 연결을 구축할 수 없습니다. 핑 패킷 전송 후 어느 쪽도 ListenPort를 협상하여 해당 포트로 전송된 트래픽을 NAT가 수신할 수 있도록 할 수 없기 때문에 홀 펀칭을 초기화할 수 없어 연결 실패가 발생합니다. 따라서 LTE/3G 네트워크에서는 일반적으로 P2P 통신이 불가능합니다.

신호 서버 사용

이전 섹션에서 언급했듯이, 모든 피어가 엄격한 UDP 소스 포트 무작위화를 사용하는 NAT 뒤에 있는 경우, NAT 간 연결은 직접 이루어질 수 없지만, 타사 신호 서버를 통해 이루어질 수 있습니다. 신호 서버는 통신 당사자에게 상대편의 IP:포트 정보를 알려주는 중계국과 같습니다. 참고할 만한 몇 가지 프로젝트는 다음과 같습니다.

  • 타쿠타카하시/wg-connect[7]
  • git.zx2c4.com/wireguard-tools/tree/contrib/nat-hole-punching[8]

동적 IP 주소

WireGuard는 시작 시에만 도메인 이름을 확인합니다. DDNS를 사용하여 도메인 이름 확인을 동적으로 업데이트하는 경우, IP 주소가 변경될 때마다 WireGuard를 다시 시작해야 합니다. 현재 권장되는 해결책은 PostUp 후크를 사용하여 몇 분 또는 몇 시간마다 WireGuard를 다시 시작하여 도메인 이름을 강제로 확인하는 것입니다.

일반적으로 NAT-to-NAT 연결은 매우 불안정하고 많은 제약이 있으므로 릴레이 서버를 통해 통신하는 것이 좋습니다.

NAT-to-NAT 구성의 예:

Peer1:

[인터페이스]
...
청취포트 = 12000

[또래]
...
엔드포인트 = peer2.example-vpn.dev:12000
지속적 유지 = 25

피어2:

[인터페이스]
...
청취포트 = 12000

[또래]
...
엔드포인트 = peer1.example-vpn.dev:12000
지속적 유지 = 25

추가 정보:

  • 사미크/프낫[9]
  • en.wikipedia.org/wiki/UDP_hole_punching[10]
  • stackoverflow.com/questions/8892142/udp-hole-punching-algorithm[11]
  • stackoverflow.com/questions/12359502/udp-hole-punching-not-going-through-on-3g[12]
  • stackoverflow.com/questions/11819349/udp-hole-punching-not-possible-with-mobile-provider[13]
  • 와이어가드/와이어가드@주인/contrib/examples/nat-hole-punching[14]
  • staaldraad.github.io/2017/04/17/nat-to-nat-with-wireguard[15]
  • golb.hplar.ch/2019/01/expose-server-vpn.html[16]

동적으로 서브넷 IP 할당

이는 엔드포인트가 아닌 DHCP와 유사하게 피어 노드(피어)의 VPN 서브넷 IP를 동적으로 할당하는 것을 의미합니다.

WireGuard는 서브넷 IP를 동적으로 할당하는 기능을 공식적으로 개발 중입니다. 구체적인 구현 내용은 WireGuard/wg-dynamic에서 확인할 수 있습니다.[17]

물론 PostUp을 사용하여 런타임에 파일에서 IP 값을 읽어 Kubernetes용 CNI 플러그인과 유사하게 동적으로 IP를 할당하는 시스템을 구현할 수도 있습니다. 예를 들면 다음과 같습니다.

[인터페이스]
...
PostUp = wg set %i allowed-ips /etc/wireguard/wg0.key <(some command)

실용적인 팁

peers.conf 파일 공유

WireGuard 구성을 간소화하는 비밀 기능을 소개합니다. 피어의 공개 키가 로컬 인터페이스의 개인 키와 일치하면 WireGuard는 해당 피어를 무시합니다. 이 기능을 사용하면 모든 노드에서 동일한 피어 목록을 공유할 수 있습니다. 각 노드는 별도의 [Interface]만 정의하면 되며, 해당 노드가 목록에 있더라도 무시됩니다. 구체적인 방법은 다음과 같습니다.

  • 각 피어에는 [Interface] 섹션 구성만 포함된 별도의 /etc/wireguard/wg0.conf 파일이 있습니다.
  • 각 피어 노드(피어)는 모든 피어를 포함하는 동일한 /etc/wireguard/peers.conf 파일을 공유합니다.
  • PostUp 후크는 Wg0.conf 파일에서 구성되어야 하며, 내용은 PostUp = wg addconf /etc/wireguard/peers.conf입니다.

peers.conf를 공유하는 방법은 여러 가지가 있습니다. Ansible과 같은 도구를 사용하여 배포하거나, Dropbox와 같은 네트워크 디스크와 동기화하거나, Ceph와 같은 분산 파일 시스템을 사용하여 여러 노드에 마운트할 수 있습니다.

파일이나 명령 출력에서 구성 읽기

WireGuard는 모든 명령이나 파일의 출력 내용을 읽어 구성 값을 수정할 수도 있습니다. 이 기능은 키 관리를 용이하게 하는 데 사용할 수 있습니다. 예를 들어, Kubernetes Secrets나 AWS KMS와 같은 타사 서비스에서 런타임에 키를 읽을 수 있습니다.

컨테이너화

WireGuard는 컨테이너에서도 실행할 수 있습니다. 가장 간단한 방법은 --privileged 및 --cap-add=all 매개변수를 사용하여 컨테이너가 커널 모듈을 로드하도록 허용하는 것입니다.

컨테이너에서 WireGuard를 실행하고 네트워크 인터페이스를 호스트에 노출할 수 있습니다. 또한, 호스트에서 WireGuard를 실행하고 인터페이스를 특정 컨테이너에 노출할 수도 있습니다.

다음은 vpn_test 컨테이너가 모든 트래픽을 WireGuard 릴레이 서버를 통해 라우팅하는 구체적인 예입니다. 이 예에서 제공된 컨테이너 구성은 docker-compose 구성 파일 형식입니다.

릴레이 서버 컨테이너 구성:

버전: '3'

서비스:
와이어가드:
이미지: linuxserver/wireguard
포트:
- 51820:51820/udp
캡_추가:
-NET_ADMIN
-SYS_MODULE
볼륨:
- /lib/modules:/lib/modules
- ./wg0.conf:/config/wg0.conf:ro

릴레이 서버 WireGuard 구성 wg0.conf:

[인터페이스]
# 이름 = relay1.wg.example.com
주소 = 192.0.2.1/24
청취포트 = 51820
개인키 = oJpRt2Oq27vIB5/UVb7BRqCwad2YMReQgH5tlxz8YmI=
DNS = 1.1.1.1,8.8.8.8
PostUp = iptables -A 포워드 -i wg0 -j 수락; iptables -t nat -A 포스트라우팅 -o eth0 -j 매스커레이드; ip6tables -A 포워드 -i wg0 -j 수락; ip6tables -t nat -A 포스트라우팅 -o eth0 -j 매스커레이드
PostDown = iptables -D 포워드 -i wg0 -j 수락; iptables -t nat -D 포스트라우팅 -o eth0 -j 매스커레이드; ip6tables -D 포워드 -i wg0 -j 수락; ip6tables -t nat -D 포스트라우팅 -o eth0 -j 매스커레이드

[또래]
# 이름 = peer1.wg.example.com
공개키 = I+hXRAJOG/UE2IQvIHsou2zTgkUyPve2pzvHTnd/2Gg=
허용된 IP = 192.0.2.2/32

클라이언트 컨테이너 구성:

버전: '3'

서비스:
와이어가드:
이미지: linuxserver/wireguard
캡_추가:
-NET_ADMIN
-SYS_MODULE
볼륨:
- /lib/modules:/lib/modules
- ./wg0.conf:/config/wg0.conf:ro

vpn_test:
이미지: curlimages/curl
진입점: curl -s http://whatismyip.akamai.com/
네트워크 모드: '서비스:와이어가드'

클라이언트 측 WireGuard 구성 wg0.conf:

[인터페이스]
# 이름 = peer1.wg.example.com
주소 = 192.0.2.2/32
개인키 = YCW76edD4W7nZrPbWZxPZhcs32CsBLIi1sEhsV/sgk8=
DNS = 1.1.1.1,8.8.8.8

[또래]
# 이름 = relay1.wg.example.com
엔드포인트 = relay1.wg.example.com:51820
공개키 = zJNKewtL3gcHdG62V3GaBkErFtapJWsAx+2um0c0B1s=
허용된 IP = 192.0.2.1/24,0.0.0.0/0
지속적 유지 = 21

점수

댓글남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다