규칙 목록은 한 줄에 하나씩 적는 일반 텍스트이며 형식은 '유형, 값, 정책'입니다. 이 글에서는 도메인 계열(DOMAIN, DOMAIN-SUFFIX, DOMAIN-KEYWORD), IP 계열(GEOIP, IP-CIDR), 그리고 마지막을 받쳐 주는 FINAL을 하나씩 짚어 매칭 대상과 적용 순서를 설명하고, Config → Rules에서 그대로 복사해 쓸 수 있는 예시를 제공합니다. 이미 구독을 가져와 트래픽을 원하는 대로 나누고 싶은 사용자에게 적합하며, 읽고 나면 서로 충돌하지 않는 규칙 목록을 직접 작성할 수 있습니다.
규칙 한 줄의 세 부분 구조
Shadowrocket의 규칙 목록은 설정 파일에 저장되는 일반 텍스트로, 한 줄에 하나씩 들어갑니다. 각 줄은 영문 반각 쉼표로 세 부분으로 나뉩니다: 유형(TYPE), 값(VALUE), 정책(POLICY). 유형은 '무엇을 기준으로 비교할지', 값은 '무엇과 비교할지', 정책은 '일치한 뒤 어떻게 처리할지'를 정합니다.
정책은 세 가지뿐입니다. PROXY는 현재 선택한 서버를 거치고, DIRECT는 직접 연결하며, REJECT는 이 연결을 버립니다. #로 시작하는 줄은 주석이라 파싱할 때 건너뛰고, 빈 줄도 마찬가지로 무시합니다. 규칙을 쓸 때 사용하는 쉼표는 반드시 영문 반각이어야 하며, 전각 쉼표를 쓰면 줄 전체가 무효가 됩니다.
# 각 줄 형식: 유형 / 값 / 정책
DOMAIN-SUFFIX,example.com,PROXY
DOMAIN-KEYWORD,analytics,DIRECT
IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
FINAL,DIRECT
세 부분 중 실수가 가장 잦은 것은 값입니다. 도메인 계열 규칙의 값은 호스트 이름, IP 계열 규칙의 값은 CIDR 대역이나 두 자리 국가/지역 코드, 포트 계열 규칙의 값은 숫자입니다. 형식이 맞지 않는 줄은 오류를 내지 않고 조용히 건너뛰어지므로, '규칙을 썼는데 반응이 없다'면 먼저 그 줄의 쉼표와 값 형식을 확인하고 그다음에 다른 부분을 의심하세요.
도메인 계열: DOMAIN, DOMAIN-SUFFIX, DOMAIN-KEYWORD
도메인 계열 규칙은 요청에 담긴 호스트 이름을 매칭합니다. HTTPS 요청의 호스트 이름은 보통 TLS 핸드셰이크의 SNI에서, HTTP 요청은 Host 헤더에서 오며, 이 정보는 연결이 막 맺어질 때 이미 확보되어 DNS 조회를 기다릴 필요가 없습니다. 그래서 도메인 규칙이 가장 빠르게 판단되고, 조회 결과의 변동에도 가장 영향을 받지 않습니다. 자주 쓰는 세 가지 작성법은 범위가 차례로 넓어집니다:
| 유형 | 매칭 대상 | 작성 예시 | 적용 범위 |
|---|---|---|---|
DOMAIN | 전체 호스트 이름, 한 글자도 다르지 않아야 함 | DOMAIN,api.example.com,PROXY | api.example.com만 매칭되며 www.api.example.com은 매칭되지 않음 |
DOMAIN-SUFFIX | 도메인 접미사, 자기 자신과 모든 하위 도메인 포함 | DOMAIN-SUFFIX,example.com,PROXY | example.com, a.example.com, a.b.example.com 모두 매칭 |
DOMAIN-KEYWORD | 호스트 이름 어느 위치에든 나타나는 키워드 | DOMAIN-KEYWORD,analytics,DIRECT | analytics.example.com, cdn-analytics.example.net 모두 매칭 |
DOMAIN-SET | 외부 도메인 목록 파일, 한 줄에 도메인 하나 | DOMAIN-SET,example-domains.txt,DIRECT | 목록에 적힌 도메인은 해당 줄의 정책으로 처리 |
범위가 넓을수록 잘못 걸릴 확률도 높아집니다. DOMAIN-KEYWORD,analytics,DIRECT는 호스트 이름 어디에든 analytics가 들어간 요청을 매칭하므로 직접 연결하고 싶지 않은 사이트까지 포함될 수 있고, DOMAIN-SUFFIX,example.com,PROXY는 mail.example.com, static.example.com까지 함께 프록시로 보냅니다. 넓은 규칙을 쓰기 전에 이 접미사 아래에 따로 처리해야 할 하위 도메인이 정말 없는지 먼저 확인하세요.
작성법을 고를 때는 다음 순서로 판단합니다:
- 구분해서 처리할 호스트 이름이 하나뿐이라면
DOMAIN을 쓰고 글자 단위로 정확히 맞춥니다. - 한 사이트와 그 모든 하위 도메인을 함께 처리하려면
DOMAIN-SUFFIX를 씁니다. - 도메인 구조가 일정하지 않고 접두사가 무작위인 CDN이나 통계 서비스라면 그때
DOMAIN-KEYWORD를 검토합니다. - 같은 성격의 도메인이 너무 많아 기본 목록이 지나치게 길어진다면 도메인을 별도 텍스트 파일로 분리해
DOMAIN-SET으로 참조합니다.
DOMAIN,www.example.com,DIRECT
DOMAIN-SUFFIX,example.com,PROXY
DOMAIN-KEYWORD,adservice,REJECT
DOMAIN-SET,example-domains.txt,DIRECT
IP 계열: GEOIP와 IP-CIDR은 조회된 주소를 비교합니다
IP 계열 규칙은 도메인을 보지 않고 연결 대상의 IP 주소만 봅니다. IP를 얻으려면 시스템이 먼저 DNS 조회를 해야 하므로 IP 규칙은 도메인 규칙보다 한 단계 늦게 적용되고, '도메인'이라는 축을 잃습니다. 같은 도메인이 서로 다른 주소로 조회되면 매칭 결과도 함께 달라질 수 있습니다.
GEOIP는 두 자리 국가/지역 코드로 주소 대역 전체의 소속을 요약합니다. GEOIP,CN,DIRECT의 의미는 '대상이 중국 IP면 직접 연결'입니다. IP-CIDR은 정확한 대역을 적으며, 내부망 직접 연결의 흔한 예는 IP-CIDR,192.168.0.0/16,DIRECT와 IP-CIDR,10.0.0.0/8,DIRECT이고, IPv6 대상에는 IP-CIDR6을 씁니다. 포트로 판단하는 일은 DST-PORT와 SRC-PORT가 맡으며, 예를 들어 DST-PORT,443,PROXY는 대상 포트가 443인 연결을 프록시로 보낸다는 뜻입니다.
GEOIP,CN,DIRECT
IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
IP-CIDR6,fc00::/7,DIRECT,no-resolve
DST-PORT,443,PROXY
내부망 대역 같은 규칙에는 보통 끝에 no-resolve를 붙입니다. 이 파라미터는 해당 규칙을 매칭할 때 IP를 얻기 위해 DNS 조회를 일으키지 않도록 합니다. 이 파라미터가 없으면 원래 바로 매칭될 수 있었던 요청이 억지로 한 번 조회를 거치게 되어 판단이 느려지고, 조회 실패로 매칭이 되지 않을 수도 있습니다.
결론: 도메인 규칙은 IP 규칙보다 앞에 둡니다
GEOIP와 IP-CIDR은 대상 IP를 먼저 확보해야 합니다. 이들이 도메인 규칙보다 앞에 있으면 DOMAIN-SUFFIX로 정확히 매칭될 수 있었던 요청이 먼저 조회를 강제당하고, 매칭 결과는 그때 어떤 주소로 조회됐는지에 좌우됩니다. 도메인 계열을 앞에, IP 계열을 뒤에 두어야 순서가 안정적입니다.
적용 순서: 위에서 아래로, 첫 일치에서 중단
Shadowrocket은 규칙 목록의 첫 줄부터 차례로 비교하고, 어떤 줄이 일치하면 그 줄의 정책을 즉시 실행하며 뒤의 규칙은 더 이상 판단에 참여하지 않습니다. 이 구조가 정하는 정렬 원칙은 간단합니다. 더 구체적이고 우선 처리해야 하는 규칙일수록 위에, 더 넓은 규칙일수록 아래에 둡니다.
FINAL은 매칭 값 없이 정책만 있는 마지막 받침 규칙으로, 앞에서 하나도 매칭되지 않은 요청을 받아냅니다. FINAL,DIRECT는 매칭되지 않은 트래픽을 직접 연결로, FINAL,PROXY는 프록시로 보냅니다. 반드시 목록의 마지막 줄에 두어야 하며, FINAL 뒤에 쓴 규칙은 실행되지 않습니다.
# 1. 내부망과 예약 주소는 먼저 직접 연결
IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
# 2. 확실히 차단할 도메인
DOMAIN-SUFFIX,ads.example.com,REJECT
# 3. 확실히 프록시로 보낼 도메인
DOMAIN-SUFFIX,example.com,PROXY
# 4. 중국 본토 주소는 직접 연결
GEOIP,CN,DIRECT
# 5. 마지막 받침
FINAL,PROXY
정렬할 때는 아래 다섯 층을 위에서 아래로 배치하면 됩니다:
- 1층: 내부망과 예약 대역, 예를 들어
IP-CIDR,192.168.0.0/16,DIRECT,no-resolve를 맨 앞에 둡니다. - 2층: 확실히 버릴 도메인.
REJECT는 같은 도메인의PROXY보다 앞에 써야 차단이 실제로 동작합니다. - 3층: 프록시 또는 직접 연결로 확실히 나눌 도메인.
DOMAIN은DOMAIN-SUFFIX보다 위에 둡니다. - 4층: 주소 소속으로 판단하는
GEOIP, 그리고 포트로 판단하는DST-PORT. - 5층:
FINAL. 마지막 줄을 지키며 나머지를 받아냅니다.
규칙을 적용하려면: Global Routing과 설정 파일
규칙 목록은 Global Routing이 Config 모드일 때만 판단에 참여합니다. 모드는 Settings → Global Routing에서 전환하며, 자주 쓰는 세 옵션의 차이는 다음과 같습니다:
Config(설정)
권장설정 파일의 규칙 목록을 한 줄씩 매칭합니다. PROXY에 일치하면 프록시로, DIRECT에 일치하면 직접 연결로, REJECT에 일치하면 연결을 버립니다.
적합: 일상적인 기본 사용, 규칙을 실제로 동작시키고 싶을 때
Proxy(프록시)
규칙 목록을 무시하고 모든 연결을 현재 선택한 서버로 보냅니다.
적합: 일시적으로 전체 트래픽을 프록시로 보낼 때, 규칙 문제 점검
Direct(직접 연결)
규칙 목록과 서버를 무시하고 모든 연결을 그대로 내보냅니다.
적합: 특정 현상이 프록시 때문에 생긴 것인지 확인할 때
또 하나의 전제는 '올바른 파일을 수정했는가'입니다. Config 탭에는 여러 설정이 동시에 있을 수 있고, 현재 선택된(체크 표시가 있는) 하나만 사용됩니다. 편집 경로는 Config → 사용 중인 설정 파일 선택 → Rules이며, 목록은 줄 단위로 표시되고 오른쪽 위 '+'로 줄을 추가하며 아무 줄이나 눌러 유형, 값, 정책을 수정할 수 있습니다. 전체 흐름은 다음과 같습니다:
모드 확인
Settings → Global Routing에서 Config를 선택해야 규칙 목록이 판단에 참여합니다.
Config 열기
하단 탭에서 Config로 이동해 체크 표시가 된 파일이 지금 사용 중인 설정 파일인지 확인합니다.
Rules로 이동
설정 파일로 들어가 Rules 항목을 찾으면 그 안에 전체 규칙 목록이 있습니다.
새 줄 추가
오른쪽 위 '+'로 새 규칙을 추가하고 '유형, 값, 정책' 세 부분으로 입력하며 쉼표는 영문 반각을 사용합니다.
순서 조정
구체적인 규칙을 넓은 규칙 앞으로 옮기고, FINAL은 마지막 줄에 둡니다.
저장 후 다시 연결
저장한 뒤 Home으로 돌아가 한 번 끊고 다시 연결해 새 규칙 목록을 적용합니다.
결론: 모드를 먼저 정하고, 그다음 규칙
규칙을 썼는데 동작하지 않으면 Global Routing이 Config 모드에 있는지, 현재 선택된 파일이 방금 수정한 그 파일인지 먼저 확인하고, 그다음에 규칙 순서와 작성법을 점검하세요. 순서를 거꾸로 점검하면 보통 작성법만 오래 붙들고 헤매게 됩니다.
자주 나오는 네 가지 질문
아래 네 가지 질문은 규칙 관련 문의에서 가장 흔한 상황을 담고 있으며, 점검 경로는 모두 '모드 → 설정 파일 → 규칙 순서 → 규칙 작성법' 순으로 내려갑니다.
DOMAIN-SUFFIX,example.com,PROXY를 추가했는데 이 도메인이 여전히 직접 연결되나요?
먼저 목록에 더 앞선 규칙이 이미 매칭되지 않는지 보세요. 예를 들어 도메인 규칙보다 앞에 있는 GEOIP,CN,DIRECT나 범위가 넓은 DOMAIN-KEYWORD 같은 것입니다. 그다음 Global Routing이 Config 모드에 있는지, 현재 선택된 것이 방금 편집한 설정인지 확인하고, 마지막으로 한 번 끊고 다시 연결합니다.
GEOIP,CN,DIRECT가 왜 중국 본토 사이트를 직접 연결하지 못하나요?
GEOIP는 도메인이 아니라 조회된 IP를 매칭합니다. 이 규칙이 도메인 규칙보다 앞에 있거나, 대상이 조회된 주소가 CN 대역에 속하지 않으면 매칭되지 않습니다. 도메인 규칙 뒤, FINAL 앞으로 옮기고 다시 연결해 확인해 보세요.
IP-CIDR 규칙이 왜 제가 쓴 도메인과 매칭되지 않나요?
IP-CIDR은 IP 주소만 비교하고 도메인은 인식하지 않습니다. 도메인으로 나누려면 DOMAIN-SUFFIX를 쓰고, 대역으로 나누려면 대상이 조회된 주소가 실제로 적어 둔 CIDR 안에 들어가는지 확인하세요. 내부망 대역을 쓸 때는 no-resolve를 잊지 마세요.
REJECT를 썼는데 일부 요청이 그대로 나가나요?
규칙은 위에서 아래로 매칭되고 첫 일치에서 멈춥니다. REJECT 위에 같은 대상을 매칭하는 PROXY나 DIRECT가 이미 있으면 요청은 이 줄까지 오지 않습니다. REJECT를 해당 도메인 규칙 앞으로 올려 다시 시도하세요.