키 생성부터 VPN 연결까지 실습해보기

network

6 분 읽기

WireGuard VPN 구성하기

앞에서 WireGuard의 핵심 개념과 설정 항목을 살펴보았다면, 이제 실제로 하나의 VPN 터널을 구성해 보자. 이번 글에서는 다음과 같은 가장 기본적인 두 장치 사이의 VPN 환경을 구축해볼 것이다.

1
2
3
4
5
6
7
8
9
WireGuard Peer1 : Linux Server
공인 IP: XXX.XXX.X.XX
VPN 주소: 10.0.0.1
UDP 포트: 51820
        ▲
        │ WireGuard Tunnel
        ▼
WireGuard Peer2 : Mobile Phone
VPN 주소: 10.0.0.2

여기서 XXX.XXX.X.XX은 인터넷에서 서버를 찾기 위한 예시 공인 IP이고, 실제 환경에서는 장치의 공인 IP나 도메인으로 Endpoint를 바꾸어야 한다. 10.0.0.110.0.0.2는 WireGuard 터널 내부에서 사용할 가상 IP다.

이번 실습의 구체적인 두 가지 목표는 다음과 같다.

1. 가장 간단한 구조의 VPN을 구축할 것이다.

두 장치가 암호화된 터널을 통해 서로의 VPN 내부 IP에 접근할 수 있는지 확인하는 것이다. 정확하게 말하면, split tunnel(분할 터널링) 방식의 VPN 구조를 구축하는 것이다. 인터넷 전체를 VPN으로 전달하는 Full Tunnel 구성은 이번 글을 따라 기본 연결을 검증한 뒤, 다음 글에서 자세히 다루도록 하겠다.


2. Server-Client 구조의 VPN을 구축할 것이다.

즉, Client Peer는 Server Peer의 인터넷 상 주소(IP)를 알지만, 반대로 Server Peer는 Client Peer의 위치를 알지 못하는 상황이다. 이 상황을 전제한 이유는, 실제 VPN 환경에서 가장 흔하게 접할 수 있는 형태이기 때문이다.

WireGuard 자체는 모든 장치를 동등한 Peer로 취급하지만, 실제 네트워크 구성에서는 이처럼 연결을 기다리는 Peer를 Server, 먼저 연결을 시작하는 Peer를 Client라고 편의상 구분하여 글을 전개해 나갈 것이니 참고!

일반적으로 VPN 서버는 외부에서 접속할 수 있는 고정된 공인 IP를 가지지만, 클라이언트는 네트워크가 수시로 변경되기 때문에 서버가 클라이언트의 현재 주소를 미리 알기 어렵다. 따라서 클라이언트가 서버의 Endpoint로 먼저 연결을 시작하고, 서버는 해당 패킷을 통해 클라이언트의 현재 IP 주소와 포트를 학습하여 이후 통신을 이어가게 된다.

split tunnel과 full tunnel 방식에 대해서는 다음에 다루기로 한다.



0. 키 생성

이전 글에서 살펴봤듯, wg genkey 명령어로 키를 생성할 수 있다. WireGuard는 Curve25519 계열 키를 사용하므로, 꼭 이 명령어를 사용하도록 하자. (다른 암호화 방식을 적용하면 안됨)

(1) Peer1 키 생성

1
sudo sh -c 'umask 077; wg genkey | tee peer1_private.key | wg pubkey > peer1_public.key'

실습을 위해 사용할 키를 생성한 결과는 아래와 같다.

1
2
3
4
5
# peer1_private.key
+AjuhQoQV3Lvlcr07Kg4dagYovIZY23ukRhrulWRsXs=

# peer1_public.key
bIdowhs44axhgTkxJW0a2ukm37O5ntiO1WZsTBk0mlA=


(2) Peer2 키 생성

1
sudo sh -c 'umask 077; wg genkey | tee peer2_private.key | wg pubkey > peer2_public.key'

실습을 위한 Peer2 의 키도 아래와 같이 만들어졌다.

1
2
3
4
5
# peer2_private.key
GLhu+yob85lCU7H1IRcPIbnvOHcw+TflC/JAKSLmu3E=

# peer2_public.key
I8+guhmhRcN25226dO9xFPuB5OSe9z7DXquoMudOIgE=


1. Peer1 설정 파일 작성

Server의 역할을 하는 Peer1에는 외부에서 접근할 수 있도록 WireGuard Port를 정의하고, 연결을 허용할 Peer를 등록한다. Peer1의 OS 가 리눅스이므로, 설정 파일은 /etc/wireguard/wg0.conf에 위치한다.

Peer1에 대한 예시를 리눅스로 들긴 하였지만, 사실 Windows든, 아이폰이든, 갤럭시폰이든, 노트북이든, 패드든 상관 없다. 네트워크가 가능하고 WireGuard를 설치할 수만 있고, 공인 IP를 가지고 있다면 상관 없다.

