- Wag는 WireGuard에 다중 요소 인증, 라우트 제한, 기기 등록을 추가하는 프로젝트로, MFA가 필요한 라우트와 항상 접근 가능한 공개 라우트를 구분할 수 있음
- 신규 클라이언트 등록 API, 고가용성, 실시간 사용자 업데이트와 알림, Security Key·SSO·PAM·TOTP 등 여러 MFA 통합을 제공함
- 서버 운영에는 IP 포워딩 활성화가 필요하며, 수동 실행 시
iptables와libpam설치,iptables와 WireGuard 장치 관리를 위한 root 실행이 필요함 - 관리는 웹 UI와 CLI로 가능하며, CLI는
start,registration,devices,users,webadmin하위 명령으로 등록 토큰, 기기 잠금, MFA 초기화, 웹 관리자 계정을 다룸 - 제약으로는 클라이언트당 하나의
AllowedIP만 지원하며, 주로 Linux 전용이고 Windows는 일부 작업을 거치면 동작할 수 있음
Wag가 추가하는 WireGuard 기능
- Wag는 WireGuard에 MFA, 라우트 제한, 기기 등록을 추가함
- 라우트는 MFA 인증이 필요한 경로와 항상 접근 가능한 공개 라우트로 나눠 정의할 수 있음
- 신규 클라이언트 등록을 위한 쉬운 API를 제공함
- 고가용성, 실시간 사용자 업데이트와 알림을 지원함
- MFA 통합은 다음 방식을 포함함
- Security Key
- SSO
- PAM
- TOTP
- 문서는 Documentation에서 제공됨
설치와 실행 조건
- 서버에서 포워딩이 활성화되어야 함
- IPv4는
net.ipv4.ip_forward=1설정을 사용함 - IPv6는
net.ipv6.conf.all.forwarding=1등 관련sysctl설정을 사용함
- IPv4는
- Docker Compose 실행 예시는
wagvpn/wag:latest이미지를 사용함- 관리 페이지 포트 예시는
4433/tcp - 공개 등록 페이지 포트 예시는
8081/tcp - WireGuard 포트 예시는
53230/udp /dev/net/tun장치를 컨테이너에 연결함
- 관리 페이지 포트 예시는
- 수동 설치에는
iptables와libpam이 필요함 - Wag는
iptables와 WireGuard 장치를 관리하기 위해 root로 실행되어야 함 - 바이너리 릴리스는
glibc 2.31+가 필요함 - 소스 빌드는
go1.23.1과npm이 필요함
관리 방식
- 관리 UI를 활성화한 뒤 Wag를 설정하면 첫 번째 관리자를 생성하고, 비밀번호를 STDOUT으로 출력함
- 이후 웹 UI에 로그인해 사용자를 관리할 수 있음
- root 사용자는 CLI로 Wag 서버를 관리할 수 있음
- CLI 형식은
wag subcommand [-options]임 - 지원 하위 명령은 다음과 같음
start: Wag 서버를 시작하며 데몬화하지 않음registration: 등록 토큰 생성, 삭제, 목록 조회를 처리함devices: WireGuard 기기 목록 조회, 삭제, 잠금, 잠금 해제, 활성 MFA 세션 조회를 처리함users: 사용자 MFA 관리, 사용자 삭제, 계정 잠금, MFA 초기화를 처리함webadmin: 웹 UI 관리자 사용자 추가, 삭제, 목록 조회, 계정 잠금과 해제를 처리함version,firewall도 지원 명령에 포함됨
등록 토큰과 MFA 흐름
- 새 기기 등록은 먼저
wag registration -add -username tester같은 명령으로 등록 토큰을 생성함 - 생성된 토큰을 공개 등록 엔드포인트에 전달하면 WireGuard 설정 응답을 받을 수 있음
- 반환되는 설정에는
Interface,PrivateKey,Address,Peer,Endpoint,PublicKey,AllowedIPs,PersistentKeepAlive같은 항목이 포함됨 - 사용자는 서버의 VPN 주소로 접속해 2FA 코드를 입력함
- 세션이 만료되기 전까지 지속되는 시간은 설정 파일에서 지정함
웹 관리 콘솔
- 관리 콘솔에 로그인하려면
Webserver.Management.Enabled를true로 설정해야 함 - 콘솔에서
sudo ./wag webadmin -add -username <your_username> -password <your-password-here>로 웹 관리자 계정을 추가함 - 이후 관리 리스닝 주소로 접속해 자격 증명을 입력함
- 웹 인터페이스 자체는 관리자 사용자 추가를 할 수 없음
- 관리 포털은 외부에 노출하지 않는 것이 권장되며,
ListenAddress를127.0.0.1또는localhost로 설정하고 SSH 포워딩으로 노출하는 방식을 권장함
주요 설정 항목
NumberProxies는 클라이언트 앞의 신뢰할 수 있는 리버스 프록시 수를 지정하며, Wag가X-Forward-For를 반영해 클라이언트 IP를 파싱하게 함Socket은 Wag 제어 소켓이며, 변경하면 같은 머신에서 여러 Wag 인스턴스를 실행할 수 있음NAT는 마스커레이딩을 켜거나 끄며, 활성화하면 모든 트래픽이 VPN 서버에서 시작된 것처럼 보임NATExcludeRanges는NAT=true일 때 NAT에서 제외할 CIDR 범위를 지정함ExposePorts는 VPN 서버의 포트를 클라이언트에 노출하며iptables규칙을 추가함CheckUpdates는 기본값이 꺼져 있으며, 활성화하면 관리 UI가 새 Wag 버전 알림을 표시하고api.github.com에 접근함Acls는 그룹과 정책을 정의하지만 첫 실행 시에만 반영되며, 런타임 중에는 웹 UI로 편집함Webserver는 공개 등록 엔드포인트, 터널 MFA 포털, 관리 포털 설정을 포함함Wireguard는 장치 이름, 리스닝 포트, 개인 키, VPN이 담당하는 서브넷, MTU, DNS 서버를 설정함Clustering은 클러스터 이름, etcd 클러스터 상태, 로그 레벨, witness 노드, 데이터베이스 위치, 클러스터 인증서 관련 설정을 포함함
ACL 정책 동작
Policies는 VPN이 캡처할 라우트와 Wag를 통과할 포트·프로토콜을 정의함- 규칙 적용은 서브넷 prefix 길이를 사용하며, 가장 구체적인 매치가 라우트 접근 수준을 결정함
- 예를 들어
/16을 MFA로 정의하고 그 안의 특정/32를 Allow로 정의하면, 더 구체적인/32가 우선되어 MFA 없이 접근 가능함 - 이 동작은
v6.0.0에서 변경되었으며, 이전에는 MFA 라우트가 항상 우선했음 - 하나의 라우트에 여러 정책이 정의되면 정책이 합성되며, MFA 규칙이 우선함
- 아직 릴리스되지 않은 버전부터
Deny규칙으로 라우트 접근을 차단할 수 있음 - 가장 구체적인 규칙은 새 규칙 “버킷”을 만들기 때문에,
/32버킷에 deny만 있으면 같은/32의 다른 포트 접근도 허용되지 않을 수 있음
포트와 프로토콜 규칙
- 서비스 접근은 포트와 프로토콜 규칙으로 정의할 수 있음
- 지원되는 규칙 유형은 3가지임
- Any: 별도 규칙이 없거나
any키워드를 쓰면 모든 서비스와 포트 조합을 허용함 - Single Service:
192.168.1.1 22/tcp 53/udp처럼 호스트의 특정 TCP·UDP 포트를 허용함 - Ranges:
192.168.1.1 22-1024/tcp 23-53/any처럼 포트 범위를 지정함
- Any: 별도 규칙이 없거나
- 포트 범위는 낮은 포트를 먼저 써야 함
- ICMP는 포트가 없으므로
1.1.1.1 icmp처럼 포트 없이 지정할 수 있음
제한 사항과 개발
- Wag는 클라이언트당 하나의
AllowedIP만 지원함 - 이 제한은 클라이언트에서 서버로 이어지는 구조에 적합함
- 주로 Linux 전용이며, Windows는 일부 작업을 거치면 동작할 수 있음
- 개발 모드에서는 터널로 들어오는 요청의 IP를 클라이언트 IP로 설정하기 위한 환경 변수를 사용할 수 있음
- 테스트 예시는
internal/router에서sudo go test -v .를 실행함 - 외부 기여는 기능 추가나 버그 수정 시 가능한 경우 테스트를 작성하고 Pull Request를 열도록 안내함