OpenWrt에서 mihomo 투명 프록시 구성하기: 보조 라우터 배포 가이드

OpenWrt 메인 라우터나 보조 라우터에서 mihomo를 직접 실행하는 방법을 정리했습니다. 코어 설치 경로와 설정 디렉터리부터 투명 프록시 포워딩, LAN 기기의 게이트웨이 설정까지 안내합니다.

먼저 배포 범위부터 정하기: 코어, 게이트웨이, 투명 프록시는 서로 다른 역할

OpenWrt에서 mihomo를 직접 실행한다고 해서 GUI가 있는 Clash 클라이언트를 설치한 것은 아닙니다. 코어는 설정을 읽고 프록시 연결을 만들며 규칙을 적용합니다. 시스템은 단말 트래픽을 코어로 전달합니다. 시작 로그가 정상이어도 프로세스가 실행 중이라는 뜻일 뿐, LAN 기기가 프록시를 사용 중이라는 의미는 아닙니다.

이 글에서는 OpenWrt 23.05 및 24.10에서 흔히 사용하는 firewall4와 nftables 환경을 기준으로 Linux TUN과 자동 라우팅을 구성합니다. 각 설정 항목의 지원 여부는 사용 중인 mihomo 버전의 설정 검사 결과를 확인하세요. 구형 firewall3, 제조사 커스텀 방화벽, 기존 프록시 플러그인에는 같은 규칙을 그대로 적용하면 안 됩니다.

  • 메인 라우터에 배포: OpenWrt가 이미 단말의 기본 게이트웨이이므로 코어의 트래픽 인계, 방화벽 허용, DNS 포워딩에 중점을 둡니다.
  • 보조 라우터에 배포: OpenWrt와 메인 라우터가 같은 LAN에 연결되어 있어야 하며, 테스트 단말의 게이트웨이와 DNS도 변경해야 합니다.
  • 명시적 프록시 테스트: 앱에서 7890 혼합 포트에 직접 연결합니다. 노드와 규칙을 먼저 확인하는 테스트일 뿐, 투명 프록시 구성이 완료됐다는 뜻은 아닙니다.

보조 라우터 주소와 단말 게이트웨이 계획하기

먼저 단말 한 대로 검증하고, LAN 전체의 DHCP 설정을 바로 변경하지 마세요. 아래는 서로 맞물리는 설정 예시입니다. 실제 환경에서는 기존 서브넷에 맞춰 함께 조정해야 하며, 주소 하나만 따로 바꾸면 안 됩니다.

기기 또는 설정예시 값용도
LAN 서브넷192.168.10.0/24메인 라우터, 보조 라우터, 단말이 같은 서브넷을 사용합니다
메인 라우터192.168.10.1인터넷에 연결하고 DHCP 서비스를 계속 제공합니다
OpenWrt 보조 라우터192.168.10.2DHCP 주소 범위와 겹치지 않는 고정 주소
보조 라우터의 기본 게이트웨이192.168.10.1코어가 노드와 직접 연결 대상에 접속할 때 사용하는 상위 게이트웨이
테스트 단말192.168.10.100기존 서브넷 마스크 유지
단말 게이트웨이 및 DNS192.168.10.2테스트 단말의 트래픽과 DNS 요청을 보조 라우터로 전달

LuCI에서 먼저 「네트워크」→「인터페이스」→「LAN」→「편집」으로 이동해 고정 주소, IPv4 게이트웨이, DNS 설정을 확인하세요. 단일 포트 보조 라우터는 보통 br-lan을 통해 메인 라우터에 연결합니다. 포트가 두 개인 메인 라우터는 PPPoE나 다른 WAN 장치로 나갈 수 있으므로, 네트워크 인터페이스 이름만 보고 출구를 판단하면 안 됩니다.

ip -4 addr show
ip -4 route show
ip route get 223.5.5.5
cat /etc/resolv.conf

