1. 개요
이번 포스팅에서는 Wireguard의 기본 개념, VPN 피어(Peer), 내부 IP 주소의 이해
그리고 리눅스 서버 및 Windows 클라이언트에서의 구축 방법과 함께
도커 기반의 wireguard-ui
를 사용하여 클라이언트 키를 쉽게 생성하는 방법에 대해서 기록해보려고 합니다!
2. VPN 피어(Peer)
VPN에서 피어(Peer) 란 서로 VPN 터널을 통해 통신하는 개별 노드를 의미합니다.
- 서버 피어: VPN 네트워크의 중심이 되는 서버로, 여러 클라이언트와의 연결을 관리.
- 클라이언트 피어: 서버에 연결하는 각 단말기로, 각 클라이언트마다 고유 키와 내부 IP가 할당됨.
3. VPN 내부 IP의 이해
VPN 구축 시 사용하는 내부 IP 주소 는 가상의 네트워크를 구성하는 데 사용됩니다.
예시로, 10.0.0.0/24
와 같이 서브넷을 지정하여,
서버에 10.0.0.1
클라이언트에 10.0.0.2
등으로 할당해요.
해당 IP는 인터넷상의 real ip와 별개로 VPN 내에서만 사용이 되구요,
안전한 터널링 및 라우팅을 위해 사용된다고 보면 됩니다!
4. Wireguard 설치하기
이번 챕터에서는 Ubuntu 환경에서 Wireguard를 설치하고
서버를 구성하는 방법을 알아볼거에요!s
4-1. 사전 준비
- 운영체제: Ubuntu 20.04 이상 (다른 배포판도 가능)
- 커널 버전: Linux 커널 5.6 이상 (이하일 경우 backport 패키지 필요)
- 루트 권한: sudo 권한 필요
4-2. wireguard 설치
아래 명령어를 실행해 wireguard
를 설치합시다.
sudo apt update
sudo apt install wireguard -y
4-3. 키 생성
Wireguard는 공개키 암호 방식 을 사용합니다.
서버와 클라이언트 각각에서 개인키와 공개키를 생성해줘야 해요!
서버 측 키 생성
# 서버 개인키 생성 후 파일에 저장하고, 그 결과를 기반으로 공개키 생성
wg genkey | sudo tee /etc/wireguard/server_privatekey | wg pubkey | sudo tee /etc/wireguard/server_publickey
클라이언트 측 키 생성 (리눅스 클라이언트인 경우)
wg genkey | tee ~/client_privatekey | wg pubkey | tee ~/client_publickey
4-4. 서버 구성 파일 작성
서버에서는 /etc/wireguard/wg0.conf
파일을 생성하여 VPN 인터페이스를 구성합니다!
[Interface]
# 서버의 VPN 내부 IP 주소
Address = 10.0.0.1/24
# 서버가 수신할 포트 (기본 51820)
ListenPort = 51820
# 서버 개인키 (이전에 생성한 값)
PrivateKey = <서버_개인키_여기에_입력>
# NAT 설정: 외부 인터페이스(예: eth0)를 통해 인터넷 공유
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# 클라이언트 공개키 (생성한 값을 입력)
PublicKey = <클라이언트_공개키_여기에_입력>
# 클라이언트에 할당할 내부 IP 주소
AllowedIPs = 10.0.0.2/32
위 코드에서 NAT 설정 관련해서 조금 더 자세하게 설명해보도록 할게요!
NAT(Network Address Translation)
일반적으로 서버가 VPN 클라이언트의 트래픽을 인터넷으로 전달할 때,
VPN 내부 IP는 일반 공인 IP와 다르기 때문에 라우팅 및 응답에 문제가 발생할 수 있습니다.
그렇기 때문에 NAT 설정을 해주는 것이에요!
그럼 잠깐 옵션을 살펴볼까요?
PostUp 명령어 (인터페이스가 올라갈 때 실행됨)
iptables -A FORWARD -i %i -j ACCEPT
%i
는 현재 인터페이스(예:wg0
)로 대체됩니다.- 설명: 해당 인터페이스를 통해 들어오는 패킷들을 허용(ACCEPT)하여, VPN 클라이언트에서 오는 트래픽이 서버를 통해 다른 네트워크로 전달될 수 있도록 합니다.
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
-t nat
: NAT 테이블을 사용합니다.POSTROUTING
: 패킷이 라우팅 결정 후 외부로 나가기 전 처리하는 체인입니다.-o eth0
: 외부 인터페이스 이름(예: eth0)를 지정합니다.MASQUERADE
: 패킷의 출발지 IP를 서버의 외부 IP로 변경합니다.- 설명: VPN 클라이언트의 내부 IP가 아닌 서버의 공인 IP로 바꾸어 응답 패킷이 올바른 경로로 돌아올 수 있게 합니다.
PostDown 명령어 (인터페이스가 내려갈 때 실행됨)
iptables -D FORWARD -i %i -j ACCEPT
- 위의 FORWARD 체인에 추가된 규칙을 삭제합니다.
iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
- NAT 테이블의 MASQUERADE 규칙을 삭제합니다.
- 설명: VPN 연결 종료 시, 위에서 추가했던 iptables 규칙을 제거하여 서버의 네트워크 설정을 원래 상태로 복구합니다.
주의사항!
<서버_개인키_여기에_입력>
과<클라이언트_공개키_여기에_입력>
부분에 실제 키 값을 입력하세요.eth0
는 서버의 외부 네트워크 인터페이스 이름이므로, 실제 인터페이스 이름으로 변경해야 합니다.
4-5. IP 포워딩 활성화
서버에서 VPN을 통해 외부 네트워크에 접속하려면 IP 포워딩을 활성홰해야 합니다!
일시적 활성화
sudo sysctl -w net.ipv4.ip_forward=1
영구적 활성화
/etc/sysctl.conf
파일에서 아래 라인을 수정(또는 추가)합니다.
net.ipv4.ip_forward = 1
그리고 변경 사항을 적용해줘요!
sudo sysctl -p
4-6. wireguard 인터페이스 재시작
구성이 완료되면 다음 명령어로 인터페이스를 활성화합니다!
sudo wg-quick up wg0
상태 확인은 아래 명령어를 실행해보세요.
sudo wg
인터페이스를 중지하려면 다음 명령을 실행해 중지해주세요.
sudo wg-quick down wg0
5. wireguard-ui를 활용해 클라이언트 키 생성하기
wireguard 설정을 웹 UI로 관리할 수 있는 wireguard-ui를 사용하면,
브라우저 상에서 손쉽게 피어(클라이언트) 추가 및 키 생성이 가능합니다!
5-1. 주의사항
wiregurad-ui
를 사용하는 경우,
이전에 사용하던 /etc/wireguard/wg0.conf
파일은 wireguard-ui
에서 설정한 내용으로 새롭게 덧씌워집니다!
5-2. 사전 준비
- Docker 설치: Docker 및 Docker Compose가 설치되어 있어야 합니다.
- WireGuard 설정 디렉터리: 서버의
/etc/wireguard
디렉터리를 사용합니다. - 필요 권한: 컨테이너에
NET_ADMIN
,SYS_MODULE
권한을 부여해야 합니다.
5-3. wireguard-ui 설치하기
- 최신 설치 코드는 다음 링크를 참고하세요!
도커 컴포즈를 사용하는 경우 아래 명령어를 실행하여 도커 컴포즈를 다운로드 받으세요!
wget -O docker-compose.yaml https://raw.githubusercontent.com/ngoduykhanh/wireguard-ui/refs/heads/master/docker-compose.yaml
옵션 설명
-p 5000:5000
: 컨테이너의 5000번 포트를 호스트에 노출합니다./etc/wireguard:/etc/wireguard
: 서버의 WireGuard 설정 파일 디렉터리를 컨테이너와 공유합니다../db:/app/db
: wireguard-ui의 데이터(피어 목록 등)를 저장할 로컬 디렉터리입니다. 실제 경로로 변경하세요.--cap-add=NET_ADMIN
: 네트워크 및 모듈 관리 권한 부여
5-4. 서버 설정 수정하기
이전에 서버 구성 파일 작성 챕터에서 /etc/wireguard/wg0.conf
파일에 직접 코드를 작성했었죠?
wiregurad-ui
에서는 웹 UI에서 변경해야 합니다!
실제로 wireguard-ui
를 실행하고 /etc/wireguard/wg0.conf
파일 상단을 보면
아래와 같이 파일을 직접 수정하지 말라고 되어있어요!
# This file was generated using wireguard-ui (https://github.com/ngoduykhanh/wireguard-ui)
# Please don't modify it manually, otherwise your change might get replaced.
서버 설정은 웹 UI로 이동한 후에, Wireguard Server 탭으로 이동하여
서버 구성 파일 작성에서 작성했던 내용 그대로 작성해주고
우측 상단에 Appliy config
버튼을 눌러주면 됩니다 !~
5-5. 키 생성
키 생성 파트에서
클라이언트에서 별도로 키를 생성 한 후,
그 공개키를 서버의 /etc/wireguard/wg0.conf
파일 내 [Peer]
섹션에 직접 입력 설정 값들을 입력했었는데요!
[Peer]
PublicKey = 클라이언트에서_생성한_공개키
AllowedIPs = 10.0.0.2/32
wireguard-ui
는 웹 UI를 통해 피어(클라이언트)를 자동으로 추가할 수 있도록 도와주니까
위처럼 수동으로 작성할 필요는 없어요!
[Peer] 섹션
- 서버의
/etc/wireguard/wg0.conf
파일은 초기 [Interface] 설정만 수동으로 작성해두고, 피어에 관한 부분은 wireguard-ui가 추가하도록 할 수 있습니다.- 즉, wireguard-ui에서 새 피어를 추가하면 해당 피어의 공개키, 내부 IP, 기타 필요한 옵션들이 자동으로 [Peer] 섹션에 기록됩니다.
그럼 이제 키 생성 방법에 대해서 알아볼까요?
웹 인터페이스 접속
브라우저에서 wireguard-ui에 접속합니다.
피어 추가
UI 상단의 Wireguard Clients를 눌러 이동해주세요!
키 생성
New Client
버튼을 눌러 새로운 클라이언트를 생성해봅시다!
IP Allocation
은 VPN에 접속했을 때 할당받을 나의 IP 주소로 입력해주시면 됩니다!
5-5-1. AllowedIPs
그리고 밑에 Allowed IPs
에 기본 값으로 0.0.0.0/0
으로 설정이 되어있을텐데요
AllowedIPs 설정은 Wireguard의 라우팅 및 트래픽 제어에 핵심 역할을 해요!
AllowedIPs의 역할을 확인해볼까요?
라우팅 정보
- AllowedIPs에 지정된 IP 대역은 해당 피어를 통해 전달해야 하는 트래픽의 목적지를 의미합니다.
- 예를 들어, 클라이언트 피어의 AllowedIPs에
10.0.0.0/24
가 있다면, 서버는 이 대역으로 향하는 모든 패킷을 VPN 터널로 보내게 됩니다.
액세스 제어
- 또한, 어떤 피어가 어떤 IP 대역에 접근할 수 있는지를 결정하는 ACL(Access Control List) 역할도 합니다.
참고로 주의사항도 존재합니다!
0.0.0.0/0
을 설정하게 되면 다음과 같은 문제가 발생할 수 있어요! 잘 읽어보세요.
- 만약 서버의 피어 설정(클라이언트에 대한 AllowedIPs)을 0.0.0.0/0으로 지정하면, WireGuard는 해당 피어가 “모든 IP 주소”를 소유하고 있다고 인식합니다.
- 그 결과, 서버는 내부 LAN(예: 10.0.0.0/24)이나 외부 인터넷으로 가는 모든 트래픽을 그 피어로 보내려고 시도합니다.
올바른 트래픽 분배 불가
- 일반적으로 서버에서는 피어마다 고유의 VPN IP (예: 10.0.0.3/32)를 할당합니다.
- 0.0.0.0/0로 설정하면, 서버는 “어떤 목적지든” 해당 피어에게 전달하게 되어, 다른 네트워크(내부 LAN 또는 인터넷)로의 올바른 라우팅이 이루어지지 않습니다.
결과
- VPN 클라이언트가 내부망이나 외부망에 접근하려 할 때, 서버는 모든 트래픽을 그 클라이언트로 보내므로, 다른 경로(내부 LAN의 다른 장비나 인터넷 게이트웨이)로 전달되지 않아 통신이 이루어지지 않게 됩니다.
이제 생성하면 다음과 같이 클라이언트 키 파일 목록이 뜰거에요!
5-6. wg0 인터페이스 재시작!
wireguard-ui
웹 UI에서 서버 설정을 완료하고, 클라이언트 생성까지 마쳤다면 /etc/wireguard/wg0.conf
에
새로운 설정이 저장되었을텐데요!
이를 wg0
인터페이스에 반영하기 위해서 아래 명령어를 실행해줍시다.
wg-quick down wg0
wg-quick up wg0
6. 접속 테스트
이제 모든 설정이 끝났다면,
내부망에 정상적으로 접근할 수 있는지 테스트를 해봐야겠죠?
wireguard-ui
웹 UI에서 클라이언트 키 파일을 다운로드 받고
wireguard client 프로그램을 다운로드 받은 후에 해당 키 파일을 넣어 내부망에 접속해보도록 합시다!
저는 Iphone에서 wireguard 클라이언트 프로그램을 다운로드 받고 접속한 상태에서
VPN 서버의 터미널로 이동하여 wg
명령을 사용해봤습니다. (Peer 상태 확인 가능해요)
그리고 Peer 접속 현황은 웹 UI의 Status 탭에서도 확인 가능해요!