WebSocket 1006 오류로 인해 브라우저에서 VNC 연결 실패 - 서버 환경에서는 연결 가능하나 브라우저 보안 정책으로 차단 - 역방향 프록시 솔루션 문서화 완료 - 추후 nginx 프록시 구현 필요 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
8.1 KiB
8.1 KiB
VNC WebSocket 연결 문제 및 프록시 솔루션
🚨 현재 문제 상황
WebSocket 1006 연결 실패 원인
WebSocket connection to 'wss://pve7.0bin.in/api2/json/nodes/pve7/qemu/102/vncwebsocket...' failed:
Failed when connecting: Connection closed (code: 1006)
WebSocket Error Code 1006는 "Abnormal Closure"를 의미하며, 연결이 설정되기도 전에 종료되었음을 나타냅니다.
🔍 근본 원인 분석
1. 브라우저 보안 정책 (Mixed Content)
- 현재 상황: HTTPS 웹사이트 (
pqadmin.0bin.in)에서 자체 서명 인증서를 사용하는 WebSocket 연결 시도 - 브라우저 제한: Chrome, Firefox 등 모던 브라우저는 HTTPS 페이지에서 신뢰할 수 없는 SSL 인증서로의 WebSocket 연결을 자동 차단
- 에러 발생: 브라우저가 연결 시도 자체를 거부하여 1006 에러 발생
2. SSL/TLS 인증서 신뢰 문제
# Proxmox 서버의 자체 서명 인증서
Subject: CN=Proxmox Virtual Environment
Issuer: PVE Cluster Manager CA
- 자체 서명 인증서:
pve7.0bin.in이 공인 CA가 아닌 자체 서명 인증서 사용 - 브라우저 불신: 사용자가 명시적으로 인증서를 신뢰하지 않으면 WebSocket 연결 거부
3. CORS (Cross-Origin Resource Sharing) 정책
- Origin 불일치:
pqadmin.0bin.in에서pve7.0bin.in으로의 크로스 오리진 WebSocket 연결 - Preflight 검사: 브라우저가 연결 전 OPTIONS 요청을 보내지만 Proxmox가 적절한 CORS 헤더를 반환하지 않을 가능성
💡 해결책 1: 역방향 프록시 (Reverse Proxy)
구현 방식: nginx를 통한 WebSocket 프록시
# /etc/nginx/sites-available/pqadmin-vnc
server {
listen 443 ssl;
server_name pqadmin.0bin.in;
ssl_certificate /path/to/ssl/cert.pem;
ssl_certificate_key /path/to/ssl/key.pem;
# VNC WebSocket 프록시
location /vnc-proxy/ {
# WebSocket 업그레이드 헤더
proxy_pass https://pve7.0bin.in/api2/json/nodes/pve7/qemu/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $proxy_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# SSL 검증 비활성화 (자체 서명 인증서 때문)
proxy_ssl_verify off;
proxy_ssl_server_name on;
# 타임아웃 설정
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
장점
- ✅ 같은 도메인:
pqladmin.0bin.in/vnc-proxy/로 WebSocket 연결하여 CORS 문제 해결 - ✅ 신뢰할 수 있는 SSL: nginx가 공인 인증서를 사용하여 브라우저 신뢰 확보
- ✅ 투명한 프록시: 클라이언트는 Proxmox 직접 연결과 동일하게 작동
구현 단계
# 1. nginx 설정 파일 생성
sudo nano /etc/nginx/sites-available/pqadmin-vnc
# 2. 심볼릭 링크 생성
sudo ln -s /etc/nginx/sites-available/pqadmin-vnc /etc/nginx/sites-enabled/
# 3. nginx 설정 테스트
sudo nginx -t
# 4. nginx 재시작
sudo systemctl reload nginx
클라이언트 코드 수정
// 기존: 직접 Proxmox 연결
// const websocketUrl = 'wss://pve7.0bin.in/api2/json/nodes/pve7/qemu/102/vncwebsocket?...'
// 변경: nginx 프록시를 통한 연결
const websocketUrl = 'wss://pqladmin.0bin.in/vnc-proxy/102/vncwebsocket?...'
💡 해결책 2: WebSocket 프록시 서버
구현 방식: Node.js/Python WebSocket 중계 서버
# vnc_websocket_proxy.py
import asyncio
import websockets
import ssl
import json
from urllib.parse import parse_qs
class VNCWebSocketProxy:
def __init__(self):
self.proxmox_host = "pve7.0bin.in"
self.proxmox_port = 443
async def proxy_websocket(self, websocket, path):
# 클라이언트 요청 파싱
query_params = parse_qs(path.split('?', 1)[1] if '?' in path else '')
vmid = query_params.get('vmid', [''])[0]
ticket = query_params.get('vncticket', [''])[0]
# Proxmox WebSocket URL 생성
proxmox_url = f"wss://{self.proxmox_host}:{self.proxmox_port}/api2/json/nodes/pve7/qemu/{vmid}/vncwebsocket?port=5900&vncticket={ticket}"
# SSL 컨텍스트 (자체 서명 인증서 허용)
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
try:
# Proxmox WebSocket 연결
async with websockets.connect(proxmox_url, ssl=ssl_context) as proxmox_ws:
# 양방향 데이터 중계
await asyncio.gather(
self.forward_messages(websocket, proxmox_ws),
self.forward_messages(proxmox_ws, websocket)
)
except Exception as e:
await websocket.send(json.dumps({"error": f"Proxmox connection failed: {str(e)}"}))
async def forward_messages(self, source, destination):
try:
async for message in source:
await destination.send(message)
except websockets.exceptions.ConnectionClosed:
pass
# 프록시 서버 시작
if __name__ == "__main__":
proxy = VNCWebSocketProxy()
start_server = websockets.serve(proxy.proxy_websocket, "0.0.0.0", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
장점
- ✅ 완전한 제어: WebSocket 연결 과정을 완전히 제어 가능
- ✅ 에러 처리: 연결 실패 시 상세한 에러 메시지 제공
- ✅ 로깅: 모든 WebSocket 트래픽 로깅 및 디버깅 가능
- ✅ 인증 확장: 추가적인 인증 로직 구현 가능
구현 단계
# 1. 의존성 설치
pip install websockets asyncio
# 2. 프록시 서버 실행
python vnc_websocket_proxy.py
# 3. systemd 서비스 등록
sudo systemctl enable vnc-websocket-proxy.service
클라이언트 코드 수정
// WebSocket 프록시 서버로 연결
const websocketUrl = 'ws://localhost:8765/vnc-proxy?vmid=102&vncticket=' + encodeURIComponent(ticket);
📊 솔루션 비교
| 기준 | 역방향 프록시 (nginx) | WebSocket 프록시 서버 |
|---|---|---|
| 구현 복잡도 | 🟡 중간 | 🔴 높음 |
| 성능 | 🟢 우수 | 🟡 양호 |
| 유지보수 | 🟢 쉬움 | 🟡 보통 |
| 확장성 | 🟡 제한적 | 🟢 우수 |
| 디버깅 | 🟡 제한적 | 🟢 우수 |
| 보안 | 🟢 안전 | 🟡 주의 필요 |
| 리소스 사용량 | 🟢 낮음 | 🟡 보통 |
🎯 추천 솔루션
단기 해결책: 역방향 프록시 (nginx)
- 빠른 구현: 기존 nginx 설정에 location 블록만 추가
- 안정성: nginx의 검증된 WebSocket 프록시 기능 활용
- 보안: 공인 SSL 인증서로 브라우저 신뢰 확보
장기 해결책: 하이브리드 접근
- nginx 프록시: 기본적인 WebSocket 중계
- 커스텀 미들웨어: 인증, 로깅, 모니터링 기능 추가
- 로드 밸런싱: 다중 Proxmox 호스트 지원
🚀 구현 우선순위
Phase 1: nginx 역방향 프록시 구현
# 1. nginx 설정 파일 작성
# 2. SSL 인증서 설정
# 3. WebSocket 프록시 규칙 추가
# 4. 클라이언트 URL 변경
Phase 2: 에러 처리 및 모니터링 강화
# 1. 연결 실패 시 재시도 로직
# 2. WebSocket 상태 모니터링
# 3. 로그 수집 및 분석
Phase 3: 다중 호스트 지원
# 1. 동적 백엔드 라우팅
# 2. 헬스체크 구현
# 3. 로드 밸런싱 설정
결론: WebSocket 1006 에러는 브라우저 보안 정책과 인증서 신뢰 문제가 주요 원인입니다. nginx 역방향 프록시를 통해 이 문제를 근본적으로 해결할 수 있으며, 이는 가장 실용적이고 안정적인 솔루션입니다.