결론: 시스템 프록시를 따르지 않는 앱에는 TUN 사용

브라우저는 연결되는데 게임, 명령줄 프로그램 또는 데스크톱 앱은 연결되지 않는다면 해당 앱이 시스템 프록시를 따르는지 먼저 확인하세요. 시스템 프록시는 앱에 HTTP 프록시 설정을 제공할 뿐이며, 앱이 이를 사용할 수도 무시할 수도 있습니다. TUN은 네트워크 계층에서 가상 네트워크 어댑터로 라우팅된 IP 패킷을 받아 처리하므로 앱마다 프록시 주소를 설정할 필요가 없습니다.

이 문서의 설정 예시는 Clash Meta의 후속 프로젝트인 mihomo의 설정 키를 기준으로 합니다. Clash는 커널과 클라이언트 생태계를 통칭하는 이름으로 널리 쓰이지만, 화면에 “TUN”이 표시된다고 해서 커널이나 운영체제별 구현이 모두 같은 것은 아닙니다. 클라이언트의 “정보” 또는 커널 정보에서 실제 사용하는 커널을 확인한 뒤 해당 설정을 적용하세요.

  • 브라우저만 사용: 시스템 프록시로 충분한 경우가 많고, 문제를 추적하기도 더 쉽습니다.
  • 앱에 프록시 설정이 없음: TUN이 더 적합합니다. 다만 해당 앱의 TCP·UDP 트래픽이 실제로 처리되는지 확인해야 합니다.
  • 게임, 음성 통화 또는 QUIC: TUN뿐 아니라 프록시 프로토콜과 서버가 UDP 전달을 지원하는지도 확인하세요.
  • 회사 VPN이나 원격 데스크톱을 사용 중: 먼저 작업 내용을 저장하고 기존 라우팅과 DNS 설정을 기록하세요. 원격 연결이 유일한 접속 수단일 때는 기본 경로를 섣불리 변경하지 마세요.

가상 네트워크 어댑터의 원리: IP 패킷부터 규칙 기반 분기까지

트래픽 처리 과정은 네 단계입니다

  1. 앱이 연결을 시작합니다. 프로그램이 도메인이나 IP에 접속하려 하면 시스템은 라우팅 테이블을 바탕으로 전송할 네트워크 어댑터를 결정합니다.
  2. 라우팅이 TUN으로 향합니다. 클라이언트가 가상 네트워크 어댑터를 만들고 필요한 경로를 설정합니다. 조건에 맞는 패킷은 TUN 장치로 들어갑니다.
  3. 커널이 연결을 처리합니다. 네트워크 스택이 IP 패킷을 받고 대상 주소와 포트, 확인 가능한 도메인 정보를 추출해 규칙 엔진으로 전달합니다.
  4. 아웃바운드 정책을 적용합니다. 직접 연결 트래픽은 실제 네트워크 인터페이스를 통해 전송하고, 프록시 트래픽은 선택한 프록시 연결을 통해 보냅니다. 응답은 해당 경로를 따라 앱으로 돌아옵니다.

여기서 말하는 “가상 네트워크 어댑터”는 물리 네트워크를 새로 추가하는 것이 아닙니다. 운영체제와 사용자 공간 네트워크 프로그램이 패킷을 주고받는 인터페이스입니다. 클라이언트의 프록시 아웃바운드 트래픽이 다시 TUN으로 들어가 라우팅 루프를 만들지 않도록 해야 합니다. 이 때문에 아웃바운드 인터페이스 식별과 권한 설정이 중요합니다.

처리 범위는 라우팅과 제외 설정에 따라 달라집니다

auto-route: true는 TUN으로 향하는 경로를 자동 설정하고, auto-detect-interface: true는 아웃바운드 인터페이스를 자동으로 식별합니다. 두 설정만으로 모든 환경의 트래픽을 처리할 수 있는 것은 아닙니다. 다른 VPN의 경로, 특정 네트워크 어댑터에 바인딩된 앱, 클라이언트 제외 설정, IPv6 구성에 따라 실제 경로가 달라질 수 있습니다.

