network / knowledge

WireGuard 서버와 클라이언트 설정 짝 맞추기

paul 2025.01.03 285words (1m)

WireGuard 설정은 짧은데 서버와 클라이언트가 서로를 어떻게 가리키는지 헷갈리기 쉽다. 두 파일을 나란히 놓고 보면 규칙이 단순하다.

키 만들기

console
$ wg genkey | tee privatekey | wg pubkey > publickey

wg genkey 가 개인키를 뱉고, tee 로 파일에 쓰면서 그 출력을 wg pubkey 에 넘겨 공개키를 만든다. 서버와 클라이언트 각각 한 쌍씩 만든다.

console
$ wg genpsk > preshared.key

preshared key는 선택이지만 넣어뒀다. 공개키 암호 위에 대칭키를 한 겹 더 얹는 것이라 양쪽 conf에 같은 값이 들어간다.

서버

ini
[Interface]
Address = 10.7.0.1/24
PrivateKey = <서버의 개인키>
ListenPort = 51820

[Peer]
PublicKey = <클라이언트의 공개키>
PresharedKey = <공유 키>
AllowedIPs = 10.7.0.2/32

클라이언트

ini
[Interface]
Address = 10.7.0.2/24
DNS = 1.1.1.1, 1.0.0.1
PrivateKey = <클라이언트의 개인키>

[Peer]
PublicKey = <서버의 공개키>
PresharedKey = <공유 키>
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = <서버 공인 IP>:51820
PersistentKeepalive = 25

읽는 규칙

  • [Interface]다. 여기 들어가는 건 내 개인키와 내가 이 터널에서 가질 주소다.
  • [Peer]상대다. 여기 들어가는 건 상대의 공개키다.

AllowedIPs 가 양쪽에서 뜻이 다르다. 이게 가장 헷갈리는 부분이다.

서버 쪽의 AllowedIPs = 10.7.0.2/32 는 "이 peer한테서 오는 패킷 중 출발지가 이 주소인 것만 받고, 이 주소로 갈 패킷은 이 peer로 보낸다"는 뜻이다. peer마다 /32 로 잘라줘야 서로 섞이지 않는다.

클라이언트 쪽의 AllowedIPs = 0.0.0.0/0, ::/0 는 "모든 트래픽을 이 peer로 보낸다"는 뜻이다. 전체 트래픽을 VPN으로 태우는 설정이다. 집 네트워크에만 접근하고 싶으면 여기를 그 대역으로 좁히면 된다.

Endpoint 는 클라이언트 쪽에만 있다. 서버는 공인 IP가 고정이라 클라이언트가 찾아가지만, 클라이언트는 주소가 계속 바뀌므로 서버가 먼저 찾아갈 수 없다. 서버는 패킷이 들어온 주소를 기억해뒀다가 그쪽으로 답한다.

PersistentKeepalive = 25 도 클라이언트 쪽이다. NAT 뒤에 있으면 잠깐 조용해지는 순간 NAT 매핑이 사라져서 서버가 답을 못 보낸다. 25초마다 빈 패킷을 보내 매핑을 살려둔다.

휴대폰에 넘기기

conf 파일을 QR로 만들면 앱에서 찍어 넣을 수 있다.

console
$ apt install qrencode
$ qrencode -t ansiutf8 < phone.conf

터미널에 바로 QR이 그려진다. 파일로 뽑을 수도 있다.

console
$ qrencode -o phone.png < phone.conf

개인키가 들어 있는 이미지이므로 넘기고 나서 지운다.