Skip to content

vitalylerner/reverse-proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Reverse proxy tunnel using WebSocket

A lightweight reverse tunnel solution that allows an internet-isolated computer to access the web through another computer with internet access.

File Names:

  • tunnel_on_b: Server (Computer B - internet-isolated)
  • tunnel_on_a: Client (Computer A - internet-connected)

Problem Statement

Scenario:

  • Computer B: No internet access, has admin rights, can listen on ports
  • Computer A: Has internet access, limited privileges, cannot listen on ports
  • Goal: Enable Computer B to browse the web and access internet services

Traditional solutions don't work because:

  • Computer A can't run a server (no admin rights)
  • Standard proxies require the proxy server to have internet access
  • VPNs require server-side listening, which Computer A can't do

Solution

This project implements a reverse tunnel architecture:

  • Computer B acts as the server (listens on ports)
  • Computer A acts as the client (connects outbound)
  • Traffic flows: B → A → Internet → A → B

Architecture Diagram

┌─────────────────────────────────────────────────────────────┐
│ Computer B (No Internet, Admin Rights)                      │
│ Runs: tunnel_on_b.py                                        │
│                                                              │
│  ┌──────────────┐      ┌───────────────────────────────┐   │
│  │ Applications │─────→│ tunnel_on_b (SOCKS Proxy)     │   │
│  │ (Browser,    │      │ - Listens: 127.0.0.1:3128     │   │
│  │  VS Code)    │      │ - WebSocket: 0.0.0.0:3000     │   │
│  └──────────────┘      └───────────────────────────────┘   │
│                                       ↕                      │
└───────────────────────────────────────────────────────────────┘
                                        │
                        (Local Network Connection)
                                        │
┌─────────────────────────────────────────────────────────────┐
│ Computer A (Internet Access, Limited Privileges)            │
│ Runs: tunnel_on_a.py                                        │
│                                       ↕                      │
│  ┌───────────────────────────────────────────────────┐     │
│  │ tunnel_on_a (Forwarder)                           │     │
│  │ - Connects to tunnel_on_b WebSocket              │     │
│  │ - Forwards requests to internet                   │     │
│  │ - Returns responses                               │     │
│  └───────────────────────────────────────────────────┘     │
│                         ↕                                    │
│  ┌─────────────────────────────────────────┐               │
│  │         Internet / Web Services         │               │
│  └─────────────────────────────────────────┘               │
└─────────────────────────────────────────────────────────────┘

Features

  • SOCKS5 Proxy: Standard protocol, works with browsers and most applications
  • WebSocket Tunnel: Reliable bidirectional communication
  • Automatic Reconnection: A-Client automatically reconnects on connection drop
  • Multiple Connections: Handles concurrent connections efficiently
  • Stream Multiplexing: Multiple requests over a single WebSocket connection
  • Lightweight: Pure Python, minimal dependencies
  • Cross-Platform Ready: Designed for Windows, Linux support planned

Requirements

  • Python 3.7+
  • websockets library (conda install -c conda-forge websockets)
  • Local network connectivity between Computer A and B

Quick Start

1. Configure:

# Copy example settings
copy settings.example.json settings.json  # Windows
cp settings.example.json settings.json    # Linux/Mac

# Edit settings.json with Computer B's IP address
# Update both b_ip_address and b_server_address fields

2. On Computer B (tunnel_on_b - Server):

python tunnel_on_b.py

3. On Computer A (tunnel_on_a - Client):

python tunnel_on_a.py

4. Configure Applications on Computer B:

  • SOCKS Proxy: 127.0.0.1:3128
  • Protocol: SOCKS5

For detailed setup instructions, see SETUP.md.

Project Structure

TempoRemote/
├── README.md                  # Project overview (this file)
├── SETUP.md                   # Detailed setup instructions
├── .gitignore                 # Git ignore rules
├── settings.example.json      # Example configuration (copy to settings.json)
├── settings.json              # Your local configuration (gitignored)
├── tunnel_on_a.py             # Computer A - Client forwarder (with internet)
├── tunnel_on_b.py             # Computer B - Server with SOCKS proxy (isolated)
├── tests/
│   ├── A/                     # Tests for Computer A
│   │   ├── probe.py           # Connectivity diagnostics (A → B)
│   │   └── test_connectivity.py  # Internet access test
│   ├── B/                     # Tests for Computer B
│   │   ├── test_bind.py       # WebSocket port binding test
│   │   └── test_b_local.py    # Local server connectivity test
│   └── utils/                 # Shared utilities
│       └── check_ip.py        # IP address checker
└── .claude/                   # Claude AI configuration
    └── plan.md                # Original project plan

How It Works

Computer B (tunnel_on_b.py - Server)

  1. WebSocket Server (port 3000):

    • Listens for connection from Computer A
    • Maintains persistent connection
    • Multiplexes multiple streams
  2. SOCKS5 Proxy (port 3128):

    • Applications connect here
    • Parses SOCKS5 protocol
    • Forwards requests through WebSocket tunnel to A
  3. Stream Management:

    • Each SOCKS connection gets a unique stream ID
    • Queues responses for each stream
    • Handles connection lifecycle

Computer A (tunnel_on_a.py - Client)

  1. WebSocket Client:

    • Connects to tunnel_on_b's WebSocket server
    • Automatic reconnection on failure
    • Listens for forwarding requests
  2. Internet Forwarder:

    • Receives connection requests from tunnel_on_b
    • Opens TCP connections to destination servers
    • Forwards data bidirectionally
    • Returns responses through tunnel
  3. Connection Pooling:

    • Manages multiple remote connections
    • Buffers requests if connection not yet established
    • Cleans up closed connections

