개요
이번 포스팅에서는 Wireguard의 기본 개념, VPN 피어(Peer), 내부 IP 주소의 이해
그리고 리눅스 서버 및 Windows 클라이언트에서의 구축 방법과 함께
도커 기반의 wireguard-ui
를 사용하여 클라이언트 키를 쉽게 생성하는 방법에 대해서 기록해보려고 합니다!
VPN 피어(Peer)
VPN에서 피어(Peer) 란 서로 VPN 터널을 통해 통신하는 개별 노드를 의미합니다.
- 서버 피어: VPN 네트워크의 중심이 되는 서버로, 여러 클라이언트와의 연결을 관리.
- 클라이언트 피어: 서버에 연결하는 각 단말기로, 각 클라이언트마다 고유 키와 내부 IP가 할당됨.
VPN 내부 IP의 이해
VPN 구축 시 사용하는 내부 IP 주소 는 가상의 네트워크를 구성하는 데 사용됩니다.
예시로, 10.0.0.0/24
와 같이 서브넷을 지정하여,
서버에 10.0.0.1
클라이언트에 10.0.0.2
등으로 할당해요.
해당 IP는 인터넷상의 real ip와 별개로 VPN 내에서만 사용이 되구요,
안전한 터널링 및 라우팅을 위해 사용된다고 보면 됩니다!
Wireguard 설치하기
이번 챕터에서는 Ubuntu 환경에서 Wireguard를 설치하고
서버를 구성하는 방법을 알아볼거에요!s
사전 준비
- 운영체제: Ubuntu 20.04 이상 (다른 배포판도 가능)
- 커널 버전: Linux 커널 5.6 이상 (이하일 경우 backport 패키지 필요)
- 루트 권한: sudo 권한 필요
wireguard 설치
아래 명령어를 실행해 wireguard
를 설치합시다.
sudo apt update
sudo apt install wireguard -y
1. Wireguard 서버 설정
1-1. 서버 키페어 생성
Wireguard는 공개키 암호 방식 을 사용합니다.
서버와 클라이언트 각각에서 개인키(Private Key
)와 공개키(Public Key
)를 생성해줘야 해요!
1. Private Key 생성
sudo wg genkey | sudo tee /etc/wireguard/server_private.key
sudo chmod 600 /etc/wireguard/server_private.key
server_private.key
파일에는 서버의 개인키가 저장됩니다. 절대 외부에 노출하지 마세용!!
2. Public Key 생성
sudo cat /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
server_public.key
파일에는 서버의 공개키가 저장됩니다. 이 키는 클라이언트 설정에 필요해요!
1-2. 서버 설정 파일 작성
이제 VPN 서버의 동작 방식을 정의하는 설정 파일을 생성해주겠습니다.
wg0.conf
라는 이름으로 파일을 생성해줄게요.
(Wireguard는 /etc/wireguard/wg0.conf
파일을 생성하여 VPN 인터페이스를 구성합니다!)
먼저 ip a
명령어를 실행하여 외부 트래픽용 인터페이스 이름(예: ens18
)과 퍼블릭 IP를 확인할게요.
ip a
그리고 /etc/wireguard/wg0.conf
파일을 생성하고 편집하겠습니다.
[Interface]
# 서버의 VPN 내부 IP 주소
Address = 10.0.0.1/24
# 설정을 저장할지 여부
SaveConfig = true
# WireGuard 서비스가 시작될 때 실행할 명령어 (NAT 설정)
# eth0는 서버의 실제 네트워크 인터페이스 이름입니다. 'ip a' 명령어로 확인 후 다르면 수정하세요.
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# WireGuard 서비스가 중지될 때 실행할 명령어 (NAT 설정 복원)
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# WireGuard가 사용할 포트 (UDP)
ListenPort = 51820
# 2단계에서 생성한 서버의 '개인키'를 여기에 붙여넣으세요.
PrivateKey = <서버의 privatekey 파일 내용>
# --- 클라이언트 정보 ---
# 이곳부터는 연결할 클라이언트(Peer) 정보를 추가합니다.
[Peer]
# 클라이언트의 '공개키'를 여기에 붙여넣으세요. (클라이언트 설정 시 생성)
PublicKey = <클라이언트의 publickey 내용>
# 이 클라이언트에게 할당할 VPN 내부 IP 주소
AllowedIPs = 10.0.0.2/32
자 그러면, 상기 설정 파일에 작성된 설정 관련해서 조금 더 자세하게 설명해보도록 할게요!
NAT(Network Address Translation)
일반적으로 서버가 VPN 클라이언트의 트래픽을 인터넷으로 전달할 때,
VPN 내부 IP는 일반 공인 IP와 다르기 때문에 라우팅 및 응답에 문제가 발생할 수 있습니다.
그렇기 때문에 NAT 설정을 해주는 것이에요!
그럼 잠깐 옵션을 살펴볼까요?
Address
설명: Wireguard 인터페이스가 사용할 IP 주소 대역입니다.
10.0.0.1/24
는 서버 자신은 10.0.0.1
을 사용하고, 10.0.0.2
~ 10.0.0.254
까지 클라이언트에게 할당할 수 있다는 뜻입니다!
서브넷에 대한 개념이 잡혀있다면 쉽게 이해가 가능합니다.
PostUp
(인터페이스가 올라갈 때 실행됨)
설명: VPN 클라이언트의 내부 IP가 아닌 서버의 공인 IP로 바꾸어 응답 패킷이 올바른 경로로 돌아올 수 있게 합니다.
iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
%i
는 현재 인터페이스(예:wg0
)로 대체됩니다.- 설명: 해당 인터페이스를 통해 들어오는 패킷들을 허용(ACCEPT)하여, VPN 클라이언트에서 오는 트래픽이 서버를 통해 다른 네트워크로 전달될 수 있도록 합니다.
-t nat
: NAT 테이블을 사용합니다.POSTROUTING
: 패킷이 라우팅 결정 후 외부로 나가기 전 처리하는 체인입니다.-o eth0
: 외부 인터페이스 이름(예: eth0)를 지정합니다 (실제 인터넷 연결에 사용되는 인터페이스를 뜻해요!)MASQUERADE
: 패킷의 출발지 IP를 서버의 외부 IP로 변경합니다.
PostDown
(인터페이스가 내려갈 때 실행됨)
설명: VPN 연결 종료 시, 위에서 추가했던 iptables 규칙을 제거하여 서버의 네트워크 설정을 원래 상태로 복구합니다.
iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
- 위의 FORWARD 체인에 추가된 규칙을 삭제합니다.
- NAT 테이블의 MASQUERADE 규칙을 삭제합니다.
ListenPort
설명: WireGuard가 클라이언트의 연결을 기다릴 UDP 포트를 명시하는 것입니다.
PrivateKey
설명: 서버 키페어 생성에서 생성했었던 server_private.key
파일에 있는 키 값을 붙여 넣어주세요.
[Peer]
설명: 연결을 허용할 클라이언트에 대한 설정 섹션입니다.
PublicKey
설명: 클라이언트에서 생성할 공개키를 나중에 추가해줘야 해요.
AllowedIPs
설명: 해당 클라이언트에게 할당하고, 해당 클라이언트로부터 들어오는 것을 허용할 IP 주소입니다.
1-3. IP 포워딩 활성화
서버가 VPN 클라이언트로부터 받은 트래픽을 인터넷으로 전달(포워딩)할 수 있도록 커널 설정을 변경해야 합니다!
1. IP 포워딩 활성화
echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
2. 방화벽 설정
서버의 방화벽(예: ufw
)에서 Wireguard가 사용하는 UDP 포트(51820
)을 열어줘야 합니다.
# ufw를 사용하는 경우
sudo ufw allow 51820/udp
sudo ufw allow OpenSSH # SSH 연결이 끊기지 않도록 SSH 포트도 허용
sudo ufw enable
sudo ufw status
[주의] iptables 중복 설정
간혹, Wireguard 설정을 기록한 블로그들을 보면 iptables 설정을 중복해서 작성하는 게시글들이 종종 보이는데요!
서버 설정 파일 작성에서 wg0.conf
의 POSTUP
지시어에 iptables 규칙을 넣었던 것 기억하시죠?
그런데 소수의 블로그 글들을 보면 wg0.conf
에 POSTUP
지시어를 추가했음에도 불구하고, 추가적으로 서버에 아래와 같은 설정을 해주는 분들이 계세요!
sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o <IF> -j MASQUERADE
sudo iptables-save | sudo tee /etc/iptables/rules.v4
위 명령어 또한 VPN에 연결된 기기들이 인터넷을 사용할 수 있도록하고, 또한 iptables rules에 영구적으로 적용하는 명령어입니다.
이미 wg0.conf
의 POSTUP
지시어에 iptables 규칙을 명시해줬다면 위 명령어를 또 입력할 필요는 전혀 없어요 ..
또한 wg0.conf
의 PostUp/PostDown
방식을 사용하는걸 더 권장하고 있답니다.
그 이유는 이 방식은 Wireguard 서비스와 규칙의 생명주기를 일치시키는데
이 때 sudo wg-quick up wg0
명령으로 VPN이 켜질 때 PostUp
규칙이 자동으로 추가되고,
sudo wg-quick down wg0
명령으로 VPN이 꺼지면 PostDown
규칙에 의해 설정했던 iptables 규칙이 자동으로 삭제됩니다.
그러나 iptables-save
방식으로 규칙을 설정해버리면 해당 규칙은 서버에 영구적으로 남아서 관리자가 지우기 전까지는 절대로 없어지지 않아요!
1-4. 서비스 시작 및 자동 실행
# WireGuard 서비스 시작
sudo wg-quick up wg0
# 부팅 시 자동 시작 설정
sudo systemctl enable wg-quick@wg0
# 서비스 상태 확인
sudo wg-quick down wg0 # 잠시 내렸다가
sudo wg-quick up wg0 # 다시 올려서 확인
sudo wg show
2. Wireguard 클라이언트 설정
클라이언트는 어떤 운영체제이든 상관없습니다.
이번 포스팅에서는 Linux(Ubuntu)
클라이언트 기준으로 설명하지만, 다른 OS도 설정하는 내용은 동일합니다!
1. 클라이언트 기기에 Wireguard 설치하기
각 운영체제에 맞는 Wireguard 클라이언트를 공식 홈페이지에서 설치해주세요!
2. 클라이언트용 키 생성
서버에서와 마찬가지로 클라이언트에서도 개인키와 공개키를 생성합니다.
# (클라이언트 PC에서 실행)
umask 077
wg genkey | tee client_privatekey | wg pubkey > client_publickey
client_privatekey
: 클라이언트의 개인키 (클라이언트 설정에 사용)client_publickey
: 클라이언트의 공개키 (서버 설정 파일에 추가해야 함)
3. 클라이언트 설정 파일 작성 (client.conf
등)
아래 내용으로 설정 파일을 작성할게요!
[Interface]
# 클라이언트의 개인키를 여기에 붙여넣으세요.
PrivateKey = <클라이언트의 client_privatekey 내용>
# 서버에서 할당받을 VPN 내부 IP 주소
Address = 10.0.0.2/32
# DNS 설정 (선택사항이지만 권장)
DNS = 8.8.8.8
[Peer]
# 서버의 공개키를 여기에 붙여넣으세요.
PublicKey = <서버의 publickey 파일 내용>
# VPN을 통해 라우팅할 트래픽 대역. 0.0.0.0/0은 모든 트래픽을 의미합니다.
AllowedIPs = 0.0.0.0/0, ::/0
# 서버의 공인 IP 주소와 포트
Endpoint = <서버의 공인 IP 주소>:51820
# NAT 환경에서 연결 유지를 위한 설정 (25초마다 핑)
PersistentKeepalive = 25
클라이언트 설정 파일에 작성한 설정 내용들을 조금 살펴볼까요?
PrivateKey
: 클라이언트에서 생성한 개인키입니다.Address
: 서버 설정 파일(wg0.conf
)의 [Peer] 섹션에서AllowedIPs
에 지정한 IP와 동일해야 합니다.DNS
: VPN 연결 시 사용할 DNS 서버입니다. Google DNS(8.8.8.8)나 Cloudflare DNS(1.1.1.1)를 많이 사용합니다.PublicKey
: 서버의 공개키(sudo cat /etc/wireguard/publickey로 확인)입니다.AllowedIPs
: 0.0.0.0/0, ::/0으로 설정하면 클라이언트의 모든 인터넷 트래픽이 VPN 서버를 거치게 됩니다. (일반적인 VPN 사용 목적)Endpoint
: 접속할 서버의 실제 공인 IP 주소와 ListenPort를 입력합니다.PersistentKeepalive
: 클라이언트가 방화벽이나 NAT 뒤에 있을 때 연결이 끊기는 것을 방지합니다.
3. 연결 완료 및 테스트하기!
1. 서버에 클라이언트 정보 등록하기
다시 서버로 돌아와서, 2. Wireguard 클라이언트 설정에서 생성한 클라이언트의 공개키(client_publickey
의 내용)를 서버 설정 파일에 추가해야 합니다.
# 서버에서 실행
sudo nano /etc/wireguard/wg0.conf
# ... (상단 생략) ...
[Peer]
# 2단계에서 생성한 클라이언트의 공개키를 여기에 붙여넣습니다.
PublicKey = PASTE_CLIENT_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.2/32
2. 설정 적용을 위해 Wireguard 재시작!
# 서버에서 실행
sudo wg-quick down wg0
sudo wg-quick up wg0
3. 클라이언트에서 VPN 연결
Windows
/ MacOS
/ 모바일 클라이언트의 경우에는 클라이언트 앱을 설치해주시고 앱을 실행해서
'터널 추가' 또는 import tunnel(s) from file
메뉴를 선택해 위에서 작성한 client.conf
파일을 불러와서 연결해주면 됩니다!