먼저 배포 경로 결정하기: 데스크톱 클라이언트인가 mihomo 서비스인가
Linux에서 흔히 말하는 “Clash 설치”는 실제로 두 가지 경로를 뜻합니다. 첫 번째는 GNOME, KDE Plasma, Xfce 같은 데스크톱 환경에 그래픽 클라이언트를 설치하는 방식입니다. 클라이언트가 구독 가져오기, 설정 전환, 코어 실행, 시스템 프록시와 로그 표시를 담당합니다. 두 번째는 서버, 소프트 라우터, 개발 머신 또는 데스크톱 환경이 없는 호스트에서 mihomo 코어를 직접 실행하고 systemd로 프로세스를 관리하는 방식입니다. 두 경로는 비슷한 YAML 설정을 사용할 수 있지만 조작 창구, 권한 범위와 문제 진단 방법은 서로 다릅니다.
| 배포 방식 | 적합한 환경 | 설정 경로 | 프로세스 관리 | 트래픽 처리 |
|---|---|---|---|---|
| 데스크톱 클라이언트 | 일반 데스크톱, 개발 워크스테이션 | 클라이언트 UI 및 설정 디렉터리 | 클라이언트 자체 | 시스템 프록시 또는 TUN |
| mihomo 서비스 | 서버, 헤드리스 호스트, 보조 게이트웨이 | YAML 파일을 직접 관리 | systemd | 환경 변수, 명시적 프록시 또는 TUN |
데스크톱 클라이언트와 mihomo는 서로 바꿔 부를 수 있는 동일한 제품 계층이 아닙니다. 클라이언트는 UI, 업데이트와 설정 관리를 제공하고, mihomo는 설정을 읽어 프록시, DNS와 규칙을 실행하는 코어입니다. 일부 클라이언트에는 mihomo가 내장되어 있고, 다른 클라이언트는 코어 버전을 선택할 수 있습니다. 데스크톱 클라이언트가 이미 코어를 실행 중이라면 동일한 포트를 수신하는 systemd 서비스를 함께 시작하지 마세요. 일반적으로 address already in use 오류가 발생합니다.
Linux 데스크톱 클라이언트: 설치 후 코어와 설정 디렉터리 확인
배포판에 맞는 설치 패키지 선택
Debian, Ubuntu, Linux Mint 등에서는 보통 .deb를 사용하고, Fedora, RHEL 계열과 openSUSE에서는 .rpm을 주로 사용합니다. 다른 배포판은 클라이언트가 제공하는 AppImage나 압축 패키지를 선택할 수 있습니다. 다운로드 전에 uname -m으로 아키텍처를 확인하세요. 출력이 x86_64이면 amd64 또는 x64, aarch64이면 arm64에 해당합니다. 패키지 형식과 CPU 아키텍처가 모두 맞아야 합니다.
uname -m
# Debian、Ubuntu에서 로컬 deb 설치
sudo apt install ./client-linux-amd64.deb
# Fedora에서 로컬 rpm 설치
sudo dnf install ./client-linux-x86_64.rpm
처음 실행한 뒤 클라이언트의 「설정」→「코어 설정」 또는 「설정」→「매개변수 설정」으로 이동해 현재 코어 이름, 코어 버전과 작업 디렉터리를 확인하세요. 클라이언트마다 메뉴 이름은 조금씩 다를 수 있지만, 코어, 설정 디렉터리, 수신 포트와 로그를 찾는 것이 핵심입니다. “클라이언트 버전”을 “코어 버전”으로 착각하지 마세요. 규칙이나 DNS 호환 문제를 진단할 때는 두 버전을 모두 기록해야 합니다.
구독을 가져왔다고 해서 트래픽이 프록시로 들어간 것은 아닙니다
- 「설정」 또는 「구독」 페이지에 구독 주소를 붙여 넣고 가져오기를 실행합니다.
- 방금 가져온 설정을 선택하고 클라이언트가 파싱을 완료한 뒤 코어를 시작할 때까지 기다립니다.
- 「프록시」 페이지에서 정책 그룹을 선택하세요. 설정의
PROXY는 일반적으로 정책 그룹 이름이며, 고정된 내장 출구가 아닙니다. - 필요에 따라 「시스템 프록시」 또는 「TUN 모드」를 켜세요. 두 기능이 처리하는 트래픽 범위는 서로 다릅니다.
- 로그를 확인해 포트 충돌, YAML 파싱 또는 DNS 초기화 오류가 없는지 확인합니다.
시스템 프록시는 일반적으로 데스크톱 환경에 HTTP 및 SOCKS 프록시 매개변수를 기록하므로 시스템 프록시 설정을 따르는 브라우저와 그래픽 앱에 적합합니다. TUN 모드는 가상 네트워크 인터페이스를 통해 더 넓은 범위의 트래픽을 처리하며 관리자 권한, 네트워크 권한 또는 추가 DNS 설정이 필요할 수 있습니다. 구독만 가져오고 트래픽 진입점을 활성화하지 않으면 코어가 실행 중이어도 앱이 자동으로 코어를 사용하지 않습니다.
포트로 클라이언트가 실제로 코어를 시작했는지 확인
Clash 계열 설정에서는 혼합 프록시 포트를 7890으로 지정하는 경우가 많고, HTTP 7890과 SOCKS 7891을 나누어 사용하기도 합니다. 이는 흔한 예시일 뿐이므로 최종적으로는 현재 설정과 클라이언트 설정을 기준으로 해야 합니다. ss로 수신 중인 프로세스를 확인할 수 있습니다:
ss -lntp | grep -E '7890|7891|9090'
# 로컬 HTTP 프록시를 통한 테스트
curl -I -x http://127.0.0.1:7890 https://example.com
# SOCKS5를 사용하고 프록시 측에서 도메인 이름 해석
curl -I --proxy socks5h://127.0.0.1:7891 https://example.com
curl은 성공하지만 브라우저가 실패한다면 브라우저 자체의 프록시 확장 기능이나 데스크톱 시스템 프록시를 먼저 확인하세요. 브라우저는 성공하지만 터미널이 실패한다면 터미널 환경 변수를 확인해야 합니다. 두 앱의 프록시 진입점은 완전히 독립적일 수 있으며, 규칙 모드를 전환하는 것으로 진입점 설정을 대신할 수 없습니다.
헤드리스 호스트: mihomo 바이너리와 작업 디렉터리 준비
고정 디렉터리와 전용 계정 만들기
서버에 배포할 때는 바이너리, 설정과 실행 상태를 분리해야 합니다. 아래 예시에서는 프로그램을 /usr/local/bin/mihomo에, 기본 설정을 /etc/mihomo/config.yaml에, 실행 데이터를 /var/lib/mihomo에 둡니다. 전용 시스템 계정을 사용하면 일반 프록시 서비스가 접근할 수 있는 파일 범위를 제한할 수 있습니다.
sudo install -m 0755 mihomo /usr/local/bin/mihomo
sudo useradd --system --home /var/lib/mihomo --shell /usr/sbin/nologin mihomo
sudo install -d -o mihomo -g mihomo /etc/mihomo
sudo install -d -o mihomo -g mihomo /var/lib/mihomo
sudo install -m 0640 -o mihomo -g mihomo config.yaml /etc/mihomo/config.yaml
일부 배포판에서는 nologin이 /sbin/nologin에 있으므로 먼저 command -v nologin을 실행해 경로를 확인할 수 있습니다. 설정에서 GeoIP, GeoSite, 규칙 세트 또는 인증서 파일을 참조한다면 mihomo 계정에 해당 파일을 읽을 권한도 부여해야 합니다. 설정에서 상대 경로를 사용하면 경로는 일반적으로 mihomo의 작업 디렉터리를 기준으로 해석됩니다. 따라서 systemd의 WorkingDirectory와 실행 인자는 일치해야 합니다.
설정을 먼저 테스트한 뒤 systemd에 맡기기
sudo -u mihomo /usr/local/bin/mihomo \
-t \
-d /var/lib/mihomo \
-f /etc/mihomo/config.yaml
-t는 설정을 테스트하고, -d는 실행 디렉터리, -f는 설정 파일을 지정합니다. 테스트 통과는 현재 코어가 설정을 파싱할 수 있다는 뜻일 뿐, 모든 노드에 연결할 수 있거나 시스템 트래픽이 이미 프록시로 들어간다는 뜻은 아닙니다. mihomo를 업그레이드하거나 규칙 프로바이더를 수정한 뒤에는 테스트를 다시 실행하고 서비스를 재시작해야 합니다.
systemd로 mihomo 서비스 관리
기본 프록시 서비스 유닛
HTTP, SOCKS 또는 mixed-port만 제공한다면 일반적으로 TUN 권한은 필요하지 않습니다. /etc/systemd/system/mihomo.service를 생성하세요:
[Unit]
Description=mihomo proxy service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=mihomo
Group=mihomo
WorkingDirectory=/var/lib/mihomo
ExecStartPre=/usr/local/bin/mihomo -t -d /var/lib/mihomo -f /etc/mihomo/config.yaml
ExecStart=/usr/local/bin/mihomo -d /var/lib/mihomo -f /etc/mihomo/config.yaml
Restart=on-failure
RestartSec=5
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
저장한 뒤 systemd 설정을 다시 불러오고 시작합니다:
sudo systemctl daemon-reload
sudo systemctl enable --now mihomo
systemctl status mihomo --no-pager
sudo journalctl -u mihomo -n 100 --no-pager
ExecStartPre는 시작할 때마다 YAML을 검증합니다. 테스트에 실패하면 주 프로세스가 시작되지 않으며, 재시작 작업 중 기존 프로세스가 이미 종료되었을 수도 있습니다. 따라서 운영 환경에서 설정을 수정하기 전에도 테스트 명령을 수동으로 실행해야 합니다. Restart=on-failure는 비정상 종료에 대응하는 데 적합하지만 잘못된 설정이나 다른 프로세스가 점유한 포트를 해결해 주지는 않습니다.
TUN을 켤 때 네트워크 권한 추가
mihomo의 TUN 설정은 보통 다음과 같은 구조입니다. 사용 가능한 필드는 현재 mihomo 버전과 시스템 네트워크 스택에 따라 다르므로 기존 설정을 옮길 때는 사용 중인 버전의 문서를 기준으로 해야 합니다.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
전용 계정으로 TUN을 실행할 때 서비스에는 일반적으로 CAP_NET_ADMIN이 필요하며 호스트에 /dev/net/tun도 제공되어야 합니다. 서비스의 [Service] 섹션에 다음을 추가할 수 있습니다:
AmbientCapabilities=CAP_NET_ADMIN
CapabilityBoundingSet=CAP_NET_ADMIN
DeviceAllow=/dev/net/tun rw
서비스를 수정한 뒤 sudo systemctl daemon-reload와 sudo systemctl restart mihomo를 실행합니다. 이어서 ip link, ip route와 서비스 로그로 가상 인터페이스와 라우팅을 확인하세요. 컨테이너 환경에서는 호스트가 컨테이너에 TUN 장치와 네트워크 관리 권한을 추가로 허용해야 합니다. 컨테이너 안에서 YAML만 수정해도 호스트의 장치 및 권한 제한을 우회할 수는 없습니다.
프록시 환경 변수: 터미널 프로그램에서 mihomo 사용하기
현재 터미널에서만 임시 적용
TUN을 켜지 않은 경우 명령줄 프로그램에는 보통 명시적인 프록시 설정이 필요합니다. mihomo가 로컬에서 mixed-port 7890을 수신한다고 가정하면 다음과 같이 설정할 수 있습니다:
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export all_proxy=socks5h://127.0.0.1:7890
export no_proxy=localhost,127.0.0.1,::1
curl -I https://example.com
변수 이름은 대문자와 소문자 표기가 모두 존재하며, 프로그램마다 읽는 방식이 완전히 같지는 않습니다. 특정 도구와의 호환이 필요하면 HTTP_PROXY, HTTPS_PROXY, ALL_PROXY와 NO_PROXY를 함께 설정할 수 있습니다. 다만 CGI 같은 환경에서는 대문자 HTTP_PROXY에 추가 보안 제약이 있으므로 서버 전체에 설정하기 전에 실제 실행 환경을 확인해야 합니다.
socks5h의 h는 SOCKS 프록시 측에서 도메인 이름을 해석한다는 뜻입니다. socks5를 사용하면 앱이 로컬에서 도메인을 먼저 해석한 뒤 IP를 프록시에 전달할 수 있어 DNS 경로가 달라집니다. DNS 문제를 진단할 때는 socks5와 socks5h 중 무엇을 사용했는지 명확히 기록해야 합니다.
Git, APT와 systemd 서비스별 설정
Git은 현재 셸에 의존하지 않고 자체 설정을 사용할 수 있습니다:
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
# 확인
git config --global --get http.proxy
# 삭제
git config --global --unset http.proxy
git config --global --unset https.proxy
APT는 /etc/apt/apt.conf.d/80proxy에서 프록시를 지정할 수 있습니다:
Acquire::http::Proxy "http://127.0.0.1:7890";
Acquire::https::Proxy "http://127.0.0.1:7890";
다른 systemd 서비스가 mihomo를 거쳐야 한다고 해서 로그인 셸의 변수를 상속한다고 가정하지 마세요. systemctl edit 서비스명으로 오버라이드 설정을 생성합니다:
[Unit]
After=mihomo.service
Wants=mihomo.service
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1,::1"
저장한 뒤 sudo systemctl daemon-reload를 실행하고 대상 서비스를 재시작합니다. After는 시작 순서만 제한하고 Wants는 약한 의존성을 뜻합니다. 둘 다 mihomo의 특정 프록시 노드가 연결 가능한지 확인할 때까지 기다리지는 않습니다. 시작 단계에서 반드시 네트워크가 필요한 작업이라면 애플리케이션 자체에 재시도 로직을 추가하세요.
포트, 규칙과 컨트롤 인터페이스 설정
최소 수신 설정의 범위
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: false
external-controller: 127.0.0.1:9090
secret: "replace-with-a-long-random-secret"
rules:
- DOMAIN-SUFFIX,example.org,DIRECT
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- MATCH,PROXY
mixed-port는 HTTP와 SOCKS 연결을 모두 수락합니다. allow-lan: false는 로컬에서만 사용하는 환경에 적합합니다. LAN 장치의 접근이 꼭 필요하다면 수신 주소, 방화벽과 접근 범위도 함께 설정해야 합니다. external-controller는 컨트롤 인터페이스이며 프록시 포트가 아닙니다. 예시는 루프백 주소 127.0.0.1:9090에 바인딩되어 있습니다. 컨트롤 키는 실제 무작위 값으로 변경하고 신뢰할 수 없는 네트워크에 컨트롤 인터페이스를 직접 노출하지 마세요.
규칙은 순서대로 평가되며 처음 일치하는 항목이 연결 경로를 결정합니다. DIRECT는 직접 연결, REJECT는 거부를 뜻하고, PROXY는 설정에 이미 정의된 정책 그룹과 일치해야 합니다. no-resolve는 해당 IP 규칙이 도메인 이름 해석을 능동적으로 실행하지 않는다는 뜻이며, 모든 DNS를 끈다는 의미는 아닙니다.
구독 관리와 로컬 오버라이드 분리
그래픽 클라이언트에는 보통 자체 구독 캐시, 실행 설정과 오버라이드 메커니즘이 있습니다. 생성된 실행 파일을 직접 수정하면 다음 업데이트 때 덮어써질 수 있습니다. 헤드리스 mihomo는 특정 구독 URL을 완전한 운영 설정으로 자동 인식하지 않습니다. 별도의 업데이트 스크립트, 설정 생성 도구 또는 프록시 프로바이더로 다운로드와 변환을 수행한 뒤 테스트, 교체와 리로드를 실행해야 합니다.
- 원격 콘텐츠는 현재 설정을 바로 덮어쓰지 말고 임시 파일에 다운로드하세요.
- 정책 그룹 이름, 규칙 참조, DNS 필드와 규칙 프로바이더 경로를 확인합니다.
- 현재 실행 중인 mihomo 바이너리로
-t테스트를 실행합니다. - 테스트를 통과하면 설정 파일을 원자적으로 교체합니다.
- 서비스를 재시작하고 최근 로그 100줄과 수신 포트를 확인합니다.
로그와 문제 해결: 프로세스, 포트, 진입점을 단계별로 확인
systemd 서비스 시작 실패
systemctl status mihomo --no-pager
sudo journalctl -u mihomo -b --no-pager
sudo journalctl -u mihomo -f
- YAML 줄 번호나 필드 오류가 나타나면 먼저 설정 테스트를 실행하고 들여쓰기와 현재 코어가 지원하는 필드를 확인하세요.
permission denied가 나타나면 설정, 규칙 세트, 실행 디렉터리와/dev/net/tun권한을 확인하세요.address already in use가 나타나면ss -lntp로 7890, 7891 또는 9090을 점유한 프로세스를 찾으세요.- 서비스가 계속 재시작된다면 재시작 횟수만 보지 말고 최초 실패 시점의 로그를 확인하세요.
- TUN 시작 실패: 커널 모듈, 장치 노드, systemd capability와 라우팅 권한을 확인하세요.
포트는 열려 있지만 요청이 여전히 실패함
먼저 로컬 프록시로 요청을 보내 앱 설정 문제를 배제한 뒤, mihomo 로그에서 연결 대상, 일치한 규칙과 최종 정책을 확인하세요. 로그에 해당 요청이 전혀 없다면 트래픽이 프록시 포트에 도달하지 않은 경우가 많습니다. 요청은 기록되지만 정책이 예상과 다르면 규칙 순서와 정책 그룹 선택을 확인하세요. 정책은 올바르지만 연결 시간이 초과되면 노드 상태, 서버 시간, DNS와 상위 네트워크를 점검하세요.
# HTTP 프록시 진입점
curl -v -x http://127.0.0.1:7890 https://example.com
# SOCKS 프록시 진입점, 원격에서 도메인 이름 해석
curl -v --proxy socks5h://127.0.0.1:7890 https://example.com
# 로컬 라우팅 확인
ip route
# DNS 상태 확인, systemd-resolved에 해당
resolvectl status
mihomo가 다른 호스트에서 실행 중이라면 테스트 주소를 해당 호스트의 LAN IP로 바꾸고 allow-lan, 수신 주소와 방화벽 규칙을 확인하세요. 컨트롤 포트 9090을 HTTP 프록시 포트로 사용하지 말고 SOCKS URL을 HTTP URL로 작성하지도 마세요.
데스크톱 클라이언트와 systemd 충돌
같은 Linux 워크스테이션에 데스크톱 클라이언트와 systemd 서비스를 모두 설치했다면 상시 실행 담당자는 하나만 두는 것이 좋습니다. systemctl disable --now mihomo를 실행해 시스템 서비스를 일시 중지한 뒤 데스크톱 클라이언트를 시작하거나, 데스크톱 클라이언트를 종료하고 코어 프로세스가 끝난 것을 확인한 뒤 systemd를 시작하세요. 클라이언트 창만 닫았다고 트레이 프로세스까지 종료된 것은 아닐 수 있으므로 수신 포트와 프로세스 명령줄을 다시 확인해야 합니다.
배포 완료 후 점검 목록
- 클라이언트 버전과 mihomo 코어 버전을 기록하고 현재 누가 코어를 시작했는지 명확히 합니다.
- 설정 파일, 실행 디렉터리와 규칙 세트 파일을 실행 계정이 모두 읽을 수 있는지 확인합니다.
mihomo -t로 현재 설정을 테스트합니다.ss -lntp로 프록시 포트와 컨트롤 포트에 충돌이 없는지 확인합니다.curl -x또는curl --proxy로 명시적 프록시 진입점을 검증합니다.- 앱별로 터미널 변수, Git, APT 또는 systemd 환경 변수를 설정합니다.
- TUN을 활성화한 뒤 가상 인터페이스, 기본 경로, DNS와 SSH 반환 경로를 확인합니다.
- 구독이나 코어를 업데이트한 뒤 설정을 다시 테스트하고 시작 로그를 확인합니다.
Linux 데스크톱 배포의 핵심은 클라이언트가 설정, 코어와 시스템 진입점을 통합 관리하게 하는 것입니다. 헤드리스 배포의 핵심은 mihomo를 일반 시스템 서비스로 관리하는 데 있습니다. “설정 가져오기 완료”, “코어 수신 완료”, “앱이 프록시를 가리킴”과 “TUN이 트래픽을 처리함”이라는 네 상태를 항상 구분하면 대부분의 포트 충돌과 프록시 미적용 문제를 피할 수 있습니다.