SSH forward and reverse tunneling

SSH forward and reverse tunneling

SSH (Secure Shell) tunneling is a technique that allows you to securely forward network traffic from one networked device to another. There are two main types of SSH tunneling: forward tunneling and reverse tunneling.

  1. SSH Forward Tunneling:

    • Description:
      • Forward tunneling is the more common type of SSH tunneling. It allows you to establish a secure connection from a local machine to a remote machine, forwarding specific ports or services through the encrypted SSH connection.
    • Use Cases:
      • Remote Access:
        • Accessing a service (e.g., a web server) on a remote machine securely.
      • Bypassing Firewalls:
        • Accessing services behind firewalls or network restrictions.
      • Secure Data Transfer:
        • Transmitting data securely over an untrusted network.
    • Example:
      • Suppose you have a web server running on a remote machine, and you want to access it securely from your local machine. You can use the following command to create a forward tunnel:
        ssh -L local_port:remote_server:remote_port user@remote_server
        
        This forwards traffic from local_port on your local machine to remote_port on the remote server.
  2. SSH Reverse Tunneling:

    • Description:
      • Reverse tunneling is used to create a secure connection from a remote machine to a local machine, allowing the remote machine to access services on the local machine.
    • Use Cases:
      • Remote Support:
        • Allowing remote support personnel to access services on a local machine securely.
      • Exposing Local Services:
        • Making services on a local machine accessible from the internet securely.
    • Example:
      • Suppose you have a service on your local machine that you want someone on a remote machine to access securely. You can use the following command to create a reverse tunnel:
        ssh -R remote_port:local_machine:local_port user@local_machine
        
        This forwards traffic from remote_port on the remote machine to local_port on your local machine.

In both forward and reverse tunneling, the SSH protocol is used to create a secure, encrypted connection between the two machines, providing a secure way to transmit data over potentially insecure networks. These techniques are valuable for various scenarios, including remote access, bypassing network restrictions, and securing data transfer.

Python
#!/usr/bin/env python

"""
Sample script showing how to do remote port forwarding over paramiko.

This script connects to the requested SSH server and sets up remote port
forwarding (the openssh -R option) from a remote port through a tunneled
connection to a destination reachable from the local machine.
"""

import getpass
import socket
import select
import sys
import threading
from optparse import OptionParser

import paramiko

SSH_PORT = 22
DEFAULT_PORT = 4000

g_verbose = True


def handler(chan, host, port):
    sock = socket.socket()
    try:
        sock.connect((host, port))
    except Exception as e:
        verbose("Forwarding request to %s:%d failed: %r" % (host, port, e))
        return

    verbose(
        "Connected!  Tunnel open %r -> %r -> %r"
        % (chan.origin_addr, chan.getpeername(), (host, port))
    )
    while True:
        r, w, x = select.select([sock, chan], [], [])
        if sock in r:
            data = sock.recv(1024)
            if len(data) == 0:
                break
            chan.send(data)
        if chan in r:
            data = chan.recv(1024)
            if len(data) == 0:
                break
            sock.send(data)
    chan.close()
    sock.close()
    verbose("Tunnel closed from %r" % (chan.origin_addr,))


def reverse_forward_tunnel(server_port, remote_host, remote_port, transport):
    transport.request_port_forward("", server_port)
    while True:
        chan = transport.accept(1000)
        if chan is None:
            continue
        thr = threading.Thread(
            target=handler, args=(chan, remote_host, remote_port)
        )
        thr.setDaemon(True)
        thr.start()


def verbose(s):
    if g_verbose:
        print(s)


HELP = """\
Set up a reverse forwarding tunnel across an SSH server, using paramiko. A
port on the SSH server (given with -p) is forwarded across an SSH session
back to the local machine, and out to a remote site reachable from this
network. This is similar to the openssh -R option.
"""


def get_host_port(spec, default_port):
    """parse 'hostname:22' into a host and port, with the port optional"""
    args = (spec.split(":", 1) + [default_port])[:2]
    args[1] = int(args[1])
    return args[0], args[1]


