Python项目-----CMDB自动化资产扫描

一、项目介绍

1.项目介绍
本项目基于Django实现后台管理,nmap 识别网络上的主机、使用telnet命令探测主机SSH端口存活扫描、使用paramiko对远程服务器进行命令或文件操作。最终实现Web形式的自动化资产扫描系统,可以通过IP来扫描到所对应主机的详细信息。项目基于HTTP实现自动化任务接受和响应接口设计,基于MySQL用作的关系型数据存取。本次项目实战就是用最短的时间、手把手地完成运维开发系统的开发实战。

二、项目环境搭建

  • 创建Django项目devops,查看本地django版本,远程服务器的虚拟环境django版本也需要为2.2
    在这里插入图片描述

连接并配置远程服务器

  • 连接并配置远程服务器 [Tools] -> [Deployment]
    在这里插入图片描述
  • 配置本地目录和远程服务器目录的映射(Mapping), 上述操作完成, 本地文件修改, 远程服务器文件也同时修改.
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200525192533956.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0MjQxODYx,size_16,color_FFFFFF,t_70

远程服务器虚拟环境的配置

  • 连接远程服务器命令行bash
    在这里插入图片描述
  • 创建虚拟环境并激活虚拟环境
  • `cd /data/www/devops
  • virtualenv -p /usr/bin/python3 env
    遇到的问题:换了一个云服务器后,虚拟环境没有安装,因此需要先pip3 install virtualenv
  • source env/bin/active
    在这里插入图片描述
  • pip install django==2.2 -i https://pypi.douban.com/simple` 安装虚拟环境需要的django

远程服务器解释器和目录映射的配置

  • 项目在远程创建,因此本地虚拟环境应该修改为远程python虚拟环境 settings中设置
    在这里插入图片描述
  • 虚拟环境使用项目下的虚拟环境
    在这里插入图片描述
    在这里插入图片描述
  • 上传项目:把本地项目和远程服务器关联
    在这里插入图片描述

三、MySQL数据库配置

  • 远程服务器虚拟环境下安装数据库:
    在这里插入图片描述
  • 用户授权:让任意主机的指定用户可以访问
  • ` create database if not exists devopsProject default charset utf8;
  • MariaDB [(none)]> create user devops@’%’ identified by ‘123’;
  • MariaDB [(none)]> grant all on devpsProject.* to devops@’%’;
  • 测试:mysql -udevops -p123`在这里插入图片描述
  • 测试用户授权是否成功
    在这里插入图片描述
  • 遇到的问题:阿里云 数据库无法登录
  • 报错信息:Access denied for user ‘root’@‘localhost’ (using password: YES)
  • 1)修改密码 mysql–> use mysql; --> update user set authentication_string=password(‘新密码’) where user=‘root’;—>flush privilage;(不建议使用)
  • 2)阿里云安全组对于mysql端口3306的设置
  • 3) 终端关闭防火墙
  • 经过分析最终解决方法:
    解决方法:本次的问题呢,mysql 可以登录,但是mysql -uroot -p123不能登录 说明是一开始安装mysql设置密码的问题,默认情况下-h不指定是连接本机的数据库,如果连接远程主机数据库要通过-hIP指定;
    mysql设置密码:mysql_secure_installation来初始化设置密码。修改密码才能进入mysql数据库中设置。

Django数据库配置

  • 修改配置文件的信息:Settings 数据库设置为mysql 、中文汉字时区的设置
    注意:settings中allowhost中必须加入外网ip 47.92.233.236,或者直接ALLOWED_HOSTS = [’*’]
  1. 中文汉字时区的设置:LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai'在这里插入图片描述
  • 生成数据库表
    在这里插入图片描述
    操作中遇到的问题:

django2.2/mysql ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3
报错环境 python=3.6,django=2.2,PyMySQL=0.9.3