Message Protocol

Messages are JSON-encoded with the following types:

connect (tunnel_on_b → tunnel_on_a)

Request to establish connection to a remote host:

{
  "type": "connect",
  "id": "stream_123",
  "payload": {
    "host": "www.example.com",
    "port": 443
  }
}

request (tunnel_on_b → tunnel_on_a)

Data from SOCKS client to forward:

{
  "type": "request",
  "id": "stream_123",
  "payload": {
    "data": "<base64-encoded-data>",
    "length": 1024
  }
}

response (tunnel_on_a → tunnel_on_b)

Data received from remote server:

{
  "type": "response",
  "id": "stream_123",
  "payload": {
    "data": "<base64-encoded-data>",
    "length": 2048
  }
}

close (tunnel_on_a → tunnel_on_b or tunnel_on_b → tunnel_on_a)

Connection closed:

{
  "type": "close",
  "id": "stream_123"
}

Configuration

All network settings are configured in settings.json. Create this file by copying settings.example.json:

copy settings.example.json settings.json  # Windows
cp settings.example.json settings.json    # Linux/Mac

Configuration Options

{
  "b_server": {
    "websocket_port": 3000,      // Port for WebSocket tunnel
    "socks_port": 3128,           // Port for SOCKS proxy
    "bind_address": "0.0.0.0",   // Address to bind to
    "b_ip_address": "XXX.XXX.XX.XX" // Computer B's IP (for logs)
  },
  "a_client": {
    "b_server_address": "XXX.XXX.XX.X", // Where to connect
    "b_server_port": 3000              // WebSocket port
  },
  "network": {
    "ping_interval": 20,        // WebSocket keepalive (seconds)
    "ping_timeout": 20,         // Ping timeout (seconds)
    "reconnect_delay": 5        // Reconnect delay (seconds)
  }
}

Required Changes:

  • Update b_ip_address with Computer B's actual IP
  • Update b_server_address with Computer B's actual IP

Optional Changes:

  • Adjust ports if 3000 or 3128 are already in use
  • Tune network timeouts based on your network latency

Finding Your IP Address

# Use the included utility
python tests/utils/check_ip.py

# Or use system commands
ipconfig                    # Windows
ip addr show               # Linux
ifconfig                   # Mac/Linux

Testing

Computer A Tests

cd tests/A

# Test connectivity to Computer B
python probe.py

# Test internet access
python test_connectivity.py

Computer B Tests

cd tests/B

# Test WebSocket port binding
python test_bind.py

# Test local server connectivity
python test_b_local.py

Utility Tests

cd tests/utils

# Check IP address
python check_ip.py

Use Cases

  1. Web Browsing: Use Firefox/Chrome with SOCKS proxy on Computer B
  2. VS Code Remote: Connect to remote servers through the tunnel
  3. API Access: Command-line tools with SOCKS support (curl --socks5)
  4. Development: Access cloud services, GitHub, npm registries
  5. Package Managers: pip, conda with proxy configuration

Limitations

  • No Encryption: Traffic between A and B is unencrypted (use on trusted networks only)
  • No Authentication: Anyone on the network can connect to B's WebSocket server
  • Performance: Adds latency due to tunneling overhead
  • Windows-focused: Current version optimized for Windows (Linux support planned)
  • Single Tunnel: One A-Client per B-Server (no load balancing)

Security Considerations

⚠️ Important Security Notes:

  1. Local Network Only: This solution is designed for trusted local networks
  2. No Built-in Encryption: Use only on networks you trust
  3. HTTPS Still Encrypted: End-to-end HTTPS encryption is maintained
  4. Firewall Protection: B's firewall limits external access to port 3000
  5. No Access Control: Anyone who can reach B's WebSocket can use the tunnel

For Production Use:

  • Add TLS encryption to the WebSocket connection
  • Implement authentication (API keys or certificates)
  • Add rate limiting and traffic monitoring
  • Consider using a VPN for additional security

Troubleshooting

Issue Solution
"Connection refused" Verify B-Server is running, check IP address in a_client.py
"Address already in use" Kill existing process: netstat -ano | findstr :3000 then taskkill /PID <PID> /F
No internet through tunnel Check SOCKS proxy settings, verify A-Client has internet
Firewall blocking Run PowerShell as admin: New-NetFirewallRule -DisplayName "WebSocket Tunnel Port 3000" -Direction Inbound -LocalPort 3000 -Protocol TCP -Action Allow

For detailed troubleshooting, see SETUP.md.

Performance

  • Latency: ~10-50ms overhead (local network)
  • Throughput: Limited by local network speed (typically 100Mbps - 1Gbps)
  • Concurrent Connections: Tested with 10+ simultaneous connections
  • Memory Usage: ~20-50MB per process

Future Enhancements

  • TLS encryption for WebSocket tunnel
  • Authentication mechanism
  • HTTP CONNECT proxy support (in addition to SOCKS)
  • Web dashboard for monitoring
  • Linux compatibility testing
  • Multiple A-Client support (load balancing)
  • Bandwidth throttling and QoS
  • Connection statistics and logging

Contributing

This is a personal project currently in active development. Feel free to:

  • Report issues
  • Suggest improvements
  • Fork and modify for your use case

License

This project is provided as-is for personal and educational use.

Acknowledgments

Inspired by reverse tunneling tools like:

  • ngrok - Secure tunnels to localhost
  • frp - Fast reverse proxy
  • chisel - Fast TCP/UDP tunnel over HTTP
  • SSH reverse tunneling - The OG reverse tunnel

Built with:

  • Python 3 - Core language
  • websockets - WebSocket implementation
  • asyncio - Asynchronous I/O

Documentation:

Quick Links: