堡垒机

1. 需求分析

1、 实际开发中,运维团队与 IDC 机房是分开的,即有专门的放置服务器服务器的机房(称为 IDC 机房)。因此运维人员只能远程连接操作服务器

2、 开发人员开发出一款软件经测试之后,交给运维人员,然后再远程将程序上线到服务器中

3、 一般一个公司会有很多 “业务线”,如:广告线、电商、等,不同的业务线一般也会配备多个运维人员,当一个运维休息时,另一个则接管

4、 运维人员以 SSH 方式连接远程服务器,服务器要防火墙策略来识别该 IP 是否安全,这样就需要给每台服务器设置防火墙策略,太过繁琐

5、 实际运维是以 VPN(虚拟专用网络,会形成一个安全隧道,供运维人员使用),它不受时间和地点的限制,即使不在公司,只要进入虚拟专用网络即可进入。

6、 人为因素导致的安全隐患:

  • 假如同一条业务线上的几个运维人员A和B,他们都有操作服务器的权限(即知道这台服务器的账户密码)。
  • 若A与B之间有矛盾,B 打算陷害A。他在休假前,在服务器中写了一个脚本程序(引发服务器某个错误),并且设置好定时任务(并清除痕迹)。
  • 当A值班时,到时间脚本执行,服务器出现错误。不管A是否登录服务器,A都要负主要责任,然而这是B搞的鬼。

因此就需要有一个系统或程序来记录操作服务器的人员、时间、地点等,任何对服务器的操作,都要经过此程序记录(一般上市公司都会定期检查类似这种记录)。

7、 这个程序就是“堡垒机”,在运维人员与服务器之间有一台特殊的服务器(堡垒机),运维人员要想操作服务器就需要经过堡垒机,它会将所有操作都记录下来,并保存在堡垒机上


堡垒机特点,包括但不限于:

  • 它可以保存服务器的账户和密码,运维人员连接某台服务器时,不需要再手动输入账户密码,只需提供主机名即可。因为堡垒机上存储有服务器的登录账户、主机信息等
  • 记录操作服务器的账户(即运维人员)、时间、以及对服务器有哪些操作等,这在一定程度上提高了服务器的安全性。
  • 允许用户对不同的目标设备有不同的访问权限,如:10.0.2.34 有mysql 用户的权限,192.168.3.22 有root用户的权限等
  • 分组管理,即可以对设置进行分组,允许用户访问某组机器,但对组里的不同机器依然有不同的访问权限
  • 堡垒机也是一台服务器,但是它是一台特殊的服务器,运维人员需要事先登录堡垒机,才能操作服务器。

2. 堡垒机架构

主要作用是权限控制和用户行为审计,所有的用户操作服务器都必须经过堡垒机,所有人的足迹都会有记录下来(不管是否愿意)。

不同的用户有不同的权限,能够操作服务器的范围也是有区别的,如:

  • 运维:服务器的所有权限
  • DBI:只能操作数据库
  • Web:只能查看或其他权限等

3. 登录服务器的两种方式

3.1 密码形式登录

客户端通过 xshell(SSH 形式),连接远程服务器,需要知道服务器:主机名、 账号、密码

3.2 SSH key(公钥)

当有很多服务器,而又不想使用密码登录,且较为安全。那么可以在客户端生成公钥,再将其 copy 到目标服务器上,进行相应的配置即可登录到目标服务器上。

1、 概述:

两个 Linux 机器之间使用 SSH 不需要用户名、密码,而是采用数字签名 RSA 或 DSA 来完成

2、 模型分析

  • 客户机:192.168.20.59
  • 目标机:192.168.20.60

3、 实现的目标

A 连接B,无需密码,加密方式使用 RSA 或 DSA 皆可,默认DSA

1、登录A机器,使用命令:ssh-keygen -t [rsa|dsa],生成公钥(id_rsa.pub)和私钥(id_rsa)
2、将公钥复制到 B 中的 .ssh 目录,(scp -rp id_rsa.pub 192.168.20.60:/home/xxx/)
3、将 id_rsa..pub 重命名为 authorized_keys,或直接内容覆盖(cat id_rsa.pub > authorized_keys),没有authorized_keys文件,就新建一个。
4、登录 B,直接运行 ssh 192.168.20.60 即可。
5、若失败,则要看看 authorized_keys 和 .ssh 权限,要保证用户自己有写权限。
Chmod 600 authorized_keys,chmod 700 -R.ssh