1
2
3
4
5
6
7
8
[Interface]
PrivateKey = +AjuhQoQV3Lvlcr07Kg4dagYovIZY23ukRhrulWRsXs=
Address = 10.0.0.1/24
ListenPort = 51820

[Peer]
PublicKey = I8+guhmhRcN25226dO9xFPuB5OSe9z7DXquoMudOIgE=
AllowedIPs = 10.0.0.2/32

각 항목의 의미는 다음과 같다.

항목 의미
Interface Peer1 자신의 정보
PrivateKey Peer1 자신의 비밀키
Address Peer1이 WireGuard 인터페이스에서 사용할 내부 IP
ListenPort WireGuard 연결을 수신할 UDP 포트
[Peer] Peer1이 통신할 Peer2 정의
PublicKey Peer2의 공개키
AllowedIPs 해당 Peer2에 허락된 VPN IP

[Interface]에는 Peer1 자신의 정보가 들어간다. 따라서 PrivateKey에는 Peer1을 위해 생성한 비밀키를 입력해야 한다.

반면 [Peer]PublicKey에는 상대방인 Peer2의 공개키를 입력한다. 이 방향을 반대로 작성하면 양쪽에 올바른 키가 있어도 인증이 성립하지 않는다.

서버의 AllowedIPs = 10.0.0.2/32는 10.0.0.2로 향하는 트래픽을 이 Peer2에게 전달하겠다는 뜻이다. /32는 하나의 IP 주소만 지정하는 범위이므로, 특정 클라이언트에 하나의 VPN 주소를 할당하는 기본 구성을 뜻한다.

또한 ListenPort 로 사용할 UDP 51820 포트가 허용되어야 한다. 51820은 WireGuard에서 흔히 사용하는 기본 예시 포트일 뿐 반드시 고정된 값은 아니다.

또한 서버가 외부에서 연결을 받을 수 있으려면 클라우드 보안 그룹, 호스트 방화벽, 공유기 포트 포워딩 등의 환경이 구성되어 있어야 한다. 네트워크의 구조와 각 설정 항목들에 대해서는 다음 글에서 자세히 살펴볼 것이다.



2. Peer2 설정 파일 작성

Peer2에도 자신의 WireGuard 인터페이스와 Peer1에 대한 정보를 정의한다. 이번 예제에서는 스마트 폰(IPhone)을 Peer2 사용자로 해보도록 하겠다. (아이폰에서의 설치 방법은 이전 글을 참고하기 바란다.)

아이폰에서 WireGuard를 설치하고 나면 다음과 같은 화면을 볼 수 있다. 여기서 우측 상단의 + 버튼을 누른다.

2026-08-31 기준, 세 가지 방식으로 WireGuard 설정을 등록할 수 있다.

  1. Create from file or archive : 파일로 등록
  2. Create from QR code : QR code를 통해 등록
  3. Create from scratch : 직접 입력

셋 중 어떤 방법으로 진행해도 상관 없으나, 이것저것 따지지 않고 그냥 바로 등록해보고 싶다면 3. Create from scratch를, 여러 Peer를 효율적으로 등록하고 싶다면 2.Create from QR code를 선택하는 걸 권장한다. 파일로 등록하는 건 안해봐서 편한지 모름

Create From scratch 를 선택한 뒤에는, 위 이미지처럼 입력하면 된다. 이를 리눅스 설정파일에 적용해보면 아래와 같은 내용이다. (Name은 그저 아이폰 WireGuard 앱 내에서 VPN 인터페이스에 붙일 이름 = wg0과 같은 느낌)

1
2
3
4
5
6
7
8
9
[Interface]
PrivateKey = GLhu+yob85lCU7H1IRcPIbnvOHcw+TflC/JAKSLmu3E=
Address = 10.0.0.2/32

[Peer]
PublicKey = bIdowhs44axhgTkxJW0a2ukm37O5ntiO1WZsTBk0mlA=
Endpoint = XXX.XXX.X.XX:51820
AllowedIPs = 10.0.0.0/24
PersistentKeepalive = 25

설정의 각 항목은 다음과 같이 해석할 수 있다.

항목 의미
PrivateKey Peer2 자신의 비밀키
Address Peer2의 VPN 내부 IP
[Peer] Peer2가 연결할 서버 정의
PublicKey Peer1의 공개키
Endpoint Peer1의 실제 인터넷 주소와 UDP 포트
AllowedIPs Peer1을 통해 전달할 목적지 네트워크
PersistentKeepalive NAT 환경에서 연결 상태를 유지하기 위한 주기

Peer1과 달리 Peer2의 [Peer]에는 Peer1의 PublicKey가 들어간다.

