
앞서 NAS에 시도해봤던 OpenVPN 은 접속은 되었으나, 인터넷이 되지 않았던 안좋은 기억이 있기 때문에, 이번에는 WireGuard 라는 VPN 프로그램을 이용하여 Raspberry Pi 에 설치하고, 집안의 네트워크들이 동작 중인 서브넷을 외부에서 접속하는 것을 시도해 보자.
1. WireGuard Package 설치하기
먼저 SSH 프로토콜로 Raspberry Pi 에 접속하고, apt update 후, wireguard 패키지를 설치해준다.
ssh kang@192.168.0.54
sudo apt update
sudo apt install wireguard

2. 키 생성하기
2-1. VPN 을 설정하는 데 왜 '키 생성'을 해야하나?
라즈베리파이에 WireGuard VPN을 설치하고 나면, 대부분 가이드에서 처음에 wg genkey로 키를 생성하라고 한다.
공부해 보니, 이 '키 생성'은 VPN에서 서로를 안전하게 인증하는 데 핵심 역할을 한다. WireGuard 의 키 인증 방법과 구조(?) 에 대해 간략히 정리하자면
- WireGuard 는 비밀번호가 아니라, '키 쌍'으로 인증하는 시스템이다. 라즈베리 파이에 ssh 로 접속하거나, 다른 pc에 로그인 할 땐 ID / PW 를 사용하지만, WireGuard 는 '공개키 기반 암호화'라는 방식을 쓴다. 서버와 클라이언트가 각자 "개인키(private key)"와 "공개키(public key)" 한 쌍씩 만들어 놓고, 서로의 공개키만 알고 있으면 안전하게 통신할 수 있는 구조다.
2-2. 키 생성 명령어
umask 077
wg genkey | tee privatekey | wg pubkey > publickey
이렇게 하면 두 개의 파일이 만들어진다:
- privatekey: 내 비밀키 (절대 유출 금지)
- publickey: 상대에게 줄 공개키
이 키들을 설정 파일에 잘 넣으면, 서버도 나를 허용해주고, 나도 서버에 접속할 수 있게 된다.
cat publickey
cat privatekey
위 명렁어를 입력해서 무작위 난수가 나오면 제대로 설정이 된 것이다.

3. 설정파일 생성 및 작성
3-1. etc 경로 아래에 있는 wireguard 폴더 아래에 설정파일(wg0.conf)을 만들어야 한다.
sudo vi /etc/wireguard/wg0.conf
편집기는 익숙한 vi 편집기로 사용한다.

- PirvateKey 는 key 를 생성하고 cat 으로 확인하면 반환되는 키 값을 넣어준다.
- Address 는, VPN 인터페이스의 IP 주소를 의미하고, 이후 클라이언트가 접속하면 할당받을 IP 대역을 설정하는 것 이기 때문에 커스터마이징 하고 싶은 것이 아니면, 위와 같이 임의로 설정해도 무방하다.
4.인터페이스 활성화
sudo systemctl start wg-quick@wg0
sudo wg
sudo systemctl enable wg-quick@wg0
위의 명령어대로 WireGuard 를 시작하고 활성화 한다.
- sudo systemctl start wg-quick@wg0
>> WireGuard 를 wg0 환경 설정을 적용하여 시작한다. - sudo wg
>> Wireguard 확인
wg0 환경설정 파일의 내용이 반환되어야 한다. (제대로 설정이 되었다면)
sudo systemctl enable wg-quick@wg0 - >> 시스템 재시작 시에도 WireGuard 가 실행되도록 설정한다.

5. 포트포워딩 & DDNS 셋팅
외부에서 우리집의 공인IP: 포트명 으로 접속을 시도하면 이 접속을 라즈베리 파이(VPN server)로 안내해주는 설정(포트 포워딩)을 해준다.
예전에 설정을 해 두었지만 DDNS 가 제대로 설정되어 있나 확인했다. 집 인터넷은 공인 IP가 수시로 바뀔 수 있어서, 외부에서 VPN 서버로 접속할 때 문제가 된다. 그래서 DDNS(Dynamic DNS) 를 설정해두면, 공인 IP가 바뀔 때마다 자동으로 도메인 주소에 연결된 IP도 갱신된다. 결국 (내가 설정한)문자열로 된 고정된 이름으로 언제든지 우리집 공유기를 찾을 수 있게 된다.


이렇게 까지 셋팅하면, 외부로 부터 접속을 시도하면 라즈베리파이 까지 연결이 되도록 설정이 완료된 상태이다. (외부 접속을 가정해서, DDNS - 포트포워딩 - 인터페이스 - 키&값 확인 의 과정과 반대로 설정을 했다.)
이제 WireGuard VPN 의 클라이언트 셋팅을 하도록 하자.
앞서 언급했던 것과 같이, WireGuard 는 키-값 이 일치하면 연결을 수락하는 방식이기 때문에, 현재 VPN 의 서버측(라즈베리파이)은 셋팅이 끝났고, 클라이언트 측에 필요한( 외부 IP를 통한 접속 시도)키 생성 및 환경설정 파일을 작성하도록 하자.
6. 라즈베리파이(서버) 에서 클라이언트 키 만들기
등록 된 사용자만 접근이 가능하도록, 서버에서 클라이언트 키를 생성한다.
umaks 077
wg genkey | tee client_privatekey | wg pubkey > client_publickey

