← ~/notes · 3 min read

JetKVM이 Cloudflare Tunnel 너머에서 USB가 disconnected — WebRTC가 막힌다

Web UI는 잘 뜨는데 키보드/마우스 입력이 안 먹는다. 자료가 거의 없는 구체적 함정을 직접 부딪혀 정리.

목차
  1. 증상
  2. 원인 — WebRTC가 막힘
  3. 시도했지만 안 된 것들
  4. 1) Cloudflare WebSockets 토글
  5. 2) --protocol http2 옵션
  6. 3) Cloudflare Spectrum
  7. 4) UDP 프록시 별도 설정
  8. 실제로 작동한 해결책
  9. Tailscale 셋업
  10. 검색해도 안 나온 이유
  11. 같은 패턴으로 막히는 다른 도구
  12. 만들면서 알게 된 것들

JetKVM은 라즈베리파이 크기의 KVM-over-IP다. 서버에 USB+HDMI 꽂아두면 어디서든 브라우저로 BIOS까지 진입 가능. GPU 패스스루 셋업 막혔을 때 산 게 이거.

문제는 외부 노출 방식. 공유기 포트 안 열고 Cloudflare Tunnel로 노출하려 했는데 — Web UI는 뜨는데 키보드/마우스/USB가 안 먹는다.

검색해도 자료 거의 없어서 직접 정리.


증상

1. 로컬 IP로 직접 접속 (192.168.x.x:80)        → 모든 기능 정상
2. Cloudflare Tunnel로 접속 (kvm.lab-it.net)  → Web UI 뜨고 화면 보이지만:
   - 키보드 입력이 게스트 OS에 안 들어감
   - 마우스 클릭이 안 됨
   - USB 가상 디스크가 "disconnected" 상태
   - 그러나 화면은 정상적으로 흐름

원인 — WebRTC가 막힘

JetKVM Web UI 자체는 HTTP 위에서 동작 (정적 파일 + WebSocket 컨트롤). 화면은 MJPEG/H264 스트림으로 HTTP 또는 WebSocket으로 옴.

키보드/마우스/USB는 WebRTC 데이터 채널 로 처리한다. 저지연이 필수라 WebSocket보다 WebRTC를 쓰는 듯.

WebRTC는 UDP 기반. ICE/STUN/TURN으로 NAT 뚫고 P2P 연결.

Cloudflare Tunnel은 TCP 기반 reverse proxy다. UDP는 프록시 못 한다.

따라서:

  • HTTP/WebSocket(TCP) → Cloudflare Tunnel 통과 ✓
  • WebRTC(UDP) → 차단 ✗

화면은 뜨지만 입력 못 함의 정확한 원인.


시도했지만 안 된 것들

1) Cloudflare WebSockets 토글

대시보드 Network → WebSockets ON. WebSocket은 어차피 동작하던 거라 효과 없음.

2) --protocol http2 옵션

cloudflared 시작 옵션에 HTTP/2 강제. WebRTC와 무관.

3) Cloudflare Spectrum

Spectrum은 임의 TCP/UDP 노출 가능하지만 유료 (Enterprise). 학생 인프라엔 부담.

4) UDP 프록시 별도 설정

cloudflared에 UDP 라우팅 추가 시도. WireGuard용 udp 라우팅은 제공되지만 일반 WebRTC용 동적 포트엔 안 맞음.


실제로 작동한 해결책

WebRTC를 우회 — JetKVM이 WebRTC fallback으로 WebSocket을 쓸 수 있는지 확인.

JetKVM 문서엔 명시 없고, 펌웨어 코드를 보니 ?fallback=ws 같은 쿼리 파라미터도 없었다. 사실상 WebRTC가 강제.

최종 결론: Cloudflare Tunnel로 JetKVM 풀기능 노출은 불가능. UDP 프록시 가능한 다른 방법이 필요.

대안:

  • Tailscale — WireGuard 기반 메시 VPN, UDP 통과. Tailscale 무료 플랜으로 vm0 + Mac 연결 → JetKVM 로컬 IP로 접근. 이게 정답.
  • Cloudflare Tunnel + WARP — 일부 시나리오에서 WARP 클라이언트로 WebRTC 가능할 수 있다는 글이 있음. 미확인.
  • 공유기 UDP 포트 포워딩 — 가능하지만 그게 싫어서 Tunnel 쓴 건데 본말 전도.

Tailscale 셋업

Tailscale을 vm0과 Mac에 깔면 둘이 직접 P2P (UDP NAT-traversal 자동).

# vm0 (Proxmox 호스트)
curl -fsSL https://tailscale.com/install.sh | sh
tailscale up

# Mac
brew install tailscale
tailscale up

이제 vm0의 Tailscale IP(100.x.x.x)로 어디서든 접근. JetKVM이 vm0 내부 LAN에 있으면 Tailscale → vm0 → JetKVM 라우팅 가능 (tailscale up --advertise-routes=192.168.0.0/24).


검색해도 안 나온 이유

이 문제 원인이 정확히 잡혀야:

  • “JetKVM Cloudflare Tunnel” — 자료 없음 (제품 자체가 신생)
  • “WebRTC behind reverse proxy not working” — 너무 일반적
  • “cloudflared WebRTC support” — Cloudflare 측 명시적 답변 부재

키워드를 정확히 합쳐도 글이 거의 없다. 누군가 같은 함정에 빠지면 이 글이 검색되길.


같은 패턴으로 막히는 다른 도구

WebRTC를 쓰는 KVM-over-IP/원격 도구는 거의 같은 함정.

도구WebRTC 사용Cloudflare Tunnel 통과?
JetKVM✓✗
TinyPilot✗ (MJPEG/HID over USB)✓
PiKVM△ (모드에 따라)△
MeshCentral✓✗
RustDesk✓✗
Apache Guacamole✗ (HTML5 over WebSocket)✓

WebRTC 안 쓰는 TinyPilot이나 Guacamole은 Tunnel과 잘 맞는다. 도구 고를 때 미리 확인.


만들면서 알게 된 것들

Cloudflare Tunnel은 TCP만이다. 무료 + 강력해서 만능처럼 보이지만 UDP는 못 한다. WebRTC, WireGuard, 게임 서버 등 UDP 의존 서비스엔 부적합.

Tailscale은 UDP의 답. WireGuard 기반이라 UDP 직접 프록시. Cloudflare Tunnel과 보완 관계: Tunnel은 공개 노출, Tailscale은 비공개 메시.

“화면 보이는데 입력 안 됨”은 UDP 막힌 거의 결정적 시그널. 영상 스트림은 TCP로 종종 fallback 가능, 입력은 저지연이 필수라 UDP 강제. 이 비대칭이 진단 단서.


처음에 글을 시작할 때 “Cloudflare Tunnel로 다 됨”이라 자신했는데, 한 번 더 경계의 비용을 배웠다. 모든 도구는 자기 가정이 있고, 그 가정 밖에선 안 통한다.