def parse_options():
    global g_verbose

    parser = OptionParser(
        usage="usage: %prog [options] [:]",
        version="%prog 1.0",
        description=HELP,
    )
    parser.add_option(
        "-q",
        "--quiet",
        action="store_false",
        dest="verbose",
        default=True,
        help="squelch all informational output",
    )
    parser.add_option(
        "-p",
        "--remote-port",
        action="store",
        type="int",
        dest="port",
        default=DEFAULT_PORT,
        help="port on server to forward (default: %d)" % DEFAULT_PORT,
    )
    parser.add_option(
        "-u",
        "--user",
        action="store",
        type="string",
        dest="user",
        default=getpass.getuser(),
        help="username for SSH authentication (default: %s)"
        % getpass.getuser(),
    )
    parser.add_option(
        "-K",
        "--key",
        action="store",
        type="string",
        dest="keyfile",
        default=None,
        help="private key file to use for SSH authentication",
    )
    parser.add_option(
        "",
        "--no-key",
        action="store_false",
        dest="look_for_keys",
        default=True,
        help="don't look for or use a private key file",
    )
    parser.add_option(
        "-P",
        "--password",
        action="store_true",
        dest="readpass",
        default=False,
        help="read password (for key or password auth) from stdin",
    )
    parser.add_option(
        "-r",
        "--remote",
        action="store",
        type="string",
        dest="remote",
        default=None,
        metavar="host:port",
        help="remote host and port to forward to",
    )
    options, args = parser.parse_args()

    if len(args) != 1:
        parser.error("Incorrect number of arguments.")
    if options.remote is None:
        parser.error("Remote address required (-r).")

    g_verbose = options.verbose
    server_host, server_port = get_host_port(args[0], SSH_PORT)
    remote_host, remote_port = get_host_port(options.remote, SSH_PORT)
    return options, (server_host, server_port), (remote_host, remote_port)


def main():
    options, server, remote = parse_options()

    password = None
    if options.readpass:
        password = getpass.getpass("Enter SSH password: ")

    client = paramiko.SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.WarningPolicy())

    verbose("Connecting to ssh host %s:%d ..." % (server[0], server[1]))
    try:
        client.connect(
            server[0],
            server[1],
            username=options.user,
            key_filename=options.keyfile,
            look_for_keys=options.look_for_keys,
            password=password,
        )
    except Exception as e:
        print("*** Failed to connect to %s:%d: %r" % (server[0], server[1], e))
        sys.exit(1)

    verbose(
        "Now forwarding remote port %d to %s:%d ..."
        % (options.port, remote[0], remote[1])
    )

    try:
        reverse_forward_tunnel(
            options.port, remote[0], remote[1], client.get_transport()
        )
    except KeyboardInterrupt:
        print("C-c: Port forwarding stopped.")
        sys.exit(0)


if __name__ == "__main__":
    main()

This Python script demonstrates how to perform reverse port forwarding over SSH using the Paramiko library. Reverse port forwarding allows a remote machine to access services on the local machine through an SSH tunnel.

Explanation:

  1. Importing Libraries:

    • The script imports necessary modules, including socket, select, sys, threading, and paramiko.
  2. Constants:

    • The script defines some constants, such as the default SSH port (22) and a default port for the reverse tunnel (4000).
  3. Global Variable:

    • g_verbose is a global variable used to control verbose output. If set to True, it prints informative messages.
  4. Handler Function:

    • The handler function is responsible for managing the data transfer between the SSH channel and the local/remote sockets.
  5. Reverse Forward Tunnel Function:

    • The reverse_forward_tunnel function sets up the reverse forwarding tunnel. It requests port forwarding from the remote server and continuously accepts incoming connections to the specified port.
  6. Verbose Function:

    • The verbose function prints messages if the global variable g_verbose is set to True.
  7. Help Message:

    • The HELP string provides a brief description of the script’s purpose.
  8. Helper Functions:

    • get_host_port: Parses a string in the format “hostname:port” into host and port components.
    • parse_options: Parses command-line options using the OptionParser class.
  9. Main Function:

    • The main function is the entry point of the script. It parses command-line options, establishes an SSH connection to the specified server, and initiates the reverse forwarding tunnel.
  10. Script Execution:

    • The script checks if it’s being run directly (if __name__ == "__main__":) and calls the main function.

This script provides a command-line interface for setting up reverse port forwarding over SSH, allowing a remote machine to access local services securely. Users can specify the SSH server, remote host and port, and other parameters through command-line options. The Paramiko library is used for SSH-related functionalities.

Total
3
Shares

Leave a Reply

Previous Post
SSH server and client to run remote commands with Paramiko

SSH server and client to run remote commands with Paramiko

Next Post
Packet Sniffing on window and linux

Packet Sniffing on window and linux

Related Posts