远程控制是网络安全的一个极为重要的内容,维护者的目标一般是保证远程控制的安全,而攻击者则是希望凭借各种手段获得目标设备的远程控制权,因为一旦得到目标机器的远程控制权,则基本表明已经渗透成功。
编写一个基于ssh的远程控制程序
在实际生产环境中,远程控制是一个十分重要的功能,大量的服务器,路由器,交换机都是存在专门的机房中,网络管理人员大部分时间是不会直接接触这些设备来进行管理,除非出现了物理问题,大多数时间是通过网络来进行远程控制。
Telnet与SSH:
在TCP/IP协议族中提供了一些可以用来远程控制的协议,Telnet和SSH就是其中使用最为广泛的两个协议。网络管理人员通过Telnet和SSH可以在本地计算机中完成对远程主机的控制。由于这种控制是通过网络实现的,因此被控制的设备需要使用安全的认证机制,才能避免被人滥用。Telnet提供的认证机制是口令认证,而SSH则提供了口令和密钥认证两种方法。
目前,Telnet由于安全性方面的缺陷,已经逐渐被真实的生产环境所抛弃,而SSH已经成为远程控制的首选,这两者的主要区别就在于Telnet在通信过程中没有使用任何加密机制,而SSH提供了十分安全的加密机制,使用Telnet被抓包后很容易直接获得用户的用户名和密码,而SSH提供的两种级别的安全认证可以保证用户信息的安全性:
1,基于口令的安全认证:
这种机制使用的仍是账号+密码的方式,只有当网络管理人员输入合法的授权的信息之后,服务器端才会接收控制请求,整个过程都会被加密,即使被人窃取,也不好进行解密,,但是这种机制仍存在缺陷,即客户端无法验证服务器端的真实性,攻击者可能会用其他设备冒充服务端,从而获得认证信息.
2,基于密钥的安全认证:
在这种认证中没有使用账户+密码的方式,而是使用一对密钥,分别是公钥和私钥来代替账号+密码,其中服务器和客户端都要使用公钥,而私钥就由客户端自己掌握,当客户端试图连接服务端时,首先向服务端提供公钥,服务端在比对自己的公钥与客户端提供的公钥是否一致后,就会使用该公钥进行加密询问客户端,客户端接收到询问后,会使用自己的私钥对其解密后再将其发送给客户端完成认证,整个过程需要进行加密和解密,所以花费的时间远远多于第一种方式,但是安全性也远远高于第一种认证方式
基于paramiko实现SSH客户端:
paramiko是一个用SSH实现远程控制的python模块,因为其中封装了SSH的各种功能,所以再编写时无须考虑加密和通信的具体实现。
(1)首先引入paramiko模块
import paramiko
(2)创建SSHClient对象
Client = paramiko.SSHClient()
(3)使用connect()函数并指定参数连接服务器端,如果使用基于口令的安全认证方式,那么connect()函数的连接方式如下。
Client.connect(hostname='目的服务器的IP或者域名',port=22,username='你的用户名',password='你的密码')
如果使用的是基于密钥的连接方式,那么connect()函数的连接方式如下。
Client.connect(hostname='目的服务器IP或者域名',port=22,username='你的用户名',pkey='你的私钥')
(4)使用exec_command()函数执行系统命令如下。
stdin,stdout,stderr = Client.exec_command(cmd)
#这里的stdin,stdout,stderr分别表示程序的标准输入,输出,错误语句,参数cmd表示要执行的系统命令,格式为字符串
#比如stdin,stdout,stderr = Client.exec_command('ls')表示展开目录
完整代码如下:
import paramiko
Client = paramiko.SSHClient()
Client.connect(hostname='目的服务器的IP或者域名',port=22,username='你的用户名',password='你的密码')
stdin,stdout,stderr = Client.exec_command('ls')
stdout.read()
如果你选择是编写一个基于密钥登录的客户端控制程序,首先需要生成密钥对,这个工作可以在Linux中完成,输入ssh-keygen -t rsa,然后再选择放入文件的位置,然后输入密码,会同时生成公钥和私钥
我们将这个私钥复制到客户端之后,就可以进行代码登录并执行命令:
import paramiko
private_keypath = '你的私钥的存放的位置'
key = paramiko.RSAKey.from_private_key_file(private_keypath)
#从指定路径加载私钥文件并用变量key接收
client = paramiko.SSHClient()
#创建客户端变量
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#设置客户端缺失主机密钥的策略为AutoAddPolicy(),用于在首次连接到未知主机时自动添加主机密钥到本地 known_hosts 文件中,以避免出现主机密钥验证的警告或错误。
client.connect(hostname='服务器域名或IP',port=22,pkey=key)
stdin,stdout,stderr=client.exec_command('df')
#df的作用是用于显示文件系统的磁盘空间利用情况
stdout.read()
我们远程登录服务器之后,如果想做点其他的事情,比如上传或者下载文件,使用SFTPClient()函数可以实现从服务器下载文件和向服务器上传文件,步骤如下:
(1):建立客户端与服务器的连接
transport = paramiko.Transport(('主机IP或域名',22))
(2)通过服务器的认证,如果服务器使用口令认证,那么代码如下
transport.connect(username='你的用户名',password='你的密码')
如果服务器使用密钥认证,那么代码如下:
pravite_keypath='你的密钥的路径'
key = paramiko.RSAKey.from_private_key_file(pravite_keypath)
transport.connect(username='你的用户名',pkey=key)
(3)上传的命令为put,将test.py上传到服务器端,并改名为test1.py,代码如下
sftp.put('test.py的文件地址','test1.py的文件地址')
(4)下载的命令为get,下载服务器端的test1.py文件,并改名为test2.py,代码如下:
sftp.get('test1的文件地址','test2的文件地址')
下面给出一个使用paramiko实现基于口令登录的客户端文件上传下载程序的代码:
import paramiko
transport = paramiko.Transport(('主机IP或域名',22))
transport.connect(username='你的用户名',password='你的密码')
sftp = paramiko.SFTPClient.from_transport(transport)
#创建sftp对象
sftp.put('test.py的文件地址','test1.py的文件地址')
sftp.get('test1的文件地址','test2的文件地址')
transport.close()