2011-05-31 38 views
13

¿Alguien puede recomendar algo para hacer una conexión ssh en python? Lo necesito para ser compatible con cualquier sistema operativo.¿Cómo hacer una conexión ssh con python?

Ya he intentado con pyssh solo para obtener un error con SIGCHLD, que he leído porque Windows no tiene esto. He intentado que paramiko funcione, pero he tenido errores entre paramiko y Crypto hasta el punto en que las últimas versiones de cada uno no funcionan juntas.

Python 2.6.1 actualmente en una máquina con Windows.

Respuesta

29

El módulo pxssh hace exactamente lo que quiere.
Por ejemplo, para ejecutar 'ls -l' y para imprimir la salida, tiene que hacer algo así:

from pexpect import pxssh 
s = pxssh.pxssh() 
if not s.login ('localhost', 'myusername', 'mypassword'): 
    print "SSH session failed on login." 
    print str(s) 
else: 
    print "SSH session login successful" 
    s.sendline ('ls -l') 
    s.prompt()   # match the prompt 
    print s.before  # print everything before the prompt. 
    s.logout() 

Algunos enlaces:
docs Pxssh: http://dsnra.jpl.nasa.gov/software/Python/site-packages/Contrib/pxssh.html
Pexpect (pxssh se basa en pexpect): http://www.noah.org/wiki/pexpect

+1

Advertencias dado el requisito multiplataforma: "[pexpect] debería funcionar en cualquier plataforma que admita el módulo Python estándar". lista de plataformas de módulos pty: linux. Además: "Pexpect actualmente no funciona en el Python de Windows estándar (consulte el requisito pty); sin embargo, parece funcionar bien con Cygwin". – jtniehof

+1

Gracias por las respuestas. Logré obtener paramiko para conectarme, sin embargo, aún no lo he probado en múltiples plataformas. Definitivamente voy a tener estas otras opciones en mente. – Takkun

+0

Me parece que pxssh se ha integrado en pexpect que se encuentra aquí: https://github.com/pexpect/pexpect – AlanObject

3

Twisted tiene soporte SSH: http://www.devshed.com/c/a/Python/SSH-with-Twisted/

El paquete twisted.conch añade soporte SSH en Twisted. Este capítulo muestra cómo puede usar los módulos en twisted.conch para construir servidores y clientes SSH.

Configuración de un servidor SSH personalizada

La línea de comandos es una interfaz increíblemente eficiente para ciertas tareas. Los administradores de sistemas adoran la capacidad de administrar aplicaciones escribiendo comandos sin tener que hacer clic a través de una interfaz gráfica de usuario. Un shell SSH es aún mejor, ya que es accesible desde cualquier lugar en Internet.

Puede usar twisted.conch para crear un servidor SSH que proporcione acceso a un shell personalizado con los comandos que defina. Este shell incluso admitirá algunas características adicionales, como el historial de comandos, para que pueda desplazarse por los comandos que ya ha escrito.

¿Cómo puedo hacer eso? Escriba una subclase de twisted.conch.recvline.HistoricRecvLine que implemente su protocolo de shell. HistoricRecvLine es similar a twisted.protocols.basic.LineReceiver, pero con características de nivel superior para controlar la terminal.

Escriba una subclase de twisted.conch.recvline.HistoricRecvLine que implemente su protocolo de shell. HistoricRecvLine es similar a twisted.protocols.basic.LineReceiver, pero con características de nivel superior para controlar la terminal.

Para hacer que su caparazón esté disponible a través de SSH, debe implementar algunas clases diferentes que twisted.conch necesita para construir un servidor SSH. En primer lugar, necesita las clases de autenticación twisted.cred: un portal, verificadores de credenciales y un reino que devuelve avatares. Utilice twisted.conch.avatar.ConchUser como la clase base para su avatar. Su clase de avatar también debería implementar twisted.conch.interfaces.ISession, que incluye un método de openShell en el que crea un protocolo para administrar la sesión interactiva del usuario. Finalmente, cree un objeto twisted.conch.ssh.factory.SSHFactory y establezca su atributo de portal en una instancia de su portal.

El ejemplo 10-1 muestra un servidor SSH personalizado que autentica a los usuarios por su nombre de usuario y contraseña. Le da a cada usuario un shell que proporciona varios comandos.

Ejemplo 10-1. sshserver.py

from twisted.cred import portal, checkers, credentials 
from twisted.conch import error, avatar, recvline, interfaces as conchinterfaces 
from twisted.conch.ssh import factory, userauth, connection, keys, session, common from twisted.conch.insults import insults from twisted.application import service, internet 
from zope.interface import implements 
import os 

