두 커널의 버전 현황과 계보

오리지널 Clash(Dreamacro/clash)는 2023년 말에 아카이브되었고 마지막 정식 버전은 v1.18.0으로 이후 새 커밋이 없습니다. 같은 시기에는 TUN, rule-provider, script 기능을 제공한 클로즈드 소스 Clash Premium 커널도 있었지만 소스를 공개하지 않았고 오리지널과 함께 업데이트가 멈췄습니다. Clash.Meta는 커뮤니티가 오리지널 커널을 기반으로 다시 작성한 포크이며, 2024년에 mihomo로 이름을 바꾸고 MetaCubeX/mihomo 저장소에서 지금도 꾸준히 업데이트되고 있습니다.

설정 파일 수준에서 두 커널은 상위 호환됩니다. port, socks-port, mixed-port, allow-lan, mode, log-level, external-controller, proxies, proxy-groups, rules 같은 필드는 양쪽 모두 인식합니다. 차이는 인바운드 프로토콜, 규칙 유형, DNS 해석 체인, TUN 구현 네 가지에 집중됩니다. 아래에서 항목별로 비교하고 마이그레이션 시 수정해야 할 필드를 제시합니다.

기능 오리지널 Clash v1.18.0 mihomo
인바운드 방식 port, socks-port, redir-port 세 가지 최상위 스위치 최상위 스위치 + listeners 섹션으로 여러 인바운드 선언
프록시 프로토콜 ss、vmess、trojan、snell、socks5、http 위 항목 전체 + vless, hysteria2, tuic, wireguard, ssh, anytls
규칙 유형 도메인, IP, 포트, GEOIP, MATCH 위 항목 전체 + GEOSITE, IP-ASN, 정규식, 논리 조합, SUB-RULE
규칙 세트 미지원, 규칙을 설정 파일에 직접 작성해야 함 rule-providers, mrs 바이너리 포맷 지원
DNS nameserver + fallback + fallback-filter nameserver-policy, 분할 DNS, DoQ, fake-ip 화이트리스트 모드
TUN 미지원 system / gvisor / mixed 세 가지 스택
유지보수 상태 2023년 말 아카이브 지속 업데이트

프로토콜 지원: mihomo만 인식하는 proxy type

오리지널 Clash의 proxies 섹션은 ss, vmess, trojan, snell, socks5, http 여섯 가지 type만 인식합니다. 목록에 없는 type을 만나면 커널은 파싱 단계에서 unsupported proxy type 오류를 내고 종료하며, 해당 노드를 건너뛰고 계속 실행하지 않습니다. 커널을 바꾼 뒤 가장 흔히 마주치는 첫 번째 오류 유형입니다.

mihomo는 여기에 vless(XTLS Vision과 REALITY 포함), hysteria2, tuic v5, wireguard, ssh, anytls를 추가했고, Shadowsocks 암호화 방식도 2022 시리즈로 확장했습니다: 2022-blake3-aes-128-gcm, 2022-blake3-aes-256-gcm, 2022-blake3-chacha20-poly1305. 아래 세 노드의 필드 조합은 오리지널 커널에서 하나도 파싱할 수 없습니다.

proxies:
  - name: vless-vision
    type: vless
    server: edge.example.com
    port: 443
    uuid: 8f2c1d40-3a7e-4b91-9c2d-5e6f7a8b9c0d
    network: tcp
    tls: true
    udp: true
    flow: xtls-rprx-vision
    servername: www.example.com
    client-fingerprint: chrome
    reality-opts:
      public-key: uM7Kd2QpX1sVbN4tRzY8wLcE3aHfJgOiPqSvTnBm5kU
      short-id: 6ba85179e30d4fc2

  - name: hy2-edge
    type: hysteria2
    server: edge.example.com
    port: 8443
    password: 9f2c7d1a4b6e
    sni: www.example.com
    skip-cert-verify: false
    up: "30 Mbps"
    down: "200 Mbps"

  - name: tuic-edge
    type: tuic
    server: edge.example.com
    port: 10443
    uuid: 8f2c1d40-3a7e-4b91-9c2d-5e6f7a8b9c0d
    password: 9f2c7d1a4b6e
    congestion-controller: bbr
    udp-relay-mode: native
    alpn: [h3]

