이 글이 필요한 증상
브라우저에서는 저장소 페이지가 열리는데 터미널의 git clone은 멈추고, npm install은 패키지 다운로드 중 시간 초과가 나거나, Docker 이미지의 레이어를 받다가 연결이 끊기는 경우가 있습니다. 이런 증상은 “인터넷이 안 된다”는 한 문장으로 묶기 어렵습니다. 브라우저는 운영체제 시스템 프록시를 사용하는 반면, 셸에서 실행되는 Git·Node.js·Docker는 각 프로그램의 프록시 설정이나 네트워크 경로를 따로 사용할 수 있기 때문입니다.
이 글에서는 Clash Verge Rev와 Mihomo 계열 클라이언트의 TUN 모드를 중심으로 개발용 터미널 트래픽을 점검합니다. TUN은 가상 네트워크 인터페이스를 통해 운영체제의 연결을 처리하므로, 앱마다 HTTP_PROXY를 설정하지 않아도 일부 CLI 트래픽을 라우팅할 수 있습니다. 다만 TUN을 켰다는 사실만으로 모든 프로그램과 Docker 데몬이 같은 경로를 타는 것은 아닙니다. DNS, 라우팅 규칙, 관리자 권한, 컨테이너의 실행 위치까지 확인해야 원인을 좁힐 수 있습니다.
먼저 문제가 발생한 명령, 대상 호스트, 실행 환경을 기록하세요. 예를 들어 로컬 셸에서 실패한 git clone과 원격 Linux 서버에서 실패한 Docker 빌드는 같은 종류의 문제처럼 보여도 네트워크 출구가 다릅니다. 로컬 PC에서 Clash를 실행 중이라면 그 PC의 트래픽을 다루고 있는지, Docker 데몬이 같은 PC에서 실행되는지부터 구분하는 것이 좋습니다.
TUN과 터미널 환경 변수의 역할 구분
TUN 모드는 운영체제 수준에서 가상 인터페이스와 경로를 구성해 일반 프로그램의 IP 트래픽을 Clash 코어로 전달하는 방식입니다. 시스템 프록시 설정을 읽지 않는 CLI에도 적용될 수 있다는 점이 장점입니다. 하지만 라우팅 모드, 운영체제 권한, DNS 처리 방식, 클라이언트 코어 설정에 따라 동작 범위는 달라집니다. 일부 애플리케이션은 자체 DNS나 네트워크 스택을 사용하므로, TUN에서 보이지 않거나 예상과 다른 규칙을 탈 수 있습니다.
환경 변수 방식은 프로그램이 HTTP 또는 SOCKS 프록시를 지원할 때 명시적으로 경로를 지정합니다. 두 접근은 경쟁하는 해결책이 아니라, 문제를 구분하고 필요한 범위에 적용하는 도구입니다. TUN을 켰는데도 특정 명령만 실패한다면 해당 CLI가 프록시 환경 변수를 읽는지 확인하고, 반대로 모든 연결을 무조건 프록시로 보내기보다 TUN의 연결 로그에서 실제 매칭 결과부터 살펴보세요.
- TUN을 우선 확인할 상황: 여러 CLI가 함께 실패하거나, 프록시 변수를 지원하지 않는 앱의 네트워크 경로를 확인해야 할 때
- 환경 변수를 확인할 상황: HTTP 클라이언트가 프록시 변수를 지원하거나, 한 명령만 로컬 프록시를 사용하도록 분리하고 싶을 때
- 규칙을 확인할 상황: 연결은 기록되지만 대상 호스트가
DIRECT, 예상하지 않은 그룹 또는REJECT로 처리될 때 - Docker를 별도로 볼 상황: 컨테이너 내부의 앱이 아니라 호스트의 Docker 데몬이 이미지 레지스트리에 접속하지 못할 때
개발 머신에서 쓰는 TUN 설정은 운영체제와 클라이언트 버전에 따라 메뉴 이름이나 권한 승인 절차가 다를 수 있습니다. 설정 화면에서 TUN 활성화, 자동 경로 설정, DNS 처리 항목을 확인하되, 다른 VPN이나 보안 제품도 가상 어댑터를 설치했다면 동시에 경로를 수정하지 않는지 점검하세요. 변경 전에는 현재 설정을 내보내거나 복사해 두면 원래 상태로 되돌리기 쉽습니다.
개발용 기준 설정과 적용 범위
먼저 Clash 프로필이 정상적으로 로드되고 코어가 실행 중인지 확인합니다. 그다음 현재 사용 중인 프록시 그룹과 연결 모드를 확인하고, TUN을 켜기 전에 mixed port 또는 HTTP·SOCKS 포트 번호도 메모해 둡니다. mixed port는 일반적으로 HTTP 프록시와 SOCKS 프록시 요청을 함께 받을 수 있지만, 실제 지원 방식과 포트 번호는 클라이언트 설정을 기준으로 확인해야 합니다. 예시의 숫자를 그대로 복사하지 말고 자신의 설정에 맞춰 바꾸세요.
Mihomo 프로필을 직접 관리한다면 TUN 관련 항목의 의미를 이해한 뒤 기존 구독 설정과 병합하세요. 프로필 전체를 아래 예시로 대체하면 DNS, 규칙, 프록시 그룹 등 기존 설정이 사라질 수 있습니다.
tun:
enable: true
auto-route: true
strict-route: true
stack: mixed
mixed-port: 7890
이 설정은 구조를 보여 주는 예시이며, 모든 운영체제에서 같은 값이 최선이라는 뜻은 아닙니다. strict-route는 경로 누출을 줄이는 데 도움을 줄 수 있지만, 로컬 네트워크 접근이나 다른 VPN과의 공존에 영향을 줄 수 있습니다. TUN 활성화 후 사내망, 프린터, 로컬 개발 서버에 접속할 수 없게 됐다면 해당 네트워크 대역을 어떻게 처리할지 규칙과 경로를 확인하세요. 자동 경로 설정을 사용할 때 관리자 권한이나 시스템 네트워크 확장 승인이 필요한 환경도 있습니다.
라우팅 규칙은 가능한 한 구체적으로 유지하는 편이 문제를 분석하기 쉽습니다. Git 호스트, 패키지 레지스트리, 컨테이너 레지스트리는 서로 다른 도메인을 사용할 수 있으며, CDN이나 리전별 호스트가 추가되기도 합니다. 특정 제품의 도메인 목록을 무작정 넓게 규칙에 넣기보다, 실패한 요청 직후 Clash 연결 로그에 나타나는 호스트와 최종 선택된 정책 그룹을 확인하세요. 로그에 대상이 나타나지 않는다면 DNS 또는 TUN 경로 단계에서 요청이 코어에 도달하지 않았을 가능성도 있습니다.
Git·npm·Docker를 순서대로 테스트하기
이제 실제 개발 작업으로 연결을 확인합니다. 아래 순서는 로컬 셸에서 수행하는 기준입니다. 프록시 포트가 다르면 명령의 주소를 바꾸고, 조직에서 별도의 인증 프록시를 제공한다면 해당 정책을 우선 따르세요. 비밀번호가 포함된 프록시 URL을 셸 기록이나 저장소에 남기지 않도록 주의합니다.
- Clash 연결 로그 확인: TUN을 활성화하고 규칙 모드에서 대상 호스트가 어떤 그룹으로 연결되는지 봅니다. 테스트 직전 로그를 지우거나 새 연결만 보이게 하면 기존 기록과 구분하기 편합니다.
- 간단한 HTTPS 요청: 대상 서버의 응답이 오는지와 DNS 해석이 되는지 확인합니다. 웹사이트의 루트 경로가 403을 반환하더라도 TLS 연결 자체는 성공했을 수 있으므로, HTTP 상태와 연결 오류를 구분합니다.
- Git 복제 테스트: 공개 저장소 하나로
git clone을 실행합니다. 실패하면 저장소 호스트가 로그에 잡히는지, 인증 단계까지 진행했는지 확인하세요. SSH 주소를 사용한다면 HTTPS 요청과 다른 포트 및 경로를 쓸 수 있으므로, HTTPS로도 비교 테스트합니다. - npm 패키지 테스트: 프로젝트의 잠금 파일을 보존한 상태에서 설치를 다시 시도합니다. 패키지 레지스트리뿐 아니라 tarball을 제공하는 CDN 도메인도 요청할 수 있습니다. 전체 레지스트리 주소를 바꾸기 전에 실패 로그에 표시된 호스트와 npm의 현재 설정을 확인합니다.
- Docker 이미지 테스트: 이미지 가져오기를 실행하고, 실패가 데몬의 레지스트리 접속인지 컨테이너 안의 애플리케이션 접속인지 구분합니다. Docker Desktop의 데몬은 별도 네트워크 설정을 사용할 수 있으며, 원격 Docker 호스트라면 로컬 PC의 TUN만으로 원격 호스트의 다운로드 경로가 바뀌지 않습니다.
환경 변수 방식과 비교하고 싶다면 먼저 한 터미널 세션에만 임시로 프록시를 지정해 보세요. 아래는 주소와 포트가 예시인 셸 명령입니다. 테스트가 끝나면 같은 세션에서 변수를 해제하거나 터미널을 닫으면 됩니다.
export HTTP_PROXY="http://127.0.0.1:7890"
export HTTPS_PROXY="http://127.0.0.1:7890"
export ALL_PROXY="socks5://127.0.0.1:7891"
export NO_PROXY="localhost,127.0.0.1,::1"
git clone https://example.com/owner/project.git
모든 프로그램이 환경 변수 이름을 똑같이 처리하는 것은 아닙니다. 일부는 소문자 http_proxy를 읽고, 일부는 자체 설정을 우선하거나 프록시를 지원하지 않습니다. 터미널에서 변수 값을 확인했는데 IDE 통합 터미널에서 결과가 다르다면, IDE가 셸을 시작한 시점에 주입된 환경이 오래된 것일 수 있습니다. 변수를 설정한 뒤 IDE를 완전히 종료하고 다시 열어 비교하세요.
Git에는 명령줄 환경 변수 대신 저장소 또는 사용자 범위의 프록시 설정이 있을 수 있고, npm에도 별도의 프록시 설정이 남아 있을 수 있습니다. 환경 변수를 바꿨는데 연결이 계속 이전 프록시를 향한다면 각 도구의 현재 설정과 셸 프로필을 확인합니다. 반대로 TUN이 이미 모든 대상 연결을 처리하는데 환경 변수까지 설정하면 프록시가 중복될 수 있으므로, 어느 방식이 요청을 처리하는지 로그와 간단한 테스트로 확인해야 합니다.
Docker 이미지 다운로드는 특히 실행 주체를 확인해야 합니다. 호스트에서 docker pull을 실행할 때 레지스트리에 접속하는 주체는 보통 Docker 데몬이며, 컨테이너에 HTTP_PROXY를 전달하는 설정은 컨테이너 내부 앱의 요청에 해당합니다. 따라서 앱 컨테이너에 변수를 넣었는데 이미지 다운로드가 계속 실패하는 것은 모순이 아닙니다. Docker Desktop의 프록시 설정, 데몬이 실행되는 호스트의 경로, 원격 엔진 사용 여부를 각각 살펴보세요. 빌드 중 특정 단계에서만 실패한다면 빌드 컨테이너의 환경 변수와 BuildKit 설정도 따로 점검해야 합니다.
DNS·시간 초과·인증 오류 구분하기
오류 메시지는 원인을 확정하는 답이라기보다 다음 점검 지점을 고르는 단서입니다. ENOTFOUND나 이름 해석 실패가 보이면 DNS 서버 응답, Clash DNS 설정, 로컬 캐시를 확인합니다. TUN 연결 로그에 도메인이 표시되지 않거나 IP 주소로만 보일 때는 DNS 요청이 Clash 경로를 통과하는지 살펴보세요. DNS 설정을 바꾼 직후에는 운영체제와 애플리케이션의 캐시가 남을 수 있으므로, 설정을 한 번에 여러 군데서 변경하기보다 캐시 상태와 새 요청 결과를 비교합니다.
ETIMEDOUT, i/o timeout, TLS 핸드셰이크 시간 초과는 DNS가 성공한 뒤의 경로 문제일 수 있습니다. 대상 호스트가 올바른 프록시 그룹에 들어갔는지, 선택한 노드가 안정적인지, 방화벽이 필요한 연결을 막고 있지 않은지 순서대로 확인하세요. TUN을 잠시 끄고 환경 변수만 사용한 테스트, 또는 TUN만 켜고 변수를 해제한 테스트를 각각 해 보면 문제가 가상 인터페이스, 규칙, 앱별 프록시 설정 중 어디에 가까운지 구분하는 데 도움이 됩니다.
반면 401이나 403은 네트워크가 연결된 뒤 인증 또는 접근 정책에서 거부된 경우가 많습니다. Git 자격 증명, 토큰 만료, 패키지 레지스트리 권한, 이미지 저장소 접근 권한을 확인하세요. 429는 요청 제한일 수 있으므로 프록시 노드를 바꾸는 것만으로 해결되지 않을 수 있습니다. 오류 응답의 상태 코드와 본문을 기록하되, 액세스 토큰·개인 저장소 주소·사내 호스트를 외부에 공유하지 않도록 로그를 가리세요.
연결이 간헐적으로 끊긴다면 한 번의 성공 여부만으로 판단하지 말고 동일한 명령을 짧은 간격으로 몇 차례 실행해 보세요. 특정 프록시 그룹에서만 실패하는지, 다운로드 초반과 큰 파일 전송 중 어느 시점에 끊기는지, Clash 로그의 연결 시간과 오류 시각이 맞는지 함께 확인합니다. 여러 노드의 자동 선택이 원인인지 알고 싶다면 테스트 중에는 그룹을 고정해 변수를 줄일 수 있습니다. 확인이 끝나면 평상시 정책으로 되돌리는 것도 잊지 마세요.
자주 묻는 질문
TUN을 켜면 HTTP_PROXY 설정은 필요 없나요?
항상 그런 것은 아닙니다. TUN은 운영체제의 경로를 통해 연결을 처리할 수 있지만, 애플리케이션의 자체 네트워크 설정이나 Docker 데몬의 실행 환경에 따라 별도 프록시가 필요할 수 있습니다. 먼저 TUN 연결 로그에서 해당 프로그램의 호스트가 보이는지 확인한 뒤, 환경 변수를 추가해 결과가 달라지는지 비교하세요. 두 방식을 동시에 무작정 적용하기보다 한 번에 하나씩 검증하는 편이 원인 파악에 유리합니다.
NO_PROXY에는 어떤 주소를 넣어야 하나요?
localhost, 루프백 주소, 개발 중인 로컬 서비스처럼 프록시를 거칠 필요가 없는 대상을 우선 고려할 수 있습니다. 사내 도메인이나 내부 IP 대역은 조직의 네트워크 정책에 맞춰 추가해야 합니다. 너무 넓은 와일드카드나 상위 도메인을 넣으면 외부 서비스까지 프록시를 우회할 수 있으므로, 제외 범위를 작게 시작하고 실제 요청 경로를 확인하세요.
TUN은 정상인데 Docker 이미지 다운로드만 실패하는 이유는 무엇인가요?
이미지 다운로드를 수행하는 Docker 데몬이 로컬 셸과 같은 네트워크 경로를 사용하지 않을 수 있기 때문입니다. Docker Desktop의 프록시 설정, 원격 Docker 엔진 여부, 데몬의 DNS 및 네트워크 설정을 확인하세요. 컨테이너 내부 앱에 프록시 변수를 전달하는 것과 데몬이 레지스트리에서 이미지를 받는 것은 서로 다른 단계입니다.
Git은 되는데 npm 또는 특정 저장소만 실패하면 어떻게 하나요?
도구마다 접속하는 호스트와 프록시 처리 방식이 다를 수 있습니다. npm은 패키지 메타데이터와 파일을 서로 다른 호스트에서 받을 수 있고, Git도 HTTPS와 SSH 주소가 다른 연결 경로를 사용합니다. 실패한 요청 직후 Clash 로그에서 실제 도메인과 정책 그룹을 확인하고, 해당 도구의 개별 설정이나 인증 상태를 함께 점검하세요.
개발 환경에서는 단순히 시스템 프록시만 제공하는 도구가 통합 터미널이나 Docker 데몬까지 자동으로 처리하지 못하는 경우가 있고, 반대로 모든 트래픽을 무조건 우회시키는 설정은 내부 저장소와 로컬 서비스까지 불필요하게 바꿀 수 있습니다. Clash TUN은 연결 로그와 규칙을 함께 확인하면서 CLI 트래픽의 경로를 조정하고, 필요할 때 Git·npm 같은 도구에만 프록시 변수를 적용할 수 있어 문제 범위를 단계적으로 좁히기 좋습니다. 여러 앱의 설정을 따로 관리하기보다 개발 머신의 네트워크 흐름을 직접 확인하고 싶다면, 사용 중인 플랫폼에 맞는 클라이언트를 살펴보세요.