IPv4만 처리하도록 설정했는데 앱이 IPv6를 우선 사용하면 일부 연결은 다른 경로로 나갈 수 있습니다. “웹페이지가 열린다”는 이유만으로 모든 트래픽이 처리된다고 판단하지 마세요. 대상 앱의 연결 기록과 규칙 일치 결과, 실제 아웃바운드 정책을 함께 확인해야 합니다. TUN이 같은 LAN의 다른 기기까지 자동으로 프록시 처리하는 것도 아닙니다. 게이트웨이 공유에는 별도의 포워딩과 라우팅 설정이 필요합니다.

system과 gvisor 비교: 네트워크 스택을 선택하고 호환성을 테스트하세요

stack은 TUN 패킷을 처리할 네트워크 스택을 지정합니다. 노드 프로토콜이나 프록시 암호화 방식이 아닙니다. 성능은 운영체제, 커널 버전, 연결 유형과 기기 성능에 따라 달라지므로 특정 스택을 무조건 “가장 빠르다”고 단정할 수 없습니다.

네트워크 스택 처리 방식 선택 기준
system 운영체제의 네트워크 스택으로 연결을 처리하며, 구체적인 구현은 플랫폼마다 다릅니다. 우선 사용해 볼 만한 기본 선택입니다. 특정 앱이나 UDP 호환성 문제가 있을 때 다른 스택으로 바꿔 확인하세요.
gvisor gVisor 기반 사용자 공간 네트워크 스택으로 패킷을 처리합니다. system과 비교 테스트할 때 유용합니다. 사용자 공간에서 처리하므로 CPU 사용량이 늘어날 수 있습니다.
mixed mihomo에서 TCP는 system, UDP는 gvisor로 처리합니다. TCP와 UDP를 각각 다른 방식으로 처리할 때 사용할 수 있습니다. 현재 커널과 클라이언트가 이 옵션을 지원하는지 확인하세요.

비교 테스트에서는 한 번에 한 가지 설정만 변경하세요

  1. 프록시 정책, 규칙 모드와 네트워크 환경을 동일하게 유지하고 먼저 system을 사용합니다.
  2. 대상 앱을 열고 약 60초 동안 연결 여부, 연결 끊김 여부, CPU 사용량이 계속 높은지 확인해 기록합니다.
  3. 네트워크 스택만 gvisor로 바꾸고 커널을 다시 시작한 다음 같은 작업을 반복합니다.
  4. UDP를 사용하는 앱에서만 문제가 생긴다면 프록시 서버가 UDP를 지원하는지 먼저 확인하세요. 모든 문제를 네트워크 스택 탓으로 돌리지 마세요.

비교 기록은 “system: 웹페이지 정상, 음성 연결 실패 / gvisor: 웹페이지 정상, 음성 연결 성공”처럼 작성할 수 있습니다. 이는 기록 예시일 뿐, 이 문서에서 직접 측정한 결과가 아닙니다. 지연 시간이 40ms로 측정되더라도 게임 UDP가 제대로 전달된다는 증거는 아닙니다.

mihomo 설정: TUN, DNS, 라우팅을 함께 확인하세요

아래는 전체 설정에 병합할 수 있는 기본 예시이며, 프록시 서버 정보와 정책 그룹은 포함하지 않습니다. 기존 구독 설정의 proxies, proxy-groups, rules는 유지하세요. 가능하면 클라이언트의 오버라이드 또는 병합 기능을 사용하세요. 구독으로 생성된 파일을 직접 수정하면 업데이트할 때 변경 사항이 덮어써질 수 있습니다.

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info

tun:
  enable: true
  stack: system
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53
    - tcp://any:53

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - "*.lan"
    - "*.local"
  nameserver:
    - 1.1.1.1
    - 8.8.8.8

각 포트의 용도

  • 7890: HTTP와 SOCKS가 함께 사용하는 혼합 프록시 수신 포트입니다. 시스템 프록시나 앱이 명시적으로 연결할 때 사용합니다. TUN이 모든 IP 패킷을 이 포트로 보내는 것은 아닙니다.
  • 127.0.0.1:1053: 로컬 DNS 수신 주소입니다. 시스템의 53번 포트를 직접 사용하는 것을 피할 수 있지만, 시스템 DNS가 자동으로 이 주소로 변경되는 것은 아닙니다.
  • any:53 및 tcp://any:53: 처리 경로로 들어온 일반 UDP·TCP 53번 포트 DNS 요청을 찾아 내장 DNS로 전달합니다.
  • 198.18.0.1/16: fake-ip에 사용하는 주소 풀입니다. 커널이 도메인과 가상 주소를 연결하도록 돕는 주소로, 프록시 서버 주소가 아닙니다.

