구성·보안 · · 약 17분 소요

Clash Meta(mihomo) 외부 컨트롤러·Secret·바인드 주소: Yacd-meta 웹 패널과 LAN·REST API를 안전하게 쓰는 순서 (2026)

mihomo·Clash Meta 코어는 이미 켜 두었는데, 웹 대시보드(Yacd-meta 등)나 스크립트용 REST API만 어디에 맞춰 열어야 할지 막막한 검색이 많습니다. external-controller는 트래픽이 나가는 mixed-port와 다른 축인데, 예제가 127.0.0.1:9090로만 적혀 있으면 「같은 Wi-Fi 휴대폰에서 패널 보기」가 안 되고, 반대로 0.0.0.0에 넓게 열어 secret을 비워 두면 관리 API가 사실상 공개가 됩니다. 이 글은 Secret·바인드 범위·방화벽·대시보드 URL을 본인 PC만신뢰하는 LAN 두 패턴으로 나눠, 콘솔을 「벌거벗은 노출」로 두지 않는 순서를 정리합니다. 출국 트래픽용 allow-lan·mixed-port 공유 글과 겹치지 않게, 여기서는 제어 평면(control plane)만 다룹니다.

1. external-controller가 mixed-port와 다른 이유

mixed-port(또는 port·socks-port)는 브라우저·앱·터미널이 실제 프록시 트래픽을 넣는 데이터 경로입니다. 반면 external-controller는 코어가 노출하는 관리용 HTTP REST 소켓으로, 연결·규칙·프로필 상태 조회, 심지어 일부 빌드에서는 설정 변경까지 건드릴 수 있습니다. 그래서 검색어로 웹 콘솔·Yacd-meta를 찾을 때 나오는 포트는 보통 9090 같은 관리 포트이고, 사용자 트래픽용 7890류와 섞어 쓰면 안 됩니다. 한마디로, 프록시는 열려 있는데 패널이 안 보인다고 해서 mixed-port를 헤매기보다, 먼저 external-controller 줄이 최종 머지 YAML에 있는지·어느 주소에 붙었는지를 확인하는 편이 빠릅니다.

GUI 클라이언트(예: Verge 계열)는 화면에서 토글만 건드리게 해 주지만, 내부적으로는 같은 키를 씁니다. 고급 편집으로 YAML만 본다면 중복 키나 구독 템플릿 머지 뒤에 값이 덮인 경우가 흔합니다. 구독 소스와 로컬 오버라이드가 겹칠 때 어떤 파일이 이김인지는 다중 구독·머지 흐름과 같이 봐야 하고, 여기서는 「관리 포트가 사라졌다」가 아니라 「다른 조각이 127.0.0.1로 다시 고정했다」는 패턴도 기억해 두면 좋습니다.

2. Secret: 비우면 생기는 일과 강도

secret은 REST 요청에 실어 보내는 공유 비밀번호 역할이며, 빌드에 따라 Authorization: Bearer 형태로 맞춥니다. 값이 비어 있거나 기본 예제 문자열 그대로면, LAN에 관리 포트가 보이는 순간 누구나 규칙을 읽고 바꿀 수 있는 셈입니다. 실제 위험은 「이웃이 악의적이다」 수준이 아니라, 카페·기숙사처럼 같은 브로드캐스트 도메인에 노트북이 여러 대 있을 때 스캐너 한 번에 걸리는 경우까지 포함합니다. 그래서 실기에서는 비워 두지 말고, 패스워드 매니저로 만든 충분히 긴 무작위 문자열을 넣고, 바꿀 때마다 대시보드·스크립트 양쪽을 같이 갱신합니다.

# Local-only example — replace host, port, and secret
external-controller: '127.0.0.1:9090'
secret: 'replace-with-long-random-token'

일부 튜토리얼이 편의상 secret: ''를 보여 줄 수 있으나, 그대로 복사해 배포하면 관리면 노출과 동일한 사고로 이어집니다. 「데모용」 주석을 달았다 해도 실제 프로필에는 남지 않게 삭제하는 습관이 안전합니다. Clash 생태계 전반에서 설정 파일은 구독 URL·노드 이름까지 들어 있으니, Git에 올릴 때는 반드시 별도 규칙으로 마스킹한다는 전제도 같이 둡니다.

주의: Secret은 브라우저 북마크·대시보드 프리셋·모바일 앱에 평문으로 남기 쉽습니다. 기기 분실·화면 공유 시 그대로 유출되므로, 장기 값은 주기적으로 교체하고 노트·메신저에 붙여 넣지 마세요.

3. 바인드 주소 — 본인만 vs LAN

