개요
이번 포스팅에서는 Wireguard의 기본 개념, VPN 피어(Peer), 내부 IP 주소에 대해서 간략하게 알아보고,
리눅스 기반의 환경에서 Wireguard를 설치하고 구축하는 방법에 대해서 자세하게 기록해볼겁니다!
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
파일을 불러와서 연결해주면 됩니다!
마무리
지금까지 리눅스 환경에서 Wireguard를 설치하고 설정하는 방법에 대해서 익혔습니다!
근데 이제 매번 클라이언트별 설정 파일을 CLI로 생성해주는게 너무 귀찮다고 생각이 들지 않으시나요?
물론 이러한 과정을 해결하기 위해 제 스스로 fzf
도구를 사용하여 쉘 스크립트를 나름 구축도 했었습니다만,
역시 UI가 있어야 편하겠더라구요!
그래서 이러한 고민을 단번에 해결할 수 있는 유익한 게시글을 추가로 작성하였습니다!
바로 wireguard-ui
라는 프로젝트를 활용하는건데
자세한 내용은 해당 게시글을 참고해주세요!