개요
애플리케이션 기반 서비스를 개발하는 과정에서, 클라우드 서비스에 서버를 배포하게 되었다.
하지만 IP 포트 개방 규제 때문에, 한정적인 IP 주소로만 접속이 가능한 상황이어서, 모바일 환경에서의 테스트에 제약이 생기게 되었다.
따라서 모바일 환경에서도 쉽게 테스트를 할 수 있도록 VPN 서버를 구축하게 되었다.
0. 사전 작업
0.1. IP Forwarding 활성화
# 설정 파일 수정
sudo nano /etc/sysctl.conf
# 아래 줄 추가 또는 주석 해제
net.ipv4.ip_forward=1
# 적용
sudo sysctl -p
0.2. 방화벽 설정
# WireGuard 포트 열기
# 클라우드 환경이라면 클라우드의 방화벽 허용
sudo ufw allow 51820/udp
1. VPN 서버 구축
1.1. wireguard 도구 설치
sudo apt update
sudo apt install wireguard
1.2. 키 생성
# 서버 키 생성
sudo sh -c 'umask 077 && wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key'
# 생성 된 키 확인
Server key
ubuntu@medeasy:~$ sudo cat /etc/wireguard/server_private.key
<server private key>
ubuntu@medeasy:~$ sudo cat /etc/wireguard/server_public.key
<server public key>
ubuntu@medeasy:~$
# 클라이언트 키 생성
sudo sh -c 'umask 077 && wg genkey | tee /etc/wireguard/client1_private.key | wg pubkey > /etc/wireguard/client1_public.key'
# 생성된 키 확인
Client key
ubuntu@medeasy:~$ sudo cat /etc/wireguard/client1_public.key
<client public key>
ubuntu@medeasy:~$ sudo cat /etc/wireguard/client1_private.key
<client private key>
1.3. 서버 설정 파일 작성
wireguard 설정 파일은 전부 /etc/wireguard 경로에 존재한다.
sudo vi /etc/wireguard/wg0.conf
네트워크 인터페이스 확인
패킷을 적절하게 전달하기 위해 네트워크 인터페이스를 확인한다.
ip a
wg0.conf:
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <server private key>
# IP forwarding 설정
# 1. wg0에서 들어오는 패킷 포워딩 허용
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
# 2. wg0로 나가는 패킷 포워딩 허용
PostUp = iptables -A FORWARD -o wg0 -j ACCEPT
# 3. ens4로 나가는 패킷에 NAT 적용 (소스 IP를 VPN 서버 IP로 변경)
PostUp = iptables -t nat -A POSTROUTING -o ens4 -j MASQUERADE
# 4. 이미 연결된(ESTABLISHED) 또는 관련된(RELATED) 패킷 허용
PostUp = iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# iptables 규칙 비활성화
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -D FORWARD -o wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o ens4 -j MASQUERADE
PostDown = iptables -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# 클라이언트1 (나중에 추가)
[Peer]
PublicKey = <client public key>
AllowedIPs = 10.0.0.2/32
상세설명
- interface: VPN 클라이언트와 통신할 interface 정의
- postup/down: wireguard 실행 시 iptables 규칙 설정, NAT 적용
- 클라이언트 → VPN Server → 목적지의 흐름에서 소스의 요청 IP(10.0.0.2)를 외부 목적지에서는 파악할 수 없기 때문에 VPN Server IP로 MASQUERADE한다.
- conntract(connection tracking)를 통해 연결 추적 → 응답 반환시 목적 IP 다시 변환
- ESTABLISHED: 연결된 상태에서는 패킷에 대해 검사 PASS 설정
전체흐름
IP Forwarding (커널 기능)
↓ 활성화됨
iptables FORWARD 규칙
↓ 트래픽 제어
iptables NAT MASQUERADE
↓ 소스 IP 변환
패킷 전달 완료
NAT 적용 흐름
1. 나갈 때 (POSTROUTING):
소스: 10.0.0.2 → 203.0.113.50 (VPN 서버 공인 IP)
목적지: 198.51.100.10 (목적지 서버)
2. 목적지 서버가 보는 것:
"203.0.113.50에서 요청이 왔네!"
3. 목적지 서버 응답:
소스: 198.51.100.10
목적지: 203.0.113.50 ← 라우팅 가능!
4. 들어올 때 (역변환):
목적지: 203.0.113.50 → 10.0.0.2
소스: 198.51.100.10
2. VPN 연결 설정
2.1. 클라이언트 연결 설정 파일 작성
*# 클라이언트 설정 파일 생성*
sudo nano /etc/wireguard/client1.conf
client1.conf :
[Interface]
PrivateKey = <client_private.key 내용>
Address = 10.0.0.2/32
DNS = 8.8.8.8
MTU = 1280
[Peer]
PublicKey = <server_public.key 내용>
Endpoint = <이 VPN 서버의 공인 IP>:51820
AllowedIPs = 10.0.0.0/24, <VPN 서버를 통해 요청을 보낼 목적지>
PersistentKeepalive = 25
상세내용
- PrivateKey: 클라이언트의 private key, wg0.conf파일에 등록된 client public key와 매칭된다.
- Address: Client의 IP주소 설정, wg0.conf의 Peer 설정과 일치해야함.
- EndPoint: Peer의 위치 명시
- AllowdIPs:
- 어떤 요청을 Peer에게 보낼지 명시
- 명시한 네트워크로 요청을 보낼 때만 VPN 서버를 거침
- 일반 인터넷의 경우 본 클라이언트 인터넷 사용
- VPN 서버와의 연결을 위해 가상 네트워크 추가 명시
- PersistentKeepalive: 세션 유지 health check 주기
필요한 정보:
*# 서버 public key 확인*
sudo cat /etc/wireguard/server_public.key
*# VPN 서버 공인 IP 확인*
curl ifconfig.me
추가. MTU 설정 주의
MTU(Maximum Transmission Unit)는 네트워크에서 한 번에 전송할 수 있는 패킷의 최대 크기이다.
네트워크 상 경로에서 하나의 요소라도 MTU의 값이 작다면, 패킷이 전달되는 과정에서 분할(fragmentation)과정이 필요하다.
하지만 WireGuard는 패킷을 암호화하여 전달하기 때문에, 무결성 문제로 분할을 하지 못하고 드롭한다.
예를 들어, 웹 백엔드 애플리케이션의 Swagger URL를 호출하였을 때, html, css 파일은 정상적으로 받으나, js의 파일이 누락되어, 페이지 로딩에 실패할 수 있다.
이 문제를 해결하기 위해, 경로상 가장 작은 MTU 값 1280으로 설정하여, 문제를 해결한다.
3. VPN 활성화
앞서 작성한 클라이언트 설정 파일을 통해 VPN에 접속, 요청 테스트를 진행할 예정이다.
3.1. WireGuard 시작
# 이미 실행되어 있다면 종료
sudo wg-quick down wg0
# 시작
sudo wg-quick up wg0
# 부팅 시 자동 시작 설정
sudo systemctl enable wg-quick@wg0
# WireGuard 상태 확인
sudo wg show
# 인터페이스 확인 (wg0가 보여야 함)
ip a | grep wg0
# *추가* 재시작 없이 적용, interface 설정 적용은 불가능하나, Peer 추가/제거에 무중단 적용 가능
# 방법 1: 절대 경로 사용
sudo wg syncconf wg0 <(wg-quick strip /etc/wireguard/wg0.conf)
# 방법 2: bash 명시
sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'
3.2. QR 코드 생성 (모바일용 - 가장 쉬움)
개발하고 있는 시스템이 모바일 앱환경에서 실행되기 때문에, 제일 먼저 모바일 환경에서 VPN에 접속할 수 있어야 한다. 따라서 먼저 WireGuard(aos, ios)를 설치하고, VPN 서버에서 QR 코드를 생성하여 촬영 → 연결해준다.
*# qrencode 설치*
sudo apt install qrencode
*# QR 코드 생성*
sudo sh -c 'qrencode -t ansiutf8 < /etc/wireguard/client2.conf'
세부단계:
- WireGuard 앱 설치
- iOS: App Store에서 "WireGuard"
- Android: Play Store에서 "WireGuard"
- 앱 실행 → "+" 버튼 → "QR 코드 스캔"
- 위에서 생성한 QR 코드를 스캔
- 연결 버튼 클릭
3.3. 컴퓨터에서 연결
방법 A: 파일 다운로드
*# client1.conf 파일 내용 복사*
sudo cat /etc/wireguard/client1.conf
이 내용을 복사해서:
- Windows/Mac: 로컬에 client1.conf 파일로 저장
- WireGuard 앱 설치 후 "Import from file"
방법 B: 직접 전송
*#SCP로 파일 다운로드 (로컬 컴퓨터에서 실행)*
scp ubuntu@<서버IP>:/etc/wireguard/client1.conf ./
4. 연결 테스트
VPN 연결 후 가상 네트워크에 잘 속해있는지, 연결이 잘 전달되는지 테스트할 예정이다.
4.1. VPN 서버 Ping 테스트
가상 네트워크에 잘 접속되었는지 확인한다.
# 내부 네트워크가 잘 설정되었는지 확인한다.
# window powershell
ipconfig
# linux, mac
ifconfig
# VPN 서버로 연결이 잘 되는지 확인
ping 10.0.0.1
4.2. VPN 서버 모니터링
VPN 서버에서 패킷이 잘 들어오고 나가는 과정을 모니터링하여, 정상 연결을 확인한다.
# 1. 클라이언트로부터 패킷이 잘 전달되는지 테스트
sudo tcpdump -i wg0 -n host 10.0.0.2
# 2. 패킷 전달 후 목적지로부터 응답이 잘 도착하는지 테스트
sudo tcpdump -i ens4 -n host 목적지IP
'Linux' 카테고리의 다른 글
| GCP 로드밸런서 HTTPS 적용 (2) | 2025.03.27 |
|---|