external-controller 값에 호스트를 같이 쓰는 형태(127.0.0.1:9090 vs 0.0.0.0:9090)가 가장 직관적입니다. 루프백이면 같은 PC의 브라우저·로컬 스크립트만 붙고, 휴대폰이나 옆자리 PC에서는 http://노트북-LAN-IP:9090으로는 연결되지 않습니다. 반대로 모든 IPv4 인터페이스에 열려 있으면, 방화벽을 안 막는 한 같은 서브넷의 누구나 SYN을 보낼 수 있는 상태가 됩니다. 일부 배포에서는 bind-address 키가 전역 리슨 정책과 함께 쓰이므로, 최종 YAML에서 관리 포트 한 줄전역 바인드가 서로 모순되지 않는지 같이 확인하세요.

「집 안에서만 태블릿으로 대시보드 본다」는 요구는 흔합니다. 그때도 최소 권한 관점에서는 가능하면 루프백을 유지한 채 PC 쪽 브라우저만 쓰거나, SSH 로컬 포워딩으로 9090을 노트북으로 가져오는 편이 낫습니다. 정말로 LAN IP에 직접 열어야 한다면 secret을 절대 빼지 말고, OS 방화벽에서 소스 IP를 가족 기기 대역으로만 제한할 수 있는지 검토합니다. 이 단계는 프록시 공유용 allow-lan과 별개이며, 관리 포트를 열었다고 해서 자동으로 mixed-port가 같이 안전해지지도 않습니다.

4. Yacd-meta·웹 UI에 API 주소 넣기

Yacd-meta 같은 대시보드는 정적 파일로 배포되는 경우가 많아, 「API 베이스 URL」 칸에 http://127.0.0.1:9090 또는 코어가 안내하는 /ui 경로를 넣습니다. HTTPS만 강제하는 환경에서는 로컬 혼합 콘텐츠 경고가 날 수 있으니, 브라우저 정책을 확인하거나 로컬 전용 프로필로 여세요. LAN에서 전화기 브라우저로 열려면 대시보드 호스트도 접속하는 기기가 해석 가능한 주소여야 하므로, 노트북의 사설 IP까지 포함한 URL이 되고, 그만큼 external-controller도 같은 인터페이스에서 리슨해야 합니다.

일부 빌드는 내장 웹 UI를 같이 제공합니다. 경로가 헷갈리면 코어 로그의 「API listening」 한 줄을 먼저 보고, 브라우저에서 /version 같은 가벼운 엔드포인트에 Secret을 넣어 호출해 401이 아닌 응답이 오는지 확인하는 방법이 확실합니다. 캐시된 옛 Secret으로 북마크가 남아 있으면 「연결 불가」가 아니라 무한 로딩처럼 보일 수 있어, 개발자 도구 네트워크 탭에서 상태 코드를 보는 습관이 좋습니다.

5. REST API 호출 시 Authorization 헤더

스크립트·모니터링 도구가 REST API를 직접 칠 때는 브라우저가 대신 넣어 주지 않으므로, 요청마다 헤더를 붙여야 합니다. 관행적으로는 Authorization: Bearer <secret> 패턴을 따르고, 로컬에서만 쓰는 짧은 테스트라도 토큰을 셸 히스토리에 남기지 않게 주의합니다. 대시보드와 스크립트가 서로 다른 secret을 보게 되면 한쪽만 401이 나오므로, 설정을 바꾼 뒤에는 두 경로를 같이 재시작·재로그인합니다.

# Example curl — use loopback in scripts when possible
curl -sS -H 'Authorization: Bearer YOUR_SECRET' \\
  'http://127.0.0.1:9090/version'

자동화가 길어질수록 토큰을 환경 변수나 OS 비밀 저장소에 두고, 저장소 전체를 백업할 때 평문이 새지 않는지도 점검합니다. CI에서 같은 스크립트를 돌린다면 저장소 Secret과 러너 로그 마스킹 정책까지 한 세트로 보는 것이 안전합니다.

6. LAN에 열 때 방화벽·게스트 Wi-Fi

Windows라면 Defender 방화벽이 인바운드 TCP 9090(실제 포트는 프로필대로)을 막아 사실상 외부에서 안 보이게 만들 수 있습니다. 다만 규칙을 열어두면 그 순간부터는 SSID 뒤의 모든 인접 노트북이 스캔 대상이 됩니다. 게스트 네트워크에 관리 PC를 두는 구성은 피하고, 공유기의 클라이언트 격리가 꺼져 있어도 「같은 방」이면 L2에서 보이는 것이 정상이라는 점을 잊지 마세요. 프록시 트래픽용 포트를 연 LAN 공유 글과 달리, 이번 줄은 규칙·노드·로그를 한 번에 바꿀 수 있는 관리선이라 피해 반경이 큽니다.