구독을 계속 오리지널 커널에 넣을 수 있는지는 두 곳만 보면 됩니다. proxies에 등장한 type과 ss 노드의 cipher입니다. type이 ss, vmess, trojan, snell 안에 있고 cipher도 aes-128-gcm 같은 구형 값이라면 양쪽 모두에서 동작합니다. 반대로 reality-opts, congestion-controller 또는 2022-blake3-로 시작하는 암호화 방식이 나오면 mihomo로 바꿔야 합니다.

역방향 마이그레이션에도 함정이 있습니다 mihomo의 노드 설정을 오리지널 커널로 되돌리면 client-fingerprint, reality-opts, packet-encoding이 모두 알 수 없는 필드가 됩니다. 버전마다 허용 범위가 달라서 어떤 버전은 파싱 단계에서 바로 오류를 내고 종료하고, 어떤 버전은 무시한 뒤 기본 파라미터로 연결합니다. 이 경우 노드는 표시되는데 지연 테스트가 전부 타임아웃되어 회선 장애로 오판하기 쉽습니다.

규칙 문법과 매칭 순서

매칭 모델은 양쪽이 동일합니다. rules를 위에서 아래로 한 줄씩 비교해 처음 일치하는 규칙에서 멈추고, MATCH가 마지막을 받칩니다. 차이는 사용 가능한 유형, 매칭 비용, 규칙 세트 로딩 방식에 있습니다.

규칙 유형 오리지널 Clash mihomo 설명
DOMAIN / DOMAIN-SUFFIX / DOMAIN-KEYWORD 지원 지원 도메인 인덱스를 사용해 단일 항목 비용이 매우 낮음
DOMAIN-REGEX / DOMAIN-WILDCARD 미지원 지원 항목마다 정규식 매칭, 상단에 두면 첫 패킷이 느려짐
IP-CIDR / IP-CIDR6 / SRC-IP-CIDR 지원 지원 도메인 연결 시 해석이 발생하므로 no-resolve 추가 권장
GEOIP 지원 지원 GeoIP 데이터 파일에 의존
GEOSITE 미지원 지원 geosite 데이터 파일에 의존
IP-ASN / IP-SUFFIX 미지원 지원 ASN 또는 IP 접미사 대역으로 분기
PROCESS-NAME 클로즈드 소스 Premium 전용 지원 데스크톱에서 프로세스 이름으로 분기
PROCESS-PATH / PROCESS-NAME-REGEX 미지원 지원 실행 파일 경로로 매칭
RULE-SET 클로즈드 소스 Premium 전용 지원 format: mrs 추가 가능
SUB-RULE / AND / OR / NOT 미지원 지원 여러 조건 조합, 괄호와 쉼표 주의
IN-TYPE / IN-USER / IN-PORT / NETWORK 미지원 지원 인바운드 출처와 전송 계층 프로토콜로 매칭
MATCH 지원 지원 반드시 마지막 항목에 배치

규칙 세트의 차이는 규칙 유형보다 놓치기 쉽습니다. 오리지널 Clash는 rule-providers를 지원하지 않아 규칙을 config.yaml에 직접 써야 합니다. mihomo의 rule-providers는 behavior에 domain, ipcidr, classical을, format에 yaml, text, mrs를 지정할 수 있으며, mrs는 바이너리 포맷이라 domain 또는 ipcidr과만 함께 쓸 수 있습니다. mrs는 로딩 시 도메인 접두사로 인덱스를 만들어 YAML 전체를 객체로 파싱할 필요가 없어, 규칙이 수만 개일 때 차이가 가장 큽니다.

rule-providers:
  reject-list:
    type: http
    behavior: domain
    format: mrs
    url: "https://rules.example.com/reject.mrs"
    path: ./ruleset/reject.mrs
    interval: 86400

