- Published on
와이어가드 VPN 구축 오픈VPN보다 빠르고 가벼운 VPN 서버 만들기
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
VPN을 처음 구축할 때 많은 사람이 OpenVPN부터 떠올립니다. 기능은 풍부하지만 설정 파일이 길고, TLS/인증서 체인 관리가 번거롭고, 성능 튜닝 포인트도 많습니다. 반면 WireGuard는 “필요한 것만” 남긴 설계 덕분에 설정이 짧고, 커널 레벨에서 동작해 빠르고 가볍게 운영할 수 있습니다.
이 글에서는 Ubuntu 서버(예: VPS, EC2, 베어메탈)에서 WireGuard VPN을 구축해 외부에서 집/사내 네트워크로 안전하게 접속하거나, 클라이언트 트래픽을 서버를 통해 라우팅(Full tunnel) 하는 방법을 다룹니다. 중간중간 실제로 자주 터지는 문제(핸드셰이크는 되는데 인터넷이 안 됨, DNS가 안 됨, 모바일에서만 안 됨 등)도 함께 해결합니다.
인프라를 코드로 만들고 싶다면 VPC/보안그룹/EC2를 자동화하는 글도 함께 보면 좋습니다: 테라폼으로 AWS 인프라 자동화 VPC와 EC2를 클릭 없이 만드는 실전 가이드
WireGuard가 OpenVPN보다 실전에서 편한 이유
1) 설정이 단순하다
WireGuard는 기본적으로 키 기반(공개키/개인키) 이고, “피어(peer) 목록”만 선언하면 됩니다.
- 서버: 어떤 포트로 듣고(UDP), 어떤 IP 대역을 줄지
- 클라이언트: 서버의 공개키/엔드포인트, 내가 사용할 터널 IP, 어떤 트래픽을 터널로 보낼지
2) 성능이 좋다
- UDP 기반 + 간결한 프로토콜
- Linux에서는 커널 모듈로 동작(대부분 배포판에서 기본 제공)
3) 운영이 쉽다
wg show한 방으로 현재 피어 상태/트래픽/핸드셰이크 시간을 확인 가능- 설정 파일이 짧아 실수 지점이 줄어듦
목표 아키텍처
- 서버 OS: Ubuntu 22.04/24.04 LTS 가정
- WireGuard 인터페이스:
wg0 - VPN 대역:
10.8.0.0/24- 서버:
10.8.0.1 - 클라이언트1:
10.8.0.2
- 서버:
- 서버 WireGuard 포트:
51820/udp
두 가지 사용 시나리오를 모두 커버합니다.
- Split tunnel: 사내/집 내부망(예:
192.168.0.0/24)만 VPN으로 - Full tunnel: 모든 인터넷 트래픽을 VPN 서버로
서버 구축 (Ubuntu)
1) 설치
sudo apt update
sudo apt install -y wireguard
커널 모듈/툴이 설치되며, wg, wg-quick 명령을 사용할 수 있습니다.
2) 키 생성
sudo -i
umask 077
wg genkey | tee /etc/wireguard/server.key | wg pubkey > /etc/wireguard/server.pub
cat /etc/wireguard/server.pub
server.key: 서버 개인키(절대 외부 유출 금지)server.pub: 클라이언트에 배포할 서버 공개키
3) IP 포워딩 활성화
VPN 서버를 라우터처럼 쓰려면 포워딩이 필요합니다.
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
IPv6도 쓸 경우:
echo 'net.ipv6.conf.all.forwarding=1' | sudo tee -a /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
4) 서버 설정 파일 작성
/etc/wireguard/wg0.conf:
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>
# NAT(Full tunnel용): wg0로 들어온 트래픽을 서버의 공인망 인터페이스로 마스커레이드
# 아래 eth0는 환경에 따라 ens3, ens5, enp0s1 등으로 바뀔 수 있습니다.
PostUp = iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
# (선택) 포워딩 허용 규칙을 wg-quick에 묶어서 관리하고 싶다면
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT
eth0는 반드시 실제 외부 인터페이스로 바꾸세요.ip route | grep default예:
default via ... dev ens3라면-o ens3.
nftables/ufw를 쓰는 경우
- Ubuntu에서 UFW 사용 시, 기본적으로 iptables 백엔드(nft)로 동작하므로 위 규칙이 대부분 잘 먹습니다.
- 다만 UFW에서 포워딩 정책이 DROP이면 트래픽이 막힙니다. 아래 “트러블슈팅” 참고.
5) 서버 기동
sudo systemctl enable --now wg-quick@wg0
sudo wg show
sudo ip a show wg0
6) 방화벽/보안그룹 열기
서버에 UDP 51820 인바운드를 열어야 합니다.
- 클라우드(예: AWS): Security Group 인바운드
UDP 51820허용 - 서버 방화벽(UFW):
sudo ufw allow 51820/udp
sudo ufw status
클라이언트 추가 (PC/모바일 공통)
1) 클라이언트 키 생성
클라이언트 장치에서 생성하는 것이 가장 안전합니다.
Linux/macOS:
umask 077
wg genkey | tee client1.key | wg pubkey > client1.pub
cat client1.pub
Windows/모바일은 WireGuard 앱에서 “Add tunnel” 시 자동 생성 가능.
2) 서버에 피어 등록
서버의 /etc/wireguard/wg0.conf에 아래를 추가합니다.
[Peer]
PublicKey = <CLIENT1_PUBLIC_KEY>
AllowedIPs = 10.8.0.2/32
적용:
sudo wg syncconf wg0 <(wg-quick strip wg0)
sudo wg show
wg-quick down/up으로 재기동해도 되지만, 운영 중에는syncconf가 깔끔합니다.
3) 클라이언트 설정 파일
(A) Split tunnel 예시 (내부망만 VPN)
예를 들어 서버 뒤쪽 사설망이 192.168.0.0/24이고, 그쪽 자원(NAS, DB, 내부 서비스)만 접근하고 싶다면:
[Interface]
PrivateKey = <CLIENT1_PRIVATE_KEY>
Address = 10.8.0.2/32
DNS = 1.1.1.1
[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = <SERVER_PUBLIC_IP_OR_DNS>:51820
AllowedIPs = 10.8.0.0/24, 192.168.0.0/24
PersistentKeepalive = 25
AllowedIPs가 “어떤 목적지로 가는 트래픽을 이 터널로 보낼지”를 결정합니다.- NAT 환경(모바일/공유기 뒤)에서는
PersistentKeepalive=25가 연결 안정성에 도움이 됩니다.
(B) Full tunnel 예시 (모든 트래픽 VPN)
[Interface]
PrivateKey = <CLIENT1_PRIVATE_KEY>
Address = 10.8.0.2/32
DNS = 1.1.1.1
[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = <SERVER_PUBLIC_IP_OR_DNS>:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
- 이 경우 서버에서 NAT(MASQUERADE) + 포워딩이 제대로 되어야 인터넷이 됩니다.
동작 확인 체크리스트
서버에서
sudo wg show
확인 포인트:
latest handshake: 최근 시간이 찍히는지transfer: RX/TX가 증가하는지
클라이언트에서
10.8.0.1ping- 내부망 접근(Split tunnel일 때):
ping 192.168.0.10같은 대상 - Full tunnel일 때:
curl ifconfig.me로 공인 IP가 서버로 바뀌는지
트러블슈팅: “연결은 되는데 인터넷/내부망이 안 된다”
WireGuard는 “터널 자체”는 쉽게 붙지만, 라우팅/포워딩/NAT/DNS 중 하나만 어긋나도 체감상 “안 됨”이 됩니다.
1) 핸드셰이크가 안 잡힘
증상:
wg show에latest handshake: (none)
원인/해결:
- 서버 인바운드 UDP 51820 미오픈 (클라우드 보안그룹 포함)
- Endpoint IP/DNS 오타
- 서버가 NAT 뒤에 있고 포트포워딩이 안 됨
- 시간 동기 문제는 드물지만, 서버/클라 시간 오차가 심하면 문제될 수 있음(NTP 확인)
2) 핸드셰이크는 되는데 Full tunnel에서 인터넷이 안 됨
증상:
latest handshake는 갱신됨ping 10.8.0.1은 됨- 그런데 웹이 안 열림
점검 순서:
- 서버 IP 포워딩:
sysctl net.ipv4.ip_forward
= 1이어야 합니다.
- NAT 규칙 확인:
sudo iptables -t nat -S POSTROUTING | grep MASQUERADE
규칙이 없거나, -o eth0 인터페이스명이 틀린 경우가 많습니다.
- FORWARD 정책/방화벽:
- UFW 사용 시
/etc/default/ufw에서DEFAULT_FORWARD_POLICY="ACCEPT"필요할 수 있습니다. - 또는 UFW에 라우팅 허용 규칙 추가:
sudo ufw route allow in on wg0 out on eth0
sudo ufw route allow in on eth0 out on wg0
- 클라이언트 AllowedIPs:
- Full tunnel은
0.0.0.0/0 - Split tunnel은 필요한 대역만 포함
3) DNS만 안 됨
증상:
- IP로는 접속되는데 도메인은 실패
해결:
- 클라이언트 설정에
DNS = 1.1.1.1또는 사내 DNS 지정 - 사내 DNS를 쓰려면 Split tunnel에서 해당 DNS 서버 IP가
AllowedIPs에 포함되어야 함
4) 특정 클라이언트만 접속이 불안정(특히 모바일)
해결:
PersistentKeepalive = 25추가- 모바일 데이터/공유기 NAT가 세션을 빨리 끊는 환경에서 효과적
5) 여러 클라이언트가 같은 터널 IP를 씀
증상:
- 한쪽이 붙으면 다른 쪽이 끊기거나, 트래픽이 엉킴
해결:
- 각 피어는 반드시 고유한
Address(예:10.8.0.2/32,10.8.0.3/32) - 서버의 각
[Peer] AllowedIPs도 각각/32로 분리
Best Practice: 운영 관점에서 꼭 챙길 것
1) 키/설정 파일 권한
sudo chmod 600 /etc/wireguard/*.key
sudo chmod 600 /etc/wireguard/wg0.conf
2) 피어 추가/삭제 자동화
피어가 많아지면 수작업이 실수로 이어집니다.
- 간단히는 “클라이언트별 템플릿 + IP 할당 규칙”을 문서화
- 더 나아가면 Ansible/Terraform(인스턴스/보안그룹) + 스크립트로 프로비저닝
3) 라우팅 정책을 명확히
- Split tunnel은 필요한 대역만
AllowedIPs에 넣어 “업무/개발용 접근”에 적합 - Full tunnel은 공용 와이파이/해외망에서 보안 강화에 적합하지만, 서버 트래픽 비용/대역폭 고려 필요
4) 모니터링
wg show로 마지막 핸드셰이크 시간, 전송량 확인- 시스템 레벨에서는
journalctl -u wg-quick@wg0로 장애 분석
결론: WireGuard는 “작게 시작해서 안정적으로 키우기” 좋은 VPN
WireGuard는 OpenVPN에 비해 설정이 훨씬 짧고, 성능과 운영 편의성이 뛰어나 개인/팀 단위 VPN에 특히 잘 맞습니다.
핵심만 요약하면:
- 서버는
wg0.conf+ IP 포워딩 + (Full tunnel이면) NAT(MASQUERADE) 가 필수 - 클라이언트는
AllowedIPs로 Split/Full을 결정 - 핸드셰이크는 되는데 통신이 안 되면 대부분 인터페이스명, 포워딩, 방화벽(UFW), DNS 문제
이 구성으로 먼저 1~2명의 클라이언트를 붙여 안정화한 뒤, 피어 추가 자동화와 모니터링을 붙이면 “가볍지만 강한” VPN을 운영할 수 있습니다.