第十三章 堡垒机
1.堡垒机的概念
2.堡垒机的实现
概念:
背景,公司为了主机系统的管理和安全,更有效的工作,产生的一种工作模式,往往一个公司有很多台服务器,这些服务器又有许多人需要去操作,运维、开发、测试等。人多
手杂,谁操作了什么,导致了什么问题,用户的管理。主机的管理,都需要高效的实现,堡垒机实现了这些管理上的方便。
直接说事
堡垒机执行流程:
1、管理员为用户在服务器上创建帐号(将公钥放置服务器,或者使用用户名密码)
2、用户登录堡垒机,输入堡垒机用户名密码,现实当前用户管理的服务器列表
3、用户选择服务器,并自动登录
4、执行操作并同时将用户操作记录
注:配置.brashrc实现ssh登录后自动执行脚本,如:/usr/bin/python /home/wulaoer/menu.py
实现过程
步骤一,使用用户登录
1 #!/usr/bin/env python 2 # --*--coding:utf-8 --*-- 3 import getpass 4 5 user = raw_input('username:') 6 pwd = getpass.getpass('password:') 7 if user == 'wulaoer' and pwd == '123': 8 print '登陆成功' 9 else: 10 print '登陆失败'
步骤二,根据用户获取相关服务器列表
1 dic = { 2 'laowu': [ 3 '172.16.103.189', 4 'c10.puppet.com', 5 'c11.puppet.com', 6 ], 7 'wu': [ 8 'c100.puppet.com', 9 ] 10 } 11 12 host_list = dic['laowu'] 13 #用户可以连接的主机IP 14 print 'please select:' 15 for index, item in enumerate(host_list, 1): 16 print index, item 17 #循环可以连接的主机 18 inp = raw_input('your select (No):')#选择要连接的IP 19 inp = int(inp) 20 hostname = host_list[inp-1]#连接的主机IP 21 port = 22
步骤三,根据用户名、私钥登录服务器
1 tran = paramiko.Transport((hostname, port,)) 2 #连接服务器的端口和IP 3 tran.start_client() 4 default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') 5 #连接方式,使用密钥 6 key = paramiko.RSAKey.from_private_key_file(default_path) 7 #密钥默认路径 8 tran.auth_publickey('wulaoer', key) 9 #连接用户名和密钥 10 11 # 打开一个通道 12 chan = tran.open_session() 13 # 获取一个终端 14 chan.get_pty() 15 # 激活器 16 chan.invoke_shell() 17 18 ######### 19 # 利用sys.stdin,肆意妄为执行操作 20 # 用户在终端输入内容,并将内容发送至远程服务器 21 # 远程服务器执行命令,并将结果返回 22 # 用户终端显示内容 23 #########
用户监控日志:
1 while True: 2 # 监视用户输入和服务器返回数据 3 # sys.stdin 处理用户输入 4 # chan 是之前创建的通道,用于接收服务器返回信息 5 readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1) 6 if chan in readable: 7 try: 8 x = chan.recv(1024) 9 if len(x) == 0: 10 print ' *** EOF ', 11 break 12 sys.stdout.write(x) 13 sys.stdout.flush() 14 except socket.timeout: 15 pass 16 if sys.stdin in readable: 17 inp = sys.stdin.readline() 18 chan.sendall(inp)
1 # 获取原tty属性 2 oldtty = termios.tcgetattr(sys.stdin) 3 try: 4 # 为tty设置新属性 5 # 默认当前tty设备属性: 6 # 输入一行回车,执行 7 # CTRL+C 进程退出,遇到特殊字符,特殊处理。 8 9 # 这是为原始模式,不认识所有特殊符号 10 # 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器 11 tty.setraw(sys.stdin.fileno()) 12 chan.settimeout(0.0) 13 14 while True: 15 # 监视 用户输入 和 远程服务器返回数据(socket) 16 # 阻塞,直到句柄可读 17 r, w, e = select.select([chan, sys.stdin], [], [], 1) 18 if chan in r: 19 try: 20 x = chan.recv(1024) 21 if len(x) == 0: 22 print ' *** EOF ', 23 break 24 sys.stdout.write(x) 25 sys.stdout.flush() 26 except socket.timeout: 27 pass 28 if sys.stdin in r: 29 x = sys.stdin.read(1) 30 if len(x) == 0: 31 break 32 chan.send(x) 33 34 finally: 35 # 重新设置终端属性 36 termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
1 def windows_shell(chan): 2 import threading 3 4 sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF. ") 5 6 def writeall(sock): 7 while True: 8 data = sock.recv(256) 9 if not data: 10 sys.stdout.write(' *** EOF *** ') 11 sys.stdout.flush() 12 break 13 sys.stdout.write(data) 14 sys.stdout.flush() 15 16 writer = threading.Thread(target=writeall, args=(chan,)) 17 writer.start() 18 19 try: 20 while True: 21 d = sys.stdin.read(1) 22 if not d: 23 break 24 chan.send(d) 25 except EOFError: 26 # user hit ^Z or F6 27 pass
注:密码验证t.auth_password(username,pw)
详见:paramiko源码demo