베지밀

[VPN 프로젝트] 리눅스 서버 간 WireGuard VPN 구성 본문

대외활동/KISIA

[VPN 프로젝트] 리눅스 서버 간 WireGuard VPN 구성

vegimil 2024. 11. 12. 22:45

WireGuard란?

 

https://www.wireguard.com/

WireGuard는 최근 등장한 새로운 VPN 프로토콜로, 기존 VPN과 달리 코드 라인 수가 4000줄 정도로 간결하다는 특징이 있다.

 

WireGuard의 특징?

  1. 암호화 프로토콜은 ChaCha20, Poly1305, Curve25519로 고정되어있다.
    사전 공유키 방식을 사용하며, 최신 암호화 프로토콜로 안전하고 빠른 암/복호화가 가능하다.
  2. UDP에서만 동작하며, IPv6도 지원이 가능하다.
    UDP를 사용하기 때문에 가볍고 빠르다는 장점이 있다.
  3. 사전 공유키 방식을 활용한 단순한 키 교환 프로세스를 사용한다.
    기존 VPN과 달리 단 한 번의 요청/응답으로 키를 교환할 수 있다.
  4. 커널 수준에서 작동하기 때문에 높은 성능과 효율성을 가진다.
  5. 관리가 용이하다.
    SSO 인증 없이 공개키로 Peer를 증명하기 때문에 사용성이 좋다.

 

 

이제 동일 호스트 내에서 리눅스 가상머신 2대를 띄워 WireGuard 통신 설정을 해보자.

 

 

환경 구성
> 서버(왼) : 우분투 10.10.10.10 / VPN IP 192.168.10.1
> 클라이언트(오) : 우분투 10.10.10.13 / VPN IP 192.168.10.2

 

 

0. WireGuard 설치

서버/클라이언트 간 다음 명령을 통해 WireGuard를 설치한다.

sudo apt update
sudo apt install wireguard

 

1. 키 생성

서버

umask 077
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key

# 생성된 키 확인
root@server:/etc/wireguard# cat private.key
wN+x3PUvRvVZeQd4cmICBajU1LzH24gx3tZaDEFvXW4=

root@server:/etc/wireguard# cat public.key
vxP5k8DH032NlDdJaWZZVgMhplDfYx+E0+J/rA8SASI=

 

클라이언트

umask 077
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key

# 생성된 키 확인
root@client:/etc/wireguard# cat private.key
GITuyew7XWuDKpJ3ZjRHoW1RiLxqbgm1GDb0MCMtpno=

root@client:/etc/wireguard# cat public.key
KLb8N1dqlxTZOzJLBEyJp9xmdv9W7E6PooZkPMH+nUM=

 

 

📌umask 077을 하는 이유?

  • umask는 파일 생성 시 기본 권한에서 특정 권한을 제거하는 마스크값
    • 디렉터리 777과 파일 666의 기본 권한에서 077을 하면 사용자 이외의 권한(그룹/기타 사용자)를 없앨 수 있다.
    • umask를 적용하면 경로와 무관하게 적용 후 생성되는 모든 파일과 디렉토리에 권한이 적용된다.

 

  • WireGuard에서 비밀키는 절대 알려져선 안된다!
    • 비밀키가 유출되면 VPN 서버/클라이언트에 대한 접근 권한을 잃어버림
    • 따라서 umask 077을 통해 파일을 생성해서 다른 사용자가 접근하지 못하도록 제한해야 함

 

2. 설정 파일 구성 (/etc/wireguard/wg0.conf)

[Interface] : 호스트의 IP 주소, 비밀키, 수신 대기 포트를 설정한다.

이 때, Address는 VPN에 사용할 가상 ip 주소로, 사설 ip 대역 중 임의로 설정한다.

 

iptables를 통해 wg0 인터페이스 활성화 시 포워딩을 위해 필요한 NAT 설정을 해준다.

eth0, enp0s3, ens33 등 호스트가 vpn 통신에 사용할 인터페이스 이름을 입력한다.

 

[Peer]는 상대방과의 연결 정보에 대해 설정하는 부분이다. 상대방의 공개키와 ip를 입력한다.

 

서버

[Interface]
Address = 192.168.10.1/24                   		# 서버의 VPN IP 주소
SaveConfig = true                       			# WireGuard 종료 시 설정을 저장 (선택 사항)
PrivateKey = wN+x3PUvRvVZeQd4cmICBajU1LzH24gx3tZaDEFvXW4=    # 서버의 비밀키 (wg genkey로 생성)
ListenPort = 51820                      			# 서버가 수신 대기할 포트

# NAT 설정 및 트래픽 포워딩을 위한 iptables 규칙
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens33 -j MASQUERADE

[Peer]
PublicKey = KLb8N1dqlxTZOzJLBEyJp9xmdv9W7E6PooZkPMH+nUM=   	# 클라이언트의 공개키
AllowedIPs = 192.168.10.2/32                 				# 클라이언트의 VPN IP 주소

 

 

클라이언트

[Interface]
Address = 192.168.10.2/24                				    # 클라이언트의 VPN IP 주소
PrivateKey = GITuyew7XWuDKpJ3ZjRHoW1RiLxqbgm1GDb0MCMtpno=   # 클라이언트의 비밀키 (wg genkey로 생성)
DNS = 8.8.8.8                           					# (선택 사항) VPN 연결 시 사용할 DNS 서버 주소

[Peer]
PublicKey = vxP5k8DH032NlDdJaWZZVgMhplDfYx+E0+J/rA8SASI=    # 서버의 공개키
Endpoint = 10.10.10.10:51820    							# 서버의 IP 주소 및 포트 번호
AllowedIPs = 0.0.0.0/0, ::/0           						# 전체 트래픽을 VPN을 통해 전송 (라우팅 설정)
PersistentKeepalive = 25              						# 연결이 유지되도록 keepalive 설정 (NAT 환경에서 유용)

 

 

3. 설정 파일 적용

서버/클라이언트 모두 다음 명령을 통해 wg 서비스를 적용한다.

sudo wg-quick up wg0
sudo wg show

sudo wg show 결과, 2번에서 설정한 파일 내용이 보이면 성공

 

 

4. 방화벽 설정

wireguard 포트를 방화벽에서 허용해야 클라이언트가 서버에 접근할 수 있다.

서버-클라이언트 구조로 테스트할 것이므로 서버에만 설정해도 좋다.

 

sudo ufw allow 51820/udp
sudo ufw reload

51820/udp로의 연결을 허용하고 방화벽을 재실행했다.