보조 라우터의 기본 경로는 자신이 아니라 메인 라우터를 향해야 합니다. 처음 배포할 때는 보조 라우터의 시스템 DNS가 직접 접근 가능한 DNS 서버를 사용하도록 하세요. 코어가 시작되려면 노드 도메인 조회가 필요한데 DNS 조회가 아직 실행되지 않은 코어에 의존하는 순환을 방지할 수 있습니다.

메인 라우터에서 DHCP 서비스를 하나만 유지하면 됩니다. 같은 브로드캐스트 도메인에서 보조 라우터가 별도의 주소를 배포하지 않도록 하세요. IPv6도 별도로 계획해야 합니다. 단말의 IPv4 게이트웨이를 수동으로 바꿔도 메인 라우터의 IPv6 라우터 광고를 통해 직접 외부로 연결될 수 있습니다.

mihomo 코어와 설정 디렉터리 배치하기

아키텍처, 커널 모듈, 저장 공간 확인하기

먼저 CPU 아키텍처와 펌웨어 정보를 확인한 다음 알맞은 Linux 실행 파일을 선택하세요. x86_64, aarch64, 각종 MIPS 변형은 서로 호환되지 않습니다. 배포 패키지에 따라 명령어 세트 버전도 다를 수 있습니다. 파일 이름이 비슷해 보여도 같은 기기에서 실행된다는 보장은 없습니다.

uname -m
ubus call system board
df -h /overlay /tmp
opkg list-installed | grep -E 'kmod-tun|firewall4|nftables'

opkg를 사용하는 공식 펌웨어에서는 opkg update와 opkg install kmod-tun으로 TUN 모듈을 설치할 수 있습니다. 모듈은 현재 펌웨어의 커널과 일치해야 합니다. 의존성 불일치가 발생하면 펌웨어와 소프트웨어 저장소의 대응 관계를 바로잡고, 다른 커널 버전용 모듈을 강제로 설치하지 마세요. 자동 트래픽 인계에 필요한 nftables 기능은 펌웨어의 빌드 옵션에 따라서도 달라집니다.

실행 파일 경로와 작업 디렉터리 고정하기

압축을 풀고 아키텍처가 맞는 코어를 /usr/bin/mihomo에 업로드하고, 설정 파일은 /etc/mihomo/config.yaml에 저장하세요. 설정에는 구독 인증 정보가 포함될 수 있으므로 일반 사용자가 디렉터리와 파일에 접근하지 못하도록 해야 합니다. 기기의 영구 저장 공간이 부족하다면 재부팅 시 지워지는 /tmp에 운영 설정을 장기간 보관하지 말고 외부 저장 공간을 먼저 계획하세요.

mkdir -p /etc/mihomo
chmod 700 /etc/mihomo
chmod 755 /usr/bin/mihomo
chmod 600 /etc/mihomo/config.yaml
/usr/bin/mihomo -v
/usr/bin/mihomo -t -d /etc/mihomo -f /etc/mihomo/config.yaml

-d는 작업 디렉터리, -f는 설정 파일을 지정하며, -t는 설정만 검사합니다. 설정에서 GeoIP, GeoSite, 규칙 세트, 프록시 제공자 파일을 참조한다면 해당 파일의 경로와 읽기 권한, 다운로드 네트워크도 확인해야 합니다. 처음 문제를 진단할 때는 이런 외부 의존성을 잠시 제거해 다운로드 실패를 TUN 오류로 오인하지 않도록 하세요.

먼저 명시적 프록시를 확인한 뒤 TUN 트래픽 인계 활성화하기

두 단계로 실행하는 방법을 권장합니다. 첫 번째는 실제로 사용할 수 있는 노드 설정으로 tun.enable을 false로 지정하고, 라우터 자체에서 혼합 포트 연결을 테스트합니다. 노드가 정상임을 확인한 다음 두 번째 단계에서 TUN과 자동 라우팅을 활성화하세요. 이렇게 하면 노드 문제와 트래픽 포워딩 문제를 분리할 수 있습니다.

