WebSocket-to-Stratum Proxy Setup

Why You Need a Proxy

Important: Most Monero mining pools (including SupportXMR, MoneroOcean, etc.) use the TCP Stratum protocol, not WebSocket. Browsers cannot make direct TCP connections due to security restrictions, so WebMiner requires a WebSocket-to-Stratum proxy to bridge the connection.

The Problem

Browser (WebMiner) --[WebSocket]--> ❌ --[TCP Stratum]--> Mining Pool
                                   Cannot connect directly!

The Solution

Browser (WebMiner) --[WebSocket]--> Proxy --[TCP Stratum]--> Mining Pool
                                     ✅ Bridges the protocols

Quick Setup with Node.js Proxy

1. Install Dependencies

mkdir webminer-proxy
cd webminer-proxy
npm init -y
npm install ws net

2. Create Proxy Server (proxy.js)

const WebSocket = require('ws');
const net = require('net');

const WS_PORT = 8080;  // WebSocket port for browsers
const POOL_HOST = 'gulf.moneroocean.stream';  // Stratum pool
const POOL_PORT = 10128;  // Stratum port

const wss = new WebSocket.Server({ port: WS_PORT });

console.log(WebSocket-to-Stratum proxy listening on ws://localhost:${WS_PORT});
console.log(Forwarding to ${POOLHOST}:${POOLPORT});

wss.on('connection', (ws) => {
    console.log('Browser client connected');
    
    // Create TCP connection to pool
    const poolSocket = net.connect(POOLPORT, POOLHOST, () => {
        console.log('Connected to mining pool');
    });
    
    // Forward WebSocket messages to pool
    ws.on('message', (data) => {
        console.log('Browser -> Pool:', data.toString());
        poolSocket.write(data + '\n');
    });
    
    // Forward pool messages to browser
    poolSocket.on('data', (data) => {
        const lines = data.toString().split('\n').filter(line => line.trim());
        lines.forEach(line => {
            console.log('Pool -> Browser:', line);
            ws.send(line);
        });
    });
    
    // Handle disconnections
    ws.on('close', () => {
        console.log('Browser disconnected');
        poolSocket.end();
    });
    
    poolSocket.on('close', () => {
        console.log('Pool disconnected');
        ws.close();
    });
    
    poolSocket.on('error', (err) => {
        console.error('Pool connection error:', err.message);
        ws.close();
    });
});

3. Start the Proxy

node proxy.js

4. Configure WebMiner

<script src="webminer.js" 
        data-pool="ws://localhost:8080"
        data-wallet="YOURMONEROADDRESS"
        data-throttle="0.25">
</script>

Production Deployment

Using SSL/TLS (Recommended)

For production, use wss:// (secure WebSocket):
const https = require('https');
const fs = require('fs');

const server = https.createServer({
    cert: fs.readFileSync('/path/to/cert.pem'),
    key: fs.readFileSync('/path/to/key.pem')
});

const wss = new WebSocket.Server({ server });
server.listen(443);
Then update WebMiner config:
<script src="webminer.js" 
        data-pool="wss://your-proxy.example.com"
        data-wallet="YOURMONEROADDRESS"
        data-throttle="0.25">
</script>

Popular Mining Pools

MoneroOcean (Best for WebMining)

- 10001 (Auto-diff)

- 10128 (128000 fixed diff) - 20001 / 20128 (SSL)

SupportXMR

- 3333 (Low-end hardware)

- 5555 (Mid-range) - 7777 (High-end) - 9000+ (SSL)

Nanopool

Docker Deployment

Dockerfile

FROM node:18-alpine
WORKDIR /app
COPY package.json proxy.js ./
RUN npm install --production
EXPOSE 8080
CMD ["node", "proxy.js"]

Build and Run

docker build -t webminer-proxy .
docker run -d -p 8080:8080 --name proxy webminer-proxy

Environment Variables

Make the proxy configurable:
const WSPORT = process.env.WSPORT || 8080;
const POOLHOST = process.env.POOLHOST || 'gulf.moneroocean.stream';
const POOLPORT = process.env.POOLPORT || 10128;
Run with custom pool:
POOLHOST=pool.supportxmr.com POOLPORT=3333 node proxy.js

Security Considerations

1. Rate Limiting

const rateLimit = require('express-rate-limit');
// Limit each IP to 100 requests per minute

2. Origin Validation

wss.on('connection', (ws, req) => {
    const origin = req.headers.origin;
    const allowedOrigins = ['https://yoursite.com'];
    
    if (!allowedOrigins.includes(origin)) {
        ws.close();
        return;
    }
    // ... rest of connection logic
});

3. Connection Limits

let activeConnections = 0;
const MAX_CONNECTIONS = 1000;

wss.on('connection', (ws) => {
    if (activeConnections >= MAX_CONNECTIONS) {
        ws.close();
        return;
    }
    activeConnections++;
    
    ws.on('close', () => {
        activeConnections--;
    });
});

Monitoring

Log Mining Statistics

let stats = {
    connections: 0,
    shares: 0,
    errors: 0
};

setInterval(() => {
    console.log('Stats:', stats);
}, 60000); // Every minute

Troubleshooting

Connection Fails Immediately

High Latency

WebSocket Drops

ws.on('pong', () => {

ws.isAlive = true; });

setInterval(() => { wss.clients.forEach((ws) => { if (!ws.isAlive) return ws.terminate(); ws.isAlive = false; ws.ping(); }); }, 30000);

Alternative: Public Proxy Services

⚠️ Not recommended for production - Use only for testing If you don't want to host your own proxy, some public services exist (use at your own risk):

Cost Estimates

Self-Hosting

Bandwidth Usage


Next Steps:
  • Set up your proxy following this guide
  • Test with local ws://localhost:8080 connection
  • Deploy to production with SSL (wss://)
  • Monitor performance and adjust pool/ports as needed
  • Need Help? Open an issue on the WebMiner GitHub repository with your proxy setup details.