class SSHDemoProtocol(recvline.HistoricRecvLine): 
    def __init__(self, user): 
     self.user = user 

    def connectionMade(self) : 
    recvline.HistoricRecvLine.connectionMade(self) 
     self.terminal.write("Welcome to my test SSH server.") 
     self.terminal.nextLine() 
     self.do_help() 
     self.showPrompt() 

    def showPrompt(self): 
     self.terminal.write("$ ") 

    def getCommandFunc(self, cmd): 
     return getattr(self, ‘do_’ + cmd, None) 

    def lineReceived(self, line): 
     line = line.strip() 
     if line: 
      cmdAndArgs = line.split() 
      cmd = cmdAndArgs[0] 
      args = cmdAndArgs[1:] 
      func = self.getCommandFunc(cmd) 
      if func: 
       try: 
        func(*args) 
       except Exception, e: 
        self.terminal.write("Error: %s" % e) 
        self.terminal.nextLine() 
      else: 
       self.terminal.write("No such command.") 
       self.terminal.nextLine() 
     self.showPrompt() 

    def do_help(self, cmd=”): 
     "Get help on a command. Usage: help command" 
     if cmd: 
      func = self.getCommandFunc(cmd) 
      if func: 
       self.terminal.write(func.__doc__) 
       self.terminal.nextLine() 
       return 

     publicMethods = filter(
      lambda funcname: funcname.startswith(‘do_’), dir(self)) 
     commands = [cmd.replace(‘do_’, ”, 1) for cmd in publicMethods] 
     self.terminal.write("Commands: " + " ".join(commands)) 
     self.terminal.nextLine() 

    def do_echo(self, *args): 
     "Echo a string. Usage: echo my line of text" 
     self.terminal.write(" ".join(args)) 
     self.terminal.nextLine() 

    def do_whoami(self): 
     "Prints your user name. Usage: whoami" 
     self.terminal.write(self.user.username) 
     self.terminal.nextLine() 

    def do_quit(self): 
     "Ends your session. Usage: quit" 
     self.terminal.write("Thanks for playing!") 
     self.terminal.nextLine() 
     self.terminal.loseConnection() 

    def do_clear(self): 
     "Clears the screen. Usage: clear" 
     self.terminal.reset() 

class SSHDemoAvatar(avatar.ConchUser): 
    implements(conchinterfaces.ISession) 

    def __init__(self, username): 
     avatar.ConchUser.__init__(self) 
     self.username = username 
     self.channelLookup.update({‘session’:session.SSHSession}) 

    def openShell(self, protocol): 
     serverProtocol = insults.ServerProtocol(SSHDemoProtocol, self) 
     serverProtocol.makeConnection(protocol) 
     protocol.makeConnection(session.wrapProtocol(serverProtocol)) 

    def getPty(self, terminal, windowSize, attrs): 
     return None 

    def execCommand(self, protocol, cmd): 
     raise NotImplementedError 

    def closed(self): 
     pass 

class SSHDemoRealm: 
    implements(portal.IRealm) 

    def requestAvatar(self, avatarId, mind, *interfaces): 
     if conchinterfaces.IConchUser in interfaces: 
      return interfaces[0], SSHDemoAvatar(avatarId), lambda: None 
     else: 
      raise Exception, "No supported interfaces found." 

def getRSAKeys(): 
    if not (os.path.exists(‘public.key’) and os.path.exists(‘private.key’)): 
     # generate a RSA keypair 
     print "Generating RSA keypair…" 
     from Crypto.PublicKey import RSA 
     KEY_LENGTH = 1024 
     rsaKey = RSA.generate(KEY_LENGTH, common.entropy.get_bytes) 
     publicKeyString = keys.makePublicKeyString(rsaKey) 
     privateKeyString = keys.makePrivateKeyString(rsaKey) 
     # save keys for next time 
     file(‘public.key’, ‘w+b’).write(publicKeyString) 
     file(‘private.key’, ‘w+b’).write(privateKeyString) 
     print "done." 
    else: 
     publicKeyString = file(‘public.key’).read() 
     privateKeyString = file(‘private.key’).read() 
    return publicKeyString, privateKeyString 

if __name__ == "__main__": 
    sshFactory = factory.SSHFactory() 
    sshFactory.portal = portal.Portal(SSHDemoRealm()) 
    users = {‘admin’: ‘aaa’, ‘guest’: ‘bbb’} 
    sshFactory.portal.registerChecker(
checkers.InMemoryUsernamePasswordDatabaseDontUse(**users)) 

    pubKeyString, privKeyString = 
getRSAKeys() 
    sshFactory.publicKeys = { 
     ‘ssh-rsa’: keys.getPublicKeyString(data=pubKeyString)} 
    sshFactory.privateKeys = { 
     ‘ssh-rsa’: keys.getPrivateKeyObject(data=privKeyString)} 

    from twisted.internet import reactor 
    reactor.listenTCP(2222, sshFactory) 
    reactor.run() 

{mospagebreak title=Setting Up a Custom SSH Server continued} 

sshserver.py se ejecutará un servidor SSH en el puerto 2222.Conectarse a este servidor con un cliente SSH utilizando el nombre de usuario y contraseña de administrador AAA, y pruebe a escribir algunos comandos:

$ ssh [email protected] -p 2222 
[email protected]’s password: aaa 

>>> Welcome to my test SSH server. 
Commands: clear echo help quit whoami 
$ whoami 
admin 
$ help echo 
Echo a string. Usage: echo my line of text 
$ echo hello SSH world! 
hello SSH world! 
$ quit 

Connection to localhost closed. 
Cuestiones relacionadas