rules:
  - DOMAIN-SUFFIX,example.org,직접 연결
  - GEOSITE,category-ads-all,REJECT
  - RULE-SET,reject-list,REJECT
  - IP-CIDR,198.18.0.0/16,직접 연결,no-resolve
  - AND,((NETWORK,udp),(DST-PORT,443)),노드 선택
  - MATCH,노드 선택

rules 섹션을 작성할 때 순서 때문에 가장 자주 실수하는 세 가지가 있습니다:

  1. 구체적인 도메인은 GEOSITE보다 앞에 두어야 합니다. GEOSITE는 매칭 범위가 넓어 DOMAIN-SUFFIX,example.org보다 위에 있으면 뒤의 규칙은 절대 실행되지 않습니다.
  2. IP-CIDR을 도메인 규칙보다 앞에 두면 도메인 연결은 먼저 IP로 해석해야 비교할 수 있습니다. DNS 조회가 한 번 더 발생할 뿐 아니라 해석 결과가 업스트림 리졸버로 전달됩니다. no-resolve를 붙이면 도메인 연결은 이 규칙을 바로 건너뜁니다.
  3. MATCH가 가리키는 정책 그룹에는 사용 가능한 노드가 최소 하나 있어야 합니다. 규칙 세트 업데이트 후 커버되지 않는 도메인이 생기면 모든 트래픽이 MATCH로 몰리고, 그룹이 비어 있으면 기기 전체가 인터넷에 연결되지 않습니다.

GEOSITE와 GEOIP는 데이터 파일에 의존합니다. 오리지널 Clash는 첫 실행 시 Country.mmdb를 내려받습니다. mihomo는 geodata-mode, geox-url, geo-auto-update, geo-update-interval이 추가되어 데이터 소스를 자체 주소로 바꾸고 시간 단위로 자동 업데이트할 수 있어 파일을 직접 교체할 필요가 없습니다.

DNS와 fake-ip 구현 차이

오리지널 Clash의 dns 섹션에는 nameserver, fallback, fallback-filter, enhanced-mode, fake-ip-range, fake-ip-filter, hosts 정도의 스위치만 있고, 모든 도메인이 같은 해석 체인을 탑니다. fallback-filter의 geoip와 ipcidr로 결과의 신뢰성을 판단합니다. 아래는 예전 설정에서 가장 흔히 보이는 형태입니다:

# 오리지널 Clash 방식, mihomo에서도 파싱되지만 계속 쓰는 것은 권장하지 않음
dns:
  enable: true
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - 223.5.5.5
  fallback:
    - https://1.1.1.1/dns-query
  fallback-filter:
    geoip: true
    ipcidr:
      - 240.0.0.0/4

mihomo는 해석을 여러 체인으로 나눕니다. default-nameserver는 DNS 서버 자체의 도메인을 해석하는 용도로 IP만 넣어야 하고, proxy-server-nameserver는 프록시 서버 주소를 해석하며, direct-nameserver는 직접 연결 트래픽을 처리하고, nameserver-policy는 도메인이나 규칙 세트별로 업스트림을 지정합니다. 이 분리는 같은 문제를 해결합니다. 프록시 서버 도메인을 어느 체인으로 해석하느냐가 노드 연결 가능 여부를 바로 좌우합니다.

dns:
  enable: true
  listen: 0.0.0.0:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter-mode: blacklist
  fake-ip-filter:
    - "*.lan"
    - "+.stun.*.*"
  default-nameserver:
    - 223.5.5.5
    - 1.1.1.1
  proxy-server-nameserver:
    - https://223.5.5.5/dns-query
  nameserver:
    - https://1.1.1.1/dns-query
    - quic://dns.adguard-dns.com:784
  nameserver-policy:
    "geosite:cn":
      - 223.5.5.5
    "rule-set:reject-list":
      - rcode://refused
  respect-rules: true
  cache-algorithm: arc