리눅스 서버나 NAS에 올린다면 systemd 유닛과 함께 iptables/nftables로 소스 대역을 씌우거나, 앞단 리버스 프록시에 mTLS를 얹는 식으로 방어 깊이를 더할 수 있습니다. 이 글의 기본 권고는 여전히 루프백 + Secret + 필요 시 SSH이며, 인터넷에 직접 노출하는 구성은 전제하지 않습니다.

7. 권장 패턴: 루프백 고정 vs SSH 터널

대부분의 단일 사용자 데스크톱에는 127.0.0.1:9090 고정이면 충분합니다. 멀리 있는 서버를 관리할 때는 VPN 대신 임시로 SSH 로컬 포워딩(-L 9090:127.0.0.1:9090)을 쓰면, 원격 코어는 여전히 루프백에만 붙어 있고 노트북 브라우저만 열리게 만들 수 있습니다. 조직망에서 보안팀 정책이 있을 수 있으니, 터널도 허용 범위 안에서만 쓰세요.

「패밀리 대시보드」처럼 정말 LAN 직접 오픈이 필요하면, 최소한 (1) 긴 secret, (2) OS 방화벽으로 소스 범위 제한, (3) 사용 후 바인드를 다시 루프백으로 되돌리거나 서비스 중지, (4) 공용 장소에선 해당 SSID 자체를 쓰지 않기를 같이 적용합니다. 이때도 mixed-port 쪽 allow-lan을 켠 상태라면 데이터 경로와 제어 경로가 동시에 넓어진 것인지 대조표를 한 번 그려 보는 것이 좋습니다.

8. 자주 막히는 증상

연결 거부는 코어 미기동·포트 충돌·방화벽·바인드 주소 불일치 중 하나입니다. 다른 프로세스가 9090을 잡았는지 OS 도구로 확인하고, YAML에 같은 포트가 두 번 정의되지 않았는지 봅니다. 401·403 류는 Secret 불일치·헤더 누락이 대부분입니다. PC에서는 되는데 폰만 안 됨은 전형적으로 루프백만 열린 경우이며, 이 글 3절으로 돌아가 주소를 다시 선택합니다.

GUI가 자체 포트를 숨기고 내부 프록시로 대시보드를 띄우는 경우, 사용자는 파일에 없는 주소를 보게 될 수 있습니다. 그럴 때는 앱의 「디버그·최종 설정」 화면에서 실제 external-controller를 내보내 확인하세요. 구독 갱신 직후 증상이 바뀌었다면 구독 갱신·로그 글과 같이 머지 결과가 바뀌었는지도 의심합니다.

패널만 열려 있고 규칙 변경이 안 됨

빌드·프리셋에 따라 일부 엔드포인트는 읽기 전용입니다. 로그의 권한 메시지와 문서의 API 표를 대조하세요.

HTTPS UI에서 혼합 콘텐츠 경고

로컬 API가 HTTP일 때 흔합니다. 로컬 전용 창에서 열거나, 코어의 TLS 옵션·리버스 프록시 구성이 있는지 확인합니다.

정리하면, Clash Meta(mihomo)에서 external-controller는 mixed-port와 분리된 관리·REST 축이고, Secret을 비우거나 기본값 그대로 두는 순간 웹 패널·API가 곧 계정 노출에 가깝습니다. 바인드 주소는 본인 PC만이면 루프백을 유지하고, LAN에서 꼭 필요할 때만 최소 면적으로 열며 방화벽으로 둘러싸는 것이 2026년에도 변하지 않는 실무 순서입니다. Yacd-meta는 API 베이스와 토큰이 맞을 때만 의미가 있으니, 401·혼합 콘텐츠·포트 충돌을 네트워크 탭에서 먼저 확인하는 습관이 튜닝 시간을 줄여 줍니다. 규칙·프로필을 파일로 들고 다니며 UI·스크립트를 동시에 맞출 수 있다는 점에서, 상용 단일 앱보다 제어 면을 스스로 설계해야 한다는 게 부담이자 장점입니다.

Clash를 무료로 내려받아 최신 클라이언트에서 관리 포트·Secret·바인드를 한 번 점검하고, 로컬 대시보드와 스크립트가 같은 인증 값을 보는지 확인한 뒤에 LAN 확장 여부를 결정해 보세요.

주제 관련도가 높은 읽을거리 — 같은 카테고리의 Clash 실전 가이드.