Haru Utils

네트워크 · 구성 레시피

WireGuard 지점 간 VPN 구성

Ubuntu의 systemd-networkd와 WireGuard를 이용해 두 고정 지점 사이에 최소 범위 터널을 만들고, 개인키는 화면이나 명령 인자에 노출하지 않은 채 파일 참조로 안전하게 관리합니다.
WireGuard 설치WireGuard VPN지점 간 VPNPrivateKeyFileAllowedIPs
지원 환경Ubuntu Server 24.04 LTS에서 systemd-networkd가 이미 네트워크를 관리하는 서버
예상 시간55
난이도고급
검토일2026-08-28

BEFORE YOU START

시작 전에 준비하세요

01

양쪽 콘솔 접근 수단과 VPN 밖의 기존 SSH 관리 세션

02

겹치지 않는 터널 주소 2개, 각 endpoint 주소·UDP 포트, 피어 공개키

03

허용할 대상 호스트를 /32로 확정한 라우팅 표와 방화벽 변경 계획

04

systemd-networkd가 현재 물리 NIC를 정상 관리한다는 확인과 네트워크 설정 백업

권장 대상 관리망 전체를 기본 경로로 우회하지 않고 특정 서버·지점 사이만 암호화하려는 인프라 운영자

FOLLOW THE RECIPE

8단계 구성·점검 레시피

1
확인시스템을 변경하지 않는 점검 단계

커널·networkd·주소 체계 확인

이 가이드는 이미 동작 중인 systemd-networkd에 wg0 가상 인터페이스만 추가합니다. 다른 네트워크 관리자를 대체하거나 물리 NIC 구성을 바꾸지 않습니다.

운영체제와 커널
cat /etc/os-release
uname -sr
networkd 활성 상태
systemctl is-active systemd-networkd.service
networkctl list
현재 주소와 경로
ip -brief address
ip route
WireGuard 모듈 확인
modinfo wireguard
  • systemd-networkd가 이미 active이고 현재 연결이 정상이다.
  • 터널 주소가 로컬·원격 어느 네트워크와도 겹치지 않는다.
  • VPN 밖의 콘솔·SSH 복구 경로가 있다.
결과 읽기

NetworkManager만 사용하는 서버라면 이 파일을 적용하지 말고 NetworkManager의 공식 WireGuard 방식으로 별도 설계합니다.

다음 판단

기존 인터페이스·UDP 포트·라우팅 충돌을 점검합니다.

2
확인시스템을 변경하지 않는 점검 단계

인터페이스·포트·경로 충돌 점검

wg0 이름과 수신 UDP 포트, 터널 주소 경로가 비어 있는지 확인합니다. AllowedIPs는 인증 대상이면서 라우팅 범위이므로 먼저 표로 승인받습니다.

기존 WireGuard 인터페이스
ip link show wg0
sudo wg show wg0
UDP 포트 점유
sudo ss -lunp | grep ':<WG_PORT> '
터널 주소 경로 충돌
ip route get <PEER_TUNNEL_IPV4>
ip route show table all
출력에 내부 주소가 포함될 수 있으므로 외부에 그대로 공유하지 않습니다.
기존 networkd 파일 확인
sudo find /etc/systemd/network -maxdepth 1 -type f -name '*wg0*' -print
  • wg0와 <WG_PORT>를 다른 서비스가 사용하지 않는다.
  • <PEER_TUNNEL_IPV4>/32가 기존 LAN·클라우드·컨테이너 대역과 겹치지 않는다.
  • 피어 공개키를 신뢰된 별도 채널로 확인했다.
결과 읽기

겹치는 경로가 있으면 넓은 AllowedIPs로 덮지 말고 터널 주소 계획부터 변경합니다.

다음 판단

배포판 패키지를 검토하고 도구만 설치합니다.

3
변경패키지·설정·서비스 상태가 달라지는 단계

WireGuard 도구 설치

커널 지원을 확인한 뒤 공식 Ubuntu 패키지에서 wireguard-tools를 설치합니다. 패키지 설치가 기존 네트워크 구성을 변경하지는 않습니다.

변경 단계입니다. 대상 서버, 백업 파일, 서비스 중단 영향과 바로 이전 상태로 돌아가는 방법을 다시 확인하세요.
패키지 인덱스 갱신
sudo apt update
변경 목록 미리 보기
apt-get --simulate install wireguard-tools
WireGuard 도구 설치
sudo apt-get install wireguard-tools
도구 버전
wg --version
  • 의도하지 않은 커널·네트워크 패키지 제거가 없다.
  • wg 도구와 커널 모듈을 확인했다.
  • 양쪽 지점의 지원되는 패키지 수명주기를 기록했다.