키가 만들어졌으니 서버 설정파일(wg0.conf) 에 클라이언트 키 를 등록 해준다.
sudo vi /etc/wireguard/wg0.conf

- [Peer] 이하 문장을 작성해주고, client-public key 를 입력해주고, 설정파일을 저장한다.
- AllowedIPs 값은 해당 키로 접속하는 클라이언트에게 10.0.0.2 의 IP 를 부여한다는 의미이다.
7. 맥북에 WireGuard 설치 후 설정파일 작성하기
7-1. 맥북에 Wireguard 설치하기
현재 맥북에 SSH 접속 중이므로 CLI 를 통해 설치하도록 한다.
brew install wireguard-tools
7-2. 설정 파일을 작성하고 저장, 종료한다.
vi /Users/{사용자이름}/wireguard/client.conf
[Interface]
PrivateKey = <여기에 client_privatekey>
Address = 10.0.0.2/24
DNS = 1.1.1.1
[Peer]
PublicKey = <여기에 server_publickey>
Endpoint = <DDNS 또는 공인IP>:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

8. 인터페이스 생성 및 연결 시도
8-1. 연결하기
sudo wg-quick up ./client.conf
conf 파일이 있는 곳에서 실행한다.

DDNS 가 제대로 입력되었다면, 라우터 설정에서 볼 수있는 우리집의 공인 IP가 출력되고, 게이트웨이 주소까지 제대로 반환되는 것을 확인할 수 있다.
8-2. 연결 확인하기
sudo wg

현재 접속 정보가 반환된다. ifconfig 를 통해 네트워크 정보를 확인하면 utun8 인터페이스가 10.0.0.2 IP 를 할당 받은 것을 확인할 수 있다.

9. NAT (마스커레이드) 설정, IP 포워딩 설정
위의 셋팅을 통해, 클라이언트(맥북)와 서버(라즈베리파이) 간에 VPN 연결이 완료 되었다. 하지만 VPN 터널은 단순 통로 가 생긴 것 뿐이다. 즉 클라이언트에서 -> 서버로 패킷을 보내도 패킷이 언제 어디로 가야할 지 모르기 때문에 서버 안에서 패킷이 죽어버리는 상황이 발생한다.
따라서 서버로 들어온 패킷이 어디로 가야하는지, 또 어디서 보내는 것인지 설정을 해 줘야 제대로 통신이 가능하다. 즉,
- IP 포워딩은 패킷이 움직이게 해주는 신호등
- NAT는 VPN을 통해 온 패킷이 라즈베리파이 ‘인 척’ 나갈 수 있게 해주는 변장술
이 두 가지 셋팅이 없으면, 맥북에서 보내는 트래픽은 라즈베리파이에서 갇혀서 멍하니 기다리기만 한다. (ping 도 안되고, 인터넷도 안된다.)
9-1. VPN을 통해 들어온 트래픽은 처음에 라즈베리파이의 wg0 인터페이스로 도착한다. 그런데 IP 포워딩이 꺼져 있으면 그 트래픽은 거기서 멈춘다. 아래 명령어 한 줄이 들어온 패킷을 다른 인터페이스로도 보내줄 수 있어 라는 허락이다.
sudo sysctl -w net.ipv4.ip_forward=1
9-2. 내부망(192.168.0.x)에 있는 다른 장비나, 인터넷을 향해 나가는 트래픽은 VPN을 통해 들어온 맥북(10.0.0.2)의 IP를 전혀 모른다. 그래서 패킷을 받더라도 "어디서 온 거야?" 하고 무시해버릴 수 있다. 그래서 라즈베리파이가 중간에서 이걸 자기 IP(예: 192.168.0.54) 인 척하고 대신 보내줘야 한다. 이게 바로 NAT(MASQUERADE)다.
sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
9-3. 클라이언트(맥북) 에서는 en0 이라는 무선연결 인터페이스로도 패킷을 주고받고 있기 때문에, VPN 이 연결되어도 이 인터페이스로 통신을 할 수도 있다. 따라서 10.0.0.2 라는 IP 로 통신을 한다면, en0 인터페이스가 아니라, VPN 인터페이스인 utun8 을 이용해서 10.0.0.1 인 라즈베리 파이로 패킷이 가도록 설정해야 한다.
추가로 집안에 있는 네트워크 기기들에도 접근하기 위해 (192.168.0.0/24) 해당 서브넷도 utun8 로 연결되도록 추가한다.
sudo route add -net 10.0.0.0/24 -interface utun8
sudo route add -net 192.168.0.0/24 -interface utun8
위의 모든 설정을 적용하고, 라즈베리파이 (10.0.0.1) -> 맥북 (10.0.0.2) 의 ping test, 또 반대로의 ping test 를 실시한다.


