第十三章   堡垒机

  1.堡垒机的概念

 2.堡垒机的实现

 

概念:

   背景,公司为了主机系统的管理和安全,更有效的工作,产生的一种工作模式,往往一个公司有很多台服务器,这些服务器又有许多人需要去操作,运维、开发、测试等。人多

手杂,谁操作了什么,导致了什么问题,用户的管理。主机的管理,都需要高效的实现,堡垒机实现了这些管理上的方便。

  直接说事

accessclient 堡垒机 终端 堡垒机操作_用户名

堡垒机执行流程:

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 '\r\n*** EOF\r\n',
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 '\r\n*** EOF\r\n',
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.\r\n\r\n")
 5 
 6     def writeall(sock):
 7         while True:
 8             data = sock.recv(256)
 9             if not data:
10                 sys.stdout.write('\r\n*** EOF ***\r\n\r\n')
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

 

A wise man thinks all that he says, a fool says all that he thinks.