좋은 지적 셋입니다. 마지막 둘은 터널이 실제로 구현돼 있는지 부터 확인해야 답할 수 있습니다. 패키징 통합과 터미널/RDP 구현 전략을 재구성했다 패키징 통합과 터미널/RDP 구현 전략을 재구성했다 확인됐습니다. TUNNEL_* 는 타입만 선언돼 있고 에이전트에 처리 코드가 없습니다. frame.c 는 이름 조회와 검증만 합니다. 그 전제 위에서 답하겠습니다. 먼저 패키징을 합치겠습니다. 명령 2개 실행함, 파일 생성됨, 파일 읽음 명령 2개 실행함, 파일 생성됨, 파일 읽음 1. 합쳤습니다 — 맞는 지적입니다 mihosrc-8.5.5.tgz 하나에 agent/ 와 console/ 이 들어갑니다. 따로 둘 이유가 없었습니다 — 콘솔이 에이전트의 프레임 포맷과 결과 형식을 파싱하니 버전이 어긋나면 조용히 깨집니다. 다만 한 프로세스로 합치지는 않았습니다. 에이전트는 노드마다 하나씩 돌고 작아야 하는데 Node.js 런타임을 관리 대상 서버 전부에 깔 이유가 없습니다. 그리고 콘솔은 서명 개인키를 쥐고 있어서 노드에 두면 오히려 위험합니다. 같이 배포하되 따로 돕니다. 2. 터미널 — 구조는 있는데 구현이 없습니다 frame.h TUNNEL_OPEN(0x20) TUNNEL_OPEN_ACK TUNNEL_DATA(0x22) TUNNEL_CLOSE frame.c 이름 조회 + 길이 검증만 cmd_client.c ← 처리 코드 없음 process_frame 의 switch에 HELLO_ACK , HEARTBEAT_ACK , COMMAND , ERROR 뿐입니다. 설계자가 자리는 비워뒀는데 아직 안 채운 상태 입니다. 헤더에 SESSION_ID 4바이트가 있는 것도 다중화를 염두에 둔 겁니다. 구현하면 이렇게 됩니다: 브라우저 (xterm.js) ↕ WebSocket 콘솔 ↕ TUNNEL_* (기존 mTLS 채널 위에 SESSION_ID 로 다중화) 에이전트 ↕ forkpty() 호스트 셸 노드에 인바운드 포트를 새로 열지 않는다 는 게 핵심입니다. 이미 인증된 아웃바운드 채널을 재사용합니다. SSH를 22번으로 여는 것보다 낫습니다. 3. VNC와 RDP는 계층이 다릅니다 계층 게스트 OS 꺼져도 VNC 콘솔 하이퍼바이저 됩니다 (BIOS·부팅 화면) SSH / RDP 게스트 OS 안 됩니다 Proxmox 화면에서 보신 그 검은 콘솔은 VNC 입니다. /var/run/qemu-server/101.vnc 소켓이 그거고, 스크린샷에도 보입니다. RDP는 하이퍼바이저 기능이 아닙니다. 게스트 안의 Windows가 3389를 여는 거고, 브라우저는 RDP를 못 씁니다. 그래서 중계가 필요합니다: Apache Guacamole — guacd 가 RDP/VNC/SSH를 HTML5로 번역합니다. 표준 답입니다. 우리 터널이 있으면 guacd가 게스트 네트워크에 직접 접근할 필요가 없습니다. 에이전트가 TCP 터널을 뚫어주고 guacd는 로컬로 붙습니다. WireGuard 라우팅을 안 건드려도 됩니다. 권하는 순서 대상 필요한 것 A 호스트 셸 TUNNEL_* + forkpty + xterm.js. 양 끝을 다 통제하니 제일 쉽습니다 B 게스트 VNC A의 터널 위에 바이너리 스트림. noVNC. libvirt/일반 KVM용 C RDP·게스트 SSH A의 TCP 터널 + guacd PVE는 예외로 두는 게 낫습니다. vncproxy 는 티켓 발급과 전용 웹소켓 엔드포인트가 따로 있는데, 그걸 다시 만들 이득이 없습니다. Proxmox noVNC로 딥링크 하면 됩니다 — 이미 pvesh 가 UPID를 주고 있으니 같은 방식으로 URL만 만들면 됩니다. A(호스트 셸)부터 하면 터널 인프라가 생기고 B·C는 그 위에 얹힙니다. 다만 세션 다중화, 흐름 제어, 백프레셔, 세션 정리 를 제대로 해야 해서 지금까지 한 작업들보다 큽니다. A부터 들어갈까요, 아니면 2단계(제어평면 HA)를 먼저 끝낼까요? 둘 다 하려면 순서를 정하는 게 낫습니다 — 터널을 먼저 만들면 릴레이 이중화 때 터널 세션 라우팅까지 같이 풀어야 해서 복잡해집니다.