따로 기억해 둘 만한 동작 차이가 두 가지 있습니다. fake-ip-filter는 오리지널 Clash에서 블랙리스트 의미만 가졌지만, mihomo는 fake-ip-filter-mode: whitelist가 추가되어 목록 안의 도메인에만 가짜 IP를 할당하도록 뒤집어 쓸 수 있습니다. nameserver-policy의 키는 geosite: 와 rule-set: 접두사를 지원해 fallback-filter.domain을 길게 나열할 필요가 없습니다. 또한 respect-rules: true를 켜면 DNS 쿼리 자체도 rules 분기를 타므로, 켜기 전에 proxy-server-nameserver를 먼저 설정해야 합니다. 그렇지 않으면 해석 요청이 자기 자신으로 돌아가 무한 루프가 생길 수 있습니다.

마이그레이션에서 가장 자주 빠뜨리는 항목 fallback과 fallback-filter는 mihomo에서도 파싱되며 실행 실패를 일으키지 않습니다. 그래서 많은 사용자가 프로토콜 섹션과 TUN만 고치고 proxy-server-nameserver를 빠뜨립니다. 전형적인 증상은 커널은 정상적으로 시작하고 로그에도 오류가 없는데 모든 노드가 한결같이 타임아웃되는 것입니다. 프록시 서버 도메인이 통하지 않는 해석 체인을 타기 때문입니다.

TUN 구현과 세 가지 네트워크 스택

오리지널 오픈소스 Clash에는 TUN이 전혀 없습니다. TUN은 클로즈드 소스 Premium 커널에만 있었고 조정 가능한 파라미터도 적었습니다. mihomo는 TUN을 설정 파일의 일등 시민으로 만들어, 장치 이름과 MTU부터 Android의 패키지별 허용까지 필드로 다룹니다.

tun:
  enable: true
  stack: mixed
  device: mihomo
  mtu: 9000
  auto-route: true
  auto-detect-interface: true
  strict-route: false
  dns-hijack:
    - any:53
  udp-timeout: 300
  endpoint-independent-nat: false
  gso: true
  gso-max-size: 65536

stack 세 가지 값의 선택 기준:

  • system: 패킷을 시스템 프로토콜 스택으로 전달해 처리량이 가장 높지만, 시스템 라우팅과 방화벽 상태에 의존하므로 다중 NIC나 IPv6 환경에서 루프나 누수가 생기기 쉽습니다.
  • gvisor: 순수 사용자 공간 구현으로 플랫폼 간 동작이 일관되고 시스템 포워딩에 의존하지 않습니다. 단일 연결 처리량은 system보다 낮아 라우팅 테이블이 복잡하거나 권한이 제한된 환경에 적합합니다.
  • mixed: TCP는 시스템 스택, UDP는 gvisor 스택으로 처리하는 방식으로 대부분 클라이언트의 기본값이며, gvisor에서 system으로 넘어가기 전에 먼저 시험해 볼 수 있는 중간 단계입니다.

플랫폼별 의존성은 각각 다릅니다. Windows는 wintun 드라이버와 시스템 서비스 권한이 필요하고 가상 NIC 생성에 실패하면 로그에 configure tun interface가 나타납니다. macOS는 utun 장치를 사용하며 처음 활성화할 때 네트워크 권한을 요청합니다. Linux에서는 auto-route가 라우팅 테이블을 기록하고, auto-redirect가 nftables로 트래픽을 TUN으로 리다이렉트하므로 iptables 규칙을 직접 쓸 필요가 없습니다. Android 클라이언트는 include-package와 exclude-package로 어떤 앱이 TUN을 통과할지 제어합니다.

TUN 모드에서의 해석 경로 TUN을 켜면 dns-hijack이 53번 포트로 가는 쿼리를 커널 DNS로 가로챕니다. 따라서 해석이 어느 체인을 타는지는 dns 섹션이 결정하며 시스템 DNS 설정과는 무관합니다. 디버깅 단계에서는 dns-hijack을 any:53으로 쓰면 IPv4만 가로채서 생기는 해석 누락을 피할 수 있습니다.