其他命令:
1.	把远程文件 copy  到本地
scp -rp alex@192.168.10.35:/home/alex/id_rsa /tmp/
2.	查看当前用户 id:whoami
3.	没有 .ssh  文件夹时,可以退出当前登录用户,再重新用 .ssh 登录下别的用户,再退出 exit就会生成 .ssh 文件夹

参考博客:https://blog.csdn.net/kongqz/article/details/6338690

4. Paramiko 模块

堡垒机基于 Python 第三方模块 Paramiko 实现,Paramiko 基于SSH 用于连接远程服务器并执行相关操作。

安装:

 pip3 install paramiko

4.1 SSHClient

基于用户名和密码连接

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='hj', password='1xxx9')

# 执行命令
stdin, stdout, stderr = ssh.exec_command('ls')
# 获取命令结果
result = stdout.read()
print(str(result, encoding='utf-8'))

# 关闭连接
ssh.close()

运行过程中报错:hm.add_string(self.Q_C.public_numbers().encode_point())

原因:paramiko 依赖的 cryptography,在新的版本中有一些 API 被弃用了

解决办法:

pip uninstall cryptography==2.5
pip install cryptography==2.4.2

参考博客:Python 使用 paramiko CryptographyDeprecationWarning 报警处理


SSHClient 封装 Transport:

import paramiko

transport = paramiko.Transport(('hostname', 22))
transport.connect(username='wupeiqi', password='123')

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('df')
print(stdout.read())

transport.close()

基于公钥密钥连接

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('/home/hj/.ssh/id_rsa.pub')

# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='192.168.21.128', port=22, username='hj', key=private_key)

# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
print(result)

# 关闭连接
ssh.close()

SSHClient 封装 Transport:

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')

transport = paramiko.Transport(('hostname', 22))
transport.connect(username='wupeiqi', pkey=private_key)

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('df')

transport.close()

4.2 SFTPClient

用于连接远程服务器并执行上传下载.

基于用户名密码上传下载:

import paramiko

transport = paramiko.Transport(('192.168.21.128', 22))
transport.connect(username='hj', password='xxx39')

sftp = paramiko.SFTPClient.from_transport(transport)
# 将 1.jpg 上传至服务器 /tmp/1.jpg
sftp.put('C:\Users\hj\Desktop\1.jpg', '/tmp/1.jpg')

# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')

transport.close()

基于公钥密钥上传下载:

import paramiko
  
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
  
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='wupeiqi', pkey=private_key )
  
sftp = paramiko.SFTPClient.from_transport(transport)
# 将 1.jpg 上传至服务器 /tmp/1.jpg
sftp.put('C:\Users\hj\Desktop\1.jpg', '/tmp/1.jpg')

# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
  
transport.close()

4.3 示例

基于用户名和密码实现连接远程服务器,并执行相关命令操作以及上传下载文件:

import paramiko
import uuid

class SSHConnection(object):

    def __init__(self, host='192.168.21.128', port=22, username='hj', pwd='abcd110139'):
        self.host = host
        self.port = port
        self.username = username
        self.pwd = pwd
        self.__k = None

    def run(self):
        self.connect()
        pass
        self.close()

    def connect(self):
        transport = paramiko.Transport((self.host, self.port))
        transport.connect(username=self.username, password=self.pwd)
        self.__transport = transport

    def close(self):
        self.__transport.close()

    def cmd(self, command):
        ssh = paramiko.SSHClient()
        ssh._transport = self.__transport
        # 执行命令
        stdin, stdout, stderr = ssh.exec_command(command)
        # 获取命令结果
        result = stdout.read()
        return result

    def upload(self,local_path, target_path):
        # 连接,上传
        sftp = paramiko.SFTPClient.from_transport(self.__transport)
        # 将 1.jpg 上传至服务器 /home/hj/桌面/1.jpg
        sftp.put(local_path, target_path)

ssh = SSHConnection()
ssh.connect()
r1 = ssh.cmd('df')
ssh.upload('1.jpg', "/home/hj/桌面/1.jpg")
ssh.close()

5. 模型设计

1、命令行模式:

2、批量命令:

2、批量文件上传及下载操作:

源码:https://github.com/hj1933/FortressMachine

6. 相关知识

6.1 Linux 中 .bashrc 文件

利用 Linux 系统启动时会加载执行 .bashrc 文件这一特性,我们可以将其设置为当用户开启堡垒机服务器时,就执行堡垒机中的一个脚本文件。

好处就是用户只能使用堡垒机,而不能修改堡垒机,用户的一切行为都将被记录下来。

sudo vim /home/hj/.bashrc

# 在最后添加两句后保存
echo '这句话开机就会启动'			# 打印输出
python3 /home/hj/test.py			# 执行 test.py  这个脚本

# 堡垒机执行脚本
# python3 FortressMachine/crazyeye_manage.py run
# logout							# 当按下 Ctrl+C 终端脚本时,中断连接

连接堡垒机时启动相关脚本文件:


6.2 shellinabox

在上面我们都是以终端形式操控堡垒机,如果我们想以 Web 页面形式操控堡垒机可以使用 shellinabox

shellinbox 有一个内建的 web server作为基本的web ssh client,允许你通过指定的端口访问 Linux 服务器的 ssh shell,只要你的浏览器支持 AJAX/JS/CSS就可以访问,不需要额外的浏览器插件,十分的简单操作,软件轻量级,不过服务端需要 openssl 支持,debian和 ubuntu 官方还提供有 deb,centos也有 rpm包。

下载安装

# On Debian, Ubuntu and Linux Mint
$ sudo apt-cache search shellinabox
$ sudo apt-get install openssl shellinabox

# On RHEL, CentOS and Fedora
yum install openssl shellinabox

CentOS 部分系统可能找不到 shellinaboxd 包,可手动下载 rpm 包安装(找到适合自己系统版本的 rpm 包):

下载地址

rpm 安装 shellinabox

yum install -y shellinabox-2.20-5.el7.x86_64.rpm

查看安装了哪些文件及安装位置命令:

[root@hj 桌面]# rpm -ql shellinabox
/etc/sysconfig/shellinaboxd
/usr/lib/systemd/system/shellinaboxd.service
/usr/sbin/shellinaboxd
/usr/share/doc/shellinabox-2.20
/usr/share/doc/shellinabox-2.20/AUTHORS
/usr/share/doc/shellinabox-2.20/NEWS
/usr/share/doc/shellinabox-2.20/README
/usr/share/doc/shellinabox-2.20/README.Fedora
/usr/share/doc/shellinabox-2.20/print-styles.css
/usr/share/doc/shellinabox-2.20/shell_in_a_box.js
/usr/share/doc/shellinabox-2.20/styles.css
/usr/share/man/man1/shellinaboxd.1.gz
/usr/share/shellinabox
/usr/share/shellinabox/color.css
/usr/share/shellinabox/monochrome.css
/usr/share/shellinabox/white-on-black.css
/var/lib/shellinabox


配置 shellinabox

编辑 /etc/sysconfig/shellinaboxd,更改端口(默认 4200)及添加远程访问地址:

# Basic options
USER=shellinabox
GROUP=shellinabox
CERTDIR=/var/lib/shellinabox
PORT=4200						# 端口,可不更改
OPTS="--disable-ssl-menu -s /:LOGIN"


# Additional examples with custom options:

# Fancy configuration with right-click menu choice for black-on-white:
# OPTS="--user-css Normal:+black-on-white.css,Reverse:-white-on-black.css --disable-ssl-menu -s /:LOGIN"

# Simple configuration for running it as an SSH console with SSL disabled:
# OPTS="-t -s /:SSH:host.example.com"
OPTS="-t -s /:SSH:192.168.21.129"		# 远程地址

在这里只是做简单的配置,更多配置可参考 :<https://github.com/shellinabox/shellinabox>

如果要外网访问,那么还需要配置防火墙,允许 shellinabox 端口通过:

$ sudo vim /etc/sysconfig/iptables

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 4200 -j ACCEPT		# 添加这一行,需添加在 22 端口下面
-A INPUT -j REJECT --reject-with icmp-host-prohibited

COMMIT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 4200 -j ACCEPT

重启 iptables 服务:service iptables restart。启动 shellinabox 服务:service shellinaboxd start

查看是否启动:

现在我们就可以在 Windows 上访问 Linux 了,访问:<http://192.168.21.129:4200/>

参考文章:

posted @ 2019-06-24 11:15  Hubery_Jun  阅读(803)  评论(0编辑  收藏  举报