Ubuntu에서 TUN을 고르는 이유와 systemd의 역할

“시스템 프록시/환경 변수” 방식은 앱이 프록시를 존중할 때만 잘 작동합니다. 반면 TUN은 커널이 가상 인터페이스로 트래픽을 Clash 쪽으로 넘기는 형태에 가깝고, 브라우저·CLI·일부 무시하는 프로그램까지 포함해 체감 일관성이 좋아지는 경우가 많습니다. 대가로 권한과 라우팅 충돌(도커, 다른 VPN, 회사 네트워크) 같은 운영 이슈가 드러납니다.

systemd는 “터미널에서 한 번 실행”을 “서비스로 운영”으로 바꿉니다. 재부팅 후 자동 시작, 실패 시 재시작, 표준 로그 수집이 가능해져 원격 서버에서 특히 중요합니다. 개념적 배경은 TUN 모드 심화를 참고하고, 이 글은 Ubuntu 파일 시스템·권한·유닛 파일에 초점을 둡니다.

핵심: 수동 실행은 되는데 systemd만 실패하면, 거의 항상 -d 경로·실행 사용자·권한(capabilities) 중 하나가 어긋난 경우입니다. 먼저 세 값을 동일 조건으로 맞추세요.

Ubuntu는 netplan, NetworkManager, systemd-resolved가 함께 동작하는 경우가 많아 “프록시 앱에서는 되는데 서비스만 이상” 같은 증상이 환경 변수 차이로 위장하기도 합니다. 같은 사용자·같은 -d로 포그라운드 실행과 systemd 실행을 나란히 비교하면, 진짜 커널 문제인지 설정 불일치인지 빠르게 갈립니다. 클라이언트 선택이 아직이라면 클라이언트 선택 가이드로 유지보수 리듬부터 맞추는 것도 도움이 됩니다.

코어 바이너리 설치와 경로 고정

아키텍처에 맞는 단일 바이너리를 내려받아 /usr/local/bin/mihomo 또는 /opt/clash-meta/mihomo처럼 고정합니다. 실행 비트를 주고 버전을 확인합니다. 업그레이드 시 경로를 바꾸지 말고 교체하거나 심볼릭 링크를 유지하면 systemd ExecStart를 덜 고칩니다. setcap을 썼다면 업그레이드 후에도 capability를 다시 확인하세요.

config.yaml과 작업 디렉터리 정렬

흔한 사용자 경로는 ~/.config/mihomo/config.yaml 주변입니다. 전용 계정으로 서비스를 돌릴 때는 디렉터리 소유권이 어긋나면 “수동은 되는데 서비스만 구독을 못 읽는” 현상이 납니다. 시스템 경로(/etc/mihomo/ 등)를 쓰면 정책이 명확해지지만 파일 권한을 더 엄격히 관리해야 합니다. 구독 URL에 토큰이 있다면 저장소에 올리지 말고 권한을 제한하세요. 운영 습관은 구독 관리 가이드와 함께 보는 것이 좋습니다.

YAML에서 TUN(투명 프록시) 켜기

tun: 아래 enable: true가 기본이고, stack, auto-route, auto-detect-interface 같은 옵션은 버전 문서를 따라야 합니다. auto-route는 편하지만 다른 VPN/도커 브리지와 경쟁할 수 있습니다. DNS는 TUN만으로 끝나지 않습니다—규칙/모드가 어긋나면 “터널은 떴는데 일부 도메인만 실패”가 나옵니다. 규칙 라우팅 모범 사례FAQ의 DNS 설명을 함께 확인하세요.

예시 YAML(버전에 맞게 수정)
tun:
  enable: true
  stack: system
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53

/dev/net/tun과 CAP_NET_ADMIN 처리

/dev/net/tun 접근 실패는 권한 문제로 바로 이어집니다. root로 실행하면 쉬워지지만 최소 권한 원칙에는 맞지 않습니다. 전용 사용자 + setcap, 또는 systemd의 AmbientCapabilities/CapabilityBoundingSet 조합이 흔합니다. 어떤 방식이든 “왜 이 바이너리에 이 권한이 필요한지”를 문서로 남기세요.

원격 서버 주의: 잘못된 라우트는 SSH를 끊을 수 있습니다. 콘솔(아웃오브밴드)을 확보하고, 먼저 테스트 머신에서 검증하세요.

systemd 유닛: 자동 시작·재시작·로그

사용자 유닛은 ~/.config/systemd/user/, 시스템 유닛은 /etc/systemd/system/에 둡니다. After=network-online.target로 부팅 레이스를 줄이고, Restart=on-failure를 권장합니다. WorkingDirectorymihomo -d가 같은 디렉터리를 가리키게 하세요.

예시 user service(경로는 설치에 맞게)
[Unit]
Description=Mihomo (Clash Meta)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=%h/.config/mihomo
ExecStart=/usr/local/bin/mihomo -d %h/.config/mihomo
Restart=on-failure
RestartSec=3
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE

[Install]
WantedBy=default.target

검증: 인터페이스·정책 라우팅·DNS

서비스가 뜨면 ip link로 TUN 유사 인터페이스를 확인하고, ip rule/ip route로 정책 라우팅이 기대와 같은지 봅니다. 규칙이 잘못되면 터널이 살아 있어도 목적지가 엇나갈 수 있습니다. 규칙 문서와 대조하세요.

추가로, 컨테이너나 스냅으로 격리된 런타임은 호스트 라우팅 테이블과 다른 네임스페이스를 쓰기 때문에 “호스트에선 되는데 컨테이너만 안 된다”는 패턴이 흔합니다. 이때는 TUN 자체보다 네트워크 네임스페이스/브리지 설정을 먼저 의심하는 편이 빠릅니다.

journalctl로 보는 대표 오류

먼저 첫 ERROR 줄을 확인합니다. 로컬 라우팅 문제와 원격 노드 문제는 증상이 비슷해 보이므로, timeout/TLS 로그 가이드의 분리 방법을 그대로 적용할 수 있습니다. “수동은 되고 systemd만 실패”면 환경 변수·작업 디렉터리·사용자 ID를 줄 단위로 비교하세요.

업스트림 오픈소스와 배포 채널 분리

Mihomo/Clash Meta 계열은 오픈소스로 관련 문서와 이슈를 확인할 수 있습니다. 다만 일반 사용자에게 “설치 파일을 어디서 받을지”는 사이트 다운로드 페이지를 기본으로 두고, GitHub 릴리스는 소스·변경 기록 확인용으로 분리하는 편이 혼동이 적습니다.

맺음말

Ubuntu에서 Clash Linux 구성의 핵심은 경로·권한·서비스화의 세 박자가 맞는지입니다. TUN은 강력하지만 라우팅과 DNS와 함께 봐야 하고, systemd는 그걸 “재현 가능한 운영”으로 바꿉니다. GUI가 필요하면 동일한 설정 디렉터리를 공유하되, 두 프로세스가 포트와 TUN을 놓고 싸우지 않게 주의하세요.

Clash를 무료로 내려받고 더 편한 클라이언트 경험을 시작해 보세요. 서버에서 검증한 분류 규칙을 데스크톱에서도 일관되게 유지할 수 있습니다.