react-vnc-lib
v1.3.4
Published
A modern, lightweight VNC client library for React, Next.js, Node.js, and Bun with TypeScript support
Maintainers
Readme
React VNC Library 🖥️
A modern, lightweight VNC client library for React applications with working VNC authentication!
✨ Key Features
- 🎯 Working VNC Authentication - RFC 6143 compliant with proper DES implementation
- ⚡ WebSocket Support - Real-time VNC connections over WebSocket
- 🔒 Secure - Supports both VNC authentication and "None" security types
- 🌐 Hetzner Compatible - Tested with Hetzner VNC web console
- 📱 Responsive - Auto-scaling and touch/mouse input support
- 🎨 Modern React - Hooks-based API with TypeScript support
- 🔧 Flexible - Works with any VNC server (TightVNC, RealVNC, etc.)
🚀 Quick Start
Installation
npm install react-vnc-lib
# or
yarn add react-vnc-libBasic Usage
import React from 'react';
import { useVNC } from 'react-vnc-lib';
function VNCViewer() {
const { connect, disconnect, state, canvasRef } = useVNC({
url: 'wss://your-vnc-server.com/websockify',
password: 'your-vnc-password', // Now works properly!
viewOnly: false,
scale: 1.0,
debug: true
});
return (
<div>
<div>
<button onClick={connect} disabled={state.connecting || state.connected}>
Connect
</button>
<button onClick={disconnect} disabled={!state.connected}>
Disconnect
</button>
<p>Status: {state.connected ? 'Connected' : state.connecting ? 'Connecting' : 'Disconnected'}</p>
{state.error && <p>Error: {state.error}</p>}
</div>
<canvas
ref={canvasRef}
width={state.width}
height={state.height}
style={{ border: '1px solid #ccc', maxWidth: '100%', height: 'auto' }}
/>
</div>
);
}
export default VNCViewer;🎯 Authentication Status: FIXED ✅
This library now has properly working VNC authentication based on RFC 6143 compliance! Here's what was fixed:
RFC 6143 Compliance ✅
- ✅ Implements proper DES encryption with bit reversal from RFC 6143 Errata ID 4951
- ✅ Full DES implementation based on proven VNC clients (noVNC, established implementations)
- ✅ Proper challenge/response handling following Vidar Holen's VNC DES analysis
- ✅ Binary WebSocket frame support
Tested Compatibility ✅
- ✅ Hetzner VNC Web Console (Now works with proper DES!)
- ✅ TightVNC Servers
- ✅ RealVNC Servers
- ✅ Standard VNC Authentication (Security Type 2)
- ✅ No Authentication (Security Type 1)
📋 Configuration Options
interface VNCClientOptions {
url: string; // WebSocket URL (ws:// or wss://)
username?: string; // Optional username (for future auth types)
password?: string; // VNC password (now works properly!)
viewOnly?: boolean; // Read-only mode (default: false)
quality?: number; // Image quality 1-10 (default: 6)
compression?: number; // Compression level 1-10 (default: 2)
autoResize?: boolean; // Auto resize canvas (default: true)
scale?: number; // Display scale factor (default: 1.0)
timeout?: number; // Connection timeout ms (default: 10000)
debug?: boolean; // Enable debug logging (default: false)
}🔧 Advanced Usage
Connection Management
import { VNCClient } from 'react-vnc-lib';
// Direct VNC client usage
const client = new VNCClient({
url: 'wss://vnc.example.com/websockify',
password: 'secret123',
debug: true
});
// Event handling
client.on('connected', () => console.log('VNC Connected!'));
client.on('disconnected', () => console.log('VNC Disconnected'));
client.on('error', (event) => console.error('VNC Error:', event.data.message));
// Connect
await client.connect();
// Send input
client.sendKeyEvent({ key: 'Enter', down: true, code: 'Enter' });
client.sendPointerEvent({ x: 100, y: 100, buttons: 1 });
// Disconnect
client.disconnect();Error Handling
function VNCViewer() {
const { connect, state } = useVNC({
url: 'wss://vnc.example.com/websockify',
password: 'secret'
});
const handleConnect = async () => {
try {
await connect();
} catch (error) {
console.error('Connection failed:', error.message);
// Handle specific error types
if (error.message.includes('Authentication failed')) {
alert('Invalid password');
} else if (error.message.includes('Connection timeout')) {
alert('Server not reachable');
}
}
};
return (
<div>
<button onClick={handleConnect}>Connect</button>
{state.error && <p style={{color: 'red'}}>Error: {state.error}</p>}
</div>
);
}🐛 Troubleshooting
Common Issues
Authentication Fails
Enable debug mode and check console for challenge/response hex values Ensure password is correct and server supports VNC AuthenticationConnection Refused
Check WebSocket URL format (ws:// or wss://) Verify server is running and accessible Check for CORS issues in browserWebSocket Close Codes
1006: Connection lost unexpectedly 1003: Server rejected connection due to invalid data 1002: Protocol error
Debug Mode
Enable debug logging to see detailed connection information:
const { connect } = useVNC({
url: 'wss://vnc.example.com/websockify',
password: 'secret',
debug: true // Enables detailed console logging
});🏗️ Architecture
VNC Protocol Flow
- WebSocket Connection - Establish WebSocket to VNC server
- Version Handshake - Negotiate RFB protocol version (3.8)
- Security Negotiation - Choose authentication method
- Authentication - VNC password authentication with DES encryption
- Initialization - Exchange client/server capabilities
- Protocol Messages - Framebuffer updates, input events, etc.
DES Implementation
This library uses a proper DES implementation for VNC that:
- Implements correct bit reversal (RFC 6143 Errata ID 4951)
- Uses full DES algorithm with standard S-boxes and permutations
- Based on proven working VNC client implementations (noVNC, established clients)
- Maintains RFC 6143 compliance and compatibility with all major VNC servers
📜 License
MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- RFC 6143 specification authors
- VNC community for protocol documentation
- RFC 6143 Errata ID 4951 for the critical bit reversal fix
- Vidar Holen's VNC DES analysis for documenting the VNC DES quirks
- Dave Zimmerman and Jef Poskanzer for DES implementation guidance
- Open source VNC implementations for reference
Note: This library implements VNC authentication correctly based on RFC 6143 with the required errata fixes. Previous versions had authentication issues that are now resolved in v1.3.0+.
Features
- 🚀 Modern TypeScript - Full type safety and modern ES2020+ features
- ⚡ Minimal Dependencies - Zero runtime dependencies, React as optional peer dependency
- 🎯 WebSocket Based - Real-time VNC protocol over WebSocket
- 🖱️ Full Input Support - Keyboard and mouse event handling
- 📱 Responsive - Canvas-based rendering with scaling support
- 🔧 Configurable - Extensive customization options
- 🎨 React Components - Ready-to-use React hook and component
Installation
# With npm
npm install react-vnc-lib
# With yarn
yarn add react-vnc-lib
# With pnpm
pnpm add react-vnc-lib
# With bun
bun add react-vnc-libPeer Dependencies
For React usage, install the peer dependencies:
npm install react react-domQuick Start
React Component Usage
import React from 'react';
import { VNCViewer } from 'react-vnc-lib';
function App() {
return (
<div className="App">
<VNCViewer
url="ws://localhost:6080"
autoConnect={true}
scale={0.8}
viewOnly={false}
showStatus={true}
/>
</div>
);
}
export default App;React Hook Usage
import React from 'react';
import { useVNC } from 'react-vnc-lib';
function CustomVNCViewer() {
const {
state,
connect,
disconnect,
canvasRef,
error,
loading
} = useVNC({
url: 'ws://localhost:6080',
autoConnect: true,
debug: true
});
return (
<div>
<div>Status: {state.connected ? 'Connected' : 'Disconnected'}</div>
{error && <div>Error: {error}</div>}
<canvas ref={canvasRef} />
<button onClick={connect} disabled={loading}>
Connect
</button>
<button onClick={disconnect}>
Disconnect
</button>
</div>
);
}Vanilla JavaScript / Node.js Usage
import { VNCClient } from 'react-vnc-lib';
const client = new VNCClient({
url: 'ws://localhost:6080',
username: 'user',
password: 'password',
debug: true
});
// Set up event listeners
client.on('connected', () => {
console.log('Connected to VNC server');
});
client.on('error', (event) => {
console.error('VNC Error:', event.data.message);
});
client.on('framebuffer-update', (event) => {
console.log('Received framebuffer update');
// Handle framebuffer data
});
// Connect
await client.connect();
// Send keyboard input
client.sendKeyEvent({
key: 'a',
code: 'KeyA',
down: true
});
// Send mouse input
client.sendPointerEvent({
x: 100,
y: 100,
buttons: 1
});
// Disconnect
client.disconnect();API Reference
VNCClient
Main VNC client class for establishing connections and handling protocol communication.
Constructor
new VNCClient(options: VNCClientOptions)Options
interface VNCClientOptions {
url: string; // WebSocket URL to VNC server
username?: string; // Username for authentication
password?: string; // Password for authentication
viewOnly?: boolean; // Enable view-only mode (default: false)
quality?: number; // Quality setting 0-9 (default: 6)
compression?: number; // Compression level 0-9 (default: 2)
autoResize?: boolean; // Auto-resize canvas (default: true)
scale?: number; // Scale factor 0.1-2.0 (default: 1.0)
timeout?: number; // Connection timeout ms (default: 10000)
debug?: boolean; // Enable debug logging (default: false)
}Methods
connect(): Promise<void>- Connect to VNC serverdisconnect(): void- Disconnect from serversendKeyEvent(event: VNCKeyEvent): void- Send keyboard eventsendPointerEvent(event: VNCPointerEvent): void- Send mouse eventrequestFramebufferUpdate(incremental?: boolean): void- Request screen updategetState(): VNCConnectionState- Get current connection stateon(event: string, handler: VNCEventHandler): void- Add event listeneroff(event: string, handler: VNCEventHandler): void- Remove event listener
useVNC Hook
React hook for VNC client integration.
const vncState = useVNC(options: UseVNCOptions);Returns
interface UseVNCReturn {
client: VNCClient | null;
state: VNCConnectionState;
connect: () => Promise<void>;
disconnect: () => void;
sendKeyEvent: (event: VNCKeyEvent) => void;
sendPointerEvent: (event: VNCPointerEvent) => void;
requestUpdate: (incremental?: boolean) => void;
canvasRef: React.RefObject<HTMLCanvasElement>;
error: string | null;
loading: boolean;
}VNCViewer Component
Ready-to-use React component with built-in UI.
<VNCViewer
url="ws://localhost:6080"
autoConnect={true}
showStatus={true}
className="my-vnc-viewer"
style={{ width: '100%', height: '500px' }}
/>Props
All VNCClientOptions plus:
className?: string- Custom CSS classstyle?: React.CSSProperties- Custom stylesshowStatus?: boolean- Show connection status (default: true)showLoading?: boolean- Show loading indicator (default: true)disableKeyboard?: boolean- Disable keyboard inputdisableMouse?: boolean- Disable mouse inputautoFocus?: boolean- Auto-focus canvas (default: true)connectButtonText?: string- Custom connect button textdisconnectButtonText?: string- Custom disconnect button text
Events
The VNC client emits the following events:
connecting- Connection attempt startedconnected- Successfully connecteddisconnected- Connection closederror- Connection or protocol errorframebuffer-update- Screen update receivedserver-cut-text- Clipboard data from serverbell- Bell/beep from serverresize- Server resolution changed
Advanced Usage
Custom Authentication
const client = new VNCClient({
url: 'ws://localhost:6080',
username: 'admin',
password: 'secretpassword'
});High Quality Mode
const client = new VNCClient({
url: 'ws://localhost:6080',
quality: 9, // Highest quality
compression: 0 // No compression
});Mobile/Touch Support
<VNCViewer
url="ws://localhost:6080"
scale={0.5} // Scale down for mobile
autoResize={true} // Auto-resize to fit
disableKeyboard={true} // Disable for touch-only
/>Server Setup
This library connects to VNC servers via WebSocket. You'll need a WebSocket-to-VNC proxy such as:
- websockify
- noVNC proxy
- Custom WebSocket proxy
Example with websockify:
# Install websockify
pip install websockify
# Start proxy (connects WS port 6080 to VNC port 5900)
websockify 6080 localhost:5900Browser Compatibility
- Chrome/Chromium 80+
- Firefox 75+
- Safari 13+
- Edge 80+
Node.js Compatibility
- Node.js 16+
- Bun 1.0+
Development
# Clone repository
git clone https://github.com/sepandy/react-vnc-lib.git
cd react-vnc-lib
# Install dependencies
npm install
# Start development mode
npm run dev
# Build library
npm run build
# Run tests
npm test
# Lint code
npm run lintContributing
Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
See CHANGELOG.md for a list of changes.
Support
Acknowledgments
- Inspired by noVNC
- Built with modern TypeScript and React best practices
