시스템 프록시·TUN 말고 왜 mixed-port를 쓰나
많은 사용자가 Clash를 켜 두었는데도 터미널에서만 레지스트리·Git 원격·컨테이너 이미지 풀이 막히는 이유는 단순합니다. GUI 앱은 macOS·Windows의 시스템 프록시를 따르기 쉽지만, CLI와 Docker 데몬은 기본적으로 그 설정을 전혀 보지 않거나, 보는 경로가 다릅니다. 반면 TUN은 운영체제 라우팅을 바꾸므로 “한 번에 다 잡히는” 대신 VPN·사내 터널·가상 브리지와 충돌할 여지가 큽니다.
그래서 실무에서는 명시적 프록시—즉 특정 포트의 HTTP 프록시와 SOCKS5를 환경 변수로 밀어 넣는 방식이 자주 쓰입니다. Clash 계열에서 mixed-port는 그 한 포트가 CONNECT 기반 HTTP와 SOCKS를 함께 받아 주므로, 셸과 빌드 스크립트에 넣을 값이 짧아집니다. 서버에서 TUN까지 켜야 한다면 Ubuntu TUN·systemd 가이드와 개념 편인 TUN 모드 심화를 함께 보시면 흐름이 이어집니다.
mixed-port 한 곳에 HTTP와 SOCKS5 얹기
설정 파일에서 mixed-port(또는 클라이언트 UI의 동일 옵션)를 켜면, 예를 들어 7890 같은 단일 포트가 HTTP 프록시 요청과 SOCKS5 연결을 모두 처리합니다. 별도로 port(HTTP)·socks-port를 나눠도 되지만, 셸 스크립트와 문서 예시가 길어지기 쉬워 mixed-port가 검색·복붙에 유리합니다. 실제 숫자는 구독·충돌 여부에 맞게 바꾸되, 아래 예시에서는 7890을 가정합니다.
mixed-port: 7890
# optional explicit split if you prefer:
# port: 7890
# socks-port: 7891
코어·GUI 조합이 많으므로, “지금 돌아가는 인스턴스가 어느 YAML을 읽는지”를 먼저 확인하세요. 클라이언트 선택이 헷갈리면 클라이언트 선택 가이드로 편집·로그 경험부터 맞추는 편이 빠릅니다.
호스트 IP·allow-lan·방화벽
컨테이너나 VM이 호스트의 Clash에 붙으려면 리스너가 127.0.0.1에만 묶여 있으면 안 됩니다. 대개 allow-lan: true와 함께 bind-address(또는 동등 옵션)를 LAN 대역 또는 *로 열어야 합니다. 동시에 OS 방화벽에서 해당 TCP 포트를 허용했는지 확인하세요. 보안상 필요한 최소 대역만 열고, 공용 와이파이에서는 LAN 공유를 끄는 것이 안전합니다.
allow-lan: true
bind-address: '*'
터미널: ALL_PROXY·HTTP_PROXY·HTTPS_PROXY·NO_PROXY
대부분의 최신 CLI 스택은 ALL_PROXY를 인식합니다. HTTP 프록시만 쓸 때는 http://127.0.0.1:7890 형태가 단순하고, TLS까지 한 번에 실어내려면 동일 URI를 HTTPS_PROXY에도 복제합니다. SOCKS5를 택한다면 socks5://127.0.0.1:7890 또는 원격 DNS를 프록시 쪽에서 하게 하려면 socks5h:// 계열(도구별 표기 차이 있음)을 검토합니다.
export HTTP_PROXY="http://127.0.0.1:7890"
export HTTPS_PROXY="http://127.0.0.1:7890"
export ALL_PROXY="http://127.0.0.1:7890"
export NO_PROXY="localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
NO_PROXY는 내부 레지스트리·사내 Git·로컬 쿠버네티스 API를 프록시로 보내지 않기 위한 안전장치입니다. 쉼표 목록과 접미사 규칙은 런타임마다 조금씩 다르므로, 막히면 공식 문서의 패턴 예시를 그대로 대조하세요. 규칙 기반 출구 자체는 규칙 라우팅 모범 사례와 맞물립니다.
SOCKS5와 SOCKS5h(원격 DNS) 선택
일부 환경에서는 로컬이 가짜 IP를 돌려 주거나, 특정 이름이 프록시 밖에서만 올바르게 풀립니다. 이때 SOCKS5에 호스트 이름을 넘겨 원격에서 해석하게 하는 패턴이 유용합니다. 반대로 사내 DNS만 신뢰해야 한다면 HTTP 프록시 경로와 시스템 리졸버 설정을 먼저 정리하는 편이 낫습니다. DNS 동작이 궁금하면 FAQ의 DNS 관련 설명을 함께 읽어 두면 로그 해석이 수월해집니다.
git·curl이 안 탈 때 점검할 것
git은 http.proxy·https.proxy 설정이 환경 변수보다 우선할 수 있고, 일부 빌드는 자체 TLS 스택을 써서 프록시를 무시합니다. git config --global --get http.proxy로 잔존 값을 확인하고, 필요하면 해제한 뒤 환경 변수만 남깁니다. curl은 -x 또는 --proxy로 단발 테스트하기 좋아, “Clash 포트는 살아 있는데 변수만 안 먹는지”를 분리할 때 유용합니다.
Docker가 호스트 Clash를 보려면: Linux·macOS
Linux 네이티브 Docker
컨테이너에서 호스트로 가는 고정 이름은 배포판마다 다릅니다. 흔히 172.17.0.1(docker0 게이트웨이)이나 host.docker.internal(최신 Docker에서 지원되는 경우)을 씁니다. 실제 주소는 ip route·docker network inspect로 확인하고, 그 IP를 프록시 URL에 넣으세요.
macOS Docker Desktop
host.docker.internal이 호스트 루프백의 Clash를 가리키는 경우가 많아, 컨테이너 내부 프록시 URL은 http://host.docker.internal:7890 같은 형태가 됩니다. 버전에 따라 동작이 조금씩 다르므로, 한 번 docker run으로 curl 테스트를 하는 것이 확실합니다.
docker pull: 데몬 프록시 vs 클라이언트 환경 변수
이미지 풀은 Docker 데몬이 수행하는 경우가 많아, 셸에만 HTTP_PROXY를 넣어서는 안 되고 /etc/docker/daemon.json(Linux)이나 Docker Desktop 설정에 프록시를 넣어야 합니다. 반대로 docker compose 일부 하위 명령은 클라이언트 측 변수를 탈 수 있어, 증상이 “풀만 안 된다” vs “빌드만 안 된다”로 갈리면 주체를 먼저 나누세요.
{
"proxies": {
"http-proxy": "http://172.17.0.1:7890",
"https-proxy": "http://172.17.0.1:7890",
"no-proxy": "localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
}
}
docker build: BuildKit·build-arg
Dockerfile 안의 RUN apt-get·RUN curl는 빌드 컨텍스트 안에서 실행되므로, 호스트 셸 변수가 자동 전달되지 않습니다. BuildKit을 쓰는 경우 --build-arg HTTP_PROXY=...처럼 명시하거나, 데몬/클라이언트가 빌드 시 프록시를 주입하도록 설정해야 합니다. 멀티 스테이지에서 앞 단계와 뒤 단계가 서로 다른 네트워크 네임스페이스를 쓰는 일이 없도록, 동일한 프록시 URL을 반복해서 맞추는 편이 덜 헷갈립니다.
docker build \
--build-arg HTTP_PROXY="http://host.docker.internal:7890" \
--build-arg HTTPS_PROXY="http://host.docker.internal:7890" \
--build-arg NO_PROXY="localhost,127.0.0.1" \
.
NO_PROXY에 꼭 넣을 후보
localhost,127.0.0.1,::1— 로컬 대시보드·메트릭- 사설 대역(
10.0.0.0/8등) — 내부 레지스트리·Git - 사내 도메인 접미사 — 조직마다 다르므로 실제 호스트명을 로그에서 수집
*.svc계열 — 일부 쿠버네티스 환경(도구별 지원 확인)
너무 넓게 열어 두면 의도치 않은 트래픽이 직행하고, 너무 좁으면 내부 서비스까지 프록시로 들어가 타임아웃이 납니다. 변경 후에는 반드시 아래 검증을 반복하세요.
검증 순서
- 호스트에서
curl -I로 프록시를 통한 외부 HTTPS 응답 확인 - 같은 명령을
NO_PROXY에 넣은 내부 호스트로 실행해 직행 여부 확인 - 컨테이너 안에서 호스트 Clash IP·포트로 동일 테스트
- Clash 대시보드·로그에서 해당 세션이 기대한 정책 그룹으로 나가는지 확인
연결 단계에서 TLS·타임아웃이 섞이면 timeout·TLS 로그 가이드로 원인을 층별로 나눌 수 있습니다.
맺음말
Clash mixed-port는 “한 포트에 HTTP 프록시와 SOCKS5를 같이 올려 둔다”는 사실만 기억해도, 터미널과 CI 스크립트가 훨씬 단순해집니다. 여기에 ALL_PROXY·NO_PROXY를 일관되게 쓰고, Docker는 데몬·빌드·런타임 중 어디가 실제로 외부로 나가는지 구분하면 반복적인 삽질이 크게 줄어듭니다. TUN으로 모든 앱을 한 번에 묶는 글들과 달리, 이 접근은 “프록시를 존중하는 도구만” 골라 실어내므로 충돌 면적이 작습니다.
비슷한 범주의 도구들 가운데, 규칙 편집과 연결 로그를 한 화면에서 다루고 현대 코어를 전제로 한 클라이언트를 쓰면 운영 감각이 덜 지치는 편입니다. 다른 구성에 비해 Clash는 이런 “보이는 라우팅” 쪽에서 체감이 무난한 경우가 많습니다.
오픈소스 변경 이력·이슈는 업스트림 저장소에서 확인할 수 있지만, 일반 사용자가 클라이언트를 받을 때는 사이트 다운로드 페이지를 기본 경로로 두는 편이 덜 혼란스럽습니다.
→ Clash를 무료로 다운로드하고, mixed-port 한 줄을 기준으로 터미널과 컨테이너 설정을 같은 언어로 맞춰 보세요.