결과 읽기

모듈을 찾지 못하면 임의 DKMS를 추가하기 전에 현재 커널과 Ubuntu 지원 상태를 확인합니다.

다음 판단

개인키 파일을 출력 없이 만들고 networkd 구성을 준비합니다.

4
주의권한·연결·중단 영향을 확인할 단계

개인키 파일과 최소 피어 경로 구성

개인키는 셸 인자·브라우저·URL에 넣지 않고 제한된 파일에 바로 생성합니다. 구성에는 키 값이 아니라 PrivateKeyFile 경로만 기록합니다.

백업 접미사 생성
date -u +%Y%m%dT%H%M%SZ
보안 디렉터리 준비
sudo install -d -m 0750 -o root -g systemd-network /etc/wireguard
개인키를 화면 출력 없이 생성
sudo sh -c 'umask 037; test ! -e /etc/wireguard/wg0.key && wg genkey > /etc/wireguard/wg0.key'
이미 키 파일이 있으면 명령이 실패하며 덮어쓰지 않습니다. 개인키 내용을 cat·복사·스크린샷하지 않습니다.
개인키 파일 소유권과 권한
sudo chown root:systemd-network /etc/wireguard/wg0.key
sudo chmod 0640 /etc/wireguard/wg0.key
공개키만 별도 파일로 파생
sudo sh -c 'umask 022; wg pubkey < /etc/wireguard/wg0.key > /etc/wireguard/wg0.pub'
기존 netdev 백업
sudo cp --preserve=all --no-clobber /etc/systemd/network/30-wg0.netdev /etc/systemd/network/30-wg0.netdev.<BACKUP_SUFFIX>.bak
기존 파일이 있을 때만 실행합니다.
기존 network 백업
sudo cp --preserve=all --no-clobber /etc/systemd/network/30-wg0.network /etc/systemd/network/30-wg0.network.<BACKUP_SUFFIX>.bak
기존 파일이 있을 때만 실행합니다.
WireGuard netdev 편집
sudoedit /etc/systemd/network/30-wg0.netdev
wg0 주소 편집
sudoedit /etc/systemd/network/30-wg0.network
설정 예시 · /etc/systemd/network/30-wg0.netdev
개인키 파일 참조와 단일 피어
[NetDev]
Name=wg0
Kind=wireguard
Description=Restricted site-to-site WireGuard tunnel

[WireGuard]
PrivateKeyFile=/etc/wireguard/wg0.key
ListenPort=<WG_PORT>

[WireGuardPeer]
PublicKey=<PEER_PUBLIC_KEY>
AllowedIPs=<PEER_TUNNEL_IPV4>/32
Endpoint=<PEER_ENDPOINT_IP>:<PEER_WG_PORT>
PersistentKeepalive=25
RouteTable=main
AllowedIPs는 이 피어가 사용할 정확한 터널 호스트 /32만 넣습니다. 기본 경로나 전체 사설망을 넣으려면 별도 라우팅·접근통제 검토가 필요합니다.
설정 예시 · /etc/systemd/network/30-wg0.network
wg0 로컬 터널 주소
[Match]
Name=wg0

[Network]
Address=<SERVER_TUNNEL_IPV4>/32
서버와 피어 주소는 서로 달라야 하며 기존 네트워크와 겹치지 않아야 합니다.
  • 개인키 값이 명령 인자·출력·설정 예시에 나타나지 않는다.
  • 개인키 파일은 root:systemd-network 0640이다.
  • AllowedIPs는 단일 피어 /32이며 기본 경로가 아니다.
  • 피어 공개키와 endpoint를 별도 신뢰 채널로 대조했다.
결과 읽기

PrivateKeyFile을 읽지 못하면 키를 설정 파일에 붙여넣지 말고 파일 소유권·그룹·systemd 버전을 확인합니다.

다음 판단

UDP 인바운드를 제한하고 networkd가 구성 파일을 읽도록 합니다.

5
주의권한·연결·중단 영향을 확인할 단계

제한 규칙 확인 후 인터페이스 반영

기존 관리 세션을 유지합니다. UFW가 이미 활성 상태일 때만 피어 endpoint 한 곳에서 오는 UDP를 허용하고 networkd를 reload합니다.

