CHAPTER 01 / POLICY GROUPS
정책 그룹 유형과 실전 활용
정책 그룹은 규칙과 노드 사이에 위치합니다. 규칙의 마지막 필드는 대개 특정 노드명이 아니라 정책 그룹명이며, 정책 그룹이 사용자의 선택, 상태 점검 또는 장애 상태에 따라 실제 아웃바운드를 결정합니다. 규칙을 단일 노드에 직접 연결하면 작성은 간단하지만, 노드 장애 시 전환이나 서비스별 분기, 구독 업데이트가 어려워집니다. 안정적인 설정은 먼저 “수동 선택”, “자동 최적화”, “장애 전환”, “스트리밍”, “다운로드 직접 연결”처럼 업무 목적을 나눈 뒤 규칙이 이러한 안정적인 이름을 가리키도록 구성합니다. 구독의 노드명이 바뀌어도 필터를 통해 해당 정책 그룹에 다시 포함되기만 하면 규칙 계층은 수정할 필요가 없습니다.
select, url-test, fallback 및 load-balance
select는 사용자가 직접 선택하는 그룹으로, 장기간 특정 지역의 출구를 유지하거나 계정 로그인 위치를 수동으로 확인하거나 임시 장애를 진단할 때 적합합니다. 자동으로 노드를 바꾸지 않으므로 현재 노드를 사용할 수 없으면 대개 사용자의 개입이 필요합니다. 따라서 그룹 안에 “자동 최적화”를 선택지로 남겨 두는 것이 좋습니다. url-test는 지정된 주소로 연결 테스트를 수행하고 후보 노드 중 측정 지연 시간이 낮은 노드를 선택합니다. 테스트 지연 시간은 탐지 대상과 시점만 반영하며 모든 웹사이트의 실제 속도를 의미하지 않습니다. 간격이 너무 짧으면 불필요한 연결이 늘어나므로 데스크톱의 일상적인 사용에서는 지속적으로 갱신하기보다 보통 몇 분 간격으로 설정합니다.
fallback은 목록 순서대로 처음 사용할 수 있는 노드를 선택하므로 주 회선과 예비 회선이 명확하고 장애 발생 시에만 예비 회선이 인계하는 경우에 적합합니다. 최저 지연 시간보다 순서와 가용성을 우선합니다. load-balance는 여러 연결을 여러 노드에 분배하므로 로그인 상태가 없고 출구 변경을 허용하는 동시 작업에 적합합니다. 계정 로그인, 결제, 장시간 연결, 출발지 주소에 민감한 서비스에는 함부로 사용하지 않는 것이 좋습니다. 동일한 업무의 연결이 서로 다른 출구에서 나갈 수 있기 때문입니다. 일관성 해시 전략을 사용하면 같은 대상이 자주 출구를 바꾸는 현상을 줄일 수 있지만, 먼저 서비스가 이러한 동작을 허용하는지 확인해야 합니다.
proxy-groups:
- 수동 선택
type: select
proxies:
- 자동 최적화
- 장애 전환
- DIRECT
- name: 자동 최적화
type: url-test
use:
- remote-nodes
url: https://www.gstatic.com/generate_204
interval: 300
tolerance: 80
lazy: true
- name: 장애 전환
type: fallback
use:
- remote-nodes
url: https://www.gstatic.com/generate_204
interval: 300
lazy: true
use는 proxy-providers를 참조하며, 원격 구독 노드를 정책 그룹에 자동으로 포함할 때 적합합니다. proxies는 고정 노드나 다른 정책 그룹을 직접 나열합니다. 두 방식은 코어의 지원 범위에 따라 조합할 수 있지만, 설정을 유지 관리할 때는 출처를 명확히 구분해야 합니다. 노드가 많다면 filter 정규식으로 이름을 기준으로 지역을 필터링할 수 있습니다. 예를 들어 이름에 “홍콩” 또는 “HK”가 포함된 노드를 특정 그룹에 넣을 수 있습니다. 반대 조건으로 필터링할 때는 노드 이름이 통일되어 있지 않으면 후보가 모두 제외될 수 있으므로 주의해야 합니다. 필터 조건을 바꿀 때마다 YAML이 로드되는지만 보지 말고 클라이언트의 정책 그룹 상세 화면에서 실제 구성원을 확인하세요.
계층화된 정책으로 순환 참조 방지
실전에서는 세 계층 구조를 만들 수 있습니다. 하위 계층은 노드 제공자, 중간 계층은 자동 최적화 또는 장애 전환, 상위 계층은 사용자가 보는 업무 그룹입니다. 규칙은 상위 업무 그룹만 참조하고, 상위 그룹은 중간 그룹과 일부 고정 노드를 참조하도록 구성합니다. 어떤 정책 그룹도 간접적으로 자기 자신을 참조해서는 안 됩니다. 예를 들어 “수동 선택”이 “자동 최적화”를 포함하고 “자동 최적화”가 다시 “수동 선택”을 후보로 포함하면 순환이 발생합니다. 일부 클라이언트는 로드 시 즉시 오류를 표시하고, 일부는 빈 그룹만 보여 줍니다. 문제를 진단할 때는 오류가 난 그룹부터 참조를 단계별로 펼쳐 모든 말단이 실제 노드 또는 DIRECT, REJECT 같은 내장 정책에 도달하는지 확인하세요.
| 유형 | 선택 방식 | 적합한 상황 | 주요 한계 |
|---|---|---|---|
| select | 사용자가 직접 선택 | 고정 지역, 계정 로그인, 장애 진단 | 장애 후 자동으로 바뀌지 않는 경우가 많음 |
| url-test | 탐지 결과에 따라 자동 선택 | 일상적인 웹 사용, 후보 노드가 많을 때 | 탐지 지연 시간이 모든 업무의 속도를 의미하지 않음 |
| fallback | 순서대로 첫 번째 사용 가능 항목 선택 | 주·예비 회선, 안정적인 출구 우선 | 목록 순서가 결과에 직접 영향을 줌 |
| load-balance | 여러 노드에 연결 분배 | 동시 실행이 가능하고 고정 출구가 필요 없는 작업 | 출발지 주소에 민감한 업무에는 부적합 |
CHAPTER 02 / RULE PROVIDERS
규칙 집합 구독 관리
규칙이 수십 개에서 수천 개로 늘어나면 모든 내용을 주 설정에 직접 작성할 경우 가독성이 떨어지고 구독 업데이트가 로컬 수정 사항을 덮어쓸 수 있습니다. rule-providers는 도메인, 네트워크 대역 또는 클래식 규칙을 별도 리소스로 분리해 코어가 주기적으로 가져오고 캐시하도록 합니다. 주 설정에는 제공자 정의, 업무 정책 및 규칙 집합 참조만 남기고, 광고 차단·사설 네트워크·업무 서비스·스트리밍처럼 주제별로 규칙 내용을 관리할 수 있습니다. 특정 유형만 별도로 업데이트할 수 있고 문제가 생기면 해당 참조만 빠르게 비활성화할 수 있어 전체 설정을 다시 작성할 필요가 없습니다.
behavior와 format의 조합 관계
behavior는 규칙 집합 내용의 의미를 설명합니다. domain은 순수 도메인 목록에 적합하며 일반적으로 완전한 도메인, 도메인 접미사 또는 코어가 지원하는 도메인 표현식이 항목으로 들어갑니다. ipcidr은 IPv4·IPv6 네트워크 대역만 처리합니다. classical은 DOMAIN-SUFFIX,example.com, PROCESS-NAME,example.exe처럼 유형과 매개변수가 포함된 완전한 규칙을 저장합니다. 잘못 선택하면 파일은 성공적으로 다운로드되어도 해석되지 않을 수 있으며, 로그에 payload 형식 또는 규칙 유형 오류가 나타납니다. format은 리소스가 YAML 텍스트인지, 일반 텍스트인지, 바이너리 규칙 형식인지 설명하므로 원격 파일의 실제 내용과 일치해야 합니다. 확장자만 보고 추측해서는 안 됩니다.
rule-providers:
private-domain:
type: http
behavior: domain
format: yaml
path: ./rules/private-domain.yaml
url: https://rules.example.invalid/private-domain.yaml
interval: 86400
health-check:
enable: true
interval: 600
office-classical:
type: http
behavior: classical
format: text
path: ./rules/office.list
url: https://rules.example.invalid/office.list
interval: 43200
private-network:
type: file
behavior: ipcidr
format: yaml
path: ./rules/private-network.yaml
rules:
- RULE-SET,private-domain,DIRECT
- RULE-SET,office-classical,업무 서비스
- RULE-SET,private-network,DIRECT,no-resolve
- MATCH,수동 선택
예시 도메인은 해석되지 않는 예약 접미사를 사용하며 구조 설명만을 위한 것입니다. 실제 배포 시에는 접근 가능하고 출처가 명확한 규칙 주소로 바꿔야 합니다. path는 로컬 캐시 위치이며 같은 설정 안의 서로 다른 제공자가 같은 파일을 재사용하면 업데이트 과정에서 서로 덮어쓸 수 있습니다. 상대 경로는 대개 그래픽 클라이언트 설치 디렉터리가 아니라 설정 작업 디렉터리를 기준으로 합니다. 컨테이너나 시스템 서비스 환경에서는 실행 사용자가 해당 디렉터리를 만들고 쓸 권한이 있는지도 확인해야 합니다. 로그에 다운로드 성공 후 쓰기 실패가 표시되면 원격 주소를 반복해서 바꾸기보다 디렉터리 권한, 읽기 전용 마운트와 경로 계층을 점검하세요.
규칙 수보다 규칙 순서가 중요함
Clash와 mihomo는 일반적으로 rules를 위에서 아래로 순서대로 매칭하며, 처음 일치한 규칙에서 중지합니다. 구체적인 도메인 규칙은 포괄적인 규칙보다 앞에 두고, 사설 주소와 로컬 서비스는 보통 공용 네트워크 대역보다 앞에 배치하며 마지막에는 MATCH로 마무리합니다. 넓은 지역 네트워크 대역이나 와일드카드 도메인을 먼저 작성하면 뒤의 세부 규칙은 실행되지 않습니다. 규칙 집합 사이에도 우선순위가 있습니다. 하나의 도메인이 “업무 서비스”와 “직접 연결 도메인”에 동시에 속한다면 앞에 배치된 참조가 결과를 결정합니다. 규칙을 디버깅할 때는 항목이 존재하는지만 확인하지 말고 연결 상세나 로그에서 실제로 일치한 규칙 유형, 규칙 payload와 대상 정책을 확인하세요.
no-resolve는 IP 유형 규칙에서 자주 사용되며, 매칭을 위해 대상 IP를 얻으려고 도메인을 추가로 해석하지 말라는 의미입니다. 불필요한 DNS 조회를 줄이고 규칙 단계에서 원래 도메인 처리 경로가 바뀌는 것을 막을 수 있지만, 모든 규칙에 기계적으로 추가해서는 안 됩니다. 도메인 규칙은 도메인 자체에 의존하므로 이 매개변수가 필요하지 않습니다. 해석 결과에 따라 지역이나 네트워크 대역을 매칭해야 한다면 해석을 금지할 경우 규칙이 일치하지 않을 수 있습니다. 먼저 규칙이 도메인, 대상 IP 또는 프로세스 정보를 사용하는지 확인한 뒤 해석을 건너뛸지 결정하세요.
업데이트 실패와 캐시 롤백
원격 규칙 업데이트가 실패했다고 해서 기존 트래픽이 즉시 중단되는 것은 아닙니다. 로컬 캐시가 남아 있고 형식이 유효하다면 코어는 대개 이전 내용을 계속 사용할 수 있습니다. 최초 로드이거나 캐시가 삭제되었거나 경로가 바뀐 경우에는 롤백할 기반이 없습니다. 유지 관리 전에 규칙 파일의 캐시 디렉터리와 마지막 성공 업데이트 시각을 기록하세요. 문제가 발생하면 시스템 시간, DNS 해석, 원격 응답 상태, 프록시 아웃바운드 경로, 인증서 오류와 파일 권한을 순서대로 확인합니다. 규칙 주소가 프록시를 통해서만 접근 가능하고 해당 규칙이 프록시 경로까지 결정한다면 최초 시작 시 의존성 순환이 생길 수 있습니다. 규칙 다운로드에 이미 사용 가능한 프록시 설정을 적용하거나, 먼저 로컬 파일로 시작한 뒤 원격 업데이트를 복구하세요.
규칙 집합은 많을수록 좋은 것이 아닙니다. 여러 출처가 같은 도메인을 중복 수록할 수 있고 관리 기준도 충돌할 수 있습니다. 각 제공자에 출처, 용도, 업데이트 주기와 대상 정책을 기록하고 더 이상 참조하지 않는 캐시는 정기적으로 삭제하는 것이 좋습니다. 변경 전에는 소규모 로컬 규칙 집합으로 동작을 검증한 다음 안정된 항목을 원격 리소스로 옮기세요. 구독 구조와 호환성 차이는 Clash 구독 형식 자세히 알아보기에서 확인할 수 있습니다. 노드 구독, 전체 설정과 규칙 집합 구독을 같은 유형으로 혼동하지 마세요.
CHAPTER 03 / DNS PIPELINE
DNS 설정 최적화
DNS 설정은 도메인에서 주소를 얻는 방식을 결정하며, 규칙이 원래 도메인을 볼 수 있는지, 연결이 프록시를 우회하는지, TUN 모드와 호환되는지도 좌우합니다. 흔한 오해는 해석기를 목록에 많이 넣을수록 안정적이라고 생각하는 것입니다. 실제로는 해석기 프로토콜, 접근 경로, 지역별 응답과 규칙 모드가 서로 맞아야 합니다. 문제를 진단할 때는 클라이언트가 조회를 mihomo에 전달하는지, mihomo가 어떤 nameserver를 선택하는지, 조회가 직접 연결 또는 프록시를 통해 나가는지, 반환된 주소가 이후 규칙 매칭에 어떻게 사용되는지 네 단계로 나누어 확인하세요.
기본 해석기와 업무별 해석기
default-nameserver는 암호화 DNS 서버 자체의 도메인을 해석하는 등 초기 부트스트랩 작업에 사용됩니다. 보통 직접 접근할 수 있는 IP 주소 기반 해석기를 지정해 “해석기 도메인을 먼저 해석해야 하는” 순환 의존을 피해야 합니다. nameserver는 주 조회 출처이며 일반 UDP/TCP DNS, DoT 또는 DoH를 포함할 수 있습니다. 암호화 프로토콜은 해석기까지의 조회 전송을 보호하지만 연결 자체는 올바른 라우팅이 필요합니다. DoH 주소가 규칙에 따라 프록시로 분류되고 프록시 노드 도메인이 같은 DoH 해석을 기다리면 시작 단계에서 멈출 수 있으므로 노드 도메인과 해석기 도메인의 초기 경로를 따로 고려해야 합니다.
proxy-server-nameserver는 프록시 노드 도메인 해석을 전담하여 노드 연결이 업무 도메인용 Fake-IP 결과에 의존하지 않도록 합니다. nameserver-policy는 도메인별로 해석기를 지정합니다. 예를 들어 내부 도메인은 사설망 DNS를 사용하고 특정 지역 도메인은 해당 지역의 해석 서비스를 사용하게 할 수 있습니다. 정책은 구체적인 조건부터 넓은 조건 순서로 매칭해야 하며, 규칙 집합 표현식이 현재 코어에서 지원되는지도 확인해야 합니다. 기업 내부망의 도메인은 사설 주소를 반환하는 경우가 많습니다. 이를 공용 해석기에 맡기면 실패할 뿐 아니라 접근해서는 안 되는 해석 경로로 조회가 전송될 수 있습니다.
dns:
enable: true
listen: 0.0.0.0:1053
ipv6: true
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "*.lan"
- "*.local"
- "time.*.com"
- "ntp.*.com"
default-nameserver:
- 1.1.1.1
- 223.5.5.5
nameserver:
- https://dns.alidns.com/dns-query
- https://1.1.1.1/dns-query
proxy-server-nameserver:
- 223.5.5.5
- 1.1.1.1
nameserver-policy:
"*.corp.example.invalid":
- 192.168.1.1
수신 주소는 어떤 장치가 해당 DNS 서비스를 사용할 수 있는지 결정합니다. 로컬 장치만 사용할 경우 루프백 주소에 바인딩하고, LAN 장치가 접근해야 할 때만 모든 인터페이스에 바인딩한 뒤 방화벽, LAN 접근 허용과 포트 충돌을 함께 확인하세요. 외부 네트워크에서 접근할 수 있는 인터페이스에 DNS를 노출하면 악용 위험이 커지므로 서버 환경에서는 방화벽으로 출처를 제한해야 합니다. ipv6 활성화 여부는 로컬 네트워크와 프록시 노드의 IPv6 지원 여부에 따라 결정합니다. IPv6를 단순히 끄면 라우팅 문제를 숨길 수 있고 AAAA 레코드만 제공하는 서비스에 접근하지 못할 수도 있습니다. 반대로 상위 네트워크나 출구에 사용 가능한 IPv6가 없는데 켜면 IPv6 연결을 먼저 시도한 뒤 실패하고 다시 전환하느라 지연이 발생할 수 있습니다.
redir-host와 Fake-IP 비교
redir-host는 실제 주소를 반환하므로 기존 호환성을 이해하기 쉽지만, 투명 가로채기 후속 연결에 대상 IP만 포함되면 도메인 정보가 사라질 수 있습니다. 이때 도메인 규칙은 매핑이나 스니핑을 통해 복원해야 합니다. fake-ip는 도메인에 예약 주소를 할당하고, 코어가 매핑 테이블을 통해 연결이 들어올 때 원래 도메인을 복원합니다. 따라서 규칙 매칭이 더 안정적인 경우가 많고 애플리케이션이 코어를 우회해 해석 결과로 직접 연결하는 상황도 줄일 수 있습니다. 대신 실제 DNS 응답, LAN 검색, 시간 동기화, 게임 또는 특수 장치 서비스에 의존하는 일부 기능은 호환되지 않을 수 있으므로 fake-ip-filter에 추가해야 합니다.
필터 목록은 거대한 템플릿을 그대로 복사해 만들지 않는 것이 좋습니다. 너무 넓은 항목은 많은 도메인을 Fake-IP 흐름에서 제외해 규칙 일관성을 약화시키고, 너무 좁은 항목은 특정 애플리케이션의 장애를 남깁니다. 기본 설정에서 시작해 로그로 이상 도메인을 확인하고 한 번에 명확한 항목 하나씩 추가하는 방식이 더 안정적입니다. 변경 후에는 운영체제 DNS 캐시, 애플리케이션 캐시와 코어 매핑을 정리하고 연결을 다시 만들어야 합니다. 브라우저가 자체 보안 DNS를 사용할 수도 있으므로 진단 중에는 브라우저의 해석 경로가 시스템과 같은지 잠시 확인하세요.
DNS 유출과 원인 오판
DNS 경로 이상은 대개 단일 스위치 하나로 발생하지 않습니다. 브라우저 DoH, 시스템 DNS, TUN DNS 하이재킹, 컨테이너 내부 해석기와 LAN 라우터 전달이 동시에 존재할 수 있습니다. 먼저 로그로 조회가 mihomo에 들어오는지 확인한 뒤 해석기 연결 경로를 점검하세요. 로그에 대상 도메인 조회가 전혀 보이지 않으면 애플리케이션 또는 시스템 계층의 문제입니다. 조회는 보이지만 시간 초과가 발생하면 상위 해석기의 접근성과 라우팅을 확인하세요. 해석은 성공했지만 연결이 실패한다면 DNS를 계속 바꾸기보다 규칙, 정책 그룹과 노드를 점검해야 합니다. 비교 테스트에서는 매번 해석기 하나 또는 강화 모드 하나만 바꾸고 시각을 기록해 로그와 대조하세요.
캐시는 해석 지연을 줄이지만 잘못된 기록과 오래된 주소의 영향을 연장할 수도 있습니다. 도메인의 서버가 변경되었거나 규칙을 방금 수정했거나 Fake-IP 모드를 바꾼 경우에는 애플리케이션 캐시, 시스템 캐시와 코어 캐시를 함께 고려해야 합니다. 장치를 전체 재부팅하는 것이 유일한 방법은 아닙니다. 먼저 클라이언트가 제공하는 DNS 캐시 삭제 기능을 사용한 뒤 대상 애플리케이션을 종료하고 다시 실행하세요. 특정 브라우저, 컨테이너 또는 LAN 장치에서만 문제가 발생한다면 DNS 설정을 비교하고, 모든 장치가 불필요한 복잡성을 떠안도록 전역 설정을 바꾸지 마세요.
CHAPTER 04 / TUN AND FAKE-IP
TUN과 Fake-IP의 가로채기 범위
시스템 프록시는 프록시 설정을 따르는 애플리케이션에만 영향을 주지만, TUN은 가상 네트워크 인터페이스를 통해 더 넓은 IP 트래픽을 가로챕니다. 명령줄 프로그램, 일부 게임, 시스템 서비스와 프록시 설정을 읽지 않는 소프트웨어는 시스템 프록시에서 직접 연결할 수 있지만 TUN은 이러한 연결도 코어 규칙 체인으로 보낼 수 있습니다. 가로채기 범위가 넓어지면 라우팅, DNS, 방화벽, 가상 머신과 다른 네트워크 도구 사이의 충돌 가능성도 커집니다. 활성화하기 전에 일반 시스템 프록시 모드가 정상 작동하는지 확인하고 구독, 노드와 규칙이 유효한 상태에서 TUN만 별도로 검증하세요. 그렇지 않으면 노드 장애와 라우팅 장애가 겹쳐 원인을 찾기 어렵습니다.
핵심 매개변수와 운영체제별 차이
stack은 TUN이 사용할 네트워크 스택 구현을 결정합니다. system은 시스템 네트워크 스택을 사용하는 경향이 있어 호환성을 이해하기 쉽습니다. gvisor는 사용자 공간 네트워크 스택을 사용해 일부 환경에서 격리나 특정 프로토콜 동작을 개선할 수 있지만 오버헤드가 늘어날 수 있습니다. mixed는 트래픽 유형에 따라 조합해 처리합니다. 모든 시스템에 맞는 하나의 선택은 없으므로 특정 애플리케이션 시간 초과, UDP 이상 또는 처리량 저하가 발생하면 다른 설정은 유지한 채 하나씩 테스트하세요.
auto-route는 코어가 자동으로 라우팅을 추가해 대상 트래픽을 가상 인터페이스로 보냅니다. auto-detect-interface는 실제 아웃바운드 네트워크 카드를 식별하며, 노트북이 유선·무선·핫스팟·VPN 사이를 전환할 때 특히 유용합니다. Windows에서는 방화벽, 네트워크 프로필과 다른 가상 네트워크 카드도 확인해야 합니다. macOS에서는 시스템 권한이 필요할 수 있고, Linux 서비스 환경에서는 실행 권한, 정책 라우팅과 방화벽 프레임워크를 고려해야 합니다. 그래픽 클라이언트가 일부 권한 처리를 대신하더라도 권한 대화상자를 거부했거나 서비스 구성 요소가 시작되지 않았거나 이전 라우팅이 정리되지 않으면 화면의 스위치가 실제로 트래픽을 가로채지 못할 수 있습니다.
tun:
enable: true
stack: mixed
dns-hijack:
- any:53
- tcp://any:53
auto-route: true
auto-redirect: true
auto-detect-interface: true
strict-route: true
mtu: 1500
dns-hijack은 지정된 포트의 DNS 요청을 코어 해석 흐름으로 보내며 Fake-IP가 정상 작동하는 핵심 단계 중 하나입니다. 일부 애플리케이션은 내장 DoH를 사용해 기존 53번 포트에 접근하지 않으므로 하이재킹만으로 모든 조회를 처리할 수는 없습니다. strict-route는 다른 인터페이스를 통한 우회를 줄일 수 있지만 가상 머신, LAN 공유, 기업 VPN 또는 다중 네트워크 카드 환경에서 필요한 경로까지 차단할 수 있습니다. 활성화 후 로컬 프린터, NAS 또는 사내망에 갑자기 접근할 수 없다면 모든 사설 주소를 프록시로 보내기보다 라우팅 제외와 사설 네트워크 대역 규칙을 확인하세요.
MTU, 루프백 및 라우팅 충돌
MTU 불일치는 일부 웹사이트만 열리고 큰 요청이 멈추거나 업로드가 실패하거나 특정 터널 내부 연결이 시간 초과되는 형태로 나타나는 경우가 많습니다. 작은 패킷은 통과하기 때문에 노드 불안정으로 오해하기 쉽습니다. 노드를 고정한 상태에서 TUN MTU를 조금씩 낮춰 비교할 수 있지만 지나치게 낮추면 안 됩니다. 너무 낮으면 조각화와 처리 오버헤드가 늘어납니다. 다른 VPN, 모바일 핫스팟 또는 PPPoE 환경에서만 문제가 발생한다면 하위 링크의 추가 캡슐화로 유효 MTU가 줄어든 상황을 우선 고려하세요.
코어가 직접 만든 프록시 연결은 실제 인터페이스로 나가야 하며 다시 TUN에 포착되어서는 안 됩니다. 그렇지 않으면 루프가 발생합니다. 자동 라우팅과 인터페이스 감지가 대개 이를 처리하지만 사용자 지정 라우팅, 컨테이너 네트워크, 정책 라우팅 또는 여러 투명 프록시가 동시에 존재하면 문제가 생길 수 있습니다. 대표적인 증상은 TUN을 켠 뒤 모든 노드가 동시에 시간 초과되고 끄면 즉시 복구되는 경우입니다. 이때 라우팅 테이블과 아웃바운드 인터페이스를 확인하고 프록시 서버 주소가 제외되었는지, 기본 경로 우선순위가 올바른지, 이전 클라이언트의 가상 인터페이스가 아직 작동 중인지 확인하세요.
Fake-IP 매핑과 규칙의 연동
애플리케이션이 DNS에 도메인을 조회하면 코어는 Fake-IP를 반환하고 해당 주소와 도메인의 매핑을 기록합니다. 애플리케이션이 Fake-IP에 연결하면 TUN이 연결을 포착하고 코어가 도메인을 복원한 뒤 도메인 규칙으로 매칭하며, 마지막으로 선택된 정책을 통해 실제 대상에 접근합니다. 이 과정에서 Fake-IP는 로컬 가로채기 경로에만 존재하며 실제 원격 주소가 아닙니다. 애플리케이션이 오래된 Fake-IP를 캐시했는데 코어 재시작이나 설정 변경으로 매핑이 사라졌다면 도메인을 복원하지 못할 수 있습니다. 규칙을 계속 추가하기보다 애플리케이션 연결과 DNS 캐시를 정리하는 편이 효과적입니다.
LAN 서비스, 브로드캐스트 검색과 실제 주소 반환이 필요한 애플리케이션은 fake-ip-filter로 제외할 수 있지만 해당 사설 네트워크 대역 규칙도 적절한 위치에 있어야 합니다. 도메인만 제외한다고 트래픽이 자동으로 직접 연결되는 것은 아닙니다. 사설 주소로 해석된 뒤에도 후속 규칙이 이를 프록시 그룹으로 보낼 수 있습니다. 반대로 사설 네트워크 대역을 직접 연결로 추가하는 것만으로는 실제 DNS 응답 내용에 의존하는 애플리케이션을 고칠 수 없습니다. 문제를 진단할 때는 “DNS가 무엇을 반환하는가”와 “연결이 최종적으로 어디로 가는가”를 별개의 문제로 보세요.
TUN을 활성화한 뒤 인터넷 전체가 끊기면 다음 순서로 확인하세요. 먼저 TUN을 끄고 기본 프록시를 검증한 뒤, DNS 설정은 그대로 둔 채 TUN을 다시 켭니다. 가상 인터페이스 생성 여부, 기본 경로와 물리 인터페이스, DNS 조회 로그를 차례로 확인하고 마지막으로 고정 IP와 도메인 접근 차이를 테스트하세요. 고정 IP는 접근되지만 도메인이 되지 않으면 DNS를 우선 점검하고, 둘 다 되지 않으면 라우팅·권한·루프백을 확인해야 합니다. 더 일반적인 연결 끊김 진단 절차는 Clash 실행 로그 읽는 법을 참고하세요.
CHAPTER 05 / DOMAIN SNIFFING
도메인 스니핑과 대상 복원
투명 프록시가 받은 연결에는 대상 IP만 있고 원래 도메인이 없는 경우가 있습니다. 도메인 스니핑은 연결 초기에 나타나는 프로토콜 특징을 확인해 HTTP Host, TLS ClientHello의 서버 이름 또는 지원되는 QUIC 정보에서 도메인을 복원한 뒤 도메인 규칙이 매칭에 참여하도록 합니다. 이는 “애플리케이션이 직접 해석해 코어에는 IP만 보이는” 문제를 해결하는 기능이지 DNS의 대체재가 아니며, 모든 암호화 또는 비표준 프로토콜에서 대상을 복원할 수도 없습니다. 설정할 때는 스니핑 대상, 포트 범위와 덮어쓰기 조건을 명확히 해 관련 없는 트래픽을 잘못 식별하지 않도록 해야 합니다.
override-destination의 영향
도메인만 식별하고 대상을 덮어쓰지 않으면 코어는 복원된 도메인으로 규칙을 매칭할 수 있지만 연결은 애플리케이션이 처음 해석한 IP로 계속 향합니다. override-destination을 활성화하면 코어가 스니핑 결과에 따라 대상을 다시 결정할 수 있어 애플리케이션의 해석 결과와 프록시 측 접근 경로가 다른 문제를 보완하는 데 적합합니다. 그러나 CDN, 사설 해석, 분할 DNS와 고정 주소 서비스는 원래 IP로 연결되기를 기대할 수 있습니다. 덮어쓰기 후 도메인이 다른 주소로 다시 해석되면 지역 차이, 인증서 문제 또는 내부 서비스 접근 실패가 발생할 수 있습니다. 따라서 프로토콜과 포트 범위를 우선 좁히고 호환되지 않는 도메인은 제외 목록에 추가하세요.
sniffer:
enable: true
force-dns-mapping: true
parse-pure-ip: true
override-destination: false
sniff:
HTTP:
ports:
- 80
- 8080-8880
override-destination: true
TLS:
ports:
- 443
- 8443
QUIC:
ports:
- 443
skip-domain:
- "Mijia Cloud"
- "+.push.apple.com"
skip-src-address:
- 192.168.0.0/16
skip-dst-address:
- 10.0.0.0/8
parse-pure-ip는 대상이 순수 IP인 연결도 스니핑하도록 허용하며 투명 가로채기에서 자주 사용하는 기능이지만 검사 범위가 넓어집니다. force-dns-mapping은 DNS 매핑과 함께 작동하여 기존 매핑에서 도메인을 복원해야 하는 환경에 적합합니다. 프로토콜 포트는 실제 업무에 맞게 지정해야 합니다. HTTP가 80번 포트에서만 실행되는 것은 아니며 TLS도 8443 같은 포트를 사용할 수 있습니다. 반대로 모든 포트를 모든 스니퍼에 맡기면 오판과 처리 비용이 증가합니다. 자주 사용하는 포트에서 시작하고 로그를 통해 특정 애플리케이션이 다른 포트를 사용한다는 사실이 확인될 때만 추가하세요.
스니핑으로 해결할 수 없는 상황
암호화된 클라이언트 인사, ECH, 비표준 캡슐화, 인증서 고정과 도메인 필드가 없는 프로토콜에서는 스니핑으로 유효한 호스트명을 얻지 못할 수 있습니다. UDP 프로토콜은 HTTP보다 정보가 적은 경우가 많습니다. 이때 로그에 대상 IP만 표시된다고 해서 기능이 실패한 것은 아닙니다. 연결 자체에 읽을 수 있는 도메인이 없는 것입니다. 스니핑 범위를 계속 넓히기보다 IP 규칙이나 프로세스 규칙을 사용하거나 애플리케이션의 DNS가 코어로 들어오게 하세요. 프로세스 규칙은 플랫폼 권한과 코어 기능에 의존하므로 서버와 모바일 시스템에서의 사용 가능성이 다를 수 있으며 배포 전 실제 클라이언트 로그를 기준으로 확인해야 합니다.
잘못된 스니핑은 기능을 켠 뒤 특정 LAN 장치, 게임, 푸시 서비스 또는 특수 클라이언트가 실패하는 형태로 나타나는 경우가 많습니다. 먼저 스니핑은 유지한 채 override-destination을 끄고 문제가 식별 자체에서 발생했는지 대상 덮어쓰기에서 발생했는지 판단하세요. 그런 다음 출발지 주소, 대상 주소 또는 도메인을 기준으로 제외 항목을 추가합니다. LAN 대역은 내부 DNS와 고정 주소가 원래 경로를 유지해야 하므로 전면 스니핑할 필요가 거의 없습니다. 제외 규칙을 모든 공용 네트워크를 덮는 넓은 대역으로 작성하면 스니핑 기능이 사실상 꺼질 수 있습니다.
Fake-IP 및 규칙 매칭과의 연동
Fake-IP는 이미 매핑을 통해 코어 DNS가 처리한 대부분의 도메인을 복원할 수 있으므로, 스니핑은 시스템 DNS를 우회하는 애플리케이션이나 기존 연결, 실제 IP에 직접 연결하는 상황을 보완하는 역할이 큽니다. 두 기능을 함께 켰다면 로그에서 최종적으로 DNS 매핑 도메인을 사용했는지 스니핑 도메인을 사용했는지 확인하세요. 같은 연결에서 서로 다른 결과가 나오면 대상 덮어쓰기가 접근 주소를 바꿀 수 있습니다. 먼저 “Fake-IP는 일반 도메인 담당, 스니핑은 일반적인 HTTP/TLS 포트만 확인하고 기본적으로 덮어쓰지 않음”과 같은 보수적인 설정을 사용한 뒤 안정화되면 명확한 애플리케이션에만 덮어쓰기를 활성화하세요.
스니핑 검증은 웹페이지가 열리는지만 확인해서는 안 됩니다. 연결 상세에서 대상 호스트, 일치 규칙과 정책 그룹을 확인하세요. 스니핑을 끈 상태에서 한 번 기록하고 같은 애플리케이션과 도메인으로 연결을 새로 만든 뒤 대상이 IP에서 도메인으로 바뀌었는지, 규칙이 IP 유형에서 도메인 유형으로 전환되었는지 비교합니다. 이미 유지 중인 연결은 설정 변경만으로 다시 만들어지지 않으므로 애플리케이션을 완전히 종료하거나 연결이 닫힐 때까지 기다려야 합니다. 브라우저의 연결 재사용과 QUIC은 기존 세션을 오래 유지할 수 있으므로 새 시크릿 창을 사용하고 사이트 연결 상태를 잠시 정리하는 것이 좋습니다.
도메인 스니핑은 보완 수단입니다. DNS 조회가 안정적으로 코어에 들어오고 규칙도 도메인으로 정상 매칭된다면 설정을 완전하게 보이게 하려고 스니핑 범위를 넓힐 필요가 없습니다. 프로토콜과 포트를 하나 추가할 때마다 명확한 근거가 있어야 하며 활성화 전후 로그 차이를 기록하세요. 그래야 애플리케이션 업데이트나 네트워크 환경 변화 후 기존 호환성 예외가 여전히 필요한지 판단할 수 있습니다.
CHAPTER 06 / PROFILE MERGE
로컬 오버라이드 및 다중 구독 병합
구독을 업데이트하면 원격 설정이 다시 생성되므로 구독 파일 안에서 규칙, DNS 또는 정책 그룹을 직접 수정하면 다음 업데이트에서 대개 덮어써집니다. 유지 관리하기 좋은 방식은 원격 구독을 읽기 전용 입력으로 보고 장기 로컬 설정을 오버라이드, 확장 스크립트 또는 독립적인 주 설정에 두는 것입니다. 클라이언트마다 오버라이드 형식과 병합 순서의 구현이 완전히 같지 않으므로 특정 클라이언트의 확장 문법을 mihomo의 기본 YAML로 간주해서는 안 됩니다. 클라이언트를 바꾸기 전에는 어떤 필드가 코어에 속하고 어떤 필드가 그래픽 클라이언트의 설정 관리 계층에 속하는지 구분하세요.
덮어쓰기, 추가 및 삭제는 서로 다른 세 가지 작업
mixed-port와 mode 같은 스칼라 필드는 보통 직접 덮어쓸 수 있습니다. dns 같은 매핑 필드는 키 단위로 병합될 수도 있고 전체가 교체될 수도 있습니다. rules와 proxy-groups 같은 배열 필드는 더 복잡합니다. 단순히 덮어쓰면 구독 내용이 사라지고, 단순히 추가하면 폴백 규칙이 앞에서 후속 항목을 잘라 버릴 수 있습니다. 특히 MATCH는 규칙의 끝에 있어야 합니다. 로컬 규칙을 원격 MATCH 뒤에 추가하면 영원히 일치하지 않습니다. 안정적인 병합기는 앞에 추가, 뒤에 추가, 이름별 교체와 명시적 삭제를 지원하고 최종 출력 단계에서 순서를 점검해야 합니다.
정책 그룹을 name으로 연결할 때 같은 이름의 그룹이 교체될 수도 있고 중복 항목이 생길 수도 있습니다. 이름이 중복되면 규칙 참조 결과가 불명확해지고 클라이언트 화면에는 그중 하나만 표시될 수 있습니다. 병합 전에는 고정된 명명 규칙을 정하세요. 예를 들어 로컬 업무 그룹은 명확한 한국어 이름을 사용하고 원격 자동 그룹은 출처 접두사를 유지합니다. 노드명도 충돌할 수 있습니다. 두 구독에 모두 “홍콩 01”이 있으면 코어가 중복 프록시 이름을 보고할 수 있습니다. 해결 방법은 노드마다 수동으로 이름을 바꾸는 것이 아니라 가져오기 계층에서 출처별 접두사를 추가하는 것입니다. 다음 업데이트에서도 충돌이 다시 발생하기 때문입니다.
# 로컬에서 유지 관리하는 주 설정 조각
proxy-providers:
provider-a:
type: http
url: https://subscription.example.invalid/a
path: ./providers/a.yaml
interval: 3600
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 300
provider-b:
type: http
url: https://subscription.example.invalid/b
path: ./providers/b.yaml
interval: 3600
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 300
proxy-groups:
- name: 모든 출처
type: select
use:
- provider-a
- provider-b
proxies:
- DIRECT
rules:
- DOMAIN-SUFFIX,corp.example.invalid,DIRECT
- RULE-SET,private-domain,DIRECT
- MATCH,모든 출처
proxy-providers를 사용해 여러 노드 구독을 한데 모으는 방식이 여러 개의 전체 설정을 직접 이어 붙이는 것보다 대개 명확합니다. 전체 설정에는 각각 포트, DNS, 규칙과 같은 이름의 정책 그룹이 포함될 수 있어 기계적으로 합치면 충돌하기 쉽습니다. 노드 제공자는 프록시 항목만 제공하고 나머지는 주 설정이 통합해 관리합니다. 상위 구성이 provider 형식이 아닌 전체 Clash 설정을 반환한다면 클라이언트가 노드만 추출할 수 있는지 먼저 확인하거나 신뢰할 수 있는 로컬 절차에서 변환하세요. 접근 자격 증명이 포함된 구독을 출처가 불명확한 온라인 변환 페이지에 제공하지 마세요.
오버라이드 계층과 폴백 파일
다음 네 계층을 보존하는 것이 좋습니다. 원본 구독, 로컬 오버라이드, 병합된 최종 설정, 최근에 사용 가능한 설정입니다. 원본 구독은 상위 출처의 내용을 확인하는 데 사용하고, 로컬 오버라이드를 버전 관리할 때는 구독 주소와 접근 자격 증명을 제거해야 합니다. 최종 설정은 병합 결과를 추적하는 데 사용하고, 사용 가능한 설정은 장애 시 롤백용으로 보관합니다. 수정할 때는 로컬 오버라이드만 변경하고 생성 후 문법을 검사한 다음 코어에 로드하세요. 클라이언트가 최종 설정 내보내기를 지원하지 않는다면 실행 디렉터리에서 실제 로드 파일을 찾을 수 있지만, 클라이언트가 자동으로 다시 쓸 수 있으므로 편집 입구로 사용하기에는 적합하지 않습니다.
로컬 오버라이드는 사용자 지정 규칙, 고정 정책 그룹 구조, DNS 선택과 LAN 예외처럼 안정적인 의도를 관리하는 데 가장 적합합니다. 노드 목록, 인증 필드와 상위 구독처럼 수시로 바뀌는 속성은 계속 구독에서 제공하도록 하세요. 그러면 업데이트로 새 노드를 얻으면서도 로컬 분기 설정은 유지할 수 있습니다. 상위 제공자가 호환되지 않는 필드를 내보내기 시작하면 오버라이드 계층에서 필요한 부분만 삭제하거나 변환하고 이유를 기록하세요. 전체 이전 설정을 복사해 장기간 고정하면 노드와 프로토콜 기능이 점차 최신 상태를 잃게 됩니다.
다중 구독의 가용성과 장애 격리
여러 제공자가 같은 캐시 경로를 공유해서는 안 되며 상태 점검도 독립적으로 수행해야 합니다. 한 출처의 업데이트가 실패해도 다른 출처는 계속 로드되어야 합니다. 모든 그룹이 실패한 출처만 참조하면 설정은 성공적으로 로드된 것처럼 보여도 정책 그룹에 사용 가능한 구성원이 없을 수 있습니다. 상위 수동 그룹에 여러 자동 그룹을 남기고 출처를 명확히 표시하세요. 자동 선택 그룹에 용도와 지역이 서로 다른 모든 노드를 섞으면 탐지 결과가 자주 바뀔 수 있습니다. 먼저 출처 또는 지역별로 그룹을 나눈 다음 업무 계층에서 이러한 하위 그룹을 선택하는 방식이 더 적합합니다.
병합 후에는 정책 그룹명이 고유한지, 모든 참조 대상이 존재하는지, 제공자 경로가 서로 다른지, 규칙 끝에 예상한 폴백만 있는지, DNS 매핑이 완전한지, 민감한 필드가 로그나 내보낸 파일에 실수로 기록되지 않았는지를 확인해야 합니다. 구독 업데이트 전후의 최종 설정은 텍스트 행만 비교하지 말고 구조적으로 비교해 필드 변화를 확인하세요. 업데이트 후 시작할 수 없다면 먼저 최근 사용 가능한 설정으로 복구한 뒤 상위 설정에서 추가된 필드를 비교하세요. 사용할 수 없는 상태에서 오버라이드 규칙을 여러 개 연속으로 수정하지 않는 것이 좋습니다.
그래픽 클라이언트마다 오버라이드 메뉴와 저장 위치가 다릅니다. Clash Plus는 설정과 정책 그룹을 그래픽으로 관리하려는 데스크톱 사용자에게 적합합니다. Clash Verge Rev, FlClash, Clash Nyanpasu 등도 확장 기능이나 스크립트 기능을 제공할 수 있지만 문법은 현재 인터페이스의 설명을 기준으로 해야 합니다. 클라이언트를 다시 선택해야 한다면 클라이언트 선택 가이드를 확인하고, 복사 가능한 스크립트 하나만으로 클라이언트를 결정하지 마세요.
CHAPTER 07 / EXTERNAL CONTROLLER
외부 컨트롤 패널과 API의 경계
mihomo의 외부 제어 인터페이스를 사용하면 그래픽 인터페이스나 웹 컨트롤 패널에서 실행 상태를 읽고 정책을 전환하며 연결을 확인하고 설정을 업데이트할 수 있습니다. 이는 관리 인터페이스이지 프록시 포트가 아닙니다. external-controller를 수신 주소로 설정하면 클라이언트가 HTTP와 WebSocket으로 해당 포트에 연결합니다. 컨트롤 패널은 대개 정적 프런트엔드 파일만 포함하며 실제 데이터와 작업 기능은 코어 인터페이스에서 제공됩니다. 따라서 페이지가 열리지 않는 문제, 열리지만 데이터가 없는 문제, 조회는 되지만 조작할 수 없는 문제는 각각 정적 리소스, 인터페이스 연결, 인증 및 권한과 관련된 서로 다른 문제입니다.
수신 주소와 접근 범위
로컬에서만 사용할 때는 127.0.0.1에 바인딩하는 것이 가장 안전하며 다른 장치가 직접 접근할 수 없습니다. LAN에서 서버나 라우터를 관리해야 할 때만 0.0.0.0 또는 지정된 LAN 주소에 바인딩하고 방화벽에서 신뢰할 수 있는 네트워크 대역만 허용하세요. 모든 인터페이스에서 수신한다고 해서 공용 인터넷에 열어야 하는 것은 아닙니다. 제어 인터페이스는 노드를 전환하고 연결 대상을 읽으며 설정을 다시 로드할 수 있으므로 일반 프록시 포트보다 접근 범위를 좁혀야 합니다. 원격 유지 관리는 제어 포트를 직접 공개하기보다 SSH 터널이나 제어된 리버스 프록시로 로컬 인터페이스에 접근하는 방식을 우선하세요.
external-controller: 127.0.0.1:9090
secret: "your-password"
external-ui: ./ui
external-ui-name: dashboard
# 다른 장치에서 SSH로 로컬 인터페이스를 임시 전달
ssh -L 9090:127.0.0.1:9090 [email protected]
secret은 제어 인터페이스 인증에 사용하므로 독립적이고 추측하기 어려운 값을 설정해야 합니다. 예시 문자열은 교육용으로 명확하게 표시한 값일 뿐이므로 배포할 때 직접 바꾸세요. 컨트롤 패널은 대개 설정에서 API 주소와 키를 입력하도록 요구합니다. API 주소는 프록시의 mixed-port가 아니라 코어의 수신 위치를 가리켜야 합니다. 페이지가 HTTPS로 로드되는데 HTTP 제어 인터페이스에 접근하려 하면 브라우저가 혼합 콘텐츠 정책에 따라 요청을 차단할 수 있습니다. 이때는 브라우저 보안 제한을 끄기보다 동일 출처 리버스 프록시나 보안 터널을 사용해 접근 방식을 통일하세요.
external-ui와 정적 리소스 디렉터리
external-ui는 컨트롤 패널의 정적 파일 디렉터리를 가리키며 해당 디렉터리에는 진입점 HTML과 관련 리소스가 있어야 합니다. 이 필드는 패널을 다운로드하지 않으며 경로도 코어의 실행 작업 디렉터리를 기준으로 합니다. 시스템 서비스와 수동 실행 명령은 작업 디렉터리가 다를 수 있으므로 “터미널에서는 보이지만 서비스로 시작하면 빈 화면”인 문제는 대개 상대 경로 해석 차이에서 발생합니다. 명확한 절대 경로를 사용하거나 서비스 유닛의 작업 디렉터리와 파일 권한을 확인하세요. 읽기 전용 파일 시스템에서는 패널 파일을 미리 읽을 수 있는 위치에 배치해야 합니다.
일부 설정은 외부 UI 다운로드 주소를 통해 정적 리소스를 관리할 수 있지만, 운영 환경에서는 출처를 기록하고 업데이트 절차를 고정해야 합니다. 패널 업데이트와 코어 업데이트는 별개의 과정입니다. 새 패널이 이전 코어에서 지원하지 않는 인터페이스를 호출할 수도 있고, 이전 패널이 새 필드를 표시하지 못할 수도 있습니다. 화면의 버튼이 작동하지 않으면 먼저 브라우저 개발자 도구에서 요청 상태와 인터페이스 응답을 확인한 뒤 코어 로그와 대조하세요. 제어 패널 문제는 일반적으로 프록시 코어의 작동 여부를 바꾸지 않으므로 주 설정을 먼저 삭제하지 마세요.
CORS, 인증 및 리버스 프록시
컨트롤 패널과 API의 출처가 다르면 브라우저가 교차 출처 검사를 수행합니다. mihomo는 허용 출처 관련 설정으로 접근 가능한 페이지의 출처를 제한할 수 있습니다. 편의를 위해 모든 출처를 허용하면 브라우저 측 공격 범위가 커지므로 실제 컨트롤 패널 주소만 명시하는 것이 좋습니다. 출처 제한을 설정해도 키 인증과 네트워크 계층 제한을 대신할 수는 없습니다. 세 기능의 역할은 다릅니다. 방화벽은 누가 포트에 연결할 수 있는지 제한하고, 인증은 요청에 작업 권한이 있는지 결정하며, 출처 정책은 어떤 웹페이지가 브라우저를 통해 호출을 보낼 수 있는지 제한합니다.
리버스 프록시를 사용할 때는 WebSocket 업그레이드 요청을 올바르게 전달해야 합니다. 그렇지 않으면 일반 상태 API는 작동해도 실시간 로그와 연결 목록이 계속 끊길 수 있습니다. 프록시 계층은 인증 헤더를 유지하고 요청 본문 크기와 접근 경로도 제한해야 합니다. 프록시 포트, 제어 인터페이스와 정적 패널을 구분 없이 같은 경로에 섞지 마세요. LAN에서만 사용한다면 복잡한 공용 리버스 프록시보다 LAN 주소에 직접 바인딩하고 방화벽을 설정하는 편이 유지 관리하기 쉽습니다.
인터페이스 장애를 계층별로 확인
먼저 시스템 도구로 포트가 수신 중인지 확인하고, 기본 인터페이스를 요청해 인증을 검증한 다음 브라우저 콘솔을 확인하세요. 연결 거부는 코어가 수신하지 않거나 주소가 틀렸거나 방화벽이 차단한 경우입니다. 인증되지 않음은 인터페이스에 접근할 수 있지만 키가 일치하지 않는 경우입니다. 일반 요청은 성공하지만 실시간 콘텐츠가 실패하면 WebSocket을 우선 점검하세요. 패널 리소스를 찾을 수 없으면 external-ui 경로를 확인해야 합니다. 컨트롤 패널에 정책 그룹이 비어 있으면 API 응답과 코어 설정을 직접 확인해 패널 렌더링 문제인지 정책 그룹 자체에 구성원이 없는지 판단하세요.
외부 제어 인터페이스는 자동화된 상태 점검에도 적합하지만 스크립트가 모든 연결을 높은 빈도로 폴링해서는 안 되며 키를 공개 저장소, 명령 기록 또는 프런트엔드 페이지에 기록해서도 안 됩니다. 자동화는 필요한 엔드포인트만 읽고 실패 시 시간 제한과 백오프를 적용하세요. 설정 재로드는 상태를 변경하는 작업이므로 실행 전에 현재 사용 가능한 파일을 보존하고, 재로드 후 코어가 성공을 반환하는지 확인한 다음 정책 그룹을 다시 점검해야 합니다. 컨트롤 패널은 편리한 진입점이지만 최종 판단은 설정 파일, API 응답과 코어 로그를 기준으로 해야 합니다.
CHAPTER 08 / VALIDATION
설정 검증, 로그 진단 및 안전한 롤백
고급 설정의 어려움은 대개 특정 필드 하나가 아니라 여러 하위 시스템이 동시에 바뀐 뒤 원인을 추적하기 어렵다는 데 있습니다. 효과적인 유지 관리 절차는 문법 검증, 정적 참조 검사, 시작 로그, 실행 중 연결과 실제 업무 결과를 나누어 관찰해야 합니다. 웹페이지가 열린다는 것은 특정 경로가 작동한다는 뜻일 뿐 DNS, 규칙과 TUN이 모두 예상대로 작동한다는 의미는 아닙니다. 반대로 특정 웹사이트가 실패했다고 해서 노드가 사용할 수 없는 것도 아닙니다. 매번 변경 전에 기준 상태를 기록하고 변경 후 고정된 대상과 고정된 정책으로 테스트해야 비교 가능한 결론을 얻을 수 있습니다.
로드 전 정적 검사
먼저 YAML 들여쓰기, 콜론, 목록 계층과 중복 키를 확인하세요. YAML은 공백으로 들여쓰며 탭 문자는 해석 오류를 일으킬 수 있습니다. 콜론, 샵 또는 특수 문자가 포함된 이름은 구조나 주석으로 해석되지 않도록 따옴표로 감쌀 수 있습니다. 문법을 통과한 뒤에는 의미상 참조를 확인해야 합니다. 규칙이 가리키는 정책 그룹이 존재하는지, 정책 그룹이 참조하는 노드나 provider가 존재하는지, 규칙 집합 이름이 일치하는지, 캐시 경로가 충돌하지 않는지, 제어 인터페이스 포트가 mixed-port 및 DNS 수신 포트와 겹치지 않는지 확인하세요.
mihomo는 명령줄에서 설정 디렉터리를 지정하고 검사를 수행할 수 있지만, 배포 패키지에 따라 실행 파일 이름과 매개변수 진입점이 클라이언트에 의해 감싸져 있을 수 있습니다. 코어를 직접 사용할 때는 실제 실행 환경에서 설정 테스트를 수행해 상대 경로, 권한과 리소스 파일이 서비스 환경과 일치하는지 확인하세요. 개인 터미널에서만 검증하고 서비스는 다른 계정으로 실행하면 경로와 권한 문제를 놓칠 수 있습니다.
# 실제 설정 디렉터리로 이동한 뒤 실행
mihomo -t -d /path/to/config-directory
# 포그라운드에서 시작해 전체 로그 확인
mihomo -d /path/to/config-directory
# Linux에서 라우팅과 수신 포트 확인
ip route
ss -lntup
설정 테스트를 통과했다고 해서 원격 리소스를 반드시 다운로드할 수 있거나 노드에 연결할 수 있다는 뜻은 아닙니다. 주로 로컬 구조와 일부 리소스를 읽을 수 있는지만 확인합니다. 최초 시작 시에는 provider 업데이트, DNS 수신, TUN 인터페이스, 제어 포트와 프록시 포트의 로그를 계속 확인하세요. 로그의 첫 번째 오류가 뒤따르는 연쇄 오류보다 근본 원인에 가까운 경우가 많습니다. 예를 들어 DNS 수신 포트 충돌로 해석이 작동하지 않으면 이후에 대량으로 나타나는 노드 도메인 해석 실패는 결과일 뿐입니다.
실행 흐름에 따른 테스트 매트릭스
테스트는 최소한의 경로에서 시작해 기능을 단계적으로 추가해야 합니다. 첫 번째 단계에서는 TUN을 끄고 시스템 프록시와 고정된 수동 노드로 기본 TCP 연결을 검증합니다. 두 번째 단계에서는 노드를 유지한 채 도메인 해석과 규칙 매칭을 확인합니다. 세 번째 단계에서는 자동 정책 그룹으로 전환해 상태 점검을 확인합니다. 네 번째 단계에서 TUN을 켜고, 다섯 번째 단계에서 스니핑·오버라이드 또는 복잡한 규칙 집합을 활성화합니다. 각 단계에서는 변수 하나만 추가하세요. 세 번째 단계에서 실패했다면 다섯 번째 단계의 스니핑 매개변수를 계속 의심할 필요가 없습니다.
| 현상 | 우선 확인할 항목 | 검증 방법 | 아직 우선 수정하지 않을 항목 |
|---|---|---|---|
| 모든 노드가 동시에 시간 초과 | 기본 네트워크, 노드 도메인 해석, TUN 루프백 | TUN을 끄고 단일 노드 고정 테스트 | 규칙을 대량으로 추가하거나 삭제 |
| IP는 접근되지만 도메인은 실패 | DNS 수신, 하이재킹 및 상위 해석 | 조회 로그와 해석 결과 확인 | 정책 그룹 순서 |
| 특정 유형의 웹사이트만 잘못된 정책 사용 | 규칙 순서와 규칙 집합 내용 | 실제로 매칭된 규칙 확인 | 모든 해석기 교체 |
| TUN 활성화 후 LAN 연결 끊김 | 사설 네트워크 대역, 엄격한 라우팅, 인터페이스 선택 | 라우팅 테이블과 직접 연결 규칙 비교 | 구독 노드 목록 |
| 패널은 열리지만 실시간 로그 없음 | WebSocket, 인증, 리버스 프록시 | 브라우저 네트워크 요청 확인 | DNS 강화 모드 |
로그를 읽을 때 단계 구분
시작 단계에서는 설정 해석, 포트 바인딩, 리소스 로드와 가상 인터페이스 생성을 확인합니다. 구독 단계에서는 HTTP 상태, 시간 초과, 형식 해석과 캐시 기록을 확인합니다. DNS 단계에서는 조회 출처, 상위 해석기 선택과 반환 결과를 확인합니다. 연결 단계에서는 대상, 규칙, 정책 그룹과 실제 노드를 확인하고, 실행 단계에서는 상태 점검과 연결 종료 원인을 살펴봅니다. “timeout”이라는 단어만 보고 즉시 노드를 바꾸지 마세요. 같은 단어가 규칙 다운로드, DNS 조회, 프록시 핸드셰이크 또는 업무 서버에서 발생할 수 있으며 각각의 처리 방향이 다릅니다.
연결 상세에는 보통 출발지 주소, 대상 도메인 또는 IP, 네트워크 유형, 일치 규칙, 정책 체인과 아웃바운드 노드가 표시됩니다. 이 필드를 순서대로 읽으면 요청이 어느 계층에서 예상과 달라졌는지 판단할 수 있습니다. 예를 들어 대상 도메인은 올바른데 MATCH에 일치했다면 앞선 규칙이 포함하지 않은 것입니다. 규칙은 올바르지만 정책 그룹이 예상하지 않은 노드로 연결되면 그룹 내부 선택과 자동 테스트를 확인하세요. 정책과 노드가 모두 올바른데도 실패한다면 노드 연결, 대상 서비스와 MTU를 점검해야 합니다. 이런 순서가 모드를 반복해서 전환하는 것보다 문제를 빠르게 좁히는 데 도움이 됩니다.
롤백은 파일 하나를 복원하는 것 이상임
설정 장애는 라우팅, 가상 인터페이스, DNS 캐시와 원격 리소스 캐시를 동시에 남길 수 있습니다. YAML을 복원한 뒤에도 문제가 계속되면 코어가 해당 파일을 다시 로드했는지, 이전 프로세스가 종료되었는지, TUN 라우팅이 정리되었는지, 시스템 프록시가 복구되었는지, DNS 캐시가 갱신되었는지 확인해야 합니다. 그래픽 클라이언트는 화면 설정과 실제 실행 설정을 각각 저장할 수 있으므로 잘못된 파일을 복원하면 코어 동작이 바뀌지 않습니다. 롤백이 끝나면 시작 로그에서 설정 경로를 다시 확인하세요.
안정적인 변경마다 롤백 가능한 지점을 하나씩 만들고 최소한 설정 파일, 관련 규칙 집합 버전, 클라이언트가 사용하는 설정 디렉터리와 변경 설명을 저장하는 것이 좋습니다. 설명에는 “어떤 문제를 해결했는지, 어떤 필드를 수정했는지, 어떻게 검증했는지, 어떻게 되돌리는지”를 명확히 적고 단순히 “DNS 최적화”라고만 기록하지 마세요. 구독 주소와 제어 키는 공개 버전 관리 저장소에 넣지 않아야 합니다. 독립적인 로컬 비공개 파일이나 실행 환경 주입을 사용한 뒤 설정에서 참조할 수 있습니다. 로그를 공유할 때도 구독 매개변수, 노드 인증 정보, 제어 키와 내부 도메인을 삭제하세요.
반복 가능한 유지 관리 순서 만들기
전체 조정은 다음 순서로 진행할 수 있습니다. 현재 사용 가능한 설정을 복사하고, 최종 병합 결과를 내보내거나 기록한 뒤, 하나의 주제만 수정합니다. 정적 검사를 실행하고 포그라운드에서 로드해 첫 번째 오류를 확인합니다. 고정 노드로 시스템 프록시를 검증하고 DNS 조회와 규칙 매칭을 확인한 다음 마지막에 TUN과 스니핑을 활성화합니다. 안정화된 후 자동 정책과 원격 업데이트를 복구하세요. 어느 단계에서든 실패하면 이전에 사용 가능했던 설정으로 돌아가 해당 단계가 만든 실행 상태를 정리합니다. 다소 느려 보이지만 여러 변수가 겹친 뒤 오랫동안 무작정 진단하는 일을 막을 수 있습니다.
로그가 많은 환경에서는 대상 도메인, 출발지 프로세스 또는 시간 범위로 필터링하면 되며 가장 상세한 로그 수준을 계속 사용할 필요는 없습니다. 상세 로그는 짧은 시간 동안 문제를 찾는 데 적합하지만 계속 켜 두면 기록이 크게 늘고 민감한 정보 노출 범위도 커집니다. 문제가 해결되면 일반 수준으로 되돌리고 간결한 장애 요약을 보관하세요. 시작·구독·DNS·연결·규칙 단계의 대표 오류를 이해하려면 실행 로그 진단 순서를 참고해 항목별로 확인할 수 있습니다. LAN 공유에서 mixed-port, 수신 주소와 방화벽을 다룰 때는 혼합 포트와 LAN 프록시 설정을 참고하세요.
Related route
기본 설정에서 고급 조정으로
아직 구독 가져오기, 모드 선택과 연결 검증을 완료하지 않았다면 먼저 빠른 튜토리얼에 따라 사용 가능한 기준 상태를 만드세요. 클라이언트를 바꿔야 할 때는 플랫폼과 유지 관리 상태에 맞춰 다운로드 센터를 확인하세요.