- 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>
249 lines
6.8 KiB
Markdown
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**: 최신 버전 |