UFW와 SSH 규칙 확인
sudo ufw status numbered
피어 UDP 규칙 미리 보기
sudo ufw --dry-run allow proto udp from <PEER_ENDPOINT_IP> to <SERVER_LOCAL_LISTEN_IP> port <WG_PORT>
활성 UFW에 피어 UDP만 허용
sudo ufw allow proto udp from <PEER_ENDPOINT_IP> to <SERVER_LOCAL_LISTEN_IP> port <WG_PORT>
UFW가 이미 active이고 SSH 및 콘솔 복구가 확인된 경우에만 실행합니다. 동적 endpoint라면 광범위 허용 대신 상위 VPN 게이트웨이 설계를 검토합니다.
구성 파일 권한 확정
sudo chown root:systemd-network /etc/systemd/network/30-wg0.netdev
sudo chmod 0640 /etc/systemd/network/30-wg0.netdev
sudo chown root:root /etc/systemd/network/30-wg0.network
sudo chmod 0644 /etc/systemd/network/30-wg0.network
networkd 구성 다시 읽기
sudo networkctl reload
sudo networkctl reconfigure wg0
networkd 로그 확인
networkctl status wg0
sudo journalctl -u systemd-networkd.service -n 100 --no-pager
  • 방화벽은 한 피어 endpoint의 UDP만 허용한다.
  • 물리 NIC의 기존 주소와 기본 경로는 바뀌지 않았다.
  • wg0가 routable 또는 configured 상태다.
결과 읽기

wg0가 failed면 networkd 로그에서 섹션 이름·권한·PrivateKeyFile 읽기 오류를 확인하고 물리 NIC 설정은 변경하지 않습니다.

다음 판단

공개키·handshake·/32 경로와 실제 통신을 검증합니다.

6
확인시스템을 변경하지 않는 점검 단계

handshake와 최소 경로 검증

개인키를 보여주는 전체 구성 출력은 사용하지 않습니다. 공개 가능한 필드와 handshake 시간, 전송량, 정확한 /32 경로만 조회합니다.

공개 필드만 조회
sudo wg show wg0 public-key
sudo wg show wg0 listen-port
sudo wg show wg0 peers
sudo wg show wg0 latest-handshakes
sudo wg show wg0 transfer
터널 주소와 경로
ip -brief address show wg0
ip route get <PEER_TUNNEL_IPV4>
피어 터널 주소 확인
ping -c 3 <PEER_TUNNEL_IPV4>
UDP 리스닝과 서비스 상태
sudo ss -lunp | grep ':<WG_PORT> '
systemctl is-active systemd-networkd.service
  • latest-handshake가 현재 시각에 가깝고 전송·수신 바이트가 증가한다.
  • 피어 터널 주소의 경로만 wg0를 사용한다.
  • 기존 기본 경로와 SSH 관리 경로는 VPN 밖에 남아 있다.
결과 읽기

handshake가 없으면 endpoint·UDP 방화벽·공개키를, handshake는 있지만 통신이 없으면 AllowedIPs·주소·피어 방화벽을 확인합니다.

다음 판단

키 보관·라우팅 범위·로그 노출을 최종 점검합니다.

7
주의권한·연결·중단 영향을 확인할 단계

키·라우팅·접근 범위 최종 점검

WireGuard 공개키 인증은 서비스 접근 권한을 대신하지 않습니다. 터널 안에서도 목적지 서비스 방화벽과 애플리케이션 인증을 유지합니다.

민감 파일 권한
sudo stat -c '%U:%G %a %n' /etc/wireguard/wg0.key /etc/systemd/network/30-wg0.netdev
최종 경로
ip route show table main
최종 UFW 규칙
sudo ufw status numbered
실패 로그
sudo journalctl -u systemd-networkd.service --since '-30 minutes' --no-pager
  • 개인키를 백업·티켓·메신저·브라우저에 복사하지 않았다.
  • AllowedIPs와 설치된 route가 승인한 /32보다 넓지 않다.
  • UDP 포트는 승인한 endpoint에서만 도달할 수 있다.
  • 터널 내부 서비스도 최소 포트·최소 권한으로 제한한다.
  • 키 교체 절차와 피어 제거 절차를 양쪽 지점에 기록했다.
결과 읽기

예상하지 못한 넓은 route가 있으면 통신을 확대하지 말고 해당 피어 구성을 롤백합니다.

다음 판단

필요하면 wg0 파일만 비활성화해 원래 네트워크를 보존합니다.

8
주의권한·연결·중단 영향을 확인할 단계

wg0 구성만 비활성화하고 복원

기본 경로와 물리 NIC를 건드리지 않고 wg0만 내립니다. 개인키는 삭제하지 않고 제한된 .disabled 파일로 보존해 사고 조사와 승인된 재사용에 대비합니다.