꼭 알아둬야 할 점은, Endpoint에는 Peer1의 VPN 주소인 10.0.0.1이 아니라 인터넷에서 서버에 접근할 수 있는 실제 주소를 작성해야 한다는 것이다. (Endpoint = XXX.XXX.X.XX:51820) 또한, 서버가 도메인을 사용하는 경우에는 도메인을 넣어줘도 된다.



3. 인터페이스 시작(설정 적용)

각 Peer의 설정 파일을 작성했다면 양쪽에서 설정 반영을 실행한다.

  • 모바일 폰의 경우엔 설정값을 넣고 저장한 뒤, Deactive - Active 전환을 한 번 해주면 적용이 완료된다.
  • 리눅스의 경우 wg-quick을 사용해 wg0 인터페이스를 시작 (또는 재시작)** 한다. 먼저 현재 실행중인 WireGuard가 있다면 종료해준 뒤, 아래와 같이 WireGuard를 재시작한다.
1
sudo wg-quick down wg0

다시 시작해준다.

1
sudo wg-quick up wg0

※ 만들어져있는 설정 파일 명이 /etc/wireguard/wg0.conf 라고 가정한다.

wg-quick up wg0 명령은 /etc/wireguard/wg0.conf를 읽어 WireGuard 인터페이스를 생성하고, 설정된 VPN 주소와 라우팅 규칙을 함께 적용한다.


4. 기본 연결 확인

명령어를 실행했다면, 인터페이스가 정상적으로 올라왔는지 확인한다.

1
wg show

클라이언트에서 서버의 VPN 내부 주소로 통신을 시험한다.

1
ping 10.0.0.1

서버에서도 클라이언트 주소로 응답 여부를 확인할 수 있다.

1
ping 10.0.0.2

이번 테스트에서는 Peer2가 Peer1에만 접근할 수 있을 뿐, Peer1과 같은 대역대에 있는 다른 서버에는 접근할 수 없다. 이는 이번에 구축한 VPN이 Split Tunnel 구조이기 때문이다. (Full-Tunnel 방식으로 전환하는 방법은 아래에서 알아본다.)


Full Tunnel 맛보기

이에 이번 단락에서는 VPN을 Full-Tunnel 방식으로 전환해보고, 클라이언트의 모든 인터넷 트래픽을 상대방 서버에 보내서, 서버의 같은 대역의 네트워크에 위치한 다른 서버에도 접근해보고, 인터넷에도 접근해보도록 하겠다.

1. VPN 설정 수정

수정할 것은 많지 않다. Peer2(스마트폰)의 설정에서 상대방의 AllowedIPs를 더 전체 범위로 열어두면 된다. 수정 후에는 VPN을 Deactive -> Active 하여 설정을 적용해준다.

  • 기존
1
2
3
4
5
6
7
8
[Interface]
PrivateKey = GLhu+...
Address = 10.0.0.2/32

[Peer]
...
AllowedIPs = 10.0.0.0/24
...
  • 변경
1
2
3
4
5
6
7
8
[Interface]
PrivateKey = GLhu+...
Address = 10.0.0.2/32

[Peer]
...
AllowedIPs = 0.0.0.0/0
...


2. 테스트

이제 테스트를 진행해보자. 아래는 브라우저(Chrome, Safari 등)를 통해 VPN과 같은 대역에 위치한 더미 서비스에 접근해본 결과이다. 이미지는 ChatGPT에게 발랄한 느낌으로 만들어달라고 한 결과물인데.. 넘치게 발랄한 이미지를 만들어주었다.

글을 마무리하며

이번 글에서는 먼저 AllowedIPs = 10.0.0.0/24와 같이 필요한 네트워크만 WireGuard 터널로 전달하는 Split Tunnel 구성을 만들고, 이후 AllowedIPs = 0.0.0.0/0으로 변경하여 더 넓은 범위의 트래픽을 터널로 보내는 Full Tunnel 구성까지 간단히 확인해보았다.

다만 AllowedIPs = 0.0.0.0/0으로 설정했다고 해서 서버가 자동으로 인터넷 게이트웨이 역할까지 수행하는 것은 아니다. 실제로 모든 인터넷 트래픽을 VPN 서버를 거쳐 외부로 보내려면 서버 측의 IP Forwarding, NAT, 방화벽, 라우팅 설정도 함께 구성해야 한다.

다음 글에서는 Split Tunnel 방식과 Full Tunnel 방식에 대해 더 깊게 살펴보고, 실습해보면서 AllowedIPs 설정에 따라 실제 패킷이 어떤 경로로 이동하는지 자세히 살펴보도록 하겠다.

Reference

https://www.wireguard.com/

// reading compass

이 글과 이어지는 경로

시리즈, 카테고리, 태그 겹침, 최신도를 점수화해 가까운 글일수록 중심에 배치합니다.

hover nodes or cards · click a node to pin
Next reads 0

    댓글 남기기