Search code examples
pythonportforwardingssh-tunnel

How create port forwarding using SSHtunnelForwarder?


I am trying to replicate: ssh -i [KEY] -L [FROM_PORT]:localhost:[TO_PORT] ubuntu@[REMOTE_SERVER_IP] in python and decided to use sshtunnel for it. The command given above works and I can connect to the remote Theia IDE, but I can't figure out how I need to configure SSHtunnelForwarder to achieve the same from within python. I am probably misunderstanding its documentation: https://github.com/pahaz/sshtunnel

EDIT: This code is faulty. Look for an answer below.

    # I replaced the remote-ip with `123.45.67.89`.
    # I replaced my ip with `987.65.43.21`.
    with SSHTunnelForwarder(
        ssh_address_or_host="123.45.67.89",  # ip of remote server
        ssh_pkey="PRIVATE_KEY", # I am unsure which one is needed tried both
        ssh_private_key="PRIVATE_KEY", # I am unsure which one is needed tried both
        ssh_username="ubuntu",  # username of remote server
        ssh_bind_address= ("127.0.0.1", 9191),  # where to listen locally
        remote_bind_address= ("127.0.0.1", 8181)  # where to send info coming to 22
        # ssh-port 22 (default port)
        # localhost:9191 -> 123.45.67.89:22 -> localhost:8181
        # which is basically 987.65.43.21:9191 -> 123.45.67.89:22 -> 123.45.67.89:8181
    ) as server:
        server.start()

But when I try to connect to http://localhost:9191/ I receive unable to connect; so the tunneling is probably broken. I added plenty of comments to the code to make it easier to spot my misunderstanding.


Solution

  • When I run your code then I see error

    ValueError: You can't use both 'ssh_private_key' and 'ssh_pkey'. Please only use one of them. 
    

    You have to use one of them and example in your link show what it should be.

    ssh_pkey="/var/ssh/rsa_key",
    

    or

    ssh_private_key_password="secret",
    

    It needs to generate file rsa_key using program ssh-keygen which should be installed with ssh

    (on Linux I would keep this file in user's folder ~/.ssh)


    Next I see error

    ValueError: Unknown arguments: {'ssh_bind_address': ('127.0.0.1', 9191)} 
    

    it has to be local_bind_address instead of ssh_bind_address.
    Even example in your link uses local_bind_address.

    You can see all arguments in commends in source code
    or using help(SSHTunnelForwarder) in code.


    This code works for me:

    I can use pair username, password

        ssh_username = "pi",
        ssh_password = "raspberry",
    

    or pair username and standard file id_rsa with my keys

        ssh_username = "pi",
        ssh_pkey='/home/furas/.ssh/id_rsa',  
    

    Code:

    from sshtunnel import SSHTunnelForwarder
    import time
    
    #import sshtunnel
    #print('author :', sshtunnel.__author__)
    #print('version:', sshtunnel.__version__)
    
    #help(SSHTunnelForwarder)
    
    with SSHTunnelForwarder(
        ssh_address_or_host = "192.168.1.29",  # Raspberry Pi in my network
    
        ssh_username = "pi",
        ssh_password = "raspberry",
    
        #ssh_username = "pi",
        #ssh_pkey='/home/furas/.ssh/id_rsa',  
    
        local_bind_address  = ("127.0.0.1", 9191),
        remote_bind_address = ("127.0.0.1", 8181)
    ) as server:
        print('Starting ...')
        server.start()
    
        print('Keep running ...')
        while True:
            time.sleep(1)
            
        #print('Stopping ...')
        #server.stop()