原因分析: Django连接MySQL时默认使用MySQLdb驱动,但MySQLdb不支持Python3,因此这里将MySQL驱动设置为pymysql,:django2.2和pymysql版本不匹配。使用 pip install pymysql 进行安装,然后在工程文件__init__.py添加以下代码即可。
具体做法:
#init.py
import pymysql
pymysql.install_as_MySQLdb()
django降到2.1.4版本就OK了

  • 测试数据表是否创建?数据信息是否写入?
    连接mariadb数据库在这里插入图片描述> 配置数据库信息
    在这里插入图片描述
  • 访问数据库表和数据内容
    在这里插入图片描述

初次运行项目:查看后台管理页面

django后台创建超级用户

python manage.py createsuperuser

一切都设置好后,运行项目进入django后台:

  • python manage.py runserver 0.0.0.0:8000

    问题:网页输入外网ip:8000无法访问是因为公网ip的安全组端口没有设置8000

页面展示:

在这里插入图片描述

四、Django工程多配置文件

在这里插入图片描述

  1. base.py文件: 基本的配置文件,将原先seetings.py文件的内容拷贝进来
  2. development.py文件: 开发环境的配置文件
    from .base import *
    DEBUG = True
  3. production.py文件: 生产环境的配置文件
    from .base import *
    # 开发环境一定要关闭调试模式
    DEBUG = False
    # 允许所有主机访问
    ALLOWED_HOSTS = [’*’]
  4. 修改manage.py文件, 默认寻找的设置文件是当前项目中的settings文件, 如果是开发环境, 修改如下:
    def main():
    os.environ.setdefault(‘DJANGO_SETTINGS_MODULE’,
    'devops.settings.development’)
    #…此处省略代码
    if name == ‘main’:
    main()
  5. 如果项目将来需要上线, 修改启动项目访问的配置文件为生产环境的配置文件即可, 如下:
    def main():
    os.environ.setdefault(‘DJANGO_SETTINGS_MODULE’,
    devops.settings.production’)
    # …此处省略代码
    if name == ‘main’:
    main()
  6. 启动项目的后台展示
    在这里插入图片描述

五、Django工程应用与模块加载

为了方便在一个大的Django项目中,管理实现不同的业务功能, 我们会在项目中创建多个APP实现功能。为了更加方便管理APP, 项目结构更加清晰。可以专门创建apps目录存储项目应用, 专门创建extra_apps存储项目第三方APP, 项目结构如下所示:
在这里插入图片描述

  • 但项目运行时, 不会自动寻找apps和extra_apps子目录中创建的APP, 创建子应用方法如下:
    远程服务器创建好后download到本地
    鼠标先选择要从远程服务器下载的文件,tools的development中选择download from devops 就可以啦
    在这里插入图片描述
  • 子应用的加载
    base下:
    在这里插入图片描述

六、主机存活探测模块和工具

Nmap探测工具

Nmap,也就是Network Mapper,最早是Linux下的网络扫描和嗅探工具包。是一款用于网络发现和安全审计的网络安全工具。
功能:

  • 主机发现 - 识别网络上的主机。例如,列出响应TCP和/或ICMP请求或打开特定端口的主机。
    在这里插入图片描述
nmap -n -sP 172.25.254.197  扫描某一个IP是否存活
 nmap -n -sP 172.25.254.0/24  扫描某一个局域网下哪些主机存活
  • 端口扫描 - 枚举目标主机上的开放端口。(不常用)
$ nmap -n -p 172.25.254.197
#具体指定要扫描的端口为50-80
$ nmap -n -p50-80 172.25.254.197
#具体指定要扫描的端口为22和80
$ nmap -n -p22,80 172.25.254.197
  • OS检测 - 确定网络设备的操作系统和硬件特性。
 # -O是检测操作系统交换机
    $ nmap -O 172.25.254.197

Nmap的Python操作接口: python-nmap

python-nmap是一个使用nmap进行端口扫描的python库,它可以很轻易的生成nmap扫描报告,并且可以帮助系统管理员进行自动化扫描任务和生成报告。同时,它也支持nmap脚本输出。

  • 具体的代码调用如下:
import nmap
# 实例化对象, portScanner()类用于实现对指定主机进行端口扫描
nm = nmap.PortScanner()
# 以指定方式扫描指定主机或网段的指定端口
result = nm.scan(hosts='172.25.254.0/24', arguments='-n -sP')
print("扫描结果: ", result)
# 返回的扫描具体的nmap命令行
print("nmap命令行: ", nm.command_line())
# 返回nmap扫描的主机清单,格式为列表类型
print("主机清单: ", nm.all_hosts())
# 查看指定主机信息
print('172.25.254.197的主机信息: ', nm['172.25.254.197'])

代码执行效果如下图所示:

扫描结果:
{'nmap': {'command_line': 'nmap -oX - -n -sP 172.25.254.0/24', 'scaninfo': {},
'scanstats': {'timestr': 'Wed Dec 25 16:14:47 2019', 'elapsed': '6.06',
'uphosts': '2', 'downhosts': '254', 'totalhosts': '256'}}, 'scan':
{'172.25.254.197': {'hostnames': [{'name': '', 'type': ''}], 'addresses':
{'ipv4': '172.25.254.197'}, 'vendor': {}, 'status': {'state': 'up', 'reason':
'syn-ack'}}, '172.25.254.250': {'hostnames': [{'name': '', 'type': ''}],
'addresses': {'ipv4': '172.25.254.250'}, 'vendor': {}, 'status': {'state': 'up',
'reason': 'syn-ack'}}}}
nmap命令行: nmap -oX - -n -sP 172.25.254.0/24
主机清单: ['172.25.254.197', '172.25.254.250']
172.25.254.197的主机信息:
{'hostnames': [{'name': '', 'type': ''}], 'addresses': {'ipv4':
'172.25.254.197'}, 'vendor': {}, 'status': {'state': 'up', 'reason': 'syn-ack'}}

操作中的报错总结:
一、

  • 云服务器虚拟环境下:pip install python-nmap 报错:
  • 报错信息: pip: command not found…
  • 解决方法:
$ wget https://bootstrap.pypa.io/get-pip.py
  $ python get-pip.py

二、
云服务器虚拟环境下:pip install python-nmap之后pycharm文件中import nmap无法导入时:查看解释器环境是否正确
在这里插入图片描述

七、SSH端口存活扫描

使用telnet命令探测主机列表是否属于Linux服务器。
在这里插入图片描述

  • telnetlib模块探测 telnetlib模块提供的Telnet类实现了Telnet协议。
telnetlib模块提供的Telnet类实现了Telnet协议。
import telnetlib
import re
# 实例化对象
tn = telnetlib.Telnet(host='172.25.254.197', port=22, timeout=5)
# read_until读取直到遇到了换行符或超时秒数。默认返回bytes类型,通过decode方法解码为字符
串。
tn_result = tn.read_until(b"\n", timeout=5).decode('utf-8')
# 通过正则匹配且忽略大小写, 寻找是否ssh服务开启。
ssh_result = re.search(pattern=r'ssh', string=tn_result, flags=re.I)
# 如果能匹配到内容, 说明ssh服务开启, 是Linux服务器.
if ssh_result:
print("Linux服务器存活")
else:
print("其他服务器存活")

代码执行结果如下:

Linux服务器存活

扫描探测小结

在这里插入图片描述

八、Python的SSH登录模块paramiko

  • 什么是主机登录探测?
    用一系列的验证方式循环进行SSH登录, 得到争取的登录方式。

  • 主机SSH登录验证方式
    SSH常用来远程登录到远程机器,有两种常用的方法:
    第一种便是账号密码登录。
    第二种就是公钥私钥无密码登录。(如何实现无密码登录?)

  • 什么是paramiko?
    paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。

  • 如何安装paramiko?

# 使用豆瓣的镜像源, 安装paramiko模块并指定安装版本为2.6.0.
$ pip install -i https://pypi.douban.com/simple paramiko==2.6.0
  • paramiko核心组件
    paramiko包含两个核心组件:SSHClient和SFTPClient。
    SSHClient的作用类似于Linux的ssh命令,是对SSH会话的封装,该类封装了传输(Transport),通道(Channel)及SFTPClient建立的方法(open_sftp),通常用于执行远程命令
    SFTPClient的作用类似与Linux的sftp命令,是对SFTP客户端的封装,用以实现远程文件操作,如文件上传、下载、修改文件权限等操作。

  • 项目代码: 基于paramiko实现ssh客户端密钥远程登录

  • 客户端连接服务端公钥私钥:
    在这里插入图片描述
  • 测试之前生成公钥和私钥进行测试 :
    在这里插入图片描述
  • 本次测试将公钥分发给本机的root用户,ssh-copy-id -i ~/.ssh/id_rsa.pub root@localhost
    分发公钥时需要输入密码,此密码为root用户可以登录本机的密码,也就是root可以登录47.92.233.236的密码;
  • 测试:[root@docker .ssh]# ssh root@localhost 可以实现无密码登录

pyhon代码实现公钥和私钥的无密码连接 :

def login_ssh_key( hostname='172.25.254.197', keyfile='./id_rsa',
username='root', port=22, command='df -h'):
    """
    基于paramiko实现ssh的自动化密钥管理
    """
    # 配置私人密钥文件位置
    private = paramiko.RSAKey.from_private_key_file(keyfile)
    # 实例化SSHClient
    with paramiko.SSHClient() as client:
        # 自动添加策略,保存服务器的主机名和密钥信息,如果不添加,那么不再本地
know_hosts文件中记录的主机将无法连接
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        # 连接SSH服务端,以用户名和密码进行认证
        client.connect(hostname=hostname, port=port, username=username,
pkey=private)
        # 打开一个Channel并执行命令。 stdout 为正确输出,stderr为错误输出,同时是有1
个变量有值
        stdin, stdout, stderr = client.exec_command(command)
        # 打印执行结果
        print(stdout.read().decode('utf-8'))
if __name__ == '__main__':
    # login_ssh_passwd(hostname='127.0.0.1', command='hostname')
    login_ssh_key(hostname='127.0.0.1', command='hostname')

运行结果:foundation0.ilt.example.com

九、系统信息获取

  • 通过系统获取哪些信息
    在这里插入图片描述- 获取信息的Linux命令介绍
    获取主机名的命令(选择通用方式): hostname、uname -a、cat /etc/sysconfig/network(主 要针对Centos)
    获取系统版本: cat /etc/issue(可能为空)、cat /etc/redhat-release、uname、 lsb_release
    获取MAC地址: cat /sys/class/net/ [^vtlsb] */address、ifconfig ens33
    获取服务器硬件机型: dmidecode -s system-manufacturer、dmidecode -s systemproduct-name

十、项目的大体规划

前面说了这么多,现在就真正进入布局阶段了,Django数据库模型设计、配置文件设置、视图函数、路由配置、后台admin管理请看代码链接Django_CMDB_code

  • 最后的测试阶段:运行项目python manage.py runserver 0.0.0.0:8000
  • 访问网址http://ip:port/scan 查看扫描结果
  • 访问网址http://ip:port/admin 查看后台管理
  • 测试遇到的疑惑:
  • 在云服务器下的虚拟环境中输入 python manage.py runserver 0.0.0.0:8000可以访问,只输入python manage.py runserver浏览器页面无法访问原因:
  1. 目前8000端口只和127.0.0.1这个IP绑定,只能通过127.0.0.1:8000在浏览器访问,用其他的ip:8000访问是失败的,因为其他ip与8000端口没有关联起来;因此用公网IP:port访问浏览器不可能成功
  2. 而0.0.0.0:8000的意思:如果希望通过任意一个IP访问8000端口,每一台主机都会有多个IP,让8000端口和当前主机的任意一个IP(0.0.0.0)绑定在一起, 包含公网IP,因此公网IP:8000才可以从浏览器访问。
  3. 本机测试不指定 生产环境需要指定为0.0.0.0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章