DNS 하이재킹의 범위

앱 내장 DoH·DoT는 일반적인 53번 포트 DNS 요청을 사용하지 않으므로 위의 dns-hijack 설정만으로 DNS 내용을 바꿀 수 없습니다. 해당 연결은 TUN을 통과할 수 있지만 내장 DNS가 최종 도메인을 알아내지 못할 수도 있습니다. 도메인 규칙의 적용 여부는 fake-ip 매핑, 스니핑 설정과 실제 프로토콜에 따라서도 달라집니다.

fake-ip 모드에서 외부 도메인이 198.18.0.23과 비슷한 주소를 반환하는 것은 정상일 수 있습니다. 이는 도메인 매핑 결과이지 대상 사이트의 실제 IP가 아닙니다. LAN 프린터, NAS 또는 내부 도메인에 호환성 문제가 생기면 실제 도메인에 맞춰 필터링이나 DNS 분할을 설정하세요. 내부 도메인 하나를 해결하려고 모든 도메인을 fake-ip에서 제외하지는 마세요.

운영체제별 설정: 먼저 권한을 허용한 다음 커널을 시작하세요

메뉴 이름은 클라이언트 버전에 따라 달라질 수 있습니다. 아래에서는 일반적인 메뉴 위치와 설정 목적을 설명합니다. 같은 이름의 메뉴가 보이지 않으면 “서비스”, “권한”, “TUN”, “가상 네트워크 어댑터”를 찾아 해당 기능을 확인하세요. 다른 클라이언트의 메뉴 경로가 현재 버전에서도 동일하다고 가정하지 마세요. 클라이언트 선택은 클라이언트 비교를 먼저 참고하세요.

Windows: 서비스 모드와 가상 네트워크 어댑터 드라이버

  1. 설정을 가져온 뒤 시스템 프록시로 동일한 프록시 정책이 대상 서비스에 연결되는지 먼저 확인하세요. 혼합 포트가 7890이라면 앱 설정도 같은 포트를 사용해야 합니다.
  2. Clash Verge Rev의 일반적인 화면을 예로 들면 “설정” → “서비스 모드”에서 화면 안내에 따라 서비스를 설치하거나 활성화합니다. 이 과정에서 관리자 권한을 요청할 수 있습니다.
  3. 홈 화면에서 “TUN 모드”를 켜거나 해당 버전의 네트워크 설정에서 TUN을 활성화합니다. 서비스를 사용할 수 없다면 스위치를 반복해서 켜고 끄지 말고 먼저 서비스 상태를 해결하세요.
  4. 커널 로그에서 가상 네트워크 어댑터와 라우팅이 초기화되었는지, 권한이나 드라이버 오류가 없는지 확인한 다음 기존에 프록시를 따르지 않던 앱을 테스트합니다.

Windows 클라이언트에는 보통 Wintun 같은 가상 네트워크 어댑터 드라이버가 필요합니다. 드라이버는 클라이언트가 지원하는 절차에 따라 내려받아 설치하세요. 출처가 불분명한 곳에서 드라이버 파일을 복사하지 마세요. PowerShell에서 현재 네트워크 어댑터와 IPv4 경로를 확인할 수 있습니다:

Get-NetAdapter
Get-NetRoute -AddressFamily IPv4 |
  Sort-Object RouteMetric |
  Format-Table DestinationPrefix, InterfaceAlias, NextHop, RouteMetric

가상 네트워크 어댑터 이름은 클라이언트나 설정에 따라 달라지며 반드시 Clash라는 이름을 쓰는 것은 아닙니다. 어댑터가 보인다는 것은 장치가 생성됐다는 뜻일 뿐이므로 라우팅과 연결 기록도 확인해야 합니다. 다른 VPN을 함께 사용 중이면 두 VPN이 트래픽 처리를 두고 충돌하지 않도록 하나를 종료한 뒤 테스트하세요.

