안드로이드에서 VPN 터널 밖으로 DNS 트래픽 유출 가능성
(mullvad.net)- Android의 일부 앱·상태 조합에서 DNS 쿼리가 VPN 터널 밖으로 나갈 수 있으며, Mullvad는 VPN 앱보다 Android OS 버그가 원인이라고 봄
- 유출은 VPN이 켜져도 DNS 서버가 비어 있는 상태, 터널 재구성, VPN 앱 강제 종료·충돌 같은 짧은 전환 구간에서 발생할 수 있음
- 영향은
getaddrinfo를 직접 호출하는 앱에 집중되며, Android API인 DnsResolver만 쓰는 앱에서는 유출이 발견되지 않음 - Always-on VPN과 “Block connections without VPN”을 켜도 문제가 완전히 막히지 않으며, Android 14를 포함한 여러 버전에서 확인됨
- Mullvad는 임시로 가짜 DNS 서버를 설정해 일부 상황을 완화할 예정이지만, 재연결 중 유출은 OS 수정 없이는 완전 차단이 어려움
Android에서 발생한 DNS 유출 조건
- Mullvad는 4월 22일 Reddit 사용자 보고를 통해 “Block connections without VPN”이 켜진 상태에서 VPN을 껐다가 다시 켤 때 DNS 유출이 생길 수 있음을 확인함
- 내부 조사에서는 Android OS가 DNS 트래픽을 VPN 밖으로 보낼 수 있는 시나리오가 더 나옴
- VPN은 활성화되어 있지만 DNS 서버가 구성되지 않은 경우
- VPN 앱이 터널을 재구성하는 동안
- VPN 앱이 강제 종료되거나 충돌하는 짧은 시간
- 이 동작은 Android OS의 기대 동작이 아니며, 상위 OS 레벨에서 수정되어야 함
영향을 받는 앱과 이름 해석 경로
- 유출은 도메인 이름 해석에 C 함수
getaddrinfo를 직접 호출하는 앱에서 발생하는 것으로 보임 - Android API인 DnsResolver만 사용하는 앱에서는 유출을 발견하지 못함
- Chrome 브라우저는
getaddrinfo를 직접 사용할 수 있는 앱의 예임- 관련 Chromium 코드 위치도 공개되어 있음
getaddrinfo사용 자체가 잘못된 것은 아니며, 모든 Android 사용자를 보호하려면 OS 차원의 해결이 필요함
Always-on VPN과 차단 설정의 한계
- 확인된 유출은 Always-on VPN과 “Block connections without VPN” 활성화 여부와 관계없이 발생함
- “Block connections without VPN”이 켜져 있으면 암호화된 WireGuard 트래픽 외에는 기기 밖으로 나가면 안 되지만, 재현 과정에서는 평문 DNS가 라우터에서 관찰됨
- Mullvad는 이 설정이 이름이나 문서화된 동작을 충족하지 못하며 여러 결함이 있다고 평가함
- 위 조건에서 DNS 트래픽이 유출될 수 있음
- 이전에 보고한 것처럼 연결 확인 트래픽도 여전히 유출됨
Mullvad 앱의 임시 완화와 남은 문제
- Mullvad 앱은 현재 차단 상태에서 DNS 서버를 설정하지 않음
- 복구 불가능한 방식으로 터널 설정에 실패하면 앱은 차단 상태로 들어감
- 이 상태에서는 트래픽이 기기 밖으로 나가는 것을 막지만, DNS 서버가 비어 있어 유출 조건이 생길 수 있음
- Mullvad는 OS 버그를 우회하기 위해 당분간 가짜 DNS 서버를 설정하는 방식으로 대응할 예정이며, 이 수정이 포함된 릴리스를 곧 제공할 계획임
- 터널 재연결 중 발생하는 유출은 앱에서 완화하기 더 어려움
- Mullvad는 해결책을 찾고 있음
- 터널 재구성 횟수를 줄일 가능성은 있지만, 현재로서는 이 유출을 완전히 막을 수 있다고 보지 않음
- Mullvad는 문제와 개선 제안을 Google에 보고함
WireGuard와 Chrome으로 재현한 관찰
- 두 번째 시나리오인 VPN 터널 구성 변경 중 유출은 WireGuard 앱과 Chrome을 사용해 재현할 수 있음
- WireGuard는 Android VPN 구현의 기준 사례로 사용됨
- Mullvad는 다른 Android VPN 앱에서도 재현될 가능성이 있다고 봄
- Chrome은
getaddrinfo사용이 확인된 앱이어서 유출 트리거에 사용됨
- 재현 절차에는 다음 요소가 포함됨
- spam_get_requests.html 다운로드
- WireGuard 앱과 Chrome 설치
- wg1.conf, wg2.conf를 WireGuard에 가져오기
- WireGuard에서 wg1 터널을 활성화하고 VPN 권한 허용
- Android VPN 설정에서 WireGuard에 대해 Always-on VPN과 “Block connections without VPN” 활성화
- 라우터에서
tcpdump -i <INTERFACE> host <IP of android device>로 캡처 시작 - WireGuard와 Chrome을 분할 화면으로 열고, Chrome에서
spam_get_requests.html을 실행한 뒤 WireGuard에서 wg1과 wg2를 번갈아 전환
- 라우터에서는 Android 기기에서 OpenWrt 라우터의 53번 포트로 향하는 A 레코드 질의와 NXDomain 응답이 관찰됨
- DNS 유출은 사용자의 대략적 위치나 방문하는 웹사이트·서비스를 파악하는 데 쓰일 수 있어 프라이버시 영향이 클 수 있음
- 위협 모델에 따라 민감한 용도에서는 Android 사용을 피하거나, 유출 방지를 위한 다른 완화책을 적용해야 할 수 있음
- Mullvad 앱 사용자는 부분 완화가 포함될 수 있으므로 앱을 최신 상태로 유지해야 함
댓글과 토론
Hacker News 의견들
- Mullvad를 쓰지는 않지만 정말 존중하게 됨. 문제 설명, 단기 우회책, 다른 사람들이 쓸 수 있는 잠재적 우회책, Android에서 고쳐야 할 부분까지 정보 밀도가 높고 잘 정리돼 있음
- 경쟁사처럼 끝없는 YouTube 스폰서십을 하는 대신 이런 블로그 글을 내는 점 때문에 VPN 서비스로 Mullvad를 선택했음
- VPN을 쓰지 않더라도 Mullvad에는 무료 DNS 서비스가 있음. 트래픽/사용량 증가도 일종의 지원이 될 수 있고, DNS 요청 관점에서 Mullvad VPN 사용자들이 덜 튀게 만드는 데도 도움이 될 듯함
단점은 내 경우 ping 시간이 quad9나 cloudflare보다 꽤 높다는 점임
이 스레드에 DNS 수준 광고 차단 방법과 cloudflare 관련 정보를 적어뒀음: https://news.ycombinator.com/item?id=40056162 - 가치관, 사고방식, 핵심 신념에 대한 충성도, 수십 년 동안 모토를 지켜온 꾸준한 증거까지 보면 최고의 VPN이라고 봄
- Mullvad 사용자로서 매우 만족함. 한 번 결제 관련 질문으로 지원팀에 메일을 보내면서, 겪고 있던 문제에 대한 작은 iptables 질문도 덧붙였음
결제 문제는 빠르게 해결해 줬고, iptables에 대해서도 여러 해법의 장단점까지 담은 자세한 답변을 받았음. 한마디로 훌륭함 - VPN을 쓴다면 어떤 걸 쓰는지 궁금함
- rethinkdns 개발자임
“이 문제들은 어떤 앱을 쓰든 모든 Android 사용자를 보호하려면 OS에서 해결돼야 한다”는 말에 대해, Android의 편집증적 네트워킹은 늘 시스템 앱과 OEM 앱, 즉 Google 앱을 포함한 예외를 둬 왔음
이런 버그 수정 대부분도 그 핵심 가정을 바꾸지는 못할 가능성이 큼. 관련 코드 참고: https://github.com/celzero/rethink-app/issues/224
“터널 재연결 중 누수는 앱에서 완화하기가 더 어렵다. 아직 해결책을 찾고 있다”는 부분에 대해서는, Android가 재구성 시 두 TUN 장치 사이의 끊김 없는 전환을 지원함. 제대로 구현하기는 까다롭지만 가능함- 손전등 앱의 인터넷 권한조차 끄지 못하게 하는데, OS가 인터넷 광고 회사에 의해 운영된다는 점을 생각하면 말이 됨
- Android에서 오래전부터 있던 문제임. 내부 DNS 서버만 쓰게 하고 싶어도, Android는 필요하거나 원한다고 판단하면 셀룰러로 전환해서 그 DNS를 써버림
최근 무선 연결이 왜/언제 끊기는지 보려고 adb 디버그를 관찰했는데, 결국 생존 확인 과정에서 무언가를 보거나 해석하지 못하면 셀룰러 데이터를 켜서 시도함
내부에만 존재하는 DNS 레코드를 쓸 때 휴대폰에서 임의로 동작하지 않는 게 특히 답답함. 기기는 해당 레코드가 있는 내부 DNS 서버를 제공하는 Wi-Fi에 붙어 있는데도, Android의 어떤 이유로 외부에서 해석하고 있음
Apple이 어떤지는 모르겠지만, 기본적으로 자기들의 “privacy” VPN을 통해 DNS까지 DoH로 프록시하려 한다는 점을 보면, 경쟁 제품으로 볼 만한 걸 쓸 때 더 낫다고 상상하기 어렵고 Apple이 그런 제품을 어떻게 대하는지도 알고 있음- “셀룰러로 전환해서 필요하거나 원할 때 쓴다”는 게 Wi-Fi 지원이 켜져 있어서 그런 건 아닌지 확인해 봐야 함. 그 기능은 Wi-Fi 신호가 나쁠 때 셀룰러로 전환하도록 명시적으로 설계돼 있음
- Apple 또는 iOS에는 구성 프로파일을 이용해 트래픽을 필터링하고 차단하는 꽤 견고한 내장 방식이 있음. 앱별 설정이 가능한지는 확실하지 않지만, 호스트 이름 허용 목록/차단 목록은 확실히 설정 가능함
실제 예로는 이 시스템 전체 광고 차단기를 보면 됨: https://myxxdev.github.io/depictions/MYbloXXforiOS/MYbloXXfo... - iOS는 절대 기본으로 Private Relay를 쓰지 않음. 구독에 포함돼 있더라도 명시적으로 직접 켜야 함
- 개발자 옵션에서 “모바일 데이터 항상 사용”을 꺼봤는지 궁금함
- AOSP를 소스에서 빌드해 봤음. Google 전용 요구사항은 없어야 하는 물건이고, 몰래 Google에 접속하지 못하게 하려고 hosts 파일에서 가능한 많은 Google 서버를 막았음
내가 겪은 유일한 문제는 정상 동작하는 무선 AP에 연결돼 있는데도 기기가 인터넷이 없다고 표시했다는 것임. 실제로는 동작했지만, 상태 표시줄 아이콘과 그 밖의 내부 시스템 코드 목적상 Google 서버로 인터넷 동작 여부를 확인하는 듯했음
프라이버시를 중시한다면 Android는 멀리하는 게 좋고, 아마 기술 전반도 조심해야 함
- 몇 년 전 프로젝트용으로 여러 VPN 구성을 테스트할 때, 컴퓨터와 메인 라우터 사이에 MikroTik 방화벽 장비를 두곤 했음. 목적은 PC가 연결하려는 VPN 서버 IP 주소가 목적지가 아닌 모든 트래픽을 차단하는 것뿐이었음
이 방식은 PC에서 VPN 서버로 가는 경로 밖으로 트래픽이 새지 않도록 보장하는 데 아주 잘 동작했음. 사용하는 VPN 서버의 IP 주소는 거의 바뀌지 않고, 바뀌더라도 MikroTik 방화벽에서 바꾸기 쉬움
서버 IP를 모르거나 바뀐다면, VPN 서버가 쓰는 포트/프로토콜 쌍이 아닌 모든 트래픽을 차단하는 방법도 있음. 예를 들어 VPN 종류에 따라 UDP 1194가 목적지가 아닌 트래픽을 버리는 식임
MikroTik 라우터에는 트래픽을 빠르고 쉽게 볼 수 있는 torch라는 작은 도구도 있고, 패킷 캡처도 지원함. 가격은 30달러에서 3000달러까지 다양하고 소프트웨어 라이선스가 없으며, 다룰 줄 알면 매우 강력하고 유능함- 이런 종류의 장비는 network slug라고 부르며, 아주 훌륭한 아이디어임
엄밀히 말하면 진짜 slug는 IP 주소가 정의되지 않은 투명한 2계층 방화벽이지만, 여기서 그런 세부를 따질 필요는 없음
https://john.kozubik.com/pub/NetworkSlug/tip.html - 출발지/목적지 주소와 포트 기준의 외부 방향 필터링은 방화벽의 기본 개념이자 모든 방화벽-라우팅 플랫폼의 표준 구성임. 게이트웨이 기준으로 필터링하는 정책 기반 라우팅도 같은 맥락임: https://en.wikipedia.org/wiki/Policy-based_routing
일반적으로 기본으로 모든 외부 트래픽을 허용하는 건 소비자용이나 준전문가용 제품뿐임. 이 구성에서 “메인 라우터”는 무엇이었는지 궁금함. ISP 제공 장비였는지? - 추천하는 김에, 저렴하고 괜찮은 7계층 방화벽 라우터도 있는지 궁금함
우리도 휴대폰 앱과 모뎀 사이에 방화벽을 끼워 넣을 수 있으면 좋겠음
- 이런 종류의 장비는 network slug라고 부르며, 아주 훌륭한 아이디어임
- Android의 DNS 문제는 이 플랫폼에서 자체 IPv6 DNS 서버를 설정할 수 없다는 데 있음. Wi-Fi에 뭔가 변화가 생길 때마다 바뀌어 버림
루팅된 Android에서도 운영체제가 그것을 바꾸지 못하게 하는 앱은 없음
항상 IPv6 주소를 배포하면서 끌 수 없게 만든 라우터를 쓰고 있다면 그냥 막히는 셈임
그 라우터 뒤에 방화벽 장비를 설치해 라우터가 광고하는 IPv6 DNS 서버를 제거할 수 있는지도 모르겠음- DNS 서버 IP 주소를 설정하는 대신 시스템 수준의 DNS-over-TLS 지원을 쓰면 어떨까 함. 전역 설정이라 어떤 네트워크에 있든, 그 네트워크에서 무슨 일이 생기든 적용돼야 함
DNS 요청 누수를 신경 쓴다면 어차피 DoT나 DoH를 써야 함 - rethink로 IPv6 DNS를 바꿀 수 있지 않나?
- 휴대폰이 메인 인터페이스일 때 그런 일이 생긴다는 뜻으로 보임
Wi-Fi 테더링에서도 같은 일이 생기는지 궁금함. 휴대폰 Wi-Fi를 통해 연결한 노트북에서 VPN을 쓰면 같은 방식으로 새는 걸까?
- DNS 서버 IP 주소를 설정하는 대신 시스템 수준의 DNS-over-TLS 지원을 쓰면 어떨까 함. 전역 설정이라 어떤 네트워크에 있든, 그 네트워크에서 무슨 일이 생기든 적용돼야 함
- 가장 안전한 구성은 휴대폰의 모바일 데이터를 끄고, 휴대폰 상위에서 VPN을 처리하는 OpenWRT 핫스팟을 들고 다니는 것 같음
- 맞음. iOS에서는 더 큰 악몽임
“항상 켜진 VPN”은 Apple이 승인한 조직의 MDM 솔루션으로 “supervised” 상태인 기기에서만 설정 가능함. 문서화된 신청과 현재 직원과의 전화 통화가 필요함
아니면 Mac에서 Apple Configurator 앱을 써야만 “always-on VPN” 키가 들어간 구성 프로파일을 만들 수 있음 - 예전에 GL.inet E750과 SIM 없는 iPhone으로 몇 달씩 이렇게 해봤는데, 미국 GSM 통신사들은 이상한 포트의 UDP 트래픽을 심하게 제한하는 경우가 잦았음. 64~128kbps, 즉 0.1Mbps 수준까지 떨어지기도 함
알림도 자주 지연됨 - 공용 Wi-Fi나 모바일 통신을 쓴다면 그게 최선의 해법임. 누군가 직접 기지국을 운영하면 휴대폰이 거기에 붙을 수 있음
내 네트워크가 아니라면 모바일 라우터 없이 직접 연결하지 않는 게 좋음 - 다른 사람들이 Android가 여러 조건에서 조용히 셀룰러 데이터를 다시 켠다고 하니, 이 방법도 확실한 해결책은 아님
The Grugq가 10년 전 이런 목적의 도구를 만들었음. 지금은 아쉽게도 유지보수되지 않음: https://github.com/grugq/portal
해커를 위한 작전 보안 발표의 일부였고, 유명하거나 악명 높은 여러 해커들이 안전하다고 생각했지만 결국 잡힌 사례에 관심 있다면 볼 만함: https://www.youtube.com/watch?v=9XaYdCdwiWU
- 맞음. iOS에서는 더 큰 악몽임
- root 접근 권한이 없는 시스템은 정의상 안전하지 않음. Android와 iOS는 우스울 정도임
- root 접근이라는 개념이 있는 시스템은 정의상 안전하지 않다고도 말할 수 있음. 이런 식의 단정적인 문장은 누구나 할 수 있음
- 휴대폰이 대부분의 사람들에게 데스크톱/노트북을 대체하지 않았다면 웃고 넘길 수 있었을 것임
컴퓨터라고는 주로 미디어 소비와 사적 데이터 수집을 위해 설계된 기기만 갖고 자랐거나 자라날 아이들이 안타까움 - GrapheneOS 개발자들은 root에 정말 강하게 반대함. 이에 대해 어떻게 생각하는지 궁금함
- 요점이 뚜렷하고 주제에도 맞음. 그래서 오픈소스 소프트웨어와 하드웨어 모바일 기기 프로젝트가 계속 늘어날 수밖에 없음
https://en.wikipedia.org/wiki/PinePhone_Pro - 그 정의대로라면 내 가장 중요한 시스템 상당수가 “안전하지 않은” 셈임
그런 기기에 있는 내 SSH 개인 키 사본을 가져올 수 있다면 묻지도 따지지도 않고 현금 10만 달러를 주겠음
그 정의는 의미가 없고, 추론이나 소통에도 쓸모가 없음
- “VPN 없이 연결 차단”은 뷔페에서의 내 자제력만큼이나 믿을 수 없는 것으로 드러나는 중임. 착각이 아니라면 이런 DNS 누수는 방문한 사이트와 위치까지 꽤 드러낼 수 있어서 VPN의 목적 자체를 무너뜨림
Android는 VPN을 켜도 DNS 정보를 흘릴 수 있으니, 프라이버시에 정말 민감하다면 Android 사용 자체를 넘어 생각하거나 민감한 작업을 휴대폰에서 빼는 편이 나음 - 가끔 이런 “버그”가 의도적으로 잘 배치된 건 아닌지 의심하게 됨. 특히 대형 기술 기업들이 여러 정보기관과 협력해 온 사실이 있으니 더 그렇음
Android에서 이런 종류의 버그를 들은 게 이번이 처음도 아니라서, 이 정도로 많은 버그가 “의도치 않게” 들어갔다고는 이제 믿기 어려움- “한 번은 우연, 두 번은 coincidence, 세 번은 적의 행동이다.” —Ian Fleming, Goldfinger
- 예전부터 이럴 것 같다고 어느 정도 의심해 왔음. Android에서 VPN을 켜도 MMS와 Visual Voicemail은 여전히 동작함
둘 다 직접 모바일 접근이 필요하거나 거부되는 경우가 있음. 모바일 네트워크에만 있거나, 요청이 모바일 네트워크 내부에서 온 것이 아니면 거부되기도 함. VoLTE도 마찬가지일 것이라 의심함. VPN이 있으면 이런 기능들이 꼬일 수 있음
Mobile Linux에서는 VPN을 켜면 이 기능들이 전부 깨져서 알게 됨
Android에서 기대되는 기능을 많이 망가뜨리지 않고 이걸 고칠 명확한 방법은 없어 보임- 아이러니하게도 SMS/MMS와 VVS는 통신사 연결에 하드코딩되는 것이 정당화될 만한 몇 안 되는 작업/기능임. 시스템 업데이트도 어쩌면 그럴 수 있음
VPN을 켠 iOS에서 AT&T 고급 지원팀과 VVS 문제로 씨름해 본 적이 있어서, 이 문제가 Android에만 국한되지 않는다는 점은 확인 가능함 - VoLTE는 LTE 스택에서 전용 bearer, 즉 별도 네트워크 인터페이스를 사용함. 데이터용 인터페이스가 아님
서로 다른 bearer는 다른 우선순위/QCI, 즉 서비스 품질을 가질 수 있음. 혼잡한 LTE 네트워크에서는 VoLTE가 낮은 우선순위 bearer의 VOIP보다 나은 경험을 제공해야 함
- 아이러니하게도 SMS/MMS와 VVS는 통신사 연결에 하드코딩되는 것이 정당화될 만한 몇 안 되는 작업/기능임. 시스템 업데이트도 어쩌면 그럴 수 있음