양방향 ping test 는 성공하였다. 하지만 맥북(클라이언트)이 집 안의 WiFi 에 연결되어 있기 때문에, 이를 외부 네트워크에 연결하고, 이제 정말 외부에서 VPN 서버로 접속하고, 같은 서브넷에 있는 기기중 하나에 연결해보도록 하자.
10. 외부에서 VPN 접속 하기
10-1. 먼저 집 안의 WiFi 연결을 끊고, 모바일 핫스팟으로 네트워크를 연결해준다.
sudo systemctl enable wg-quick@wg0

내가 켜 놓은 핫스팟으로 연결한다. 신사답게.
이후 내 IP 주소를 검색해보면, 라우터를 통해 나가는 211 로 시작하는 IP 가 아닌, 다른 IP 를 할당 받은 것을 알 수 있다.

10-2. 명령어로 192.168.0.27 (데스크탑) 을 향해 가는 패킷은 어떤 인터페이스를 통해 가는지 확인한다.
sudo route get 192.168.0.27

192.168.0.27 이라는 ip 는 내가 설정한 VPN 인터페이스인 utun8 을 이용하는 것을 확인할 수 있다. 또 현재 외부 네트워크에 접속한 상태임에도 192.168.0.27 과 ping test 에 성공하는 것을 알 수 있다.
10-3. 집 안에 있는 NAS 에 접속해보기
마지막으로 [외부 접속] -> [클라이언트(맥북)] -> [서버(라즈베리파이)] -> [NAS] 연결을 검증해본다.
라즈베리파이와 같은 서브넷에 있는 NAS 는 192.168.0.20 의 주소를 가지고 있다. 따라서 VPN 에 연결한 후 ssh 연결을 시도한다.
ssh kkace22@192.168.0.20

외부에서 접속한 서버임에도 집 안에 있는 NAS 에 성공적으로 접속하였다. 접속 과정또한 검증하기 위해 traceroute 를 실행 해 보았다.

현재 접속한 기기(맥북) 에서 10.0.0.1 (라즈베리파이) 로 먼저 접속을 하고, 그 이후 192.168.0.20 인 NAS 로 접속한 것을 확인하였다. 내가 생각한 접속 경로와 100% 일치하는 것을 확인할 수 있었다.
[인터넷]
│
│ (Hot Spot)
▼
[맥북 (외부 네트워크)]
(IP: 10.0.0.2)
│
│ WireGuard VPN (utun8)
▼
[라즈베리파이 (VPN 서버)]
- wg0 인터페이스: 10.0.0.1
- LAN 인터페이스: 192.168.0.54
│
│ 로컬 서브넷 (192.168.0.0/24)
▼
[NAS (내부 장비)]
- IP: 192.168.0.20
11. 마무리
- 라즈베리 파이에서 설정파일이 부팅시에 동작하도록 적용해준다.
sudo systemctl enable wg-quick@wg0
- 클라이언트 설정은 재부팅 하면 사라지기 때문에, NAT 설정과, IP 포워딩 설정도 저장한다.
# IP 포워딩 저장
sudo vi /etc/sysctl.conf
net.ipv4.ip_forward=1
sudo sysctl -p
- vi 편집기를 열고 두번 째 항목을 맨 아래 부분에 작성한 뒤 저장하고 나오고, sysctl -p 로 저장한다.
# NAT 설정 저장
sudo apt install iptables-persistent
sudo iptables-save > /etc/iptables/rules.v4
위의 설정으로, 서버와 클라이언트가 재부팅 되더라도 다시 VPN 인터페이스를 통해 서로 연결될 수 있도록 하였다.
VPN 설정부터 연결, 그리고 같은 서브넷에 접속하기 까지 꽤 오랜 시간 Setting 을 했다. 생각보다 시간이 많이 걸렸지만, 지난번 OpenVPN의 접속실패 결과를 벗어나, 이번엔 보다 완벽하게 연결 및 접속에 성공해서 뿌듯하다.
직접 설정을 하면서 상상만 할 수 있었던 네트워크의 흐름을 직접적으로 확인할 수 있었다. 이렇게 외부에서 접속해서 집안에 기기들에 접속할 수 있다고 생각하니 보안에 더 신경을 써야하는 기술임이 분명하다는 생각도 들었다. 이제 외부에서 접속하여 할 수 있는 것들에 대해 생각해보고, 라즈베리파이에 자동화 스크립트들을 옮기는 작업도 시작해야겠다.
'네트워크 공부 & 실습 > 네트워크 실습' 카테고리의 다른 글
| [Network] AWS 탈퇴 및 Blog 스크랩 자동화 스크립트 셋팅하기 (to 라즈베리파이) (2) | 2025.05.28 |
|---|---|
| [Network] 모니터링 자동화 스크립트 파일 -> 라즈베리 파이로 이동하기 (2) | 2025.05.27 |
| [Network]포트가 열렸는지 확인하는 가장 간단한 방법 – Netcat(nc) 개념과 실습 (0) | 2025.05.07 |
| [Network] SNMP 실습편 – snmpget과 snmpwalk로 장비 상태 확인하기 (2부) (1) | 2025.04.22 |
| [Network] MTU 직접 ping 명령어로 실험해보기 (0) | 2025.04.18 |