2012-10-24 2 views
3

커맨드 라인을 사용하기에 너무 까다로운 사용자 그룹을위한 SSH 터널을 생성하고 모니터링하는 GUI 프로그램을 작성 중입니다.파이썬 서브 프로세스를 통한 SSH 패스워드

불행히도 문제의 서버는 매우 엄격합니다. RSA SecurID 토큰을 통한 이중 인증은 공식적으로 승인 된 SSH 연결을 여는 유일한 방법입니다. 암호가없는 RSA 공개/개인 키 인증은 허용되지 않습니다.

따라서 내 프로그램이 텍스트 입력 상자에서 암호를 읽고 하위 SSH 프로세스로 보내야합니다. 유감스럽게도 ssh은 암호가 실제 키보드에서만 나오는지 확인하기 위해 많은 노력을 기울이고 있습니다.

제 3 자 모듈을 사용하지 않는 것이 좋습니다. 필자는 paramiko와 pexpect (둘 다 비슷한 문제에 대한 가능한 해결책으로 제시됨)를 알고 있지만 소스에서 Python 모듈을 설치하는 방법을 내 사용자에게 설명하려고 애쓰는 것은 너무 골치 거리입니다.

그래서 : 당신은 어떻게 표준 파이썬 subprocess 모듈을 사용하여 ssh를 서브 프로세스에 암호를 보낼 수 있습니까? 하위 프로세스를 바보로 삼아 TTY를 사용하고 있다고 생각하는 방법이 있습니까? 내 프로그램에서 SSH_ASKPASS를 사용하여 읽을 수 있습니까?

다른 표준 라이브러리 모듈 (예 : os 모듈이있는 하위 수준 명령)도 허용됩니다.

+1

대부분의 경우, 모듈의 소스 디렉토리를 타르볼에서 꺼내서 자신의 스크립트와 함께 패키지 할 수 있습니다. 설치가 필요하지 않습니다. – Blender

+0

pexpect가 그 작업을위한 도구라는 데 동의합니다. 의존성 (및 인터프리터)을 실행 가능한 형태로 묶을 PyInstaller를 사용할 수도 있습니다. – wim

+1

당신은'ssh -T'와'SSH_ASKPASS'를 사용하여 성공할 수 있다고 생각합니다. – 9000

답변

4

필자는 pseudoterminal을 통해 ssh를 제어하기 위해 pty 모듈을 사용할 수있었습니다. pexpect에 해결책을 코딩 한 다음 pexpect 소스 코드를보고 this StackOverflow answer의 도움을 받아 무엇을해야할지 파악할 수있었습니다. 다음은 관련 코드의 발췌 부분입니다 (객체 메서드의 일부로 실행되므로 self에 대한 참조).

command = [ 
     '/usr/bin/ssh', 
     '{0}@{1}'.format(username, hostname), 
     '-L', '{0}:localhost:{1}'.format(local_port, foreign_port), 
     '-o', 'NumberOfPasswordPrompts=1', 
     'sleep {0}'.format(SLEEP_TIME), 
] 

# PID = 0 for child, and the PID of the child for the parent  
self.pid, child_fd = pty.fork() 

if not self.pid: # Child process 
    # Replace child process with our SSH process 
    os.execv(command[0], command) 

while True: 
    output = os.read(child_fd, 1024).strip() 
    lower = output.lower() 
    # Write the password 
    if lower.endswith('password:'): 
     os.write(child_fd, self.password_var.get() + '\n') 
     break 
    elif 'are you sure you want to continue connecting' in lower: 
     # Adding key to known_hosts 
     os.write(child_fd, 'yes\n') 
    elif 'company privacy warning' in lower: 
     pass # This is an understood message 
    else: 
     tkMessageBox.showerror("SSH Connection Failed", 
      "Encountered unrecognized message when spawning " 
      "the SSH tunnel: '{0}'".format(output)) 
     self.disconnect() 
관련 문제