아래는 설정과 직접 연결의 기본 동작을 확인하기 위한 최소 구성입니다. 프록시 노드가 없고 정책 그룹도 DIRECT뿐이므로 프록시를 통한 외부 연결은 발생하지 않습니다. 실제로 사용할 때는 구독의 유효한 노드나 proxy-providers를 합치고 실제 노드를 정책 그룹에 추가하세요. 기존의 완성된 설정을 이 예시로 덮어쓰지 마세요.

mixed-port: 7890
allow-lan: false
bind-address: 127.0.0.1
mode: rule
log-level: info
ipv6: false

tun:
  enable: false
  device: mihomo
  stack: mixed
  auto-route: true
  auto-redirect: true
  auto-detect-interface: true
  dns-hijack:
    - any:53

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  default-nameserver:
    - 223.5.5.5
  nameserver:
    - 223.5.5.5
    - 119.29.29.29

proxies: []

proxy-groups:
  - name: 출구 선택
    type: select
    proxies:
      - DIRECT

rules:
  - IP-CIDR,192.168.10.0/24,DIRECT,no-resolve
  - IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
  - MATCH,출구 선택

먼저 /usr/bin/mihomo -d /etc/mihomo -f /etc/mihomo/config.yaml을 포그라운드에서 실행하고, 다른 SSH 세션으로 포트를 확인하세요. 펌웨어에 curl이 설치되어 있다면 아래 요청을 실행할 수 있습니다. 이 명령은 라우터 자체에서 혼합 포트까지의 연결만 확인하며, LAN의 투명 프록시 포워딩은 검사하지 않습니다.

curl --proxy http://127.0.0.1:7890 --connect-timeout 10 --max-time 20 -I https://example.com/

실제 노드를 가져온 다음 「출구 선택」이 DIRECT에 머물러 있지 않은지 확인하세요. 로그에 표시된 매칭 규칙, 정책 그룹, 노드 이름을 함께 살펴 요청 경로를 판단해야 합니다. 웹페이지가 열리는지만으로는 직접 연결인지 프록시 연결인지 구분할 수 없습니다.

TUN, 정책 라우팅, OpenWrt 방화벽 연결하기

명시적 프록시가 정상 작동하면 tun.enable을 true로 바꾸고 설정을 다시 검사한 뒤 실행하세요. auto-route는 트래픽 인계에 필요한 라우트를 만들고, Linux의 auto-redirect는 nftables 등의 메커니즘으로 트래픽 리디렉션을 지원합니다. 자동 생성되는 라우팅 테이블 번호, 규칙 우선순위, 체인 이름은 버전에 따라 바뀔 수 있으므로 인터넷에서 본 특정 번호 조합을 보편적인 기준으로 삼지 마세요.

ip link show mihomo
ip rule show
ip route show table all
nft list ruleset
sysctl net.ipv4.ip_forward

시스템 조건 세 가지 확인하기

  1. TUN 장치가 존재하는지: 설정에서 지정한 mihomo 장치가 보여야 합니다. 장치가 없다면 먼저 /dev/net/tun, 모듈, 실행 권한을 확인하세요.
  2. 라우팅 인계가 적용됐는지: 실행 전후의 ip rule, 라우팅 테이블, nftables 규칙을 비교하세요. 코어 로그에 인터페이스 생성이나 규칙 추가 실패가 계속 나타나면 안 됩니다.
  3. 방화벽이 포워딩을 차단하지 않는지: IPv4 포워딩이 활성화되어 있어야 하며 LAN에서 TUN으로 가는 경로도 허용되어야 합니다. TUN 인터페이스가 보인다는 사실만으로 firewall4가 포워딩을 허용했다고 볼 수는 없습니다.

