headscale-tailscale-replace.../farmq-admin/VNC_Implementation_Technical_Documentation.md
시골약사 fb00b0a5fd Add multi-host Proxmox support with SSL certificate handling
- Added support for multiple Proxmox hosts (pve7.0bin.in:443, Healthport PVE:8006)
- Enhanced VM management APIs to accept host parameter
- Fixed WebSocket URL generation bug (dynamic port handling)
- Added comprehensive SSL certificate trust help system
- Implemented host selection dropdown in UI
- Added VNC connection failure detection and automatic SSL help redirection
- Updated session management to store host_key information
- Enhanced error handling for different Proxmox configurations

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-13 00:03:25 +09:00

249 lines
6.8 KiB
Markdown

# VNC 웹소켓 구현 기술 문서
## Proxmox API를 이용한 noVNC 통합 가이드
### 📋 개요
이 문서는 Proxmox VE API를 활용하여 웹 브라우저에서 직접 가상머신에 VNC 접속할 수 있는 시스템의 기술적 구현 내용을 설명합니다. Flask 백엔드와 noVNC 클라이언트를 통해 브라우저에서 직접 VM 콘솔에 접근할 수 있도록 구현되었습니다.
### 🏗️ 시스템 아키텍처
```
[웹 브라우저]
↓ HTTPS
[NPM 리버스 프록시]
↓ HTTP
[Flask 애플리케이션]
↓ HTTPS API
[Proxmox VE 서버]
↓ WebSocket (WSS)
[VM VNC 서버]
```
### 🔧 핵심 구성요소
#### 1. Proxmox API 클라이언트 (`utils/proxmox_client.py`)
**주요 기능:**
- Proxmox VE API 인증 및 세션 관리
- VNC 티켓 생성 및 WebSocket URL 생성
- VM 상태 관리 (시작/정지/상태확인)
**핵심 구현:**
```python
def get_vnc_ticket(self, node: str, vmid: int) -> Optional[Dict]:
"""VNC 접속 티켓 생성"""
data = {
'websocket': '1',
'generate-password': '1' # 자동 패스워드 생성
}
response = self.session.post(
f"{self.base_url}/nodes/{node}/qemu/{vmid}/vncproxy",
data=data,
timeout=10
)
if response.status_code == 200:
vnc_data = response.json()['data']
encoded_ticket = quote_plus(vnc_data['ticket'])
vnc_data['websocket_url'] = f"wss://{self.host}:443/api2/json/nodes/{node}/qemu/{vmid}/vncwebsocket?port={vnc_data['port']}&vncticket={encoded_ticket}"
return vnc_data
```
**인증 방식:**
- 세션 쿠키 방식 (PVEAuthCookie)
- CSRF 토큰 헤더 (CSRFPreventionToken)
- API 토큰 방식 지원
#### 2. Flask 웹 애플리케이션 (`app.py`)
**주요 엔드포인트:**
- `/vnc/<int:vm_id>`: VNC 클라이언트 페이지 렌더링
- API 엔드포인트들을 통한 VM 관리
**로깅 시스템:**
```python
def setup_logging():
if not os.path.exists('logs'):
os.makedirs('logs')
file_handler = RotatingFileHandler(
'logs/farmq-admin.log',
maxBytes=10*1024*1024,
backupCount=5
)
```
#### 3. noVNC 클라이언트 (`templates/vnc_simple.html`)
**핵심 기능:**
- WebSocket을 통한 VNC 프로토콜 처리
- 자동 리사이징 및 스케일링
- HTML 엔티티 디코딩 (패스워드 처리)
**WebSocket 연결 코드:**
```javascript
function connectVNC() {
const rfb = new RFB(document.getElementById('screen'), websocketUrl, {
credentials: {
password: decodeHtmlEntities('{{ vnc_data.password }}')
}
});
rfb.addEventListener("connect", () => {
console.log("VNC 연결 성공");
resizeScreen();
});
rfb.addEventListener("disconnect", (e) => {
console.log(`VNC 연결 종료: ${e.detail.clean ? '정상' : '비정상'}`);
});
}
```
**HTML 엔티티 디코딩:**
```javascript
function decodeHtmlEntities(text) {
const textarea = document.createElement('textarea');
textarea.innerHTML = text;
return textarea.value;
}
```
### 🔐 보안 및 인증
#### VNC 인증 플로우
1. **티켓 요청**: Flask → Proxmox API (`/vncproxy`)
2. **티켓 생성**: Proxmox가 일회용 VNC 티켓 및 패스워드 생성
3. **WebSocket 연결**: 브라우저 → Proxmox VNC WebSocket
4. **VNC 인증**: 생성된 패스워드로 VNC 서버 인증
#### 보안 설정
```python
# SSL 검증 무시 (내부 네트워크)
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
self.session.verify = False
# WebSocket URL에 티켓 인코딩
encoded_ticket = quote_plus(vnc_data['ticket'])
```
### 🌐 네트워크 구성
#### NPM (Nginx Proxy Manager) 설정
- **외부 도메인**: `https://pve7.0bin.in`
- **내부 주소**: `https://192.168.0.5:8006`
- **WebSocket 지원**: Upgrade 헤더 프록시 필요
#### WebSocket 프록시 요구사항
```nginx
# WebSocket 업그레이드 헤더
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
```
### ⚡ 성능 최적화
#### Canvas 자동 리사이징
```javascript
function resizeScreen() {
const canvas = document.querySelector('#screen canvas');
if (canvas) {
const container = document.getElementById('screen');
const scaleX = container.clientWidth / canvas.width;
const scaleY = container.clientHeight / canvas.height;
const scale = Math.min(scaleX, scaleY, 1);
canvas.style.transform = `scale(${scale})`;
canvas.style.transformOrigin = 'top left';
}
}
```
#### 연결 상태 관리
- 자동 재연결 로직
- 연결 품질 모니터링
- 에러 처리 및 사용자 피드백
### 🐛 문제 해결 가이드
#### 일반적인 문제들
**1. WebSocket 1006 에러 (비정상 연결 종료)**
- **원인**: NPM 프록시 WebSocket 설정 부족
- **해결**: WebSocket 업그레이드 헤더 설정 확인
**2. VNC 인증 실패 (HTTP 401)**
- **원인**: 잘못된 티켓 또는 패스워드
- **해결**: `generate-password: 1` 설정 확인
**3. 빈 화면 또는 검은 화면**
- **원인**: Canvas 리사이징 문제
- **해결**: `resizeScreen()` 함수 호출 확인
**4. HTML 엔티티 문제**
- **원인**: 패스워드의 특수문자 인코딩
- **해결**: `decodeHtmlEntities()` 함수 적용
#### 디버깅 도구
**1. 서버 사이드 테스트**
```bash
cd /srv/headscale-setup/farmq-admin
python test_vnc_websocket.py
```
**2. 로그 확인**
```bash
tail -f logs/farmq-admin.log
```
**3. 브라우저 개발자 도구**
- Network 탭: WebSocket 연결 상태 확인
- Console 탭: JavaScript 에러 확인
### 📊 모니터링 및 로깅
#### 로그 레벨
- **INFO**: 정상 동작 로그
- **WARNING**: 경고사항
- **ERROR**: 오류 발생
- **DEBUG**: 상세 디버깅 정보
#### 중요 로그 포인트
- VNC 티켓 생성 성공/실패
- WebSocket 연결 시도
- VNC 인증 결과
- 연결 종료 사유
### 🔄 배포 및 유지보수
#### 배포 체크리스트
- [ ] Proxmox API 연결 테스트
- [ ] Flask 애플리케이션 시작 확인
- [ ] NPM 프록시 설정 검증
- [ ] WebSocket 연결 테스트
- [ ] VNC 클라이언트 동작 확인
#### 백업 및 복구
```bash
# Git 커밋 상태 확인
git log --oneline -10
# 안정된 버전으로 롤백
git reset --hard 1dc09101cc7afdf09ca3b8cbbc4f95e21bb5746f
```
### 📚 참고 자료
- [Proxmox VE API 문서](https://pve.proxmox.com/pve-docs/api-viewer/)
- [noVNC 프로젝트](https://github.com/novnc/noVNC)
- [WebSocket RFC 6455](https://tools.ietf.org/html/rfc6455)
- [VNC 프로토콜 스펙](https://tools.ietf.org/html/rfc6143)
### 🏷️ 버전 정보
- **프로젝트**: FarmQ Admin VNC Integration
- **마지막 업데이트**: 2024년
- **안정 버전**: commit `1dc09101cc7afdf09ca3b8cbbc4f95e21bb5746f`
- **Python**: 3.x
- **Flask**: 최신 안정 버전
- **noVNC**: 최신 버전