트래픽 처리와 규칙에 따른 분기는 구분해야 합니다
시스템 프록시와 TUN은 앱의 연결을 Clash 코어로 전달하는 같은 단계의 문제를 해결합니다. 연결이 코어에 들어온 뒤 mode, rules, 정책 그룹에 따라 직접 연결할지, 프록시를 이용할지, 차단할지가 결정됩니다. 따라서 TUN을 켰다고 모든 연결이 프록시를 거치는 것은 아니며, 시스템 프록시를 켰다고 기기 전체의 트래픽이 처리되는 것도 아닙니다.
이 문서의 설정 예시는 Clash Meta를 이어서 개발한 mihomo 코어를 기준으로 합니다. GUI 클라이언트에 따라 일부 설정이 자동 생성되거나 덮어써질 수 있습니다. 이전 버전 Clash 코어, 모바일 VPN 인터페이스, 데스크톱 클라이언트의 옵션은 서로 완전히 같다고 볼 수 없습니다. 설정을 바꾸기 전에 클라이언트의 코어 정보나 시작 로그에서 실제 실행 중인 코어를 확인하세요.
예를 들어 mode: rule에서는 TUN으로 들어온 연결도 DIRECT 규칙에 매칭될 수 있습니다. 시스템 프록시를 통해 로컬 7890 포트로 전달된 연결도 규칙에 따라 프록시 노드로 보내질 수 있습니다. 트래픽이 들어오는 경로와 나가는 경로는 따로 확인해야 합니다.
시스템 프록시: 앱이 로컬 포트에 직접 연결
GUI 클라이언트의 시스템 프록시 기능은 보통 운영체제의 프록시 설정을 바꿔, 해당 설정을 따르는 앱의 요청을 로컬 리스닝 포트로 전달합니다. 예를 들어 mixed-port: 7890으로 설정하면 앱이 먼저 127.0.0.1:7890에 연결하고, 이후 연결은 코어가 처리합니다. mixed 포트는 HTTP 프록시와 SOCKS 프록시 연결을 모두 받습니다.
HTTPS 프록시 연결은 HTTPS 복호화를 뜻하지 않습니다
브라우저가 HTTP 프록시를 통해 HTTPS 사이트에 접속할 때는 보통 CONNECT로 터널을 만듭니다. 시스템 프록시를 켜도 사이트의 TLS 콘텐츠가 자동으로 복호화되지 않으며, 일반적인 프록시 이용에 사이트 인증서를 설치할 필요도 없습니다. 프록시 프로토콜의 HTTP와 대상 사이트의 HTTPS는 서로 다른 계층의 개념입니다.
시스템 프록시가 적용되지 않는 대표적인 경우
- 명령줄 프로그램:
HTTP_PROXY,HTTPS_PROXY등의 환경 변수만 읽거나 프록시 인수를 별도로 지정해야 할 수 있습니다. - 게임 및 자체 네트워크 프로그램: 시스템 프록시 설정을 읽지 않고 소켓을 직접 연결할 수 있습니다.
- Windows 서비스: 실행 계정과 네트워크 API가 현재 사용자와 다를 수 있습니다. 사용자 프록시 설정이 모든 서비스의 프록시 설정을 의미하지는 않습니다.
- UDP 트래픽: HTTP 프록시를 켰다고 게임의 UDP, 음성 통화, QUIC까지 프록시를 거친다고 단정할 수 없습니다.
시스템 프록시는 구독, 노드, 기본 규칙을 먼저 확인할 때 적합합니다. 현재 사용자의 프록시 설정을 바꾸는 데 관리자 권한으로 계속 실행할 필요가 없는 경우가 많고, 적용 범위도 파악하기 쉽습니다. 브라우저만 프록시가 필요하다면 처리 범위를 넓히려고 곧바로 TUN을 켤 필요는 없습니다.
TUN: 가상 인터페이스로 IP 패킷 전달
TUN은 시스템에 가상 네트워크 인터페이스를 만들고 라우팅과 함께 사용해 조건에 맞는 IP 패킷을 코어로 전달합니다. 앱은 HTTP나 SOCKS 프록시를 별도로 인식하지 않고 일반적인 방식으로 대상 주소에 연결합니다. mihomo는 전달받은 패킷을 처리한 다음 규칙에 따라 출구를 선택합니다.
auto-route: true는 관련 라우트를 자동으로 설정하고, auto-detect-interface: true는 출구 인터페이스를 자동으로 감지합니다. 두 옵션이 권한 문제를 해결하거나 다른 VPN과의 라우팅 호환성을 보장하는 것은 아닙니다. 회사 VPN에 연결하거나 Wi-Fi를 바꾸거나 유선 네트워크 어댑터를 추가하면 출구 인터페이스와 라우팅 우선순위가 달라질 수 있습니다.
| 비교 항목 | 시스템 프록시 | TUN |
|---|---|---|
| 코어로 전달되는 방식 | 앱이 로컬 프록시 포트에 연결 | 라우팅으로 IP 패킷을 가상 인터페이스에 전달 |
| 앱의 프록시 설정 지원 여부 | 프록시 설정을 읽거나 프록시를 명시적으로 지정해야 함 | 대체로 앱이 프록시 프로토콜을 인식할 필요 없음 |
| UDP 처리 | 일반 HTTP 시스템 프록시만으로 UDP까지 처리된다고 볼 수 없음 | 라우팅 범위의 UDP를 처리할 수 있지만 출구도 UDP를 지원해야 함 |
| 시스템 권한 | 대체로 현재 사용자 설정 변경으로 가능 | 대개 권한 상승, 서비스 실행 또는 플랫폼 권한 필요 |
| 주요 점검 항목 | 포트, 앱 설정, 환경 변수 | 가상 인터페이스, 라우팅, DNS, 출구 인터페이스 |
TUN을 사용해도 UDP를 지원하지 않는 노드에 UDP 기능이 생기는 것은 아니며, 모든 IP 프로토콜을 원격 프록시로 전달할 수 있는 것도 아닙니다. 특히 ping의 성공 여부만으로 TCP 웹사이트 접속 상태를 판단하지 마세요. ICMP와 실제 서비스 연결은 서로 다른 경로로 처리될 수 있습니다.
DNS: 도메인 조회 경로가 규칙 매칭에 영향을 줍니다
시스템 프록시를 사용할 때 도메인을 누가 조회하는지는 앱과 프록시 프로토콜에 따라 다릅니다. HTTP 프록시에는 도메인 형식의 대상 주소를 전달할 수 있습니다. SOCKS5는 도메인을 전달할 수도 있고, 앱이 미리 조회한 IP를 전달할 수도 있습니다. 터미널에서 socks5://와 socks5h://는 조회 경로가 달라질 수 있으므로 출구 IP가 바뀌었는지만 확인해서는 안 됩니다.
TUN이 받는 데이터는 대개 IP 패킷입니다. 도메인 규칙이 안정적으로 동작하려면 코어가 DNS 매핑이나 기존 메타데이터를 활용하거나 필요한 경우 트래픽을 스니핑해야 합니다. DNS를 확인하지 않고 가상 인터페이스만 켜면 사이트는 접속되지만 도메인 규칙이 예상과 다르게 적용될 수 있습니다.
fake-ip와 DNS 가로채기의 역할
enhanced-mode: fake-ip: 해당하는 DNS 쿼리에 매핑용 주소를 반환하고, 코어가 그 주소를 도메인과 다시 연결합니다. 예시에 나온198.18.0.1/16은 이 매핑에 쓰이며 실제 웹사이트의 출구 주소가 아닙니다.dns-hijack: 조건에 맞는 DNS 트래픽을 코어의 DNS 처리로 전달합니다. 흔히 UDP 53과 TCP 53을 설정합니다.nameserver: 코어가 실제로 사용할 업스트림 DNS 서버를 지정합니다. 암호화 여부와 접속 가능성, 분기 정책은 별도로 검토해야 합니다.
IPv6도 별도로 확인해야 합니다. IPv4 라우팅만 조정했다고 IPv6도 같은 정책으로 처리된다고 볼 수 없습니다. 사내 도메인, 프린터 이름, 로컬 네트워크 서비스가 내부 DNS에 의존한다면 해당 조회 경로를 유지하세요. 모든 DNS 문제를 노드 장애 탓으로 돌리지 마세요.
mihomo 설정: 변경은 최소한으로
아래는 설정 항목을 설명하기 위한 예시이며 완전한 구독 설정이 아닙니다. 기존 설정의 해당 위치에 합치고 proxies, proxy-groups, rules는 유지하세요. 같은 계층에 dns나 tun을 중복 선언하지 마세요. 클라이언트에 오버라이드 기능이 있다면 구독을 새로고침해도 수정 내용이 사라지지 않도록 지속성 있는 오버라이드 기능을 사용하세요.
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- "any:53"
- "tcp://any:53"
dns:
enable: true
listen: 127.0.0.1:1053
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
nameserver:
- 223.5.5.5
- 119.29.29.29
127.0.0.1:1053은 여기서 명시적으로 연 로컬 DNS 리스닝 주소입니다. 운영체제가 자동으로 이 포트에 DNS 쿼리를 보내는 것은 아닙니다. TUN의 DNS 가로채기는 코어 DNS로 들어가는 별도의 경로입니다. 예시에서는 설정 항목 간 관계를 분명히 보여주기 위해 기존 DNS를 업스트림으로 사용했습니다. 실제 환경과 개인정보 보호 요구에 맞는 업스트림을 선택하고, 이 두 주소를 일반적인 최적 설정으로 여기지 마세요.
stack은 system, gvisor, mixed 중 무엇을 선택해야 할까요?
system: 시스템 프로토콜 스택으로 연결을 처리합니다. 현재 시스템과 코어 구현에서 호환되는지 확인해야 합니다.gvisor: 사용자 공간 프로토콜 스택을 사용하며, 특정 호환성 문제를 비교할 때 대안으로 활용할 수 있습니다.mixed: mihomo에서 두 프로토콜 스택을 함께 사용합니다. TCP는 system 경로를, UDP는 gVisor 경로를 이용합니다.
특정 stack 옵션이 모든 기기에서 더 빠르다고 단정하지 마세요. 테스트할 때는 노드, 대상, 규칙을 동일하게 유지하고 stack만 바꾸세요. 코어를 재시작하고 기존 연결이 종료된 것을 확인한 다음 연결 성공률과 실제 사용 상태를 비교합니다. 현재 클라이언트나 코어가 해당 값을 지원하지 않으면 기본값으로 되돌리세요. 다른 버전의 설정을 반복해서 적용해서는 안 됩니다.
권한과 병행 사용: 먼저 각각 검증한 뒤 함께 쓸지 결정하세요
Windows에서는 가상 네트워크 어댑터 생성과 라우팅 설정에 보통 관리자 권한이 필요하며, 일부 클라이언트는 서비스 모드로 이를 처리합니다. macOS와 Linux도 적절한 권한 상승이나 서비스 권한이 필요합니다. Linux에서는 TUN 장치와 네트워크 관리 권한도 관련됩니다. GUI에서 TUN 스위치가 켜져 있더라도 작업이 요청됐다는 의미일 뿐입니다. 시작 로그에서 권한 오류, 인터페이스 생성 실패, 라우트 추가 실패가 없는지 확인하세요.
사용 범위에 따라 진입 방식을 선택하세요
- 브라우저와 일반 데스크톱 앱: 먼저 시스템 프록시만 켜고 노드, 규칙, 로컬 포트가 정상인지 확인합니다.
- 터미널 도구: 먼저 프록시 인수를 명시해 확인한 다음 환경 변수를 설정할지 결정합니다. 임시 변수는 전체 설정을 바꾸는 것보다 되돌리기 쉽습니다.
- 프록시 설정을 읽지 않는 프로그램: 시스템 프록시를 끄고 TUN만 따로 테스트합니다. 두 진입 방식을 동시에 바꾸면 문제 원인을 찾기 어려워집니다.
- 여러 진입 방식이 실제로 필요한 경우: 각각 검증한 뒤 함께 켤 수 있습니다. 앱이 로컬 프록시를 명시하면 해당 경로를 이용하고, 라우팅 조건에 맞는 나머지 트래픽은 TUN이 처리할 수 있습니다.
두 기능을 함께 켠다고 반드시 프록시가 중복 적용되는 것은 아니며, 네트워크 품질이 자동으로 좋아지는 것도 아닙니다. 일반적으로 코어 자체의 아웃바운드 연결은 루프를 피하기 위해 TUN 처리에서 제외해야 합니다. 수동 라우팅, 다른 VPN, 잘못된 출구 인터페이스가 이 전제를 깨뜨릴 수 있습니다. 함께 사용한 뒤 문제가 생기면 우선 한 가지 진입 방식만 사용하는 설정으로 되돌리세요.
시스템 프록시에는 ‘로컬 주소 우회’ 같은 규칙이 남아 있을 수 있으며, TUN의 사설망 라우팅은 별도의 설정입니다. NAS, 로컬 네트워크 프린터, 사내망에 접속해야 한다면 시스템 프록시의 우회 목록, 라우팅, mihomo 규칙을 각각 확인하세요. 두 기능의 예외 범위가 같다고 가정하지 마세요.
연결 경로 확인 및 문제 해결
같은 대상을 사용해 비교하세요. 먼저 로컬 프록시 포트가 동작하는지 확인하고, 그다음 시스템 차원의 트래픽 처리가 적용되는지 점검합니다. 아래 명령은 테스트 방법일 뿐, 실제 측정 결과를 미리 보장하지 않습니다. Windows에서는 일부 PowerShell 환경의 동명 별칭이 매개변수에 영향을 주지 않도록 curl.exe를 명시하는 것이 좋습니다.
1단계: 프록시를 명시해 시스템 처리 여부를 배제합니다
curl --proxy http://127.0.0.1:7890 --connect-timeout 10 --max-time 20 -I https://example.com/
curl --proxy socks5h://127.0.0.1:7890 --connect-timeout 10 --max-time 20 -I https://example.com/
이 경우 시스템 프록시가 꺼져 있어도 명령은 지정된 로컬 포트에 연결을 시도합니다. 연결이 거부되면 먼저 코어가 실행 중인지, 실제 리스닝 포트가 7890인지 확인하세요. 코어까지 연결되지만 접속에 실패한다면 로그에서 DNS 조회, 규칙, 노드 핸드셰이크, 원격 연결 오류를 확인합니다.
2단계: 프록시를 명시하지 않고 TUN 경로를 확인합니다
curl --noproxy "*" --connect-timeout 10 --max-time 20 -I https://example.com/
--noproxy "*"는 이번 curl 요청에서 앱 계층 프록시 설정을 사용하지 않도록 하지만, 운영체제의 TUN 라우팅을 우회하지는 않습니다. 시스템 프록시를 끄고 TUN을 켠 상태에서 명령을 실행한 뒤 클라이언트의 연결 화면에서 대상, 매칭된 규칙, 정책을 확인하세요. 명령이 성공했다는 사실만으로 프록시 노드를 사용했다고 볼 수는 없습니다. 규칙에 따라 DIRECT가 선택됐을 수도 있습니다.
3단계: 증상에 따라 점검 범위를 좁힙니다
- 프록시를 명시하면 성공하지만 TUN에서는 실패: 권한, 가상 인터페이스, 라우팅을 먼저 확인합니다. Windows에서는
route print, Linux에서는ip route로 라우팅 테이블을 확인할 수 있습니다. - 브라우저에서는 성공하지만 터미널에서는 실패: 터미널 환경 변수와 도구 자체의 프록시 옵션을 확인하세요. 노드 문제라고 바로 단정하지 마세요.
- 도메인 접속은 실패하지만 알려진 IP에는 연결 가능: DNS를 중점적으로 확인하되 적절한 테스트 서비스를 사용하세요. HTTPS 도메인을 IP로 직접 바꾸면 인증서와 SNI가 달라질 수 있습니다.
- TCP는 정상이지만 음성 통화나 게임에 문제 발생: 규칙 모드만 바꾸지 말고 UDP 처리, 노드의 UDP 지원, 서버 측 제한을 확인하세요.
- 다른 VPN을 켠 뒤 문제 발생: 둘 중 하나를 잠시 끄고 기본 라우트, DNS, 출구 인터페이스를 비교한 다음 두 VPN의 공존 범위를 설정하세요.
한 번에 변수 하나만 바꾸고 ‘진입 경로, DNS, 매칭 규칙, 실제 적용 정책, 오류 로그’ 다섯 가지를 기록하세요. 설정을 되돌릴 때는 먼저 TUN을 끄고 원래 설정을 복원한 다음 시스템 프록시 주소를 확인합니다. 클라이언트를 종료하기 전에 127.0.0.1:7890을 계속 가리키는 프록시 설정을 해제하세요. 로컬 리스닝이 중단된 뒤에도 앱이 이전 포트에 연결하는 일을 방지할 수 있습니다.