Skip to content

FlatFilers/tunnel-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SSH Tunnel Through Jump Host

This script demonstrates how to create an SSH tunnel to a remote resource by first connecting through a jump host (also known as a bastion host). Optionally, you can route the connection through a SOCKS proxy first.

Architecture

Without SOCKS Proxy

Local Machine → Jump Host → Remote Resource
     ↓              ↓              ↓
  localhost:    jump-host:    remote-host:
    3306          22           3306

With SOCKS Proxy

Local Machine → SOCKS Proxy → Jump Host → Remote Resource
     ↓              ↓              ↓              ↓
  localhost:    socks-proxy:  jump-host:    remote-host:
    3306          1080          22           3306

The script creates a local port that forwards all traffic through the chain (SOCKS proxy → jump host → remote resource).

Installation

pnpm install

Usage

  1. Edit index.js and update the configuration object with your connection details:
const config = {
  // Optional: SOCKS proxy configuration (uncomment to use)
  // socksProxy: {
  //   host: 'socks-proxy.example.com',
  //   port: 1080,                    // SOCKS proxy port (default: 1080)
  //   type: 'socks5',                // 'socks4', 'socks4a', or 'socks5' (default: 'socks5')
  //   // For SOCKS5 authentication (optional):
  //   username: 'proxy-username',
  //   password: 'proxy-password',
  //   // For SOCKS4 authentication (optional):
  //   // userId: 'user-id',
  // },
  jumpHost: {
    host: 'jump.example.com',
    port: 22,
    username: 'your-username',
    keyPath: '/path/to/jump-host-key.pem',  // Path to PEM key file for jump host
    passphrase: 'key-passphrase-if-needed',  // Optional, only if key is encrypted
  },
  remoteResource: {
    host: 'internal-server.example.com',
    port: 3306,  // e.g., MySQL: 3306, PostgreSQL: 5432, HTTP: 80
    // For SSH-to-SSH tunneling, uncomment:
    // useSSH: true,
    // username: 'remote-username',
    // keyPath: '/path/to/remote-resource-key.pem',  // Different key for remote resource
  },
  local: {
    host: '127.0.0.1',
    port: 3306,
  }
};
  1. Run the script:
pnpm start
# or
node index.js
  1. Connect to the local port as if it were the remote resource:
# Example: Connect to MySQL through the tunnel
mysql -h 127.0.0.1 -P 3306 -u username -p

# Example: Connect to PostgreSQL through the tunnel
psql -h 127.0.0.1 -p 5432 -U username -d database

SOCKS Proxy Configuration

If you need to route through a SOCKS proxy before reaching the jump host, you can configure it:

socksProxy: {
  host: 'socks-proxy.example.com',
  port: 1080,                    // SOCKS proxy port (default: 1080)
  type: 'socks5',                // 'socks4', 'socks4a', or 'socks5' (default: 'socks5')
  
  // For SOCKS5 authentication (optional):
  username: 'proxy-username',
  password: 'proxy-password',
  
  // For SOCKS4 authentication (optional):
  // userId: 'user-id',
}

Note: The SOCKS proxy is optional. If not specified, the script will connect directly to the jump host.

Authentication Methods

Jump Host Authentication

Option 1: Key File Path (Recommended)

jumpHost: {
  host: 'jump.example.com',
  username: 'user',
  keyPath: '/path/to/jump-host-key.pem',
  passphrase: 'key-passphrase-if-needed',  // Optional, only if key is encrypted
}

Option 2: Private Key Directly

jumpHost: {
  host: 'jump.example.com',
  username: 'user',
  privateKey: require('fs').readFileSync('/path/to/jump-host-key.pem'),
  passphrase: 'key-passphrase-if-needed',  // Optional
}

Option 3: Password Authentication

jumpHost: {
  host: 'jump.example.com',
  username: 'user',
  password: 'your-password',
}

Remote Resource Authentication

For TCP forwarding (most common use case - databases, HTTP services, etc.), you don't need authentication for the remote resource. Only the jump host key is required.

For SSH-to-SSH tunneling (advanced use case), you can specify a different key for the remote resource:

remoteResource: {
  host: 'internal-server.example.com',
  port: 22,  // SSH port
  useSSH: true,
  username: 'remote-username',
  keyPath: '/path/to/remote-resource-key.pem',  // Different key than jump host
  passphrase: 'remote-key-passphrase-if-needed',  // Optional
  targetPort: 3306,  // Port to forward on the remote SSH server
}

Use Cases

  • Accessing internal databases from your local machine
  • Connecting to services behind a firewall
  • Securely accessing remote resources without exposing them publicly
  • Development and debugging of remote services

How It Works

  1. Connect through SOCKS Proxy (if configured): Establishes a connection through the SOCKS proxy to the jump host
  2. Connect to Jump Host: Establishes an SSH connection to the jump host (via SOCKS if configured)
  3. Create Local Listener: Starts a local TCP server on the specified port
  4. Forward Connections: For each incoming connection, creates a forwarded connection through the jump host using forwardOut()
  5. Pipe Data: Bidirectionally pipes data between the local connection and the remote connection

API

The script exports a createTunnelThroughJumpHost function that can be used programmatically:

const { createTunnelThroughJumpHost } = require('./index.js');

const tunnel = await createTunnelThroughJumpHost({
  jumpHost: { /* ... */ },
  remoteResource: { /* ... */ },
  local: { /* ... */ }
});

// Later, close the tunnel
tunnel.close();

Notes

  • The tunnel will remain active until you press Ctrl+C or call tunnel.close()
  • Make sure the jump host has network access to the remote resource
  • The local port must be available (not already in use)
  • Ensure your SSH credentials for the jump host are correct
  • If using a SOCKS proxy, ensure the proxy has network access to the jump host
  • SOCKS proxy authentication is optional but recommended for security

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published