LuCI의 「네트워크」→「방화벽」→「일반 설정」에서 영역과 포워딩을 확인하세요. TUN 전용 영역을 사용하는 경우 실제 화면에 맞춰 mihomo 장치를 해당 영역에 연결하고 LAN에서 그 영역으로의 포워딩을 허용할 수 있습니다. 영역의 인바운드 권한과 포워딩 권한은 별개입니다. 테스트를 위해 WAN 인바운드를 무턱대고 허용으로 바꾸지 마세요.

펌웨어마다 관리되지 않는 장치를 방화벽 영역에 연결하는 방식과 자동 리디렉션, firewall4의 연동 방식이 다릅니다. 따라서 현재 규칙 세트를 확인해 판단해야 하며, 고정된 iptables 스크립트를 그대로 복사하면 안 됩니다. 특히 REDIRECT, TPROXY, 자동 TUN 규칙을 동시에 추가하지 마세요. 이 글에서는 TUN 방식을 사용합니다.

단일 인터페이스 보조 라우터에서는 같은 인터페이스를 통한 포워딩, 응답 경로, 연결 추적도 확인해야 합니다. 일부 직접 연결 트래픽은 br-lan으로 들어온 뒤 같은 인터페이스를 통해 메인 라우터로 나갈 수 있습니다. 한쪽 방향만 통하거나 연결이 간헐적으로 끊긴다면 패킷을 캡처해 출발지 주소와 응답 경로를 확인한 뒤 필요한 경우에만 출발지 주소 변환을 설정하세요. 먼저 LAN 전체에 무작정 마스커레이드를 적용하지 마세요.

처음 문제를 진단할 때는 「네트워크」→「방화벽」에서 소프트웨어 플로우 오프로드와 하드웨어 플로우 오프로드를 일시적으로 끄는 것이 좋습니다. 연결이 안정되면 하나씩 다시 켜고 테스트하세요. 보조 라우터에서는 인터넷에 접속되지만 단말에서는 접속되지 않는다면 노드를 바꾸기 전에 포워딩 경로부터 확인하세요.

DNS 포워딩을 설정해 조회 루프와 IPv6 우회 방지하기

예시의 DNS 경로는 다음과 같습니다. 단말이 보조 라우터의 53 포트에 요청하면 dnsmasq가 요청을 로컬 mihomo의 1053 포트로 전달하고, 이후 상위 DNS 서버에 질의합니다. 포트를 분리하면 dnsmasq와 mihomo가 같은 주소에서 수신을 시도하지 않습니다.

LuCI의 「네트워크」→「DHCP/DNS」→「일반 설정」에서 DNS 포워딩 대상에 127.0.0.1#1053을 지정하세요. 해당 고급 설정에서 「상위에서 제공하는 DNS 서버 사용 안 함」 옵션도 확인합니다. LuCI 버전에 따라 화면의 항목 이름은 달라질 수 있지만, 핵심은 dnsmasq가 자동으로 할당받은 다른 상위 DNS 서버에 요청을 함께 전달하지 않도록 하는 것입니다.

# 먼저 백업하세요. 아래 명령은 첫 번째 dnsmasq 인스턴스를 대상으로 합니다
cp /etc/config/dhcp /etc/config/dhcp.before-mihomo
uci set dhcp.@dnsmasq[0].noresolv='1'
uci -q delete dhcp.@dnsmasq[0].server
uci add_list dhcp.@dnsmasq[0].server='127.0.0.1#1053'
uci commit dhcp
/etc/init.d/dnsmasq restart

nslookup example.com 127.0.0.1

이 명령은 해당 인스턴스에 이미 설정된 DNS 포워딩 목록을 교체합니다. 사내 도메인의 조건부 포워딩을 사용 중이라면 먼저 기록해 두고 해당 항목을 유지하세요. dnsmasq 인스턴스가 여러 개라면 첫 번째 인스턴스가 LAN용이라고 단정할 수도 없습니다. 단말의 DNS 주소가 실제로 192.168.10.2인지도 확인해야 합니다.

일반 DNS, fake-ip, 암호화 DNS 구분하기

  • fake-ip: 이 모드에서는 조회 결과로 198.18.0.0/16 범위의 주소가 반환될 수 있습니다. 이 주소는 가상 매핑 주소이지 대상 웹사이트의 실제 공인 IP가 아닙니다. 해당 연결은 계속 코어에서 처리되어야 합니다.
  • 일반 DNS 가로채기: any:53은 해당하는 일반 DNS 요청을 가로채는 설정이며, 모든 DNS 프로토콜을 찾아 리디렉션한다는 뜻은 아닙니다.
  • DoH와 DoT: 브라우저의 보안 DNS, 앱 내 DoH, TCP 853을 사용하는 DoT는 일반적인 53 포트 가로채기를 설정해도 자동으로 dnsmasq를 따르지 않습니다. 테스트할 때는 먼저 앱이 실제로 어떤 경로로 DNS를 조회하는지 확인하세요.
  • 상위 DNS 선택: 예시에서는 시작 과정의 의존성을 줄이기 위해 일반 IP 주소를 사용하는 상위 DNS를 설정했으며, 암호화된 DNS는 사용하지 않습니다. 도메인 이름을 사용하는 DoH 주소로 바꾼다면 초기 DNS 조회와 노드 도메인 조회를 별도로 계획해야 합니다.

ipv6: false는 코어의 관련 동작만 제한하며 단말이 받은 IPv6 기본 경로를 비활성화하지는 않습니다. 처음 검증할 때는 테스트 단말의 IPv6를 일시적으로 끈 다음 IPv6 TUN, 라우터 광고, 방화벽을 별도로 계획할 수 있습니다. IPv4 출구가 올바르다는 이유로 듀얼 스택 트래픽도 모두 인계됐다고 판단하지 마세요.

procd로 시작과 재시작 관리하기

포그라운드 실행, DNS, 단말 접속이 모두 정상임을 확인한 후 부팅 서비스로 등록하세요. 아래 procd 스크립트는 프로세스 관리만 하며 구독 업데이트나 사용자 지정 방화벽 설정은 포함하지 않습니다. /etc/init.d/mihomo로 저장하고 다른 플러그인에 같은 이름의 서비스가 남아 있지 않은지 확인하세요.

#!/bin/sh /etc/rc.common

START=99
STOP=10
USE_PROCD=1

start_service() {
    /usr/bin/mihomo -t -d /etc/mihomo \
        -f /etc/mihomo/config.yaml || return 1

    procd_open_instance
    procd_set_param command /usr/bin/mihomo \
        -d /etc/mihomo -f /etc/mihomo/config.yaml
    procd_set_param respawn 3600 5 5
    procd_set_param stdout 1
    procd_set_param stderr 1
    procd_set_param file /etc/mihomo/config.yaml
    procd_close_instance
}
chmod 755 /etc/init.d/mihomo
/etc/init.d/mihomo enable
/etc/init.d/mihomo start
logread -e mihomo

서비스를 시작하기 전에 포그라운드에서 실행 중인 코어를 종료해 두 인스턴스가 포트와 TUN 장치를 놓고 충돌하지 않도록 하세요. 이 스크립트는 TUN 생성과 라우팅·방화벽 설정에 필요한 권한을 위해 기본적으로 root로 실행됩니다. 따라서 설정 파일과 구독 소스, 코어 실행 파일을 모두 엄격하게 관리해야 합니다.

설정을 수정한 뒤 먼저 mihomo -t를 실행하고 /etc/init.d/mihomo restart를 실행하세요. 스크립트에 파일 경로가 선언되어 있다고 해서 구독이 자동으로 업데이트되는 것은 아닙니다. 구독 업데이트는 다운로드, 설정 검사, 원자적 교체를 별도로 구성해야 합니다. 설정에 인증 정보가 있다면 전체 시작 로그를 공개된 곳에 그대로 올리지 마세요.

부팅 순서를 늦게 설정했다고 해서 네트워크가 이미 준비된 것은 아닙니다. 시스템을 한 번 재부팅해 인터페이스가 올라온 뒤 노드 도메인을 조회하고 연결을 수립하며 단말 접속을 복구할 수 있는지 확인하세요. 원격 규칙 세트에 의존하는 구성이라면 콜드 부팅 직후 외부 파일에 접근할 수 없는 상황도 고려해야 합니다.

연결 경로별로 검증하고 복구 방법 마련하기

라우터 자체에서 시작해 단말 한 대를 검증한 뒤 마지막으로 DHCP 배포 범위를 확장하세요. 한 번에 변수 하나만 바꾸고 관련 로그와 게이트웨이 설정을 기록합니다. 속도 측정 결과는 당시의 전송 성능만 보여 주므로 라우팅 및 DNS 경로 확인을 대신할 수 없습니다.

증상우선 확인할 항목판단 기준
코어가 시작되지 않음아키텍처, 설정, 포트, TUN 모듈설정 검사와 시작 오류를 확인하고 단말 게이트웨이는 먼저 변경하지 않음
명시적 프록시는 정상인데 단말은 연결되지 않음단말 게이트웨이, TUN 트래픽 인계, LAN 포워딩단말 요청이 코어 로그에 들어오는지 비교
IP 주소로는 접속되지만 도메인으로 접속되지 않음dnsmasq, 1053 포트 수신, 상위 DNS 조회보조 라우터와 단말에서 각각 DNS 요청 테스트
일부 앱이 계속 직접 연결됨규칙, IPv6, 앱 내 DNS실제 적용된 정책과 듀얼 스택 출구 확인
방화벽을 다시 불러온 뒤 연결이 끊김자동 생성된 규칙이 유지되는지방화벽 재적용 전후의 nftables 규칙과 정책 라우팅 비교
재부팅 후 복구되지 않음서비스 활성화 상태, 인터페이스 시작 순서, 콜드 부팅 의존성시스템 로그에서 최초 실패 지점 확인

단말 한 대 검증 후 배포 범위 확대하기

  1. 단말에서 먼저 메인 라우터와 보조 라우터의 관리 주소에 접속해 LAN 내부 직접 연결이 정상인지 확인합니다.
  2. 단말의 IPv4 기본 게이트웨이와 DNS가 모두 보조 라우터를 가리키는지 확인하고, 이전 DNS 캐시를 지운 뒤 브라우저에서 새 연결을 시도합니다.
  3. 직접 연결되어야 하는 요청과 프록시를 거쳐야 하는 요청을 각각 확인하고, 페이지가 열리는지만 보지 말고 해당 규칙과 노드를 살펴봅니다.
  4. UDP 앱, IPv6 정책, 방화벽 재적용 후의 동작을 확인한 뒤 메인 DHCP 서비스의 게이트웨이 및 DNS 배포 값을 조정합니다.

정상적으로 중지한 뒤 TUN 인터페이스, 정책 라우팅, 자동 생성 방화벽 규칙이 정리됐는지 확인하세요. 잔여 항목이 있다면 저장해 둔 기준 상태에 따라 복구합니다. 원격에서 nftables 규칙 세트 전체를 비우는 명령은 실행하지 마세요. 실행 상태를 정리해야 한다면 영구 설정을 복원한 뒤 재부팅을 예약할 수 있습니다.

OpenWrt 보조 라우터 배포의 핵심은 라우터에 실행 파일을 올리는 데 있지 않습니다. 단말 게이트웨이, DNS, 트래픽 인계, 규칙 출구, 서비스 수명 주기를 검증 가능한 하나의 경로로 연결하는 것이 중요합니다. 이 순서대로 확인하면 이후 구독 변경, 분기 규칙 조정, 코어 업그레이드 중 문제가 발생해도 어느 계층에서 비롯됐는지 파악할 수 있습니다.

Clash 다운로드 설치 파일 및 시스템 요구 사항