현재 경로와 세션 확인
ip route get <ADMIN_CLIENT_IP>
who
networkctl status wg0
wg0만 내리기
sudo networkctl down wg0
신규 netdev 비활성화
sudo mv /etc/systemd/network/30-wg0.netdev /etc/systemd/network/30-wg0.netdev.disabled.<ROLLBACK_SUFFIX>
신규 network 비활성화
sudo mv /etc/systemd/network/30-wg0.network /etc/systemd/network/30-wg0.network.disabled.<ROLLBACK_SUFFIX>
기존 netdev 백업 복원
sudo cp --preserve=all /etc/systemd/network/30-wg0.netdev.<BACKUP_SUFFIX>.bak /etc/systemd/network/30-wg0.netdev
작업 전 실제 백업이 있었던 경우에만 실행합니다.
기존 network 백업 복원
sudo cp --preserve=all /etc/systemd/network/30-wg0.network.<BACKUP_SUFFIX>.bak /etc/systemd/network/30-wg0.network
작업 전 실제 백업이 있었던 경우에만 실행합니다.
networkd 다시 읽기
sudo networkctl reload
이번 UDP 규칙만 제거
sudo ufw delete allow proto udp from <PEER_ENDPOINT_IP> to <SERVER_LOCAL_LISTEN_IP> port <WG_PORT>
이번 작업이 추가한 정확한 규칙일 때만 제거합니다.
개인키 파일 비활성화 보존
sudo mv /etc/wireguard/wg0.key /etc/wireguard/wg0.key.disabled.<ROLLBACK_SUFFIX>
sudo chmod 0600 /etc/wireguard/wg0.key.disabled.<ROLLBACK_SUFFIX>
  • 콘솔 또는 VPN 밖 관리 세션에서 롤백했다.
  • 물리 NIC와 기본 경로는 변경하지 않았다.
  • 작업 전 백업이 있던 파일만 복원했다.
  • 개인키는 화면에 출력하거나 평문 공유하지 않고 제한 보관했다.
결과 읽기

wg0를 내려도 기존 SSH가 끊긴다면 관리 경로를 터널에 의존하도록 설계한 것입니다. 콘솔에서 복원하고 관리망 경계를 다시 설계합니다.

다음 판단

endpoint·키·AllowedIPs 중 실패 원인을 분리하고 양쪽 변경 기록을 맞춥니다.

SECURITY CHECK

운영 전 마지막 보안 점검

  • 개인키는 PrivateKeyFile로만 읽고 명령 인자·출력·URL에 넣지 않는다.
  • AllowedIPs는 승인된 단일 피어 /32부터 시작한다.
  • 기본 경로와 SSH 관리 경로를 첫 구성에서 터널로 바꾸지 않는다.
  • UDP 인바운드는 가능한 경우 고정 endpoint 주소로 제한한다.
  • 터널 내부 서비스에도 별도 방화벽과 애플리케이션 인증을 유지한다.

COMMON ERRORS

자주 막히는 지점

handshake가 생성되지 않음

증상
latest-handshakes가 비어 있거나 0으로 표시됩니다.
가능한 원인
endpoint·UDP 포트·방화벽·공개키 중 하나가 양쪽에서 일치하지 않을 수 있습니다.
확인 순서
개인키를 출력하지 말고 공개키·endpoint·UDP 리스닝·상위 보안그룹을 양쪽에서 순서대로 비교합니다.
트러블슈팅으로 이어보기

handshake는 있지만 피어가 응답하지 않음

증상
전송량은 보이나 ping 또는 서비스 연결이 실패합니다.
가능한 원인
AllowedIPs·터널 주소·반대편 return route 또는 내부 방화벽이 맞지 않을 수 있습니다.
확인 순서
양쪽 route get 결과와 /32 AllowedIPs를 비교하고 서비스 포트를 최소 범위로 허용합니다.
트러블슈팅으로 이어보기

networkd가 개인키를 읽지 못함

증상
로그에 PrivateKeyFile 권한 또는 읽기 실패가 표시됩니다.
가능한 원인
파일 소유 그룹·권한이 잘못됐거나 PrivateKeyFile을 지원하지 않는 systemd 버전일 수 있습니다.
확인 순서
키 값을 설정에 붙여넣지 말고 root:systemd-network 0640과 systemd.netdev 지원 버전을 확인합니다.
트러블슈팅으로 이어보기

PRIMARY REFERENCES

공식 문서

설치 저장소와 지원 버전은 바뀔 수 있습니다. 검토일 이후에는 링크된 공식 문서와 현재 서버의 패키지 후보 버전을 함께 확인하세요.

도구 빠른 검색

최근 사용한 도구를 다시 열거나, 이름과 기능으로 검색하세요.

검색어와 도구의 입력·결과는 저장하지 않습니다.

↑↓ 이동 · Enter 열기 · Esc 닫기