macOS: 보조 서비스 권한과 utun 인터페이스

  1. 클라이언트와 해당 커널이 TUN을 지원하는지 확인하세요. 시스템 프록시만 지원하는 클라이언트는 YAML 키를 추가하는 것만으로 완전한 TUN 기능을 사용할 수 없습니다.
  2. 클라이언트의 서비스 또는 권한 설정에서 안내에 따라 보조 서비스를 설치하고 관리자 권한을 허용합니다.
  3. TUN을 활성화하고 로그에서 장치, 라우팅, DNS 초기화 정보를 확인합니다.
  4. 터미널에서 인터페이스와 라우팅을 확인한 뒤 대상 앱을 실행해 테스트합니다.
ifconfig
netstat -rn -f inet
scutil --dns

macOS에서는 utun 뒤에 번호가 붙은 가상 인터페이스를 흔히 볼 수 있지만, 다른 VPN이나 시스템 서비스도 utun을 만들 수 있습니다. utun3이 보인다는 이유만으로 현재 클라이언트의 인터페이스라고 단정하지 마세요. 잠자기에서 깨어난 뒤나 Wi-Fi를 바꾼 뒤 문제가 생기면 프록시 노드만 바꾸지 말고 아웃바운드 인터페이스를 다시 확인하세요.

Linux: TUN 장치와 네트워크 관리 권한

Linux에서 TUN을 사용하려면 일반적으로 /dev/net/tun을 사용할 수 있어야 하며, 인터페이스 생성과 라우팅 변경을 위한 네트워크 관리 권한도 필요합니다. 데스크톱 클라이언트는 서비스로 권한을 부여할 수 있습니다. 커널을 직접 실행한다면 배포판과 서비스 구성에 맞춰 권한을 설정하세요. 출처가 불분명한 실행 파일에 높은 권한을 부여하거나 편의를 위해 클라이언트 디렉터리 전체에 재귀적으로 권한을 부여하지 마세요.

ls -l /dev/net/tun
ip link show
ip rule show
ip route show table all

라우팅을 확인할 때는 모든 테이블을 살펴보세요. 자동 트래픽 처리가 정책 라우팅을 사용할 수 있으므로 ip route만 실행해서는 전체 규칙이 보이지 않을 수 있습니다. 컨테이너 환경에서는 호스트가 TUN 장치와 필요한 권한을 제공해야 합니다. 컨테이너 안에서 스위치를 켠다고 호스트의 앱까지 처리되는 것은 아닙니다.

Android·iOS: 운영체제의 VPN 권한 사용

Android용 일반적인 Clash 클라이언트는 VpnService로 트래픽을 처리하며, 처음 활성화할 때 시스템 VPN 연결 권한을 요청합니다. 대개 root 권한은 필요하지 않습니다. 앱의 VPN 모드, 우회 앱 목록과 시스템의 백그라운드 배터리 제한을 확인하세요. 일반 VPN 서비스는 보통 같은 사용자 계정에서 하나만 활성화할 수 있습니다. 다른 VPN을 시작하면 현재 연결이 대체될 수 있습니다.

iOS에서는 클라이언트 자체가 Network Extension 같은 시스템 기능을 제공하고 사용 권한을 받아야 합니다. 데스크톱 설정의 TUN 키를 추가한다고 해당 기능이 생기는 것은 아닙니다. 클라이언트 안내에 따라 VPN 구성을 추가하고 권한을 허용한 뒤, 지원되는 설정 문법을 확인하세요. mihomo의 전체 TUN 설정을 문법이 다른 iOS 클라이언트에 그대로 적용하지 마세요.

트래픽 처리 확인: TUN 스위치만 보지 마세요

세 가지 항목을 함께 확인하세요

  1. 장치와 라우팅: 가상 인터페이스가 생성되고 처리 경로가 설정됐는지, 로그에 권한 오류나 장치 열기 실패가 계속 나타나지 않는지 확인합니다.
  2. 대상 앱 연결: 이전에 시스템 프록시를 무시하던 앱을 열고 클라이언트의 “연결” 화면에서 대상 주소와 포트를 확인합니다. HTTPS는 보통 TCP 443, QUIC은 보통 UDP 443을 사용하지만 포트만으로 앱 유형을 확정할 수는 없습니다.
  3. 규칙과 아웃바운드: 연결에 예상한 규칙과 정책이 적용됐는지 확인합니다. 프록시를 거쳐야 하는 대상이 DIRECT에 일치하면 TUN이 정상이어도 기대한 대로 동작하지 않습니다.

