2016-01-23 123 views
2

我需要創建一個SSH服務器(twisted.conch已被選定爲工作),這將做到以下幾點:Python的SSH服務器(twisted.conch)命令過濾和端口轉發

  1. 進行端口轉發(附加的代碼沒有這樣做,我做 不知道要修改什麼)
  2. 過濾命令之前,他們執行(或至少記錄他們之前或之後)。

下面所附的代碼創建完美的SSH和SFTP服務器,但它缺少一個主要成分 - 端口轉發(和命令過濾,但是這不是端口轉發同樣重要)

我搜索其中我可能會,但找不到這兩個..請幫助我, - 這是拼圖的最後一個和平。

#!/usr/bin/env python 
from twisted.conch.unix import UnixSSHRealm 
from twisted.cred.portal import Portal 
from twisted.cred.credentials import IUsernamePassword 
from twisted.cred.checkers import ICredentialsChecker 
from twisted.cred.error import UnauthorizedLogin 
from twisted.conch.ssh.factory import SSHFactory 
from twisted.internet import reactor, defer 
from twisted.conch.ssh.transport import SSHServerTransport 
from twisted.conch.ssh.userauth import SSHUserAuthServer 
from twisted.conch.ssh.connection import SSHConnection 
from twisted.conch.ssh.keys import Key 
from zope.interface import implements 
from subprocess import Popen,PIPE 
from crypt import crypt 

publicKey = 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAGEArzJx8OYOnJmzf4tfBEvLi8DVPrJ3/c9k2I/Az64fxjHf9imyRJbixtQhlH9lfNjUIx+4LmrJH5QNRsFporcHDKOTwTTYLh5KmRpslkYHRivcJSkbh/C+BR3utDS555mV' 
privateKey = """-----BEGIN RSA PRIVATE KEY----- 
MIIByAIBAAJhAK8ycfDmDpyZs3+LXwRLy4vA1T6yd/3PZNiPwM+uH8Yx3/YpskSW 
4sbUIZR/ZXzY1CMfuC5qyR+UDUbBaaK3Bwyjk8E02C4eSpkabJZGB0Yr3CUpG4fw 
vgUd7rQ0ueeZlQIBIwJgbh+1VZfr7WftK5lu7MHtqE1S1vPWZQYE3+VUn8yJADyb 
Z4fsZaCrzW9lkIqXkE3GIY+ojdhZhkO1gbG0118sIgphwSWKRxK0mvh6ERxKqIt1 
xJEJO74EykXZV4oNJ8sjAjEA3J9r2ZghVhGN6V8DnQrTk24Td0E8hU8AcP0FVP+8 
PQm/g/aXf2QQkQT+omdHVEJrAjEAy0pL0EBH6EVS98evDCBtQw22OZT52qXlAwZ2 
gyTriKFVoqjeEjt3SZKKqXHSApP/AjBLpF99zcJJZRq2abgYlf9lv1chkrWqDHUu 
DZttmYJeEfiFBBavVYIF1dOlZT0G8jMCMBc7sOSZodFnAiryP+Qg9otSBjJ3bQML 
pSTqy7c3a2AScC/YyOwkDaICHnnD3XyjMwIxALRzl0tQEKMXs6hH8ToUdlLROCrP 
EhQ0wahUTCk1gKA4uPD6TMTChavbh4K63OvbKg== 
-----END RSA PRIVATE KEY-----""" 

# check if username/password is valid 
def checkPassword(username,password): 
    try: 
     ret=False 
     if username and password: 
      output=Popen(["grep",username,"/etc/shadow"],stdout=PIPE,stderr=PIPE).communicate()[0] 
      hash="" 
      if output: 
       tmp=output.split(":") 
       if tmp>=2: 
        hash=tmp[1] 
       del tmp 
      ret=crypt(password,hash)==hash 
      del output,hash 
    except Exception,e: 
     ret=False 
    return ret 

# authorization methods 
class XSSHAuth(object): 
    credentialInterfaces=IUsernamePassword,implements(ICredentialsChecker) 
    def requestAvatarId(self, credentials): 
     #print "Credentials:",credentials.username,credentials.password 
     if credentials.username=="root" and credentials.password and checkPassword(credentials.username,credentials.password): 
      # successful authorization 
      return defer.succeed(credentials.username) 
     # failed authorization 
     return defer.fail(UnauthorizedLogin("invalid password")) 
class XSSHUserAuthServer(SSHUserAuthServer): 
    def _ebPassword(self, reason): 
     addr = self.transport.getPeer().address 
     if addr.host!="3.22.116.85" and addr.host!="127.0.0.1": 
      p1 = Popen(["iptables","-I","INPUT","-s",addr.host,"-j","DROP"], stdout=PIPE, stderr=PIPE) 
      p1.communicate() 
     print(addr.host, addr.port, self.user, self.method) 
     self.transport.loseConnection() 
     return defer.fail(UnauthorizedLogin("invalid password")) 

# the transport class - we use it to log MOST OF THE ACTIONS executed thru the server 
class XSSHTransport(SSHServerTransport): 
    ourVersionString="SSH-2.0-X" 
    logCommand="" 
    def connectionMade(self): 
     print "Connection made",self.getPeer() 
     SSHServerTransport.connectionMade(self) 
     #self.transport.loseConnection() 
    def connectionLost(self,reason): 
     print "Connection closed",self.getPeer() 
     SSHServerTransport.connectionLost(self,reason) 
    def dataReceived(self, data): 
     SSHServerTransport.dataReceived(self,data) 
    def dispatchMessage(self, messageNum, payload): 
     SSHServerTransport.dispatchMessage(self,messageNum,payload) 

# start the server 
class XSSHFactory(SSHFactory): 
    protocol=XSSHTransport 
factory = XSSHFactory() 
factory.publicKeys = {'ssh-rsa': Key.fromString(data=publicKey)} 
factory.privateKeys = {'ssh-rsa': Key.fromString(data=privateKey)} 
factory.services = { 
    'ssh-userauth': XSSHUserAuthServer, 
    'ssh-connection': SSHConnection 
} 
portal=Portal(UnixSSHRealm()) 
portal.registerChecker(XSSHAuth()) 
factory.portal=portal 
reactor.listenTCP(22, factory) 
reactor.run() 
+1

我希望你的服務器不能被任何惡意方訪問 - 因爲你在這裏發佈了私鑰,供所有人查看。 –

+0

不幸的是,我不知道我不應該,我是新來的這個「海螺」的東西 - 我應該刪除它嗎?一旦準備就緒,我將使用它而不是sshd。 – Daniel

+0

您可以用另一對替換它們。 –

回答

0

由於您使用UnixConchUser它實現global_tcpip_forward,它實際是工作。當我運行你的例子並通過ssh -L4321:remote.host:1234 [email protected] -p 2222然後telnet localhost 4321連接到它時,我得到隧道到remote.host 1234。你將不得不更詳細地陳述你的問題。

0

命令日誌可能會在dataReceived(self, data)被做可以:

def dataReceived(self, data): 
     SSHServerTransport.dataReceived(self,data) 
     self.buf += data 
     if data == '\r': 
      cmd = self.buf 
      self.buf = '' 

但它不能處理的刪除鍵,選項卡,向上箭頭,箭頭向下,和其他特殊字符很好。我想知道你最後如何得到命令。