python修改paramiko模块开发运维审计堡垒机

  1.  第三方paramiko模块下载:https://github.com/paramiko/paramiko

  2.  paramiko源码包演示:运行demo.py文件远程登陆

    

  3.  通过修改paramiko源码,主要是修改demo.py文件和interactive.py开发运维审计堡垒机

  4.  堡垒机原理  

    堡垒机有一个公共账号,所有人都是通过这个公共账号登陆堡垒机,且只能用于登陆,不能做其他操作;root用户可以做任何操作;
  公共账号登陆后,选择主机组,选择主机,选择你的用户,可以使用密码登陆;也可以使用密钥登陆,登陆后的操作记录历史到文件中。

  5.  目录和文件介绍

    

  6.  修改interactive.py文件

import socket
import sys
from paramiko.py3compat import u
import time
# windows does not have termios...
try:
    import termios
    import tty
    has_termios = True
except ImportError:
    has_termios = False


def interactive_shell(chan):
    if has_termios:
        posix_shell(chan)
    else:
        windows_shell(chan)


def posix_shell(chan):
    import select
    
    oldtty = termios.tcgetattr(sys.stdin)
    try:
        tty.setraw(sys.stdin.fileno())
        tty.setcbreak(sys.stdin.fileno())
        chan.settimeout(0.0)
        records = []
        f = open('/root/tmp/record_comm/record.txt','ab+')
        while True:
            r, w, e = select.select([chan, sys.stdin], [], [])
            if chan in r:
                try:
                    x = u(chan.recv(1024))
                    if len(x) == 0:
                        sys.stdout.write('\r\n*** EOF\r\n')
                        break
                    sys.stdout.write(x)
                    sys.stdout.flush()
                except socket.timeout:
                    pass
            if sys.stdin in r:                #屏幕接收
                x = sys.stdin.read(1)         #每次只接收一个字符
                records.append(x)
                if x == '\r':
                    c_time = time.strftime('%Y-%m-%d %H:%M:%S')
                    cmd = ''.join(records).replace('\r','\n')
#                    log = ('%s     %s' % (c_time,cmd)).encode()
#                    print('your input:',log)
                    log = ('%s     %s' % (c_time,cmd)).encode()
                    f.write(log)
                    records = []
                if len(x) == 0:
                    break
                chan.send(x)

    finally:
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
        f.close()
    
# thanks to Mike Looijmans for this code
def windows_shell(chan):
    import threading

    sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n")
        
    def writeall(sock):
        while True:
            data = sock.recv(256)
            if not data:
                sys.stdout.write('\r\n*** EOF ***\r\n\r\n')
                sys.stdout.flush()
                break
            sys.stdout.write(data)
            sys.stdout.flush()
        
    writer = threading.Thread(target=writeall, args=(chan,))
    writer.start()
        
    try:
        while True:
            d = sys.stdin.read(1)
            if not d:
                break
            chan.send(d)
    except EOFError:
        # user hit ^Z or F6
        pass
interactive.py

  7.  编写zj.py脚本,选择登陆的主机组和主机

import os
def hosts_group():
    os.system('clear')
    print('【主机组列表】1.qqandroid组 2.qqios组')
    global x_1
    x_1 = input('请输入你要选择的主机组编号:')

def hosts():
    global lines
    if x_1 == '1':
        os.system('clear')
        print('【qqandroid组主机列表】 1.192.168.244.128 2.192.168.244.122 3.返回上一页')
        x_21 = input('请输入你要登陆的主机编号:')
        f = open('../hosts_user/qqandroid.txt')
        for line in f.readlines():
            line = line.strip('\n').split(' ')
            if line[0] == x_21:
                lines = line[1]
        if x_21 == '3':
            os.system('/usr/bin/python /tmp/script/demo.py')
    else:
        os.system('clear')
        print('【qqios组主机列表】 1.192.168.244.128 2.192.168.244.123 3.返回上一页')
        x_22 = input('请输入你要登陆的主机编号:')
        f = open('/root/tmp/hosts_user/qqios.txt')
        for line in f.readlines():
            line = line.strip('\n').split(' ')
            if line[0] == x_22:
                lines = line[1]
        if x_22 == '3':
            os.system('/usr/bin/python /tmp/script/demo.py')
def yh():
    os.system('clear')
    print('【用户列表】1.root 2.test 3.test1 4.返回上一页')
    xyh = input('请输入你要登陆的主机用户编号:')
    global youruser
    f = open('/root/tmp/hosts_user/users.txt')
    for line in f.readlines():
        line = line.strip('\n').split(' ')
        if line[0] == xyh:
            youruser = line[1]
    if xyh == '4':
        os.system('/usr/bin/python /tmp/script/demo.py')
    
zj.py

  8.  修改demo.py文件

#!/usr/bin/env python

# Copyright (C) 2003-2007  Robey Pointer <robeypointer@gmail.com>
#
# This file is part of paramiko.
#
# Paramiko is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation; either version 2.1 of the License, or (at your option)
# any later version.
#
# Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Paramiko; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.


import base64
from binascii import hexlify
import getpass
import os
import select
import socket
import sys
import time
import traceback
from paramiko.py3compat import input
import zj
import paramiko
try:
    import interactive
except ImportError:
    from . import interactive


def agent_auth(transport, username):
    """
    Attempt to authenticate to the given transport using any of the private
    keys available from an SSH agent.
    """
    
    agent = paramiko.Agent()
    agent_keys = agent.get_keys()
    if len(agent_keys) == 0:
        return
        
    for key in agent_keys:
        print('Trying ssh-agent key %s' % hexlify(key.get_fingerprint()))
        try:
            transport.auth_publickey(username, key)
            print('... success!')
            return
        except paramiko.SSHException:
            print('... nope.')


