What is the minimum amount of information needed to access a SSH server using twisted.conch?

163 Views Asked by At

I'm a little over my head when it comes to this SSH thing. Basically I am trying to access a friends server through and SSH tunnel using twisted conch. He has given me the following information:

MONGO_HOST = "ip address"
MONGO_DB = "server name"
MONGO_USER = "user name"
MONGO_PASS = "server password"

I was able to get this information to work using the python library motor.motor_asyncio (I need this be async compatible in order to use with other libraries) but for reasons that I can get into if necessary, will not work on the raspberry pi that I plan on running this program on.

Long story short, I was wondering if anyone could help me with some sample code to access my friends server using the information given above with twisted.conch.

I looked on the twisted.conch readthedocs, but the example needs more information than I can provide (I think) and is WAY over my head in terms of networking/SSH/etc.

Thanks in advance. I am willing to put in the work, but I need to know where to look.

Here is my relevant bit of code so far:

from motor.motor_asyncio import AsyncIOMotorClient
from sshtunnel import SSHTunnelForwarder

MONGO_HOST = "host address"
MONGO_DB = "server name"
MONGO_USER = "username"
MONGO_PASS = "password"

server = SSHTunnelForwarder(
    MONGO_HOST,
    ssh_username=MONGO_USER,
    ssh_password=MONGO_PASS,
    remote_bind_address=('address', gate),
    local_bind_address=('address', gate)
)
server.start()

client = AsyncIOMotorClient('address', gate)
db = client.server_name
1

There are 1 best solutions below

2
Jean-Paul Calderone On

You can forward ports with Conch like this:

rom twisted.internet.defer import Deferred
from twisted.conch.scripts import conch
from twisted.conch.scripts.conch import ClientOptions, SSHConnection
from twisted.conch.client.direct import connect
from twisted.conch.client.default import SSHUserAuthClient, verifyHostKey
from twisted.internet.task import react

def main(reactor):
    # authenticate as this user to SSH                                                                                                                                                                                                                                         
    user = "sshusername"
    # the SSH server address                                                                                                                                                                                                                                                   
    host = "127.0.0.1"
    # the SSH server port number                                                                                                                                                                                                                                               
    port = 22

    # a local port number to listen on and forward                                                                                                                                                                                                                             
    localListenPort = 12345
    # an address to forward to from the remote system                                                                                                                                                                                                                          
    remoteForwardHost = "127.0.0.1"
    # and the port number to forward to                                                                                                                                                                                                                                        
    remoteForwardPort = 22

    conch.options = ClientOptions()
    conch.options.parseOptions([
        # don't ask the server for a shell                                                                                                                                                                                                                                     
        "--noshell",
        # set up the local port forward                                                                                                                                                                                                                                        
        "--localforward={}:{}:{}".format(
            localListenPort,
            remoteForwardHost,
            remoteForwardPort,
        ),
        # specify the hostname for host key checking                                                                                                                                                                                                                           
        host,
    ])
    # don't stop when the last forwarded connection stops                                                                                                                                                                                                                      
    conch.stopConnection = lambda: None

    # do normal-ish authentication - agent, keys, passwords                                                                                                                                                                                                                    
    userAuthObj = SSHUserAuthClient(user, conch.options, SSHConnection())

    # create a Deferred that will tell `react` when to stop the reactor                                                                                                                                                                                                        
    runningIndefinitely = Deferred()

    # establish the connection                                                                                                                                                                                                                                                 
    connecting = connect(
        host,
        port,
        conch.options,
        verifyHostKey,
        userAuthObj,
    )

    # only forward errors so the reactor will run forever unless the                                                                                                                                                                                                           
    # connection attempt fails.  note this does not set up reconnection for a                                                                                                                                                                                                  
    # connection that succeeds and then fails later.                                                                                                                                                                                                                           
    connecting.addErrback(runningIndefinitely.errback)

    return runningIndefinitely

# run the reactor, call the main function with it, passing no other args                                                                                                                                                                                                       
react(main, [])

Some of the APIs are weird because they are CLI focused. You don't have to do it this way but port forwarding is most easily accessible with these APIs rather than the APIs that are more focused on programmatic use.