YAML 구조와 설정 의존 관계
최상위 매핑으로 설정 경계 파악하기
Clash 설정은 순서대로 실행되는 스크립트가 아니라 실행 상태를 정의하는 매핑입니다. 최상위의 mixed-port, mode, log-level은 스칼라이고, dns는 중첩 매핑이며, proxies, proxy-groups, rules는 목록입니다. 들여쓰기가 부모와 자식의 관계를 결정하므로 필드 위치도 값만큼 중요합니다. 예를 들어 rules를 dns 아래로 들여쓰면 특별한 DNS 분할 규칙이 생기는 것이 아니라 기존 구조가 바뀌어 오류가 나거나 무시될 수 있습니다.
전체 파일을 살펴볼 때는 먼저 네 가지 의존 관계를 확인하세요. 수신 경로는 연결을 코어로 전달하고, 규칙은 연결을 대상으로 보냅니다. 정책 그룹은 대상 이름을 노드나 다른 그룹에 연결하며, DNS는 도메인 접속에 필요한 주소를 확인합니다. 제공자는 노드나 규칙 데이터를 보충하지만 자동으로 트래픽 출구가 되지는 않습니다. 정책 그룹이 노드 제공자를 참조하거나 규칙이 규칙 제공자를 참조해야 해당 리소스가 실제 처리 경로에 포함됩니다. 관계를 파악하면 줄마다 추측하며 문제를 찾지 않아도 됩니다.
# 최소 직접 연결 설정: 파일 구조와 수신 경로 확인용
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
proxies: []
proxy-groups:
- name: 출구 선택
type: select
proxies:
- DIRECT
rules:
- MATCH,출구 선택
이 최소 설정은 내장 대상 DIRECT만 사용하므로 원격 프록시 서비스를 제공하지 않습니다. 코어가 파일을 읽는지, 포트가 열리는지, 클라이언트에서 규칙 모드로 전환할 수 있는지 먼저 확인할 때 적합합니다. 프록시 출구가 필요하면 실제 노드를 추가하고 노드 이름을 정책 그룹에 넣으세요. 구조 예제와 사용 가능한 구독을 혼동하지 마세요. 설정 파일의 문법 검사를 통과해도 구조와 일부 참조가 유효하다는 뜻일 뿐, 원격 서버가 존재하거나 계정에 접근 권한이 있다는 의미는 아닙니다.
들여쓰기·따옴표·목록에서 자주 생기는 문제
항상 공백 두 칸으로 들여쓰고 탭은 섞어 쓰지 않는 것이 좋습니다. 짧은 목록은 [DIRECT, 출구 선택]처럼 쓸 수 있고, 항목이 많은 객체 목록은 각 항목을 한 줄씩 작성하면 계층을 확인하기 쉽습니다. 문자열에 공백이 뒤따르는 콜론, 샵 기호 또는 불리언처럼 보이는 값이 들어가면 따옴표로 감싸 타입을 분명히 하세요. 비밀번호와 구독 주소, 숫자만으로 된 이름도 따옴표를 붙이면 파서가 다른 타입으로 해석하는 일을 막을 수 있습니다. 주석은 문자열 바깥에서만 적용되므로 계정 정보 보관에 사용하지 마세요.
같은 매핑 안에서 키를 중복 정의하지 마세요. 파일의 앞부분과 끝부분에 dns를 각각 적는 방식은 신뢰할 수 있는 추가 병합 방법이 아닙니다. 파서에 따라 중복 키를 거부하거나 한쪽만 남길 수 있습니다. DNS 필드를 추가하려면 같은 매핑 안에서 수정하세요. 목록 항목도 이름만으로 자동 병합되지 않습니다. 이름이 같은 정책 그룹 두 개는 후보 노드가 합쳐지는 것이 아니라 충돌을 일으킬 수 있습니다. 설정이 길어질수록 정의는 한곳에 두고 다른 곳에서 참조하는 원칙이 중요합니다.
원본 설정·리소스 파일·실행 설정 구분하기
클라이언트는 보통 구독 원본, 제공자 캐시, 오버라이드 조각, 코어에 전달되는 실행 설정을 함께 관리합니다. 화면에서 보이는 파일이 최종 파일과 다를 수 있고, 캐시를 수정해도 다음 업데이트 때 덮어써질 수 있습니다. 수정 전에 현재 선택한 설정 이름을 기록하고 개인 인증 정보가 없는 구조 백업을 내보내세요. 편집 대상이 구독 원본인지 지속적으로 적용되는 오버라이드인지도 확인해야 합니다. 클라이언트 설치는 Clash Plus를 선택한 뒤, 사용 플랫폼에 맞는 설정 편집 및 실행 로그 메뉴를 확인하세요.
파일 분리는 주로 유지 관리를 위한 것이며, YAML 자체가 임의의 파일 가져오기를 지원한다는 뜻은 아닙니다. include 필드를 직접 추가해 코어가 디렉터리를 읽으리라 기대하지 마세요. 노드와 규칙은 지원되는 제공자 기능으로 분리하고, 공통 설정 재사용은 클라이언트에서 병합 기능을 명시적으로 지원해야 가능합니다. 상대 경로는 일반적으로 작업 디렉터리를 기준으로 하며 편집 중인 파일의 위치를 기준으로 하지 않을 수 있습니다. 기기를 옮길 때는 기본 설정뿐 아니라 리소스 경로, 쓰기 권한, 클라이언트 생성 디렉터리도 확인하세요.
수신 포트·모드·관리 인터페이스
수신 프로토콜과 바인딩 주소
port는 HTTP 프록시 수신 포트, socks-port는 SOCKS 수신 포트이며 mixed-port는 하나의 포트에서 HTTP와 SOCKS 요청을 모두 받습니다. 보통 혼합 포트 하나면 충분하므로 모든 유형의 수신 포트를 따로 열 필요는 없습니다. 앱이 프록시 주소를 사용해야 연결이 이 포트로 들어옵니다. 수신 포트만 열어서는 시스템 트래픽이 자동으로 전달되지 않습니다. 클라이언트의 시스템 프록시 설정은 운영체제 연동 기능이고 TUN은 별도의 연결 방식이므로, 포트가 열려 있는지만으로 두 기능의 작동 여부를 판단할 수 없습니다.
| 필드 | 용도 | 확인할 점 |
|---|---|---|
port | HTTP 프록시 수신 | 앱이 HTTP 프록시 주소를 사용 중인지 |
socks-port | SOCKS 프록시 수신 | UDP 전달은 수신 경로와 앱 지원 여부도 확인 |
mixed-port | HTTP와 SOCKS가 포트 하나를 함께 사용 | 다른 프로세스가 포트를 사용 중인지 |
allow-lan | LAN 기기의 접속 허용 | 바인딩 주소 및 방화벽과 함께 확인 |
external-controller | 관리 API 제공 | 프록시 수신 포트와 분리해 보호 |
로컬 기기에서만 사용할 경우 allow-lan: false가 적합합니다. LAN 접속을 허용한다면 bind-address, 운영체제 방화벽, 네트워크 격리 정책이 다른 기기의 연결을 허용하는지 확인하세요. 루프백 주소에 바인딩된 서비스는 다른 기기에서 접속할 수 없습니다. 모든 주소에서 수신한다고 해서 방화벽이 열려 있다는 뜻도 아닙니다. 앱 하나를 점검하려고 기기 전체의 노출 범위를 넓히지 말고, 먼저 로컬 연결로 수신 상태를 확인한 뒤 필요한 범위만 단계적으로 허용하세요.
mixed-port: 7890
allow-lan: false
bind-address: "127.0.0.1"
mode: rule
log-level: info
ipv6: false
# 관리 인터페이스는 로컬에서만 수신하고, 인증 정보는 별도로 설정하세요
external-controller: "127.0.0.1:9090"
실행 모드와 로그 상세 수준
mode: rule은 규칙 목록에 따라 대상을 선택하고, global은 연결을 전역 정책으로 보내며, direct는 직접 연결합니다. 규칙 파일이 올바르더라도 화면에서 전역 모드를 사용 중이면 규칙이 예상대로 적용되지 않습니다. 일부 클라이언트는 API를 통해 마지막 사용 모드를 복원하므로 디스크의 초기값과 현재 화면 상태가 다를 수 있습니다. 분할 라우팅이 제대로 동작하지 않으면 모든 규칙을 프록시로 바꾸기 전에 실행 모드와 규칙 순서를 확인하세요.
log-level은 로그 상세 수준을 조절합니다. 평소에는 info를 유지하고 파싱, 연결, 리소스 로딩을 추적할 때만 잠시 debug로 바꾸세요. 상세 로그에는 도메인, 대상 주소, 요청 맥락이 포함될 수 있으므로 공유하기 전에 구독 주소와 계정 필드 및 기타 개인 정보를 삭제하세요. 문제 해결 후에는 불필요한 접속 정보가 오래 기록되지 않도록 원래 수준으로 되돌리세요. 로그에 연결 기록이 있어도 트래픽이 특정 처리 단계까지 도달했다는 뜻일 뿐, 요청이 끝까지 성공했다는 증거는 아닙니다.
관리 API와 실행 환경의 제약
관리 인터페이스는 정책 전환, 연결 조회, 실행 상태 변경 기능을 제공하며 일반 프록시 포트와 권한이 다릅니다. 로컬 클라이언트만 사용하도록 루프백 주소에 바인딩하는 것이 좋습니다. 기기 간 관리가 꼭 필요하다면 별도 인증 정보를 설정하고 허용할 주소를 제한한 뒤 신뢰할 수 있는 네트워크 경계 안에서 사용하세요. 공개 저장소에 인증 정보를 올리거나 관리 URL 전체를 캡처해 게시하지 마세요. 화면이 열리지 않으면 클라이언트 설정의 제어 주소와 일치하는지 확인한 다음 포트 충돌과 코어 종료 여부를 살펴보세요.
포트 번호 자체에는 고정된 특별한 의미가 없으므로 예시 값을 바꿀 수 있지만 앱, 시스템 프록시, 클라이언트 설정은 함께 맞춰야 합니다. 프록시 프로그램 여러 개를 동시에 실행하면 포트 충돌, 시스템 프록시 설정 덮어쓰기, 가상 라우팅 경합이 자주 발생합니다. 문제를 찾을 때는 트래픽을 가로채는 방식을 하나만 남기고 연결 경로를 확인한 다음 다른 도구를 다시 활성화하세요. Linux 서비스에서는 실행 사용자, 작업 디렉터리, 파일 권한도 확인해야 합니다. 데스크톱 클라이언트에서 정상인 파일도 같은 시스템 서비스가 동일한 리소스를 읽을 수 있다는 보장은 없습니다.
ipv6은 단순한 네트워크 속도 향상 스위치가 아닙니다. 활성화 여부는 로컬 네트워크, 노드 출구, DNS 응답 결과를 함께 고려해야 합니다. 코어의 IPv6 지원을 꺼도 운영체제 방화벽 정책을 대신할 수 없고, 모든 IPv6 직접 연결 문제를 자동으로 설명해 주지도 않습니다. 앱이 프록시 수신 경로를 우회해 연결한다면 주소 유형을 선택하기 전에 트래픽 가로채기 범위부터 확인하세요. 시스템 프록시 미작동, 포트 충돌, LAN 연결 문제는 FAQ 문제 해결도 참고하세요.
프록시 노드 필드와 프로토콜별 차이
노드 객체의 최소 구성
proxies의 각 객체는 하나의 출구를 정의합니다. 노드마다 참조 가능한 name이 필요하고, 프로토콜은 type으로 결정됩니다. server와 port는 서버의 수신 주소를 지정합니다. 인증 방식, 암호화 방식, 전송 계층, TLS 설정은 프로토콜에 따라 달라지므로 서로 다른 프로토콜 사이에서 그대로 복사하면 안 됩니다. 이름은 연결 매개변수는 아니지만 정책 그룹에서 참조하는 식별자입니다. 노드 이름을 바꾸면 수동으로 관리하는 그룹과 규칙 대상 등 모든 참조도 함께 수정해야 합니다.
아래는 Shadowsocks 구조 예제입니다. 예약된 예시 도메인을 서버 주소로 사용하고 비밀번호는 학습용 가짜 값이므로, 연결하려면 서비스 제공자가 안내한 값으로 바꿔야 합니다. 포트나 프로토콜 이름만 보고 비밀번호, 암호화 방식, 전송 방식을 추측하지 마세요. 구독에 노드 설정이 이미 포함되어 있다면 원본 필드를 유지하는 것이 좋습니다. 정확한 의미를 확인한 뒤에만 필요한 부분을 수정하세요. 전송 설정을 잘못 삭제하면 구문은 올바르지만 핸드셰이크에 실패하는 설정이 될 수 있습니다.
proxies:
- name: 예시 출구
type: ss
server: proxy.example.com
port: 443
cipher: chacha20-ietf-poly1305
password: "your-password"
udp: true
proxy-groups:
- name: 출구 선택
type: select
proxies:
- 예시 출구
- DIRECT
전송 계층과 TLS 필드는 프로토콜마다 다릅니다
TLS를 사용하는 프로토콜끼리도 필드 이름은 다를 수 있습니다. 일부 노드는 핸드셰이크 이름을 servername으로 지정하고, 다른 프로토콜은 sni를 사용합니다. tls 옵션이 필요한지, 특정 전송 옵션을 지원하는지는 해당 프로토콜의 코어 문서에서 확인해야 합니다. 서버 주소는 도메인이나 IP로 지정할 수 있지만, 인증서는 보통 도메인에 연결되어 있습니다. 도메인을 IP로 바꾸면서 올바른 핸드셰이크 이름을 유지하지 않으면 서버가 오프라인인 것이 아니라 인증서 이름이 일치하지 않는 문제가 생길 수 있습니다.
WebSocket, HTTP/2, gRPC 등의 전송 방식에는 경로, 호스트 헤더, 서비스 이름도 관련됩니다. 이는 서버 설정의 일부이므로 임의로 생략할 수 있는 참고 사항이 아닙니다. 문제를 찾을 때는 프로토콜, 주소, 포트, 인증, 전송 설정 순서로 확인한 다음 인증서와 네트워크 연결 상태를 살펴보세요. 인증서 검증을 끄는 것은 일반적인 해결 방법이 아닙니다. 서버 신원 확인을 약화할 뿐 아니라 잘못된 비밀번호나 경로, 서버에서 지원하지 않는 프로토콜 문제도 해결하지 못합니다.
| 필드 유형 | 주요 내용 | 수정 원칙 |
|---|---|---|
| 참조 식별자 | name | 고유한 이름을 사용하고 그룹 참조도 함께 수정 |
| 서버 위치 | server、port | 서버가 안내한 주소 사용 |
| 프로토콜 인증 | 비밀번호·사용자 식별자·암호화 방식 | 프로토콜에 맞춰 입력하고 문자열 타입 명확히 지정 |
| 핸드셰이크 및 전송 | TLS 이름·경로·전송 프로토콜 | 클라이언트와 서버 설정이 일치해야 함 |
UDP·DNS 확인·노드 업데이트
udp: true는 해당 프로토콜이 지원하는 경우 UDP 전달을 허용한다는 뜻이며, UDP를 지원하지 않는 서버에 기능을 추가해 주지는 않습니다. 앱은 UDP를 지원하는 수신 경로를 통해 코어에 연결해야 하고 출구 경로에서도 해당 트래픽을 허용해야 합니다. 웹은 열리지만 게임이나 음성 통화가 안 된다면 수신 경로, 정책 그룹에서 선택한 노드, 원격 서버의 지원 여부를 각각 확인하세요. HTTP 테스트 결과만으로 판단하면 안 됩니다. 반대로 노드 테스트는 정상이지만 특정 사이트에 접속할 수 없다면 노드 자체가 아니라 규칙에서 잘못된 출구를 선택했을 수도 있습니다.
server에 도메인을 지정하면 노드에 연결하기 전에 먼저 도메인을 확인해야 합니다. 이는 프록시를 통해 웹사이트에 접속할 때 대상 도메인을 확인하는 것과 다른 단계입니다. 노드의 DNS 조회가 아직 연결되지 않은 프록시에 의존하면 시작 단계에서 의존성 순환이 생길 수 있습니다. 프록시 서버 도메인 전용 확인기를 설정하면 초기 연결 경로를 더 명확히 할 수 있습니다. 구체적인 필드는 뒤의 DNS 항목을 참고하세요. 먼저 노드 서버 주소가 제대로 확인되는지 검증한 다음 대상 웹사이트의 DNS 정책을 살펴보세요.
구독을 업데이트하면 노드 이름과 개수가 바뀔 수 있습니다. 수동 정책 그룹에 노드를 하나씩 열거하면 상위 구독에서 삭제하거나 이름을 바꾼 뒤 참조가 끊길 수 있습니다. 동적으로 바뀌는 구독에는 제공자의 use로 노드 집합을 가져오는 방식이 더 적합합니다. 구독 내용이 의심스러우면 개인 정보를 가린 단일 노드 구조만 내보내 비교하고 구독 URL 전체를 공개하지 마세요. 노드 목록, 전체 YAML, URI 링크는 서로 다른 입력 형식입니다. 형식 차이는 구독 형식 차이와 변환 방법을 참고해 인코딩된 텍스트를 proxies에 그대로 넣지 않도록 하세요.
정책 그룹과 출구 선택
그룹 이름은 안정적으로, 노드 집합은 유연하게
정책 그룹을 사용하면 규칙과 개별 노드를 분리할 수 있습니다. 규칙은 오랫동안 출구 선택을 가리키고 노드 변경은 그룹 안에서 처리하면 되므로 규칙을 하나씩 수정할 필요가 없습니다. 그룹 이름, 노드 이름, 내장 대상은 참조 체계에 속하므로 중복을 피하고 DIRECT, REJECT와 혼동하기 쉬운 이름도 사용하지 마세요. 목록의 proxies는 대상을 직접 지정하고 use는 노드 제공자를 참조합니다. 의미가 다르므로 제공자 이름을 노드 이름처럼 입력하면 안 됩니다.
select는 사용자가 출구를 선택합니다. url-test는 탐지 결과에 따라 후보를 고르고, fallback은 목록 순서대로 사용 가능한 출구를 찾습니다. load-balance는 지정된 정책에 따라 연결을 분배합니다. 자동 선택이라고 해서 모든 트래픽을 비교해 최적 경로를 고르는 것은 아닙니다. 탐지 URL은 특정 시점에 특정 대상에 연결할 수 있는지만 보여줍니다. 목적지, 프로토콜 종류, 서버 제한에 따라 실제 동작은 탐지 결과와 다를 수 있습니다.
# 앞 장의 '예시 출구' 노드와 함께 사용
proxy-groups:
- name: 출구 선택
type: select
proxies:
- 자동 선택
- 예시 출구
- DIRECT
- name: 자동 선택
type: url-test
proxies:
- 예시 출구
url: https://www.gstatic.com/generate_204
interval: 300
tolerance: 50
rules:
- MATCH,출구 선택
탐지 주기·허용 오차·장애 전환
interval은 탐지 주기를 초 단위로 설정합니다. 적용 가능한 자동 선택 그룹에서 tolerance는 전환 허용 오차를 밀리초로 지정합니다. 허용 오차를 설정하면 작은 변동으로 자주 전환되는 일을 줄일 수 있지만 원격 서버의 혼잡을 해결하지는 못합니다. 주기가 너무 짧으면 요청이 늘고 기기가 자주 깨어나므로 모바일 기기는 배터리와 네트워크 전환도 고려해야 합니다. 탐지 주소는 예상 가능한 응답을 안정적으로 반환하고 로그인 절차가 없어야 합니다. 탐지 대상에 접속할 수 없다면 모든 후보가 사용 불가로 잘못 판단될 수 있습니다.
장애 전환 그룹에서 대상 순서는 실제 동작에 영향을 줍니다. 앞에 있는 대상이 언제나 더 빠른 것은 아니지만 사용 가능한 경우 우선 선택됩니다. 부하 분산도 보통 연결 단위로 이루어지며 한 번의 다운로드를 여러 노드로 나누어 대역폭을 합산하지 않습니다. 로그인 세션이나 출처 주소를 유지해야 하는 서비스는 출구를 분산하기 전에 서비스에서 주소 변경을 허용하는지 확인하세요. 규칙 대상이 바뀌어도 이미 연결된 TCP 연결은 새 출구로 자동 이동하지 않는 경우가 많으므로 새 연결을 만들어 검증해야 합니다.
| 그룹 유형 | 선택 방식 | 적합한 용도 |
|---|---|---|
select | 후보에서 직접 선택 | 고정 출구·수동 진단·통합 진입점 |
url-test | 주기적인 탐지 결과에 따라 선택 | 후보 출구 자동 비교 |
fallback | 순서대로 사용 가능한 항목 선택 | 주·대기 출구 및 장애 전환 |
load-balance | 분배 정책에 따라 연결 처리 | 연결 분배 기준이 명확한 서비스 |
중첩 참조와 선택 상태
정책 그룹은 다른 그룹을 참조할 수 있지만 최종 출구로 이어지는 방향성 구조를 이뤄야 합니다. A 그룹이 B 그룹을 참조하고 B 그룹이 다시 A 그룹을 참조하면 순환 의존성이 생깁니다. 화면에서 저장되더라도 실행 시 설정이 거부되거나 유효한 출구를 찾지 못할 수 있습니다. 관리할 때는 최종 규칙 대상부터 아래로 따라가 실제 노드나 내장 대상에서 각 경로가 끝나는지 확인하세요. 그룹 계층이 너무 깊으면 화면의 첫 번째 선택만으로 최종 연결 경로를 파악하기 어렵습니다.
클라이언트는 수동 선택 상태를 저장해 재시작이나 업데이트 후 복원할 수 있으므로 목록 첫 항목이 현재 출구라고 단정할 수 없습니다. profile.store-selected 등의 저장 기능과 각 클라이언트의 상태 파일도 복원 동작에 영향을 줍니다. 그룹이 제대로 작동하는지 판단하려면 현재 그룹 선택 항목과 연결 기록의 전체 경로를 함께 확인하세요. YAML 목록 순서만으로 결론 내리면 안 됩니다. 그룹 이름을 바꿨다면 이전 선택이 더 이상 적용되지 않을 수 있으므로 다시 확인해야 합니다.
노드 집합이 비어 있으면 자동 그룹도 사용할 출구를 만들어 낼 수 없습니다. 필터 표현식을 사용했다면 후보가 남아 있는지 확인하세요. 특히 상위 구독의 이름 규칙이 바뀐 경우 주의해야 합니다. 수동 그룹에 직접 연결 옵션을 둘지는 서비스 요구 사항에 따라 결정하세요. 프록시 출구를 반드시 사용해야 하는 서비스라면 직접 연결을 확인 없이 예비 경로로 두면 안 됩니다. 규칙 테스트, 정책 검사, 실제 서비스 검증을 나누어 진행해야 후보 부족, 탐지 실패, 선택 복원 오류, 원격 서비스 제한을 구별할 수 있습니다.
규칙 문법과 매칭 순서
처음 일치한 규칙이 처리 대상을 결정
rules는 순서가 있는 목록입니다. 코어는 위에서 아래로 검사하고, 일치 항목을 찾으면 해당 규칙의 대상을 사용한 뒤 더 구체적인 조건을 찾지 않습니다. 따라서 구체적인 도메인과 예외 규칙을 포괄적인 조건보다 앞에 두고 MATCH는 마지막에 기본 규칙으로 배치하세요. 규칙은 '가장 긴 접두사가 우선' 또는 '도메인 규칙이 주소 규칙보다 우선'처럼 자동 정렬되지 않습니다. 실제 우선순위는 파일의 순서입니다. 포괄적인 규칙을 앞에 두면 뒤에 있는 규칙 전체가 적용되지 않을 수 있습니다.
대부분의 규칙은 '유형, 매칭 값, 대상' 형식입니다. DOMAIN은 정확한 도메인을, DOMAIN-SUFFIX는 도메인과 하위 도메인을, DOMAIN-KEYWORD는 도메인에 포함된 키워드를 검사합니다. IP-CIDR와 IP-CIDR6는 대상 주소 대역과 일치합니다. GEOIP와 GEOSITE는 관련 지역 또는 사이트 데이터를 사용합니다. PROCESS-NAME은 프로세스 식별 기능이 필요하므로 모든 플랫폼과 모든 수신 경로에서 사용할 수 있다고 가정하면 안 됩니다.
rules:
- DOMAIN,login.example.com,출구 선택
- DOMAIN-SUFFIX,example.com,DIRECT
- DOMAIN-KEYWORD,example,출구 선택
- IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- IP-CIDR6,::1/128,DIRECT,no-resolve
- MATCH,출구 선택
이 예에서는 로그인 도메인이 먼저 프록시 규칙에 일치하고 나머지 해당 도메인 접미사는 직접 연결됩니다. 키워드 규칙은 앞의 두 규칙으로 처리되지 않은 경우에만 적용됩니다. 예시 도메인은 규칙 순서를 설명하기 위한 것으로 실제 서비스의 분할 라우팅 권장안이 아닙니다. 주소 대역 규칙의 no-resolve는 해당 규칙 때문에 도메인 확인을 새로 시작하지 않는다는 뜻입니다. 연결에 대상 IP가 이미 있으면 여전히 규칙에 일치할 수 있습니다. 모든 DNS 요청을 차단하는 옵션도 아니며, 이후 규칙의 DNS 확인 기능을 무효화하지도 않습니다.
도메인·주소·프로세스 정보는 항상 함께 제공되지 않습니다
수신 경로마다 전달되는 정보가 다릅니다. HTTP 프록시 요청은 일반적으로 대상 호스트 이름을 제공하지만 일부 앱은 확인된 IP만 프록시에 전달하므로 코어가 원래 도메인을 알지 못할 수 있습니다. TUN, fake-ip 매핑, 스니핑으로 추가 정보를 얻을 수 있지만 각각 적용 범위가 다릅니다. 도메인 규칙이 적용되지 않으면 규칙을 더 추가하기 전에 연결 정보에서 코어가 실제로 받은 값을 확인하세요. 도메인 정보가 매칭 과정에 들어오지 않았다면 도메인 규칙을 무작정 늘려도 해결되지 않습니다.
| 규칙 유형 | 필요한 정보 | 흔한 오해 |
|---|---|---|
DOMAIN-SUFFIX | 도메인 정보 | 전체 URL 경로를 직접 매칭하지 못함 |
IP-CIDR | 대상 IP 주소 | 주소 규칙이 도메인 규칙보다 우선한다고 오해 |
GEOSITE | 사이트 데이터베이스와 도메인 | 데이터베이스 분류가 없거나 오래됨 |
PROCESS-NAME | 로컬 기기 프로세스 정보 | 게이트웨이에서 다른 기기의 프로세스를 매칭 |
MATCH | 추가 조건 불필요 | 앞에 배치해 이후 규칙을 가리는 문제 |
데이터 규칙과 거부 대상
지역 데이터 규칙은 실제로 로드된 데이터 형식과 파일 경로를 확인해야 합니다. GEOSITE의 분류 이름은 데이터베이스에 정의된 것이며 임의로 붙일 수 있는 태그가 아닙니다. GEOIP 판정도 데이터 업데이트와 주소 소속 변경의 영향을 받습니다. IP 주소의 지역을 서비스 운영자의 소재지와 같다고 보거나 콘텐츠가 반드시 특정 지역에서 제공된다고 추측하지 마세요. 데이터베이스 로드 실패, 분류 누락, 규칙 순서 오류는 서로 다른 문제입니다. 해결 방법은 GeoIP 및 GeoSite 데이터베이스 업데이트 방법을 참고하세요.
REJECT는 연결을 거부하며 명확히 차단할 범위에 사용합니다. 지나치게 넓은 키워드 규칙을 거부 대상으로 지정하면 로그인, 인증 코드, 정적 리소스까지 영향을 받을 수 있습니다. 테스트할 때는 먼저 범위를 좁히고 매칭 기록을 확인하세요. 규칙 대상은 노드나 정책 그룹일 수도 있지만 실제로 존재해야 합니다. 오타, 끝의 공백, 그룹 이름 변경으로 참조 오류가 생길 수 있으므로 매칭 표현식 앞부분만 확인해서는 안 됩니다.
수정을 검증할 때는 명확한 대상을 하나 골라 모드, 요청 도메인, 일치한 규칙, 최종 출구를 기록한 뒤 한 곳만 바꾸고 새 연결을 만드세요. 브라우저 연결 풀, HTTP/2 재사용, 앱의 장기 연결은 기존 연결을 계속 사용할 수 있으므로 페이지를 새로고침해도 규칙이 다시 판정되지 않을 수 있습니다. 필요하면 해당 연결을 닫고 다시 테스트하되, 모든 연결을 일상적으로 자동 종료하지 마세요. 규칙은 코어로 들어온 트래픽만 처리합니다. 연결 목록에 요청이 전혀 없다면 수신 경로와 트래픽 가로채기 범위부터 확인해야 합니다.
DNS·fake-ip·TUN 트래픽 가로채기
DNS 확인기 역할과 시작 단계 의존성
dns.enable은 코어의 DNS 모듈을 켜고 listen은 수신 주소를 지정합니다. nameserver는 일반 DNS 확인기 목록, default-nameserver는 DNS 서버 자체의 도메인을 확인하는 초기 확인기, proxy-server-nameserver는 프록시 서버 도메인 확인용입니다. 각 필드는 서로 다른 단계를 처리하므로 응답이 더 빠르다는 이유만으로 모두 바꾸면 안 됩니다. 특히 암호화 DNS에 도메인 주소를 사용한다면 작동하는 초기 확인 경로가 먼저 있어야 하며, 그렇지 않으면 시작 시 의존성 순환이 발생할 수 있습니다.
enhanced-mode: fake-ip는 도메인에 매핑 주소를 할당하고, 이후 연결이 코어에 들어오면 이를 통해 도메인 정보를 복원할 수 있습니다. 이는 원격 서버의 실제 주소가 아니며 웹사이트가 해당 대역에 배포되었다는 뜻도 아닙니다. 앱이 코어를 우회해 매핑 주소로 연결하면 접속에 실패할 수 있으므로 DNS 응답과 트래픽 가로채기를 함께 설정해야 합니다. LAN 기기 탐색이나 특정 기기 프로토콜, 실제 주소를 확인하는 앱에서는 필요에 따라 fake-ip-filter를 설정할 수 있습니다. 모든 도메인을 제외하면서 같은 매핑 효과를 기대해서는 안 됩니다.
dns:
enable: true
listen: "127.0.0.1:1053"
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "*.lan"
- "*.local"
- "localhost"
default-nameserver:
- 1.1.1.1
nameserver:
- https://dns.cloudflare.com/dns-query
proxy-server-nameserver:
- https://dns.cloudflare.com/dns-query
DNS 확인 정책은 출구 규칙을 대신하지 않습니다
nameserver-policy를 사용하면 특정 도메인에 사용할 DNS 확인기를 지정할 수 있습니다. 이는 어디서 DNS 응답을 받을지 정할 뿐 실제 연결의 출구를 결정하지는 않습니다. fallback과 fallback-filter는 예비 확인 및 응답 필터링에 사용되지만, 첫 번째 요청이 실패하면 두 번째 요청을 순차 실행한다는 뜻으로 단순화할 수 없습니다. 실제 동작은 필터 조건에 따라 달라지므로 설정 전에 원하는 응답을 명확히 하세요. DNS 확인 경로, DNS 연결의 출구, 실제 대상 서비스의 출구는 서로 관련되지만 별개의 문제입니다. DNS 응답 하나만 보고 결론 내리면 안 됩니다.
암호화 DNS는 클라이언트와 확인기 사이의 전송을 보호하지만, HTTPS 주소를 사용한다고 DNS 누출이 없다고 단정할 수는 없습니다. 운영체제, 브라우저, 앱이 각자 다른 DNS 확인기를 사용할 수 있습니다. 브라우저 자체 암호화 DNS 요청도 일반 HTTPS 연결로 네트워크를 통과해 코어의 수신 포트를 거치지 않을 수 있습니다. 누가 요청을 보냈는지, 요청이 코어에 들어왔는지, 최종적으로 어떤 정책을 탔는지 확인하세요. 필드별 역할은 nameserver·fallback·fake-ip 안내를 참고하세요.
TUN의 라우팅·권한·가로채기 범위
TUN은 가상 네트워크 인터페이스로 트래픽을 받아 시스템 프록시를 따르지 않는 앱에 적합합니다. 보통 관리자 권한이나 이에 준하는 시스템 권한이 필요하고 라우팅 설정, 기기 인터페이스, 코어의 네트워크 스택 지원도 필요합니다. 활성화만으로 모든 네트워크 활동이 가로채지는 않습니다. 가상 머신, 컨테이너, 다른 VPN, 특정 인터페이스에 바인딩된 앱은 별도의 경로를 사용할 수 있습니다. 여러 자동 라우팅 도구를 동시에 켜서 해결하려 하지 말고, 하나만 남긴 상태에서 인터페이스와 경로가 제대로 만들어졌는지 확인하세요.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
dns-hijack은 가로채기 범위에 포함되는 기존 DNS 요청을 코어의 DNS 모듈로 전달하지만 모든 암호화 DNS 트래픽을 식별해 복호화하지는 않습니다. 위 설정은 활성화된 dns와 함께 사용해야 하며 실제 지원 여부는 플랫폼, 라우팅, 방화벽에 따라 다릅니다. auto-detect-interface는 출구 인터페이스를 자동으로 선택하지만 여러 네트워크 어댑터나 네트워크 전환, 다른 터널이 있는 경우 결과를 확인해야 합니다. 기본 출구가 잘못되면 노드 연결이 가상 인터페이스로 다시 전달되는 비정상 경로가 생길 수 있습니다.
fake-ip 모드, 매핑 범위, DNS 가로채기 방식을 바꾸면 앱과 시스템 캐시에 이전 결과가 남을 수 있습니다. 새 테스트 연결을 만들고 필요하면 관련 캐시를 지운 뒤 코어의 매핑이 재시작 후에도 유지되는지 확인하세요. 일부 앱만 실패하거나 LAN 도메인에 문제가 생기거나 절전 모드에서 깨어난 뒤 네트워크가 끊긴다면 DNS 확인 경로와 라우팅 변화를 각각 비교하세요. DNS 모듈을 계속 꺼두는 방식으로 해결하지 마세요. DNS 누출 검사 및 해결에 따라 다시 테스트하고 수정 전후 설정을 보관해 언제든 되돌릴 수 있게 하세요.
노드 구독 및 규칙 제공자
원격 리소스 선언과 실제 참조
proxy-providers를 사용하면 정기적으로 업데이트되는 구독의 노드 집합을 기본 설정에서 분리할 수 있습니다. 제공자는 리소스가 HTTP에서 오는지 로컬 파일인지, 저장 경로와 업데이트 주기를 선언합니다. 정책 그룹은 use로 해당 노드 집합을 가져옵니다. 제공자만 선언하고 그룹에서 참조하지 않으면 규칙이 해당 노드를 자동 선택하지 않습니다. 전체 설정 구독과 달리 노드 제공자는 로컬 정책과 규칙을 유지하면서 상위에서 노드만 업데이트할 수 있어 매번 바뀌는 범위를 줄이는 데 유용합니다.
아래 URL은 예시 도메인을 사용하므로 실제로 사용할 때는 로컬에서 본인의 리소스 주소로 바꾸세요. 원격 노드 파일은 일반적으로 최상위 키가 proxies인 노드 목록이어야 합니다. 임의의 웹페이지, Base64 텍스트, 변환하지 않은 URI 모음을 그대로 입력할 수는 없습니다. 일부 클라이언트는 형식 변환을 지원하지만 이는 클라이언트 기능이지 모든 코어가 임의의 형식을 받아들인다는 뜻은 아닙니다. 먼저 응답 내용을 확인한 뒤 제공자를 사용할지 전체 설정을 가져올지 결정하세요.
proxy-providers:
상위 노드:
type: http
url: "https://example.com/proxies.yaml"
path: ./providers/upstream.yaml
interval: 3600
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 300
proxy-groups:
- name: 출구 선택
type: select
use:
- 상위 노드
proxies:
- DIRECT
규칙 제공자의 동작 및 형식
rule-providers는 규칙 집합을 관리하며 기본 규칙 목록에서 RULE-SET으로 참조합니다. behavior는 집합을 해석하는 방식을 지정합니다. domain은 도메인 집합, ipcidr은 주소 대역, classical은 여러 유형의 기존 규칙 조건을 다룹니다. format은 YAML이나 텍스트 같은 리소스 인코딩 형식을 지정합니다. 동작과 형식은 별개의 기준이므로 파일 확장자가 YAML이라고 해서 전체 클래식 규칙이 들어 있다고 단정하면 안 됩니다.
rule-providers:
로컬 직접 연결 도메인:
type: file
behavior: domain
format: yaml
path: ./rules/direct.yaml
rules:
- RULE-SET,로컬 직접 연결 도메인,DIRECT
- MATCH,출구 선택
해당하는 rules/direct.yaml은 아래 구조를 사용할 수 있습니다. 도메인 집합의 +.example.com은 해당 도메인과 하위 도메인을 묶어 매칭한다는 의미이므로 기본 규칙 목록에 완전한 규칙 한 줄처럼 그대로 넣으면 안 됩니다. 클래식 규칙 집합은 대개 대상 없이 매칭 조건만 작성하며, 출구는 이를 참조하는 RULE-SET에서 지정합니다. 두 문법을 섞으면 로드에 실패하거나 예상과 다른 범위에 적용될 수 있습니다.
# rules/direct.yaml
payload:
- "+.example.com"
- "localhost"
업데이트 주기·캐시·접근 경로
리소스 업데이트 주기와 상태 점검 주기는 서로 독립적입니다. 업데이트는 새 노드나 규칙을 다운로드하고, 상태 점검은 기존 후보의 사용 가능 여부를 확인합니다. 주기를 바꿨다고 업데이트가 바로 발생하는 것은 아니므로 리소스 시간, 로그, 현재 목록을 확인하세요. 다운로드 요청은 초기 네트워크 경로에도 의존합니다. 프록시를 통해서만 리소스를 받을 수 있는데 프록시 노드가 아직 다운로드하지 않은 같은 리소스에만 있다면 시작할 수 없는 상황이 됩니다. 계속 재시작하기보다는 사용할 수 있는 캐시나 초기 다운로드 방법을 확보하세요.
path는 쓰기가 허용된 작업 디렉터리에 두고 제공자마다 다른 파일을 지정해야 합니다. 여러 제공자가 같은 캐시 경로를 쓰면 서로 파일을 덮어쓸 수 있습니다. 데스크톱에서 서버 환경으로 옮길 때 작업 디렉터리가 달라져 파일을 찾지 못할 수도 있습니다. 리소스 갱신이 실패했을 때 이전 캐시를 계속 사용하는지는 현재 클라이언트와 코어 로그를 기준으로 확인하세요. 실패 시 항상 이전 파일이 안전하게 유지된다고 가정하면 안 됩니다. 원격 리소스를 일시적으로 사용할 수 없더라도 전체 로딩에 영향을 주지 않도록 중요한 규칙은 복구 가능한 사본을 보관하세요.
구독 URL에는 계정 식별 정보가 포함되는 경우가 많으므로 전체 주소를 개인 접근 인증 정보로 취급해야 합니다. 설정을 공유할 때 URL, 인증 헤더, 노드 인증 필드를 함께 가리세요. 매개변수가 포함된 주소를 공개 스크린샷이나 문의 게시물에 올리지 마세요. 업데이트 결과가 HTML 페이지라면 페이지 내용을 YAML처럼 고치려 하지 말고 로그인 페이지로 이동했는지, 주소가 만료됐는지, 응답 상태가 무엇인지 확인하세요. 상위 리소스 형식이 올바른지 확인한 뒤 제공자 필드, 참조 이름, 캐시 경로를 점검해야 잘못된 단계만 반복해서 수정하는 일을 피할 수 있습니다.
오버라이드 병합 및 적용 결과 검증
최종 설정 파일을 생성하는 주체 확인하기
오버라이드는 원본 설정과 실행 설정 사이에서 클라이언트가 수행하는 처리이며, 모든 클라이언트에 공통으로 적용되는 코어 문법이 아닙니다. 일반적인 흐름은 구독을 읽고 공통 설정을 적용한 뒤 오버라이드나 스크립트를 실행해 실행 파일을 생성하는 방식이지만, 정확한 순서는 현재 클라이언트에서 확인해야 합니다. override.yaml을 디렉터리에 넣었다고 자동으로 적용되는 것은 아니며 클라이언트에서 명시적으로 불러와야 합니다. 업데이트 뒤 수정 내용이 사라지면 자동 생성 파일을 반복해서 편집하지 말고 편집 경로와 처리 순서를 확인하세요.
스칼라 교체, 매핑의 재귀 병합, 목록 연결은 서로 다른 작업입니다. mode를 전역에서 규칙 모드로 바꾸는 것은 보통 스칼라 값 교체입니다. dns.nameserver만 수정했을 때 다른 DNS 필드가 유지되는지는 깊은 병합을 하는지에 달려 있습니다. rules를 수정하면 목록 전체가 교체될 수도 있고 앞이나 뒤에 추가될 수도 있습니다. 클라이언트가 기능을 '병합'이라고 부르더라도 세 데이터 유형에 같은 알고리즘을 사용한다고 보장할 수 없습니다. 작은 조각으로 결과를 시험한 뒤 수정 범위를 넓히세요.
# 클라이언트 오버라이드 입력용이며 병합 방식은 클라이언트에서 확인하세요
mode: rule
log-level: info
dns:
enable: true
enhanced-mode: fake-ip
profile:
store-selected: true
목록 수정은 기존 의미를 유지해야 합니다
규칙을 앞에 추가하는 것과 뒤에 추가하는 것은 결과가 다릅니다. 예외 규칙을 MATCH 뒤에 추가하면 적용되지 않고, 새 기본 규칙을 앞에 넣으면 기존 목록을 가릴 수 있습니다. 정책 그룹도 이름만 보고 자동 병합된다고 가정하면 안 됩니다. 같은 이름의 새 객체가 충돌하거나 기존 객체를 교체하면서 원래 제공자 참조가 사라질 수 있습니다. 오버라이드를 작성하기 전에 '마지막 기본 규칙 앞에 LAN 예외만 추가'처럼 원하는 변경을 명확히 적고, 해당 작업을 클라이언트가 지원하는지 확인하세요. 비슷해 보이는 YAML부터 만들어서는 안 됩니다.
클라이언트에서 스크립트 오버라이드를 제공한다면 스크립트와 수정 설명을 로컬에 보관하고 출처가 불분명한 처리 로직을 바로 실행하지 마세요. 스크립트는 전체 설정을 읽거나 변경할 수 있어 일반 필드 오버라이드보다 영향 범위가 큽니다. 필요한 키만 수정하고 누락된 객체와 빈 목록을 처리하며 나머지 필드는 그대로 유지하는 편이 안전합니다. 클라이언트를 바꿀 때는 원하는 결과와 데이터 파일을 옮기고, 기존 클라이언트의 스크립트 API, 변수 이름, 병합 순서가 그대로 호환된다고 가정하지 마세요.
정적 검사부터 실제 연결 경로까지 검증
독립 코어는 설정 테스트 명령으로 구조와 참조를 검사할 수 있습니다. 아래 명령은 현재 디렉터리를 작업 디렉터리로 사용해 config.yaml을 읽습니다. 실행 파일 이름과 디렉터리는 실제 설치 위치에 맞게 바꾸세요. 데스크톱 클라이언트에 자체 검사나 로그 메뉴가 있다면 별도의 코어를 실행해 수신 포트를 점유할 필요가 없습니다. 테스트가 성공해도 검사 단계를 통과했다는 뜻일 뿐 계정 유효성, 원격 서버 상태, 시스템 프록시, TUN 권한, 모든 앱의 실제 트래픽 경로까지 검증되는 것은 아닙니다.
mihomo -t -d . -f ./config.yaml
수정 전에 정상 작동하는 설정을 저장하고 적용 후에는 원본 파일 저장 여부만 보지 말고 실행 파일의 주요 필드를 확인하세요. 그다음 새 테스트 연결을 만들어 수신 경로, 모드, 일치 규칙, 정책 그룹 경로, 출구를 차례로 점검합니다. DNS를 수정했다면 확인 결과와 캐시 사용 여부도 살펴보세요. 검사 항목을 나눠 기록하면 로딩, 리소스, 실제 서비스 접속 중 어디에서 문제가 생겼는지 파악할 수 있습니다. 최종 증상이 모두 '인터넷에 연결할 수 없음'이어도 해결 방법은 서로 다릅니다.
| 관찰 결과 | 우선 확인할 항목 | 다음 단계 |
|---|---|---|
| 설정 테스트 실패 | 들여쓰기·필드 유형·중복 키·참조 오류 | 오류 위치 주변의 전체 구조 수정 |
| 테스트는 통과했지만 시작 실패 | 포트·권한·리소스·작업 디렉터리 | 시작 로그를 확인하고 규칙은 먼저 수정하지 않기 |
| 실행은 정상이지만 연결 기록이 없음 | 시스템 프록시·앱 프록시·TUN 경로 | 트래픽이 코어에 들어오는지 확인 |
| 연결은 있지만 출구가 예상과 다름 | 모드·첫 일치 규칙·그룹 선택 | 테스트 중인 기존 연결을 닫고 다시 요청 |
| 업데이트 후 수정 내용이 사라짐 | 오버라이드 경로와 생성 순서 | 지속 오버라이드로 옮기고 최종 파일 확인 |
되돌릴 때는 설정뿐 아니라 실행 상태도 확인해야 합니다. 이전 파일을 복구한 뒤 현재 모드, 수동 그룹 선택, DNS 캐시, TUN 경로에 새 상태가 남아 있지 않은지 살펴보세요. 한 번에 한 종류의 동작만 수정하고 간단한 변경 기록을 남기면 노드, DNS, 규칙을 동시에 바꾸는 것보다 원인을 찾기 쉽습니다. 처음 설정하는 경우에는 빠른 시작 가이드에 따라 주요 경로를 확인하세요. 개별 문제는 자주 묻는 질문을 참고하세요. 이 매뉴얼은 모든 네트워크에 적용되는 고정 설정 조합을 제공하는 것이 아니라 필드 간 관계를 설명합니다.