성능 비교와 마이그레이션 순서

규칙 매칭 비용은 주로 유형과 개수에 달려 있습니다. 도메인 계열 규칙은 인덱스를 사용해 단일 항목 비용이 매우 낮습니다. DOMAIN-REGEX, PROCESS-NAME-REGEX는 항목마다 정규식 매칭을 하므로 rules 상단에 두면 새 연결마다 첫 패킷이 느려집니다. 연결 쪽에는 필요에 따라 켤 만한 스위치가 몇 가지 있습니다:

  • tcp-concurrent: true —— 같은 도메인의 여러 해석 결과에 동시에 핸드셰이크해 첫 패킷 대기를 줄입니다. 대신 동시 연결 수가 늘어납니다.
  • unified-delay: true —— 지연 테스트를 전체 핸드셰이크 소요 시간 기준으로 통일해 프로토콜 간 수치를 비교할 수 있게 합니다.
  • sniffer 섹션 —— IP 직접 연결 트래픽에서 도메인을 복원해 도메인 규칙이 매칭되도록 합니다. override-destination은 목적지 주소를 복원된 도메인으로 바꾸므로 일부 내부망 환경에서는 꺼야 합니다.
  • find-process-mode: strict —— 프로세스 매칭을 새 연결이 맺어질 때 한 번만 조회해 always보다 CPU를 덜 씁니다.
mixed-port: 7890
allow-lan: false
mode: rule
log-level: warning
ipv6: false
unified-delay: true
tcp-concurrent: true
find-process-mode: strict
external-controller: 127.0.0.1:9090
profile:
  store-selected: true
  store-fake-ip: true
sniffer:
  enable: true
  sniff:
    HTTP:
      ports: [80, 8080-8880]
      override-destination: true
    TLS:
      ports: [443, 8443]
    QUIC:
      ports: [443]

오리지널 Clash에서 mihomo로 옮길 때 순서를 여섯 단계로 고정하면 각 단계를 따로 검증할 수 있습니다:

  1. 기존 설정 백업

    config.yaml과 ruleset 디렉터리를 통째로 복사해 두고, 롤백 시 대조할 수 있도록 기존 커널의 버전 문자열을 기록합니다.

  2. 먼저 문법 검사

    mihomo -t -f config.yaml -d /etc/mihomo로 실행 없이 파싱해 보면 unsupported proxy type이 이 단계에서 드러나므로, 실행 후 로그를 볼 필요가 없습니다.

  3. 프로토콜 섹션 처리

    hysteria2, tuic, vless 노드는 남기고 필드 이름을 하나씩 확인합니다. ss 노드의 2022-blake3- 암호화는 커널 버전 지원이 필요하며 구버전 커널은 바로 거부합니다.

  4. DNS 재작성

    default-nameserver와 proxy-server-nameserver를 추가하고, fallback 목록을 nameserver-policy로 옮기며, fake-ip-range는 198.18.0.1/16 그대로 두면 됩니다.

  5. 마지막에 TUN 켜기

    드라이버와 서비스가 준비되었는지 먼저 확인하고, stack은 mixed로 시작하며, dns-hijack은 any:53을 사용합니다. 라우팅과 해석이 모두 정상인 것을 확인한 뒤에 system 전환을 검토합니다.

  6. 연결과 규칙 매칭 확인

    external-controller: 127.0.0.1:9090을 열고 대시보드에서 연결 목록과 규칙 매칭을 확인해, 모든 트래픽이 MATCH로 몰리지 않는지 봅니다.

오리지널 Clash에 남아야 하는 상황도 있습니다. 설정 파일에 ss, vmess, trojan만 있고 규칙이 전부 rules 섹션에 있으며 TUN이 필요 없다면, 커널을 바꿔 얻는 이득은 크지 않고 변경 위험만 커집니다. 이전 여부를 판단하는 기준은 간단합니다. 위 네 가지 항목 중 mihomo만의 문법을 쓰는 것이 하나라도 있으면 바꾸고, 없으면 그대로 두면 됩니다.