CentOS 8에 WireGuard VPN 설치 및 구성

요약
- WireGuard는 빠르고 간단한 현대적 VPN 프로토콜입니다.
- 이 가이드는 CentOS 8 기준입니다(클라이언트는 CentOS/Fedora/Ubuntu 등 리눅스 계열).
- 핵심 단계: 시스템 업데이트 → EPEL/PowerTools 활성화 → WireGuard 설치 → 키 생성 및 구성 → 방화벽 설정 → IPv4 포워딩 → 서비스 시작 → 클라이언트 설정 → 테스트 → 보안 강화.
전제 조건
- CentOS 8 서버에 루트 또는 sudo 권한이 있어야 합니다.
- 공용 IPv4 주소(예: 203.1.114.98)가 서버에 할당되어 있어야 합니다.
- 방화벽(dnf/firewalld)이 활성화된 상태를 가정합니다.
H2: 주요 용어 1문장 정의
- WireGuard: 현대적 암호 기반의 경량 VPN 구현체.
- Peer: WireGuard 구성에서의 참여자(서버 또는 클라이언트).
- AllowedIPs: 라우팅/ACL 역할을 하는 WireGuard의 주소 집합.
준비 체크리스트
- 시스템 백업 준비
- 포트(예: 37822) 사용 가능 여부 확인
- root/sudo 권한 확보
- 방화벽 및 네트워크 인터페이스 이름(예: eth0) 확인
1. 시스템 업데이트
먼저 시스템을 최신 상태로 업데이트합니다.
$ sudo dnf update
중요: 업데이트 후 커널 업그레이드가 있으면 재부팅을 권장합니다.
2. EPEL 및 PowerTools 저장소 활성화
WireGuard 패키지는 EPEL에 있으므로 EPEL과 PowerTools를 활성화합니다.
$ sudo dnf install epel-release
$ sudo dnf config-manager --set-enabled PowerTools
PowerTools는 EPEL 패키지 의존성 때문에 활성화합니다.
3. WireGuard 설치
Copr 저장소를 활성화한 뒤 WireGuard를 설치합니다.
$ sudo dnf copr enable jdoss/wireguard
$ sudo dnf install wireguard-dkms wireguard-tools
이 단계는 Linux 커널 모듈을 빌드하기 위해 GCC 컴파일러를 설치합니다.
4. 서버 구성(키 생성 및 wg0.conf)
WireGuard 설정 디렉터리 생성 및 권한 제한된 구성 파일을 만듭니다.
$ sudo mkdir /etc/wireguard
$ sudo sh -c 'umask 077; touch /etc/wireguard/wg0.conf'
키를 생성합니다.
$ cd /etc/wireguard
$ sudo sh -c 'umask 077; wg genkey | tee privatekey | wg pubkey > publickey'
개인 키를 확인합니다.
$ sudo cat privatekey
wg0.conf를 편집합니다.
$ sudo nano /etc/wireguard/wg0.conf
다음 내용을 추가합니다(예시는 설명용으로 실제 운영 시 개인키와 주소를 변경하세요).
[Interface]
## VPN server private IP address ##
Address = 192.168.10.1/24
## VPN server port - You can choose any port ##
ListenPort = 37822
## VPN server's private key i.e. /etc/wireguard/privatekey - the one from above ##
PrivateKey = GCEXafeZKqSsuLfvuHE+zLzMYwoH4qQyBh7MZ4f/3kM=
## Save and update this config file when a new peer (vpn client) added ##
SaveConfig = true
설명: [Interface] 섹션은 서버의 개인키, 리스닝 UDP 포트, VPN 내부 IP를 정의합니다. SaveConfig=true는 서비스 종료 시 활성 구성을 파일에 저장하게 합니다.
5. 방화벽 구성
WireGuard 포트를 방화벽에 등록하고 마스커레이드를 활성화합니다.
먼저 방화벽 서비스 파일을 만듭니다.
$ sudo nano /etc/firewalld/services/wireguard.xml
다음 내용을 붙여넣습니다(포트는 wg0.conf의 ListenPort와 일치시킵니다).
wireguard
WireGuard open UDP port 37822 for client connections
서비스를 방화벽에 추가합니다.
$ sudo firewall-cmd --permanent --add-service=wireguard
마스커레이스(출구 NAT)를 켭니다. 여기서는 내부 네트워크 192.168.10.0/24에서 나가는 트래픽을 서버의 공인 IP로 변환합니다.
$ sudo firewall-cmd --permanent --add-masquerade
방화벽을 다시 로드합니다.
$ sudo firewall-cmd --reload
현재 방화벽 규칙을 확인합니다.
$ sudo firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0
sources:
services: wireguard ssh
ports:
protocols:
masquerade: yes
forward-ports:
source-ports:
icmp-blocks:
rich rules:
Note: interfaces: eth0 등 네트워크 인터페이스 이름은 환경에 따라 다를 수 있습니다. 필요시 변경하세요.
6. IPv4 포워딩 활성화
sysctl 설정 파일을 만들어 포워딩 및 기본 튜닝을 설정합니다.
$ sudo nano /etc/sysctl.d/99-custom.conf
파일 내용(예시):
## Turn on bbr ##
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
## for IPv4 ##
net.ipv4.ip_forward = 1
## Turn on basic protection/security ##
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.tcp_syncookies = 1
## for IPv6 ##
net.ipv6.conf.all.forwarding = 1
변경 사항을 적용합니다.
$ sudo sysctl -p /etc/sysctl.d/99-custom.conf
WireGuard 인터페이스와 내부 네트워크를 연결합니다.
$ sudo firewall-cmd --add-interface=wg0 --zone=internal
$ sudo firewall-cmd --permanent --zone=internal --add-masquerade
7. WireGuard 서비스 활성화 및 시작
$ sudo systemctl enable wg-quick@wg0
$ sudo systemctl start wg-quick@wg0
상태 확인:
$ sudo wg
interface: wg0
public key: VWndJ4oB7ZJwC/7UOm++OLDrbAxMPsR2yd0cl3sEkUI=
private key: (hidden)
listening port: 37822
$ sudo ip a show wg0
3: wg0: mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
inet 192.168.10.1/24 scope global wg0
valid_lft forever preferred_lft forever
8. 클라이언트 설치 및 구성
클라이언트에 WireGuard를 설치한 뒤, 클라이언트 측에서 키를 생성하고 wg0.conf를 만듭니다.
$ sudo mkdir /etc/wireguard
$ sudo sh -c 'umask 077; touch /etc/wireguard/wg0.conf'
$ cd /etc/wireguard/
$ sudo sh -c 'umask 077; wg genkey | tee privatekey | wg pubkey > publickey'
$ sudo cat privatekey
클라이언트 wg0.conf 예시:
[Interface]
## client private key ##
PrivateKey = OEM6D/zt2fVWOepVv3iEDD430V0gAshKp4+5oVVt5EE=
## client ip address ##
Address = 192.168.10.2/24
[Peer]
## CentOS 8 server public key ##
PublicKey = VWndJ4oB7ZJwC/7UOm++OLDrbAxMPsR2yd0cl3sEkUI=
## set ACL ##
AllowedIPs = 192.168.10.0/24
## Your CentOS 8 server's public IPv4/IPv6 address and port ##
Endpoint = 203.1.114.98:37822
## Key connection alive ##
PersistentKeepalive = 15
PersistentKeepalive는 NAT 뒤에 있는 클라이언트가 UDP 세션을 유지하도록 주기적인 패킷을 보냅니다.
클라이언트에서 서비스 활성화:
$ sudo systemctl enable wg-quick@wg0
$ sudo systemctl start wg-quick@wg0
$ sudo systemctl status wg-quick@wg0
9. 서버에 클라이언트 추가
서버에 클라이언트의 공개키와 허용 IP를 추가합니다.
서비스를 중지한 뒤 wg0.conf를 편집하거나 wg set 명령으로 런타임에 추가할 수 있습니다.
파일 편집 방식:
$ sudo systemctl stop wg-quick@wg0
$ sudo nano /etc/wireguard/wg0.conf
파일 끝에 추가:
[Peer]
## client VPN public key ##
PublicKey = dmfO9pirB315slXOgxXtmrBwAqPy07C57EvPks1IKzA=
## client VPN IP address (note /32 subnet) ##
AllowedIPs = 192.168.10.2/32
런타임 방식(서비스 중에도 가능):
# publickey와 allowed_ips를 실제 값으로 교체
$ sudo wg set wg0 peer allowed-ips 192.168.10.2/32
설명: WireGuard는 공개키로 접속자를 인증합니다. 일치하는 공개키가 없으면 패킷은 무시됩니다.
서비스 재시작:
$ sudo systemctl start wg-quick@wg0
10. 연결 테스트
클라이언트에서 서버 내부 IP로 ping을 보냅니다.
$ ping -c 192.168.10.1
PING 192.168.10.1 (192.168.10.1) 56(84) bytes of data.
64 bytes from 192.168.10.1: icmp_seq=1 ttl=64 time=44.2 ms
64 bytes from 192.168.10.1: icmp_seq=2 ttl=64 time=45.8 ms
64 bytes from 192.168.10.1: icmp_seq=3 ttl=64 time=46.7 ms
64 bytes from 192.168.10.1: icmp_seq=4 ttl=64 time=44.1 ms
--- 192.168.10.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2800ms
rtt min/avg/max/mdev = 41.729/47.829/48.953/5.046 ms
$ sudo wg
interface: wg0
public key: dmfO9pirB315slXOgxXtmrBwAqPy07C57EvPks1IKzA=
private key: (hidden)
listening port:
peer: VWndJ4oB7ZJwC/7UOm++OLDrbAxMPsR2yd0cl3sEkUI=
endpoint: 203.1.114.98:37822
allowed ips: 192.168.10.0/24
latest handshake: 1 minute, 40 seconds ago
transfer: 938 B received, 45.67 KiB sent
persistent: keepalive: every 15 seconds
성공: ping 응답과 최근 핸드셰이크가 보이면 정상 연결입니다.
보안 강화 권장 사항
- 개인키 파일 권한을 600으로 제한하고 소유자를 root로 유지하세요.
- 관리 포트(예: 37822)는 방화벽으로 접근 가능한 IP를 제한하세요.
- 운영 중인 공개키 교체(키 로테이션) 정책을 수립하세요.
- 서버에서 사용하지 않는 포트/서비스를 비활성화하세요.
- 로그와 연결 메타데이터를 주기적으로 감사하세요.
간단한 키 롤링 절차:
- 새 키 쌍 생성(서버 또는 클라이언트별).
- 새 공개키를 상대 피어의 구성에 추가(AllowedIPs와 함께).
- 새 키로 연결 확인.
- 이전 키를 구성에서 제거.
문제 해결 가이드
- 연결이 안 되는 경우 확인 순서:
- 방화벽 규칙(포트/서비스) 확인: sudo firewall-cmd –list-all
- 서버가 포트를 리스닝하는지 확인: sudo ss -lunp | grep 37822
- 키가 정확히 복사되었는지 확인(개인/공개 키 혼동 주의).
- AllowedIPs가 올바른지 확인(클라이언트에 서버/클라이언트 서브넷이 포함되어야 함).
- NAT 환경이라면 PersistentKeepalive 설정(예: 15초)으로 유지하세요.
- sysctl에서 ip_forward=1인지 확인.
자주 발생하는 실수:
- 키 복사 시 줄바꿈이나 공백이 들어감.
- 방화벽에 포트나 서비스가 추가되지 않음.
- AllowedIPs에 넓은 범위(0.0.0.0/0)를 무심코 설정하여 전체 트래픽이 VPN으로 라우팅됨.
대안 및 아키텍처 고려사항
- 중앙 집중형 vs P2P: 소규모 환경은 단일 서버(스타 토폴로지)로 충분합니다. 대규모 분산 환경은 관리형 컨트롤러 또는 자동화가 필요합니다.
- 포트 선택: 기본 UDP 51820 대신 임의 포트(예: 37822)로 변경하면 스캔에 대한 노출을 줄일 수 있습니다.
- 클라우드 환경: 클라우드 제공업체의 보안 그룹/네트워크 ACL을 확인하세요.
역할 기반 체크리스트
- 시스템 관리자:
- 패키지 및 커널 업데이트
- 방화벽/포워딩 설정
- 서비스 활성화 및 모니터링
- 네트워크 관리자:
- NAT/라우팅 정책 검토
- 내부 DNS/라우팅 통합
- 보안 담당자:
- 키 관리 정책 수립
- 접근 제어 및 감사 정책
소규모 운영 SOP(핵심 단계 요약)
- 패키지 업데이트
- EPEL/PowerTools 활성화
- WireGuard 설치
- 키 생성 및 wg0.conf 작성
- 방화벽 서비스 등록 및 마스커레이드 활성화
- sysctl로 포워딩 활성화
- 서비스 시작 및 상태 확인
- 클라이언트 구성 및 테스트
수용 기준
- 서버와 클라이언트 간 ping이 성공한다.
- sudo wg 명령으로 최근 핸드셰이크가 확인된다.
- 내부 네트워크(192.168.10.0/24)로의 트래픽이 정상 라우팅된다.
의사결정 흐름(간단)
flowchart TD
A[WireGuard 도입 필요?] -->|예| B[서버 준비]
B --> C{공용 IP가 있나}
C -->|있음| D[설치 및 구성]
C -->|없음| E[포트 포워딩 또는 프록시 필요]
D --> F[클라이언트 구성]
F --> G[테스트]
G --> H{정상 작동}
H -->|예| I[운영]
H -->|아니오| J[문제 해결]
로컬화 팁(한국 환경 특이점)
- 국내 호스팅 또는 클라우드(예: AWS, GCP, KT 등)를 사용할 경우 보안 그룹/네트워크 ACL에서 UDP 포트를 열어야 합니다.
- 상용 방화벽/UTM 장비를 사용할 때는 NAT/포워딩 정책을 추가로 확인하세요.
개인정보 및 규정 주의사항
- VPN을 통해 전달되는 개인정보(로그인 가능 데이터 등)는 관련 법규에 따라 처리해야 합니다.
- 내부 사용자의 트래픽을 장기간 보관할 경우 개인정보보호 규정(예: 한국 개인정보 보호법)에 유의하세요.
결론
이제 CentOS 8 기반 서버에 WireGuard를 설치하고 기본 클라이언트를 연결하는 전체 절차를 익혔습니다. 이 가이드를 따라하면 안전한 사설 네트워크를 빠르게 구축할 수 있습니다. 보안 강화를 위해 키 관리, 방화벽 제한, 로그 감사 절차를 추가로 도입하세요.
중요: 운영 환경에서는 예제 값(키, IP, 포트 등)을 반드시 교체하고, 접근 제어를 엄격히 하십시오.