두 가지 유입 경로를 구분하려면 시스템 프록시를 잠시 끄고 대상 앱에 직접 입력한 HTTP·SOCKS 프록시 설정도 지운 뒤 TUN만으로 테스트할 수 있습니다. 브라우저로 인터넷에 접속된다는 것만으로는 충분하지 않습니다. 직접 연결로도 해당 사이트에 접속할 수 있기 때문입니다. 연결 기록과 아웃바운드 정책을 함께 확인하고 테스트가 끝나면 필요한 설정을 복원하세요.

증상에 따라 원인을 좁히세요

증상 우선 확인할 항목
활성화 후 모든 앱의 네트워크가 끊김 서비스 권한, 아웃바운드 인터페이스 식별, DNS 접속 가능 여부, 다른 VPN과의 라우팅 충돌
웹페이지는 열리지만 음성 통화나 게임이 작동하지 않음 UDP 처리 여부, 프록시 서버의 UDP 지원, 앱 제외 목록을 확인한 뒤 네트워크 스택을 비교 테스트합니다.
공용 인터넷은 되지만 NAS나 프린터에 연결할 수 없음 LAN 라우팅, 내부 DNS, fake-ip 필터링, 현재 네트워크의 실제 서브넷
Wi-Fi를 바꾼 뒤 연결이 끊김 아웃바운드 인터페이스가 갱신됐는지, 이전 경로가 남아 있는지 확인하고 TUN을 다시 활성화한 뒤 로그를 살펴봅니다.
연결 기록에 대상 앱이 표시되지 않음 앱이 제외됐는지, 처리되지 않는 IPv6나 특정 인터페이스를 사용하는지, 로그 기록이 필터링됐는지 확인합니다.

문제를 조사할 때 로그 수준을 잠시 debug로 설정하고 TUN 활성화와 대상 앱 실행 시간을 정확히 기록하세요. 예를 들어 14:32:10에 TUN을 켜고 14:32:20에 앱을 실행했다면 그 전후 10초 동안의 장치, 라우팅, DNS, 연결 오류를 확인합니다. 원인을 찾은 뒤에는 info로 되돌리세요. 로그를 공유하기 전 구독 주소, 토큰과 개인 네트워크 정보를 가리세요.

비활성화와 복구: 먼저 네트워크를 복원한 뒤 원인을 계속 확인하세요

기기 전체의 네트워크가 끊기면 먼저 TUN을 끄고 클라이언트가 자동 라우팅을 해제하도록 한 뒤 필요에 따라 시스템 프록시를 복구하세요. 커널 프로세스를 강제 종료하는 것보다 클라이언트를 정상 종료하는 편이 설정 정리에 유리합니다. 종료 후에도 문제가 계속되면 시스템 프록시가 더는 수신하지 않는 127.0.0.1:7890을 가리키는지, DNS·가상 인터페이스·라우팅이 복구됐는지 확인하세요.

  • 라우팅 테이블 전체를 무작정 삭제하지 마세요. 기업 네트워크, 컨테이너와 다른 VPN이 기존 규칙에 의존할 수 있습니다.
  • 가상 네트워크 어댑터를 모두 무작정 비활성화하지 마세요. 클라이언트 로그와 인터페이스 변화를 확인해 현재 클라이언트가 만든 장치를 먼저 식별하세요.
  • fake-ip 캐시 때문에 앱이 계속 가상 주소를 받는다면 앱을 종료한 뒤 다시 실행하세요. 필요하다면 운영체제 방식에 따라 DNS 캐시를 갱신합니다.
  • 네트워크를 복구한 뒤 “권한과 장치 → 라우팅과 아웃바운드 → DNS → 규칙과 정책 → 앱 프로토콜” 순서로 다시 확인하고, 한 번에 설정 하나만 변경하세요.

최종 설정은 이유를 설명할 수 있고, 검증과 복구가 가능해야 합니다. TUN은 트래픽 유입을 처리하고, DNS는 도메인 정보를 제공하며, 규칙은 아웃바운드를 결정하고, 프록시 서버는 실제 연결을 전달합니다. 설정 키에 대한 자세한 설명은 고급 설정의 TUN 설정을 참고하세요. 구독을 처음 가져온다면 빠른 시작 가이드에 따라 먼저 기본 연결을 설정하세요.