def manual_auth(username, hostname):
    default_auth = 'p'
    auth = input('Auth by (p)assword, (r)sa key, or (d)ss key? [%s] ' % default_auth)
    if len(auth) == 0:
        auth = default_auth

    if auth == 'r':
#        default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
        default_path = '/root/.ssh/id_rsa'
        path = input('RSA key [%s]: ' % default_path)
       # path = '/root/.ssh/id_rsa'
        if len(path) == 0:
            path = default_path
        try:
            key = paramiko.RSAKey.from_private_key_file(path)
       #     zj.hosts_group()
       #     zj.hosts()
       #     zj.yh()
       #     username = 'root'
        except paramiko.PasswordRequiredException:
            password = getpass.getpass('RSA key password: ')
            key = paramiko.RSAKey.from_private_key_file(path, password)
        t.auth_publickey(username, key)
    elif auth == 'd':
        default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_dsa')
        path = input('DSS key [%s]: ' % default_path)
        if len(path) == 0:
            path = default_path
        try:
            key = paramiko.DSSKey.from_private_key_file(path)
        except paramiko.PasswordRequiredException:
            password = getpass.getpass('DSS key password: ')
            key = paramiko.DSSKey.from_private_key_file(path, password)
        t.auth_publickey(username, key)
    else:
        pw = getpass.getpass('Password for %s@%s: ' % (username, hostname))
        t.auth_password(username, pw)


# setup logging
paramiko.util.log_to_file('demo.log')

username = ''
if len(sys.argv) > 1:
    hostname = sys.argv[1]
    if hostname.find('@') >= 0:
        username, hostname = hostname.split('@')
else:
#    hostname = input('Hostname: ')
    zj.hosts_group()
    zj.hosts()
    hostname = zj.lines
if len(hostname) == 0:
    print('*** Hostname required.')
    sys.exit(1)
port = 22
if hostname.find(':') >= 0:
    hostname, portstr = hostname.split(':')
    port = int(portstr)

# now connect
try:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((hostname, port))
except Exception as e:
    print('*** Connect failed: ' + str(e))
    traceback.print_exc()
    sys.exit(1)

try:
    t = paramiko.Transport(sock)
    try:
        t.start_client()
    except paramiko.SSHException:
        print('*** SSH negotiation failed.')
        sys.exit(1)

    try:
        keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
    except IOError:
        try:
            keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts'))
        except IOError:
            print('*** Unable to open host keys file')
            keys = {}

    # check server's host key -- this is important.
    key = t.get_remote_server_key()
    if hostname not in keys:
        print('*** WARNING: Unknown host key!')
    elif key.get_name() not in keys[hostname]:
        print('*** WARNING: Unknown host key!')
    elif keys[hostname][key.get_name()] != key:
        print('*** WARNING: Host key has changed!!!')
        sys.exit(1)
    else:
        print('*** Host key OK.')

    # get username
    if username == '':
        default_username = getpass.getuser()
#        username = input('Username [%s]: ' % default_username)
        zj.yh()
        username = zj.youruser
        if len(username) == 0:
            username = default_username

    agent_auth(t, username)
    if not t.is_authenticated():
        manual_auth(username, hostname)
    if not t.is_authenticated():
        print('*** Authentication failed. :(')
        t.close()
        sys.exit(1)

    chan = t.open_session()
    chan.get_pty()
    chan.invoke_shell()
    print('*** Here we go!\n')
    f = open('/root/tmp/record_comm/record.txt','ab+')
    sj = time.strftime('%c')
    f.write(('\n').encode())
    f.write((username + ' ' + 'login:' +' ' + sj + ' ' + 'from' + ' '+'192.168.244.129' + '\n').encode())
    f.close()
    interactive.interactive_shell(chan)
    f = open('record.txt','ab+')
    f.write((username+' ' + 'exit:'+' '+sj +'\n').encode())
    f.close()
    chan.close()
    t.close()

except Exception as e:
    print('*** Caught exception: ' + str(e.__class__) + ': ' + str(e))
    traceback.print_exc()
    try:
        t.close()
    except:
        pass
    sys.exit(1)
demo.py

  9.   可以登陆的服务器IP和用户名

    

  10.  在堡垒机中添加一个公共用户test,普通用户只能使用test用户登陆,并且登陆上后只能登陆后端服务器,不能做其他操作

    

  11.  修改目录权限

    

  12 .  堡垒机IP:192.168.244.129

    后端服务器IP:192.168.244.128

    登陆演示:

    

    

    

    选择登陆方式,可以使用密码(p),也可以使用密钥(r)。

    使用密钥登陆到后端服务器

  13.  退出登陆后,可以在历史记录文件中查看历史记录命令

    

  14.  基于浏览器的web shell,shellinabox

    启动shellinabox,默认启动4200端口

     shellinabox下载地址 https://github.com/SoulSu/shellinabox    

    (1)chmod +x ./configure 添加权限
    (2)./configure --prefix=/usr/local/shellinaboxed
    (3)make && make install
    (4)[root@hello ~]# cd /usr/local/shellinaboxed/bin
    (5)[root@hello bin]# ./shellinaboxd -t -t参数:取消证书
      [root@hello ~]# netstat -tnlp
      tcp 0 0 0.0.0.0:4200 0.0.0.0:* LISTEN 15887/./shellinabox

    在浏览器中输入:192.168.244.129:4200

    

 

转载于:https://www.cnblogs.com/homle/p/8734367.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值