external-controller가 하는 일
Mihomo는 실행 중인 프로필을 바꾸고 상태를 읽기 위한 HTTP API를 제공합니다. 설정 파일에서 이 리스너의 바인딩 주소와 포트를 정하는 키가 external-controller입니다. 예를 들어 127.0.0.1:9090이면 같은 머신의 루프백에서만 API에 닿고, 0.0.0.0:9090 또는 *:9090 형태(문서·빌드에 따라 표기 차이)는 모든 인터페이스에 열립니다. Yacd는 이 API를 호출해 프록시 그룹 선택, 실시간 연결 표시, 구독·룰 메타 정보 조회 같은 작업을 브라우저 UI로 감싼 프론트엔드에 가깝습니다. 즉 “패널 = 코어”가 아니라 “패널 → HTTP → 코어” 구조라는 점이 이해의 출발점입니다.
전체 설정 개념은 문서·설정 허브와 함께 보면 proxies·proxy-groups·rules가 API와 어떻게 맞물리는지 잡히기 쉽습니다.
YAML에 넣을 최소 항목
대시보드를 쓰려면 보통 아래 세 가지를 맞춥니다. 클라이언트 GUI가 자동으로 채워 주는 경우도 있지만, 직접 코어를 띄우거나 서버·컨테이너라면 직접 확인하는 편이 안전합니다.
external-controller— API가 들을 주소. 로컬만이면127.0.0.1:9090, LAN의 다른 PC에서 패널을 열 계획이면 코어가 그 인터페이스에서 듣도록 조정합니다.secret— 선택이지만 실무에서는 비어 두지 않는 것을 권장합니다. API 요청 시Authorization: Bearer …헤더로 전달됩니다.external-ui— 코어가 내장 정적 UI를 서빙할 때 쓰는 옵션으로, Yacd와는 별개입니다. 혼동하지 않도록 이름만 기억해 두면 됩니다.
# Minimal sketch (adjust to your profile)
external-controller: 127.0.0.1:9090
secret: "your-long-random-secret"
보안: 0.0.0.0으로 API를 열면 같은 네트워크의 누구나 시도할 수 있습니다. 집 Wi-Fi라도 강한 secret·방화벽·가능하면 SSH 터널만 쓰는 편이 낫습니다. 인터넷에 그대로 노출하지 마세요.
같은 PC에서 Yacd 열기
흐름은 단순합니다. (1) 코어가 127.0.0.1:9090(예시)에서 API를 받는지 확인하고, (2) Yacd 실행 화면의 API Base URL에 http://127.0.0.1:9090을 넣고, (3) secret이 있다면 같은 화면의 Secret 필드에 YAML과 동일한 문자열을 넣습니다. 이렇게 하면 브라우저와 API가 같은 호스트의 루프백에서 만나므로, 원칙적으로는 혼합 콘텐츠(https 페이지가 http API를 부르는 경우)나 CORS 이슈가 상대적으로 적습니다. 그래도 온라인에 호스팅된 Yacd(HTTPS)에서 로컬 HTTP API를 직접 호출하려다 막히는 경우가 있어, 그때는 로컬에서 정적 파일로 Yacd를 띄우기, 클라이언트에 포함된 대시보드 사용, 또는 SSH 로컬 포워딩으로 “브라우저가 보는 URL”을 정리하는 방법이 현장에서 자주 쓰입니다.
동작 확인용으로 터미널에서 curl -H "Authorization: Bearer YOUR_SECRET" http://127.0.0.1:9090/version처럼 한 번 호출해 보면, 패널 문제인지 API 자체 문제인지 빠르게 갈립니다.
LAN의 다른 기기에서 패널 쓰기
노트북 브라우저로 데스크톱에서 돌아가는 코어를 다루고 싶다면, 코어가 데스크톱의 LAN IP에서 API를 받아야 합니다. 예를 들어 데스크톱 IP가 192.168.1.20이고 포트가 9090이면 Yacd에는 http://192.168.1.20:9090을 적습니다. 이때 OS 방화벽이 해당 TCP 포트의 인바운드를 막고 있지 않은지 반드시 확인하세요. Windows·macOS·Linux 각각에서 “공용 프로필”만 열려 있고 사설망은 닫혀 있는 식의 설정도 있으므로, 연결 거부가 나오면 방화벽 로그와 규칙을 먼저 봅니다.
프록시 인바운드용 allow-lan과 API 포트는 목적이 다릅니다. 프록시는 mixed-port 등으로 따로 열리고, API는 external-controller 한 줄이 담당합니다. 둘 다 LAN에서 쓸 거면 둘 다 바인딩·방화벽·보안을 따로 생각해야 합니다. Docker를 쓰는 경우 호스트로 포트를보내는 매핑은 Docker 배포 글의 ports 절과 같은 맥락으로 맞추면 됩니다.
Yacd·대시보드 선택지
커뮤니티에서는 Yacd·Yacd Meta·각 GUI 클라이언트 내장 웹 UI가 병행됩니다. 이름이 비슷해도 배포 경로(로컬 빌드, 정적 호스팅, 클라이언트 번들)만 다를 뿐, 사용자가 입력하는 값은 대개 API 베이스 URL + secret입니다. 한 가지 빌드에서 안 되면 다른 경로를 시도하기보다, 먼저 curl로 API가 살아 있는지 확인하는 편이 시간을 아낍니다.
REST API로 무엇을 할 수 있나
패널이 하는 일 대부분은 공개된 REST 엔드포인트의 조합입니다. 예를 들어 버전 확인, 프록시 지연 측정, 정책 그룹에서 노드 선택 변경, 연결 목록, 구독 목록과 갱신 트리거 등이 여기에 해당합니다. 자동화 스크립트를 짜는 사용자는 패널 대신 curl이나 소량의 코드로 같은 API를 호출해 배치 갱신·모니터링을 붙이기도 합니다. 다만 실수로 규칙을 깨는 PUT/POST도 있으므로, 운영 환경에서는 읽기 전용 토큰 같은 분리가 없다면 스크립트 범위를 제한하는 편이 안전합니다.
구독·노드 관리를 패널에서
대시보드에서 흔히 하는 작업은 세 가지로 묶입니다. 첫째, 프록시 그룹 탭에서 지금 쓸 노드를 고르는 것 — 이는 YAML의 proxy-groups 선택 상태를 런타임에 바꿉니다. 둘째, 연결 뷰에서 어떤 도메인이 어떤 체인으로 나가는지 보는 것 — 규칙 디버깅에 유용합니다. 셋째, 구독 화면에서 URL을 추가·삭제하거나 갱신을 누르는 것 — 제공 빌드·권한에 따라 일부 작업은 읽기만 되고 편집은 클라이언트 쪽에서만 되는 경우도 있으니, 버튼이 비활성이면 “API가 막힌 것”이 아니라 그 빌드 정책일 수 있습니다.
구독 URL·토큰이 민감하다면 화면 공유·원격 데스크톱 녹화에 노출되지 않게 주의하고, 테스트 후 secret 로테이션을 고려하세요.
DNS·분류와 같이 봐야 할 때
패널에서 노드를 바꿔도 사이트가 열리지 않으면 원인이 API가 아니라 DNS·규칙인 경우가 많습니다. FakeIP·로컬 DNS 리스너를 쓰는 프로필이라면 DNS 유출 방지 가이드의 점검 순서를 함께 적용하세요. “패널은 붙는데 트래픽만 이상하다”는 증상은 대개 이 쪽입니다.
패널이 안 붙을 때 체크리스트
- 포트 불일치: YAML의
external-controller포트와 Yacd에 적은 URL이 같은지, 다른 프로세스가 이미 그 포트를 쓰지 않는지 확인합니다. - 바인딩:
127.0.0.1만 열려 있는데 LAN에서 접속하려 하면 실패합니다. 의도에 맞게 주소를 바꿉니다. - secret: 대소문자·따옴표·공백 한 글자까지 YAML과 동일한지, 헤더 형식이
Bearer인지 확인합니다. - 방화벽·보안 SW: 인바운드 차단, “로컬 네트워크 격리” 옵션, 기업 에이전트가 루프백이 아닌 경로를 막는 경우가 있습니다.
- HTTPS 혼합·CORS: 원격 HTTPS Yacd 페이지가 로컬 HTTP API를 직접 호출하지 못하면 브라우저 콘솔에 오류가 남습니다. 로컬 UI나 터널로 출발점과 도착점의 스킴을 맞춥니다.
- Docker: 컨테이너 안
9090과 호스트 매핑이 빠졌거나, 호스트에서 잘못된 IP로 접속하고 있지 않은지 봅니다.
정리
Mihomo에 external-controller를 올바르게 열고 secret을 맞추면, Yacd 같은 웹 패널로 노드·연결·구독을 손으로 다루는 경험이 한 번에 정리됩니다. 같은 PC에서는 루프백 URL이 가장 단순하고, 다른 기기에서는 바인딩 + 방화벽 + 보안을 세트로 설계해야 합니다. 커널·TUN·컨테이너 레이어는 다른 튜토리얼에 맡기고, 이 글은 관리면(API·패널)에만 초점을 맞췄습니다.
GUI가 익숙한 사용자는 코어만 서버에 두고 일상 PC에서는 Clash 계열 클라이언트로 프로필을 편집하는 구성도 흔합니다. 설치 패키지는 사이트 허브에서 고르고, 오픈소스 저장소는 이슈·소스 확인용으로 쓰면 혼선이 적습니다.