Python33 paramiko模块

发布时间:2019-09-19 08:02:03编辑:auto阅读(1571)

    paramiko模块

    ssh登录

    需要打开cmd,通过 pip install paramiko 命令来安装paramiko模块。

    import paramiko
    
    #创建SSH对象
    ssh = paramiko.SSHClient()
    
    #允许连接不在know_hosts文件中的主机
    # ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    #连接服务器
    ssh.connect(hostname='192.168.21.128',port=22,username='test',password='123qwe')
    
    #执行命令
    stdin,stdout,stderr = ssh.exec_command('df')
    ##stdin标准输入:你输入的命令,会返还给你
    ##stdout标准输出:你的命令执行结果
    ##stderr标准错误:在执行过程中出现的错误
    
    #获取命令结果
    result = stdout.read()  ##标准输出,只有在命令正确的情况下才会输出,否则返回的信息为空。
    print (result.decode()) ##因为linux是utf-8的bytes格式所以要decode
    
    #关闭连接
    ssh.close()
    
    执行结果:
    Traceback (most recent call last):
      File "E:/python/代码练习/A1.py", line 11, in <module>
        ssh.connect(hostname='192.168.21.128',port=22,username='test',password='123qwe')
      File "D:\python3.6.4\lib\site-packages\paramiko\client.py", line 402, in connect
        self, server_hostkey_name, server_key
      File "D:\python3.6.4\lib\site-packages\paramiko\client.py", line 768, in missing_host_key
        'Server {!r} not found in known_hosts'.format(hostname)
    paramiko.ssh_exception.SSHException: Server '192.168.21.128' not found in known_hosts
    

    我们可以看到报错Server '192.168.21.128' not found in known_hosts
    image_1c7akfv9c3et16b7njv1h9j3in70.png-51.4kB
    linux默认是没有.ssh文件的

    image_1c7an1a691snp1mpf14bo13et12nq7d.png-29.3kB
    第一次被ssh登录时,会弹出提示来做一个签名认证,有了这个签名认证才能正常登录,而之前用python代码去ssh登录linux时,报错就是因为找不到known_hosts这个文件,所以会报错。
    image_1c7aicl891sfq1mge3o41htl162k9.png-55.9kB
    通过ssh test@192.168.21.129 -P22 (只要通过ssh登录一次就会出现.ssh文件)

    image_1c7aijatl1gp7365142n1kn4p0rm.png-10.8kB
    而在.ssh中有known_hosts文件
    image_1c7ailvs21heqa3oqfvk5kk133.png-35.1kB
    可以看到known_hosts中的内容是一些加密的算法,会将被登录认证的信息存储到该文件中。

    注意在上面的代码中将其中一行代码给注释掉了, ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())。该代码就是当known_hosts文件中没有被登录设备信息时,就会自动将期添加进去。
    所以将该代码取消注释就可以正常登录了。

    image_1c7asvoigfkk1lne1hf81upupc47q.png-35.8kB
    这回看到可以正常执行代码了。

    import paramiko
    
    #创建SSH对象
    ssh = paramiko.SSHClient()
    
    #允许连接不在know_hosts文件中的主机
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    #连接服务器
    ssh.connect(hostname='192.168.21.128',port=22,username='test',password='123qwe')
    
    #执行命令
    stdin,stdout,stderr = ssh.exec_command('abc')
    ## 这里使用abc这个无效命令
    
    #获取命令结果
    result = stdout.read()
    print (result.decode())
    #关闭连接
    ssh.close()
    
    执行结果:
    D:\python3.6.4\python.exe E:/python/代码练习/A1.py
    
    Process finished with exit code 0
    ##可以看到 执行结果为空,这说明stdout.read()只有当命令正常执行后,得到了返回结果才会输出,如果错误的话stdout.read就不会有任何输出结果。
    
    import paramiko
    
    #创建SSH对象
    ssh = paramiko.SSHClient()
    
    #允许连接不在know_hosts文件中的主机
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    #连接服务器
    ssh.connect(hostname='192.168.21.128',port=22,username='test',password='123qwe')
    
    #执行命令
    stdin,stdout,stderr = ssh.exec_command('abc')
    ## 这里使用abc这个无效命令
    
    #获取命令结果
    res,err = stdout.read(),stderr.read()
    result = res if res else err    ##这里我们使用三元运算
    print (result.decode())
    #关闭连接
    ssh.close()
    
    执行结果:
    D:\python3.6.4\python.exe E:/python/代码练习/A1.py
    bash: abc: 未找到命令
    
    Process finished with exit code 0
    #可以看到,我们这次得到了标准错误的结果。
    

    ssh上传、下载

    ssh_sft:通过ssh上传文件
    
    import paramiko
    
    # 创建连接
    transport = paramiko.Transport(('192.168.21.128',22))
    # 连接服务器
    transport.connect(username='test',password='123qwe')
    ##根据创建的连接+用户名密码来连接服务器
    
    sftp = paramiko.SFTPClient.from_transport(transport)
    ##将transport当做参数交给paramiko.SFTPClient.from_transport
    ##接下来真正的传输协议是在SFTPClient中定义的(实际交互是通过SFTPClient实现的)
    
    # 将location.py上传至服务器 /tmp/test.py
    sftp.put('test.txt','/home/test/test_new.txt')
    
    # 将remove_path 下载到本地 local_path
    # sftp.get('remove_path','local_path')
    
    transport.close()
    

    image_1c7au539frp41ljf1725fl41rbl87.png-39.2kB
    可以看到,文件成功的被传入到linux中了。

    ssh_sft:通过ssh下载文件
    
    import paramiko
    
    # 创建连接
    transport = paramiko.Transport(('192.168.21.128',22))
    # 连接服务器
    transport.connect(username='test',password='123qwe')
    
    sftp = paramiko.SFTPClient.from_transport(transport)
    
    # 将location.py上传至服务器 /tmp/test.py
    # sftp.put('test.txt','/home/test/test_new.txt')
    
    # 将remove_path 下载到本地 local_path
    sftp.get('/home/test/aaaa.txt','from_linux.txt')
    
    transport.close()
    

    image_1c7audftbbge1feg1gjo1mhl1f5j94.png-8.6kB
    成功将linux中的文件下载到本地

    ssh认证

    之前的代码,我们通过用户名和密码来登录linux,但是我们使用的是明文,这种情况容易被非法获取。

    那么接下来我们可以通过密钥的方式来实现ssh登录。

    在 192.168.21.128 linux中生成一堆密钥(私钥和公钥)
    
    test@test-virtual-machine:~$ 
    test@test-virtual-machine:~$ ssh-keygen ##通过该命令生成
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/test/.ssh/id_rsa): 
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    Your identification has been saved in /home/test/.ssh/id_rsa.
    ##私钥存储的位置(私钥不可以给任何人,只能自己存储好)
    Your public key has been saved in /home/test/.ssh/id_rsa.pub.
    ##公钥存储的位置
    The key fingerprint is:
    SHA256:u9dlYPkYxpc4DjIVvVRNZdx7Tq1/7eRADP1lcvsXnpM test@test-virtual-machine
    The key's randomart image is:
    +---[RSA 2048]----+
    |          .o ..+*|
    |          . o. .+|
    |         . o.+o.*|
    |        o . @oo**|
    |        So = Bo*o|
    |         .  o.* *|
    |        .  . o.E=|
    |         .. .  +*|
    |        ..     .+|
    +----[SHA256]-----+
    test@test-virtual-machine:~$ 
    
    在 192.168.21.128 linux中查看公钥
    
    test@test-virtual-machine:~$ more .ssh/id_rsa.pub 
    
    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCh7LDTrqAO7p9J0UgRaNkHJX8lua4hamfnLZ07Ugg2
    E/nGR5pX+CWGmVelNZZVdUyRl2Riu28tbyG3mMBZ9aFZFVhPCD3aY2Y2oTQIK/t62IzBpMT9TL7GwRCF
    a+S6wzx2oDU+gp2VkYOxdBEYBDD1Gj0LH6qT7QIc4Xb6XufZdFV+T8XTRqrQ/KcWJp3fNbnaHWBWaERe
    +v6RZtlPW5ermK/nfgzB2Ccq/tUQNlFUOFOI6ddNazS1bIuKOTS21FeFuBda3wLbeoe785e2XFZA2FQp
    AVKtvjExsSS6PCeMbvb01JOienVm/tUPIQ21v9vup09tc/bbfS6wxkQVtc8P test@test-virtual-m
    achine
    
    ## 上面我们可以看到我们复制了一整段密钥,但是确是有好几个换行符,密钥中是不能有换行符的,否则就不是原来的密钥了,也就无效了(我们直接按照下图解决存在多余换行符问题)。
    
    test@test-virtual-machine:~$
    #我们将该公钥内容copy到其他设备上,其他设备就可以使用该公钥了。
    

    image_1c7b4eipo1hp59fss8h131fdad9h.png-36.6kB
    我们直接将公钥复制到pycharm中,可以看到有好几个换行符,那么我们就需要往前删除将其变成一行。
    image_1c7b4h48niub5rmrcd1rbn1tti9u.png-9.4kB
    这回密钥都在一行了,就不存在多余的换行符了,然后复制当前公钥即可。

    在192.168.21.129这台linux上
        通过su命令进入root模式
        通过adduser zhangsan来添加新用户
        通过su - zhangsan命令 进入zhangsan这个用户的家目录下
        注销当前用户,使用zhangsan用户登录linux,然后在/home/zhangsan下创建'.ssh'目录,然后在'.ssh'目录下创建authorized_keys文档
        将192.168.21.128生成的公钥内容copy到authorized_keys文档中,注意copy公钥后的文档中不能有换行,否则就不是原有的公钥内容了。
    
        zhangsan@test-virtual-machine:~$ ll .ssh/authorized_keys 
    -rw-rw-r-- 1 zhangsan zhangsan 412 2月  27 15:10 .ssh/authorized_keys
    ## 查看该文档当前权限是-rw-rw-r--;一共可以设置三组权限(三组rwx),第一组表示属主,第二组表示属组,第三组表示others。
    r是读,w是写,x是执行;r是4,w是2,x是1。
    
        我们可以需要修改authorized_keys文档权限,通过 'shmod 777 authorized_keys' 来修改,4+2+1(r+w+x)=7,所以是修改该文档为三个7。
    
    zhangsan@test-virtual-machine:~/.ssh$ chmod 777 authorized_keys 
    zhangsan@test-virtual-machine:~/.ssh$ ll authorized_keys 
    -rwxrwxrwx 1 zhangsan zhangsan 412 2月  27 15:10 authorized_keys*
    ## 此时我们可以看到该文档已经拥有最高操作权限。可以访问、修改、执行。
    
        但是我们只要求只有当前用户可以访问、修改、所以就要修改权限为 600。
    
    zhangsan@test-virtual-machine:~/.ssh$ chmod 600 authorized_keys 
    zhangsan@test-virtual-machine:~/.ssh$ ll authorized_keys 
    -rw------- 1 zhangsan zhangsan 412 2月  27 15:10 authorized_keys
    ##目前只有zhangsan这个用户可以读、写了。
    
    此时我们在192.168.21.128这个linux上
        test@test-virtual-machine:~$ ssh test@192.168.21.129 -P22
        test@192.168.21.129's password:
        可以看到我们ssh  test这个用户时,依然需要密码
        ## 这是因为我们只将公钥copy到了zhangsan下的.ssh/authorized_keys文件中,并没有copy到test用户下
    
        test@test-virtual-machine:~$ ssh zhangsan@192.168.21.129 -P22
    Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-21-generic x86_64)
    
     * Documentation:  https://help.ubuntu.com/
    
    687 个可升级软件包。
    355 个安全更新。
    
    Last login: Tue Feb 27 16:23:32 2018 from 192.168.21.128
    zhangsan@test-virtual-machine:~$ 
    ## 我们ssh  zhangsan可以看到此时就不需要通过密码来登录了。
    ## 这里注意,如果依然提示密码登录的话,请先关闭192.168.21.128 linux端的cmd终端,重新打开再重新试一下。
    
    之前我们通过粘贴的方式将公钥给另一台linux,粘贴的过程中出现了一些问题,那么我们下面通过其他方式来传递公钥。
    
    在 192.168.21.129 的linux上
        zhangsan@test-virtual-machine:~$ vi .ssh/authorized_keys 
        zhangsan@test-virtual-machine:~$ rm .ssh/authorized_keys 
        zhangsan@test-virtual-machine:~$ rm -d .ssh/
        ## 我们将之前创建的文件和目录都删掉
    
    在 192.168.21.128 的linux上
        ssh-copy-id -i /home/test/.ssh/id_rsa.pub zhangsan@192.168.21.129
        ## 直接将公钥传递给192.168.21.129
    
    test@test-virtual-machine:~$ ssh-copy-id -i /home/test/.ssh/id_rsa.pub zhangsan@192.168.21.129
    /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/test/.ssh/id_rsa.pub"
    /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
    /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
    zhangsan@192.168.21.129's password: 
    
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh 'zhangsan@192.168.21.129'"
    and check to make sure that only the key(s) you wanted were added.
    ## 已经成功,提示要求到192.168.21.129上检查一下。
    
    在 192.168.21.129 的linux上:
        zhangsan@test-virtual-machine:~$ ls -a
    .              .cache   .gnupg         .sogouinput       公共的  下载
    ..             .config  .ICEauthority  .ssh              模板    音乐
    .bash_history  .dbus    .local         .Xauthority       视频    桌面
    .bash_logout   .dmrc    .presage       .xinputrc         图片
    .bashrc        .gconf   .profile       .xsession-errors  文档
    zhangsan@test-virtual-machine:~$ 
    ##我们可以看到 已经存在了.ssh目录
    
    在 192.168.21.128 的linux上:
        test@test-virtual-machine:~$ ssh zhangsan@192.168.129 -p22
    
    ^C
    test@test-virtual-machine:~$ ssh zhangsan@192.168.21.129 -p22
    Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-21-generic x86_64)
    
     * Documentation:  https://help.ubuntu.com/
    
    687 个可升级软件包。
    355 个安全更新。
    
    Last login: Tue Feb 27 16:23:51 2018 from 192.168.21.128
    zhangsan@test-virtual-machine:~$ 
    ##可以看到 已经实现了 免密码登录。
    

    通过Python实现RSA秘钥认证
    
    我们直接利用Linux中的秘钥,需要私钥拷贝到Windows中
    
    在Windows下,通过xshell  ssh连接Linux,在Linux中通过sz ~/.ssh/id_rsa将私钥保存到Windows
    

    image_1c7e7lpem1oreaqj13hs14di1d0a9.png-10.7kB
    我们将id_rsa重新命名为id_rsa_win,然后剪切到当前代码目录中

    在 192.168.202.128 Linux中:
        cd .ssh ##进入.ssh目录
        cat id_rsa.pub >> authorized_keys
        ## 需要将公钥的内容copy到authorized_keys中(authorized_keys之前不存在,通过该命令会新建并将公钥内容拷贝到authorized_keys文档中);  认证时会通过authorized_keys中的公钥来认证,而不是id_rsa.pub。
    
    如此便完成了公钥的安装。有些时候,可能会有一些权限问题,可以执行如下:
    chmod 600 authorized_keys
    chmod 700 ~/.ssh
    

    python RSA认证参考网址:http://50vip.com/article/84

    通过Python实现RSA秘钥认证
    
    import paramiko
    
    #指定私钥在哪里
    private_key = paramiko.RSAKey.from_private_key_file('id_rsa_win')
    ## 因为在当前目录,所以直接指定文件名即可;如果在其他目录,就需要加上路径了
    ##这里要注意id_rsa_win是私钥、私钥、私钥(重要的事所三遍),私钥认证,公钥解密。
    
    # 创建SSH对象
    ssh = paramiko.SSHClient()
    
    #允许连接不在know_hosts文件中的主机
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    # 链接服务器
    ssh.connect(hostname='192.168.202.128', port=22, username='test', pkey=private_key)
    ## 这里注意,如果使用RSA认证,那么最后面就不是password了,而是pkey=private_key
    ## pkey 表示是private key
    
    # 执行命令
    stdin,stdout,stderr = ssh.exec_command('df')
    
    # 获取命令结果
    res,err = stdout.read(),stderr.read()
    result = res if res else err
    print (result.decode())
    
    # 关闭连接
    ssh.close()
    
    执行结果:
    文件系统          1K-块    已用     可用 已用% 挂载点
    udev             991244       0   991244    0% /dev
    tmpfs            203072    6428   196644    4% /run
    /dev/sda1      19478204 5577000 12888724   31% /
    tmpfs           1015344     112  1015232    1% /dev/shm
    tmpfs              5120       0     5120    0% /run/lock
    tmpfs           1015344       0  1015344    0% /sys/fs/cgroup
    tmpfs            203072      48   203024    1% /run/user/1000
    
    通过RSA认证上传下载
    
    import paramiko
    
    private_key = paramiko.RSAKey.from_private_key_file('id_rsa_win')
    
    transport = paramiko.Transport(('192.168.202.128',22))
    transport.connect(username='test',pkey=private_key)
    
    sftp = paramiko.SFTPClient.from_transport(transport)
    
    # 将xxx.py上传到服务器 /tmp/test.py
    sftp.put('test.txt','/home/test/test_new.txt')
    
    # 将xxx.txt下载到本地
    sftp.get('/home/test/aaaa.txt','aaaa_new.txt')
    
    transport.close()
    

关键字