먼저 시스템 프록시와 실제 트래픽 경로를 구분하세요
Clash 클라이언트의 「시스템 프록시」는 보통 모든 프로그램을 덮는 전역 터널이 아닙니다. 운영체제의 HTTP 및 HTTPS 프록시 주소를 127.0.0.1로 설정하고, Clash가 로컬에서 수신 중인 포트를 지정하는 방식입니다. 브라우저는 이 설정을 읽어 요청을 Clash로 전달하지만, 터미널 프로그램이 설정을 읽는지는 프로그램 자체와 실행 환경, 프록시 프로토콜에 따라 달라집니다.
일반적인 기본값은 HTTP 포트 7890, SOCKS5 포트 7891이며, mixed-port: 7890 하나로 HTTP와 SOCKS5를 모두 받을 수도 있습니다. 포트 번호에 정해진 표준은 없습니다. 설정 파일, 클라이언트 버전 또는 사용자의 재설정에 따라 달라질 수 있으므로, 확인할 때는 클라이언트의 「설정」→「포트 설정」이나 현재 설정의 항목을 기준으로 삼으세요.
mixed-port: 7890
allow-lan: false
mode: rule
dns:
enable: true
enhanced-mode: fake-ip
웹페이지는 열리는데 curl, git, npm 또는 특정 명령줄 다운로드 도구가 여전히 직접 연결된다면, 노드 전체가 고장 난 경우는 드뭅니다. 브라우저의 요청은 Clash로 들어가지만 터미널의 요청은 들어가지 않거나, 터미널이 다른 DNS·프로토콜·규칙을 사용한다고 보는 편이 정확합니다.
첫 번째 경로: 브라우저가 시스템 프록시를 읽는 방식
Clash 로컬 포트가 수신 중인지 확인
시스템 프록시가 수신되지 않는 포트를 가리키면 브라우저에 연결 거부가 표시되는 경우가 많습니다. Windows PowerShell에서는 7890을 확인하고, macOS와 Linux에서는 해당 프로세스를 확인할 수 있습니다. 실제 포트가 7890이 아니라면 명령의 숫자를 바꾸세요.
# Windows PowerShell
Get-NetTCPConnection -LocalPort 7890 -State Listen
# macOS
lsof -nP -iTCP:7890 -sTCP:LISTEN
# Linux
ss -lntp | grep 7890
예상 결과에는 127.0.0.1:7890 또는 0.0.0.0:7890 같은 로컬 수신 주소가 포함되어야 합니다. 결과가 없으면 클라이언트로 돌아가 설정 프로필이 실행 중인지, 프록시 스위치가 켜져 있는지, 포트를 다른 프로그램이 사용 중인지 확인하세요. 포트 충돌이 발생하면 임시로 7897로 바꾼 뒤 시스템 프록시와 터미널 변수도 함께 업데이트하세요.
운영체제의 프록시 주소 확인
- Windows 11: 「설정」→「네트워크 및 인터넷」→「프록시」→「수동 프록시 설정」으로 이동하세요. 주소는
127.0.0.1이어야 하며, 포트는 Clash의 HTTP 또는 mixed 포트와 같아야 합니다. - macOS: 「시스템 설정」→「네트워크」→현재 네트워크 인터페이스→「세부사항」→「프록시」로 이동하세요. 웹 프록시 HTTP와 보안 웹 프록시 HTTPS를 확인합니다.
- Firefox: 「설정」→「일반」→「네트워크 설정」으로 이동하세요. 「수동 프록시 설정」을 선택하면 시스템 프록시를 덮어쓰므로, 운영체제 설정을 따르려면 「시스템 프록시 설정 사용」을 선택하세요.
- Chrome과 Edge는 보통 운영체제의 프록시를 읽지만, 확장 프로그램·기업 정책·브라우저 시작 매개변수가 이 경로를 다시 설정할 수 있습니다.
브라우저를 확인할 때는 페이지 결과와 Clash 연결 기록을 함께 확인해야 합니다. 이전에 방문하지 않은 사이트를 열고 클라이언트의 연결 페이지에서 도메인으로 필터링하세요. 대상 도메인, 적용된 규칙, 출구 노드가 보이면 요청이 커널에 들어간 것입니다. 웹페이지가 열리는지만으로는 프록시 접속인지, 캐시 적중인지, 직접 연결인지 구분할 수 없습니다.
규칙 때문에 브라우저가 직접 연결되는지 확인
시스템 프록시를 켰다고 해서 반드시 프록시 노드를 사용하는 것은 아닙니다. mode: rule에서는 요청이 규칙 매칭을 거쳐야 합니다. 연결 기록에 DIRECT가 표시되면 도메인 규칙, 규칙 세트, 최종 규칙을 확인하세요. 전역 모드로 잠시 전환해 비교할 수 있지만, 확인이 끝나면 규칙 모드로 되돌리세요.
rules:
- DOMAIN-SUFFIX,example.com,Proxy
- GEOIP,CN,DIRECT
- MATCH,Proxy
전역 모드는 작동하지만 규칙 모드는 작동하지 않는다면 문제는 시스템 프록시 스위치가 아니라 규칙 순서, 정책 그룹 선택 또는 구독 생성 내용에 있습니다. Clash 규칙은 위에서 아래로 매칭되며 첫 번째로 일치한 규칙에서 멈춥니다. 범위가 넓은 DIRECT 규칙이 앞에 있으면 뒤의 도메인 규칙을 먼저 가로챌 수 있습니다.
두 번째 경로: 터미널 프로그램이 프록시를 따르지 않는 이유
터미널 창 자체가 네트워크를 자동으로 전달하는 것은 아닙니다. 실제 요청을 보내는 것은 curl, Git, Node.js, Python 패키지 관리자 또는 다른 명령입니다. 프로그램마다 프록시를 읽는 방식이 다릅니다. 일부는 HTTP_PROXY와 HTTPS_PROXY를 읽고, 일부는 소문자 변수를 읽으며, 일부는 명령 매개변수만 지원하고, 별도 설정 파일을 사용하는 프로그램도 있습니다.
curl에 프록시를 직접 지정해 기준 테스트하기
먼저 환경 변수를 우회하고 curl이 Clash의 HTTP 포트에 직접 연결하도록 하세요. 이 단계로 “터미널이 시스템 설정을 읽지 않음”과 “Clash 로컬 프록시를 사용할 수 없음”을 구분할 수 있습니다.
curl -v -x http://127.0.0.1:7890 https://api.ipify.org
curl -v --connect-timeout 10 \
-x http://127.0.0.1:7890 \
https://www.example.com/
출력에는 먼저 127.0.0.1:7890으로 연결하는 과정이 나타난 뒤 HTTPS의 CONNECT 과정이 이어져야 합니다. 프록시를 명시하면 성공하지만 -x 없이 실패한다면 노드·포트·Clash 커널은 대체로 정상이며, 이후에는 터미널 설정만 확인하면 됩니다.
SOCKS5 테스트에는 socks5h를 사용할 수 있습니다. 끝의 h는 도메인 이름 확인을 프록시 측에서 처리한다는 뜻으로, 로컬 DNS 이상을 배제할 때 유용합니다. socks5를 사용하면 보통 도메인을 먼저 로컬에서 확인한 뒤 IP를 프록시에 전달합니다.
curl -v --proxy socks5h://127.0.0.1:7891 \
https://api.ipify.org
현재 터미널에 환경 변수 설정
macOS, Linux, Git Bash 및 대부분의 Unix 계열 셸에서는 현재 세션에 변수를 내보낼 수 있습니다. 도구마다 읽는 규칙이 다르므로 대문자와 소문자 형식을 함께 설정하는 것이 좋습니다. 터미널 창을 닫으면 이 임시 변수는 사라집니다.
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
export NO_PROXY=localhost,127.0.0.1,::1
curl -v https://api.ipify.org
PowerShell에서는 현재 프로세스의 환경에 변수를 설정할 수 있습니다. 실행 후에는 해당 PowerShell 창과 그 창에서 시작한 하위 프로세스에만 적용되며, 이미 열려 있는 편집기나 다른 터미널은 자동으로 변경되지 않습니다.
$env:HTTP_PROXY="http://127.0.0.1:7890"
$env:HTTPS_PROXY="http://127.0.0.1:7890"
$env:NO_PROXY="localhost,127.0.0.1,::1"
curl.exe -v https://api.ipify.org
확인이 끝나면 테스트 변수를 삭제하세요. Clash가 종료된 뒤에도 프로그램이 작동하지 않는 로컬 포트에 계속 접속하는 일을 막을 수 있습니다.
# bash / zsh
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY NO_PROXY
# PowerShell
Remove-Item Env:HTTP_PROXY
Remove-Item Env:HTTPS_PROXY
Remove-Item Env:NO_PROXY
Git, npm, Python의 독립 설정
환경 변수는 일회성 점검에 적합합니다. 장기간 사용할 때는 도구에 이전 포트가 저장되어 있지 않은지도 확인해야 합니다. Git은 전역 설정과 저장소 설정을 각각 읽으며, 저장소 내부의 로컬 항목이 더 높은 우선순위를 가집니다.
git config --global --get http.proxy
git config --global --get https.proxy
git config --local --get http.proxy
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
# 전역 프록시 삭제
git config --global --unset http.proxy
git config --global --unset https.proxy
npm에서는 npm config get proxy와 npm config get https-proxy로 설정을 확인할 수 있습니다. 값이 null일 때만 npm이 환경 변수를 계속 참고할 가능성이 있습니다. 이전 설정이 여전히 127.0.0.1:7897을 가리키면 시스템 프록시를 7890으로 바꿔도 npm은 계속 이전 포트에 접속합니다.
npm config get proxy
npm config get https-proxy
npm config set proxy http://127.0.0.1:7890
npm config set https-proxy http://127.0.0.1:7890
npm config delete proxy
npm config delete https-proxy
Python의 pip는 환경 변수를 읽을 수 있고 명령 매개변수로도 테스트할 수 있습니다. 한 번만 설치할 때 프록시를 추가하려면 영구적으로 설정 파일에 기록하는 것보다 매개변수를 사용하는 편이 되돌리기 쉽습니다.
python -m pip install --proxy http://127.0.0.1:7890 package-name
python -m pip config list
python -m pip config debug
DNS, IPv6, UDP: 프록시에 들어간 뒤에도 실패할 수 있는 이유
이름 확인 실패와 연결 실패 구분
터미널 오류에 포함된 키워드로 원인을 좁힐 수 있습니다. Could not resolve host는 도메인 확인 단계의 문제를 가리키고, Connection refused는 보통 로컬 프록시 포트가 수신 중이지 않다는 뜻입니다. Operation timed out은 노드 경로, 규칙 출구, 방화벽 또는 대상 사이트 응답 지연 때문일 수 있습니다. TLS 인증서 오류라면 시스템 시간, 인증서 저장소, 프로그램이 사용하는 TLS 백엔드를 확인하세요.
HTTP 프록시로 HTTPS 사이트에 접속할 때 클라이언트는 보통 먼저 프록시에 CONNECT를 보냅니다. SOCKS5에서는 socks5h와 socks5가 도메인을 확인하는 위치가 다릅니다. 일반 socks5는 실패하지만 socks5h가 성공한다면 구독을 바로 바꾸지 말고 먼저 로컬 DNS를 확인하세요.
IPv4와 IPv6 결과 확인
일부 터미널 프로그램은 IPv6에 우선 연결하지만 현재 네트워크의 IPv6 라우팅이 완전하지 않을 수 있습니다. curl -4와 curl -6을 각각 실행해 비교하세요. IPv4는 2초 안에 응답하고 IPv6는 10초 후 시간 초과가 발생한다면 문제는 HTTP 프록시 변수가 아니라 IPv6 경로에 있습니다.
curl -4 -I --connect-timeout 10 https://www.example.com/
curl -6 -I --connect-timeout 10 https://www.example.com/
curl -4 -I -x http://127.0.0.1:7890 https://www.example.com/
curl -6 -I -x http://127.0.0.1:7890 https://www.example.com/
또한 기존 HTTP 시스템 프록시는 주로 TCP 기반 HTTP와 HTTPS를 처리합니다. UDP 기반 QUIC, 게임 트래픽, 음성 앱, 사용자 지정 프로토콜은 이 경로를 반드시 거치지 않습니다. 브라우저는 프록시 환경에서 TCP로 전환할 수 있지만 다른 앱은 같은 방식으로 전환하지 않을 수 있어, 웹페이지는 정상인데 특정 앱만 시간 초과되는 차이가 생깁니다.
TUN 모드로 전환해야 하는 경우
TUN 모드는 가상 네트워크 인터페이스와 시스템 라우팅을 통해 더 많은 IP 트래픽을 처리합니다. 각 앱이 HTTP 프록시를 이해하거나 HTTP_PROXY를 읽을 필요가 없습니다. 여러 터미널 도구와 UDP 앱, 프록시를 설정할 수 없는 소프트웨어를 함께 적용하거나 프록시 변수를 일일이 관리하는 일을 줄이고 싶다면 TUN이 시스템 프록시보다 적합한 경우가 많습니다.
TUN으로 전환하기 좋은 상황
- 브라우저는 안정적으로 Clash에 연결되지만 여러 명령줄 도구가 시스템 프록시를 무시하는 경우
- 앱이 사용자 지정 TCP 또는 UDP 프로토콜을 사용하며 HTTP·HTTPS·SOCKS5 프록시 설정이 없는 경우
- 개발 환경에 컨테이너, 패키지 관리자, 백그라운드 프로세스가 포함되어 각각 환경 변수를 설정하기 부담스러운 경우
- DNS 조회와 연결 트래픽이 같은 규칙을 따르게 하여 로컬 확인 경로의 차이를 줄여야 하는 경우
- 시스템 프록시를 꺼도 규칙에 따라
DIRECT, 프록시 그룹, 최종 출구를 결정하고 싶은 경우
mihomo 커널의 일반적인 설정에는 tun.enable, stack, 자동 라우팅, DNS 하이재킹이 포함됩니다. 사용할 수 있는 값은 클라이언트에 포함된 커널 버전과 운영체제 권한에 따라 달라집니다. 수정하기 전에 현재 정상 작동하는 Profile을 보존하고, 클라이언트가 제공하는 설정 화면에서 활성화하세요. 시스템 라우팅을 두 번째로 수동 생성하지 마세요.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
tun.enable: true · stack: mixed · auto-route: true
활성화한 뒤에는 먼저 시스템 프록시를 끄고 비교 테스트를 진행하세요. 같은 요청이 시스템 프록시를 거친 다음 TUN 라우팅에 다시 처리되는 일을 피할 수 있습니다. 대부분의 커널은 이런 조합을 처리하지만, 문제 해결 단계에서는 단일 경로를 유지하는 편이 판단하기 쉽습니다. 이후 브라우저, curl, Git, 대상 앱을 각각 테스트하고 연결 기록에서 적용된 규칙을 확인하세요.
Android의 시스템 프록시와 VPN 경로
Android 클라이언트는 일반적으로 데스크톱 시스템에서 흔히 사용하는 HTTP 프록시 설정이 아니라 시스템 VpnService를 통해 로컬 VPN 인터페이스를 만듭니다. 처음 시작할 때 표시되는 연결 요청은 Android 시스템 권한 승인 절차입니다. 승인하면 앱이 VPN 인터페이스를 생성하고 해당 인터페이스로 라우팅된 트래픽을 받을 수 있습니다.
Android 브라우저는 작동하지만 Termux의 명령이 작동하지 않는다면 먼저 클라이언트에서 앱별 프록시, 앱 우회 또는 선택한 앱만 프록시하는 기능이 켜져 있는지 확인하세요. 메뉴 이름은 클라이언트마다 다르지만, 일반적인 경로는 「설정」→「네트워크」→「접근 제어」 또는 「설정」→「매개변수 설정」→「앱별 프록시」입니다. Termux가 프록시 앱 목록에 포함되지 않았다면 해당 트래픽은 물리 네트워크로 직접 나갈 수 있습니다.
- 연결 기록에서 Termux 요청의 대상 도메인을 검색하세요.
- 접근 제어가 현재 「선택한 앱만 프록시」인지 「선택한 앱 우회」인지 확인하세요.
- 비공개 DNS를 잠시 끄고 비교한 뒤 원래 설정으로 복원하고 결과를 기록하세요.
- 화면이 꺼진 뒤 배터리 절전 정책이 VPN 서비스를 종료하지 않는지 확인하세요.
- 현재 Profile의 DNS, TUN, 규칙 그룹이 실제로 적용되고 있는지 확인하세요.
Termux에서는 export HTTPS_PROXY=http://127.0.0.1:포트를 사용할 수도 있지만, 여기의 루프백 주소와 포트는 Android 클라이언트가 실제로 로컬 앱에 개방한 값이어야 합니다. 클라이언트가 주로 VPN 인터페이스로 작동하고 로컬 HTTP 수신 포트를 열지 않았다면 이 변수를 설정해도 연결되지 않습니다. 이 경우 데스크톱 포트를 그대로 따라 하기보다 VPN의 앱 적용 범위를 먼저 수정하세요.
순서대로 실행하는 최종 점검표
- Clash 클라이언트에서 Profile이 실행 중이고 정책 그룹에 사용 가능한 노드가 선택되어 있는지 확인하세요.
- 현재
mixed-port,port또는socks-port값을 확인하고, 반드시7890이라고 가정하지 마세요. - 수신 확인 명령으로 로컬 포트가 존재하는지 확인하고 포트 충돌을 해결하세요.
- 브라우저에서 새 페이지를 열면서 Clash 연결 기록과 적용된 규칙을 함께 확인하세요.
-x를 포함한curl을 실행해 명시적 프록시 기준을 세우세요.- 명시적 프록시가 성공한 뒤 현재 터미널에 프록시 환경 변수를 설정하세요.
- Git, npm, pip 등의 도구에 저장된 독립 프록시 설정과 이전 포트를 확인하세요.
socks5h,-4,-6을 사용해 DNS와 IP 경로를 구분하세요.- HTTP가 아닌 트래픽, UDP 또는 많은 백그라운드 프로그램을 처리해야 한다면 TUN으로 전환해 단일 경로를 확인하세요.
- 확인이 끝나면 임시 변수를 삭제하고 규칙 모드와 기존 DNS 설정을 복원하세요.
가장 중요한 판단 기준은 “프록시 스위치가 켜져 있는가”가 아니라 요청이 실제로 어느 경로를 거쳤는가입니다. 브라우저 경로는 시스템 프록시와 규칙을, 터미널 경로는 프로그램 매개변수·환경 변수·독립 설정을, 복잡한 앱의 경로는 TUN·라우팅·DNS를 확인해야 합니다. 수신 포트, 명시적 프록시, 환경 변수, 도구 설정, TUN 순서로 점검하면 구독을 변경하지 않고도 대개 문제를 찾아낼 수 있습니다.