VPN이 실제로 하는 일과 대부분 개발자들이 잘못 사용하는 이유
출처: Dev.to
내가 아는 모든 개발자는 VPN을 사용한다. 대부분은 구글에 로그인한 상태에서 Chrome을 통해 데이터를 전송하고, 자체 인증서 고정(cert pinning)을 하는 앱을 사용할 때 VPN을 켜 둔 채로 작업한다 — 즉 그 순간 VPN은 실질적으로 거의 아무것도 보호하지 못한다.
이것은 VPN을 비난하는 것이 아니다. 범위 설정이 잘못된 것이다. 여기서 도구가 실제로 커버하는 영역, 그 주변에서 새는 것들, 그리고 올바르게 테스트하는 방법을 살펴보자.
VPN은 OSI 모델의 Layer 3 (네트워크 계층) 에서 동작한다. 장치와 VPN 서버 사이에 암호화된 터널을 만든다(보통 WireGuard, OpenVPN, IKEv2/IPSec 중 하나를 사용). 모든 IP 트래픽은 그 터널을 통해 라우팅된다.
프로토콜 비교
| 프로토콜 | 속도 | 보안 | 포트 | 비고 |
|---|---|---|---|---|
| WireGuard | ⭐⭐⭐ 빠름 | ⭐⭐⭐ 강함 | UDP 51820 | 최신, 감사된 코드, 약 4,000줄 |
| OpenVPN | ⭐⭐ 보통 | ⭐⭐⭐ 강함 | TCP 443 / UDP 1194 | 검증된 구현, 약 100k줄 |
| IKEv2/IPSec | ⭐⭐⭐ 빠름 | ⭐⭐ 좋음 | UDP 500/4500 | 모바일 기본 지원, 재연결 우수 |
| L2TP/IPSec | ⭐ 느림 | ⭐ 약함 | UDP 1701 | 사용 금지 — 손상 가능성 있음 |
2026년 현재 WireGuard가 특별한 이유가 없다면 가장 올바른 선택이다. 코드베이스가 작을수록 공격 표면도 작아진다. 대부분의 감사받은 VPN 제공업체가 이제 기본으로 WireGuard를 사용한다.
VPN은 IP 라우팅만 담당한다. 그 외의 모든 것은 다루지 않는다.
DNS 누수
가장 흔한 문제는 DNS 누수다. 시스템의 DNS 리졸버가 터널을 통해 명시적으로 라우팅되지 않으면 DNS 요청이 ISP로 직접 전송돼 VPN이 켜져 있어도 방문한 모든 도메인이 노출된다.
터미널에서 다음 명령으로 확인해 보라:
# 현재 DNS 리졸버 확인
cat /etc/resolv.conf
# DNS 누수 테스트 (VPN 활성화 상태에서 실행)
# ISP가 아닌 VPN 제공자의 DNS가 표시되어야 함
nslookup whoami.akamai.net
# 보다 정밀한 테스트
dig +short myip.opendns.com @resolver1.opendns.com
대부분의 신뢰할 수 있는 VPN 클라이언트는 DNS 라우팅을 자동으로 처리하지만, 특히 Linux에서는 systemd-resolved, dnsmasq, NetworkManager 등 배포판마다 DNS 관리 방식이 달라 확인이 필요하다.
WebRTC 누수
WebRTC 누수는 브라우저 API를 통해 VPN이 켜져 있어도 실제 IP를 노출한다. 이는 브라우저 계층 문제이며 네트워크 계층 문제는 아니다.
// WebRTC 누수 테스트 — VPN 사용 중 브라우저 콘솔에서 실행
// 실제 IP가 반환되면 WebRTC 누수가 존재함
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
pc.createDataChannel('');
pc.createOffer().then(offer => pc.setLocalDescription(offer));
pc.onicecandidate = (e) => {
if (e.candidate) {
const ip = e.candidate.candidate.match(/(\d+\.\d+\.\d+\.\d+)/);
if (ip) console.log('WebRTC를 통해 노출된 IP:', ip[1]);
}
};
해결 방법
- Firefox:
about:config에서media.peerconnection.enabled를false로 설정. - Chrome: 확장 프로그램을 설치하거나 WebRTC 누수 방지 기능이 내장된 VPN 클라이언트를 사용.
애플리케이션 계층 추적
애플리케이션 계층 추적은 네트워크 계층과 전혀 관계가 없다. 브라우저에 로그인한 상태라면 세션 쿠키, localStorage, IndexedDB 등은 IP 라우팅과 무관하게 그대로 따라다닌다. 즉, VPN이 네덜란드(암스테르담) 경유라고 해도 쿠키 기반 추적은 차단되지 않는다.
킬 스위치
킬 스위치는 VPN 연결이 끊어졌을 때 모든 트래픽을 차단한다. 킬 스위치가 없으면 터널이 재연결되는 순간 잠시라도 실제 IP가 노출될 수 있다. 프라이버시가 중요한 환경에서는 킬 스위치를 기본으로 설정하는 것이 맞다.
Linux에서 ufw로 킬 스위치를 구현하는 예시:
# 기본 정책을 차단으로 설정
sudo ufw default deny outgoing
sudo ufw default deny incoming
# VPN 인터페이스(tun0 for OpenVPN, wg0 for WireGuard)만 허용
sudo ufw allow out on tun0
sudo ufw allow out on wg0
# 필요 시 LAN 트래픽 허용
sudo ufw allow out on eth0 to 192.168.0.0/16
sudo ufw allow out on eth0 to 10.0.0.0/8
sudo ufw enable
WireGuard 사용자는 PostUp/PreDown 훅을 이용해 보다 통합된 킬 스위치를 구현할 수 있다:
[Interface]
PrivateKey = <키>
Address = 10.x.x.x/32
DNS = 1.1.1.1
PostUp = iptables -I OUTPUT ! -o wg0 -m mark ! --mark $(wg show wg0 fwmark) -j REJECT
PreDown = iptables -D OUTPUT ! -o wg0 -m mark ! --mark $(wg show wg0 fwmark) -j REJECT
스플릿 터널링
스플릿 터널링을 사용하면 특정 트래픽만 VPN을 통해 라우팅하고 나머지는 직접 전송할 수 있다. 특정 서비스에만 VPN이 필요하고 로컬 개발 트래픽이나 내부 네트워크 요청은 터널링하고 싶지 않을 때 유용하다.
대부분의 GUI 클라이언트가 이를 기본 지원한다. WireGuard 설정 예시:
[Peer]
PublicKey = <키>
Endpoint = <서버 주소>:51820
# 전체 트래픽이 아닌 특정 서브넷만 VPN을 통해 라우팅
AllowedIPs = 10.0.0.0/8, 172.16.0.0/12
# 전체 트래픽 라우팅 예시
# AllowedIPs = 0.0.0.0/0, ::/0
요약 체크리스트
-
✅ ISP가 어떤 도메인을 방문했는지 볼 수 없음
-
✅ 공용 Wi‑Fi에서 트래픽이 암호화됨
-
✅ 목적지 서버에 IP가 노출되지 않음
-
✅ DNS 쿼리가 보호됨(올바르게 설정한 경우)
-
❌ 쿠키/세션 추적에 대한 보호 없음
-
❌ 브라우저 지문(피 fingerprint) 추적에 대한 보호 없음
-
❌ 앱이나 서비스에 로그인한 상태에서는 보호되지 않음
-
❌ VPN 제공자 자체에 대한 보호 없음
VPN은 네트워크 계층 문제만 해결한다. 애플리케이션 계층 프라이버시를 원한다면 콘텐츠 차단, 세션 격리, 지문 방지 브라우저 등 애플리케이션 수준의 솔루션이 필요하다.
팀이나 개인용 VPN을 설정하고 기술적인 부분을 제대로 마무리하고 싶다면: WireGuard, DNS 라우팅 검증, 킬 스위치 활성화, DNS 누수 테스트를 반드시 수행한 뒤에 신뢰하라. 나머지는 마케팅에 불과하다.
소비자 버전 — iptables를 건드리고 싶지 않은 사람들을 위한 요약: lucas8.com/what-vpn-actually-protects