1. 整体工程设计
- 资产的自动化扫描发现 python程序扫描发现企业内部的所有资产,当资产出现变动能自动及时的发现并完成资产变更、
- ansible的自动化任务执行 使用ansible的ad-hoc和playbook实现批量主机的自动化任务。
2. 环境安装
- python3 以上
- mysql 5.7 安装
编辑repo
执行vim /etc/yum.repos.d/mongo.repo
内容如下:
[mysql57-community-dmr]\
name=MySQL 5.7 Community Server Development Milestone Rel\
easebaseurl=[http://repo.mysql.com/yum/mysql-5.7-community/el/6/$basearch/](http://repo.mysql.com/yum/mysql-5.7-community/el/6/%24basearch/)\
enabled=1gpgcheck=0\
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
执行如下命令:
yum install mysql
- Mongodb 安装
**1、编辑repo**
执行vim /etc/yum.repos.d/mongo.repo
粘贴内容如下:
[mongodb-org-3.4]\
name=MongoDB 3.4 Repositorybaseurl=[https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/](https://repo.mongodb.org/yum/redhat/%24releasever/mongodb-org/3.4/x86_64/)\
gpgcheck=0\
enabled=1\
**2、安装**
执行:yum install mongodb
mongodb.x86_64 2.4.14-4.el6 geoip-extras
mongodb-org.x86_64 3.4.10-1.el6 mongodb-org-3.4
mongodb-org-mongos.x86_64 3.4.10-1.el6 mongodb-org-3.4
mongodb-org-server.x86_64 3.4.10-1.el6 mongodb-org-3.4
mongodb-org-shell.x86_64 3.4.10-1.el6 mongodb-org-3.4
mongodb-org-tools.x86_64 3.4.10-1.el6 mongodb-org-3.4
**3 、官方安装文档**
<https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/>
- Nginx 安装
**1、编辑repo文件**
执行:vim /etc/yum.repos.d/nginx
编辑文件,如下:
注意:需要根据你的系统版本修改OS和OSRELEASE
[nginx]name=nginx repobaseurl=[http://nginx.org/packages/OS/OSRELEASE/$basearch/gpgcheck=0](http://nginx.org/packages/OS/OSRELEASE/%24basearch/gpgcheck=0)\
enabled=1
**2、安装**
nginx.x86_64 1.12.2-1.el6.ngx nginx
执行:
yum install nginx
**3、官方文档**
<http://nginx.org/en/linux_packages.html#stable>
- Redis 安装
redis和mysql和python可参考我之前发的文章juejin.cn/post/684490…
3.资产管理,自动化发现、扫描
3.1 nmap
nmap 是一款用于网络发现和安全审计的网络安全工具
python 安装:
pip install python-nmap
yum安装:
yum install -y namp
- 参数说明 -n:不做DNS解析,不用解析主机名和域名
-sP:ping扫描,不会发送多个SNP包,比ping效率高
-PE:扫描服务器端口存活状态
namp -n -sP -PE IP/掩码 探测确认主机是否存活
3.2 python-nmap使用扫描存活设备IP
python-nmap模块实例化
- 最常用的是PortScanner类,这个类实现Nmap工具功能的封装。对这个类进行实例化很简单,只需要如下语句便可实现。
import nmap
nm=nmap.PortScanner()
- PortScannerAsync类和PortScanner类的功能相似,但是这个类可以实现异步扫描,对这个类的实例化语句如下。
import nmap
nm=nmap.PortScannerAsync()
首先看一下PortScanner类,这个类中包含了如下几个函数。 scan()函数:这个函数的完整形式为scan(self,hosts=‘127.0.0.1’,ports=None,arguments=’-sV’,sudo=False),用来对指定目标进行扫描。
-
参数hosts的值为字符串类型,表示要扫描的主机,形式可以是IP地址,例如"192.168.1.1",也可以是一个域名,例如"www.nmap.org"
-
参数ports的值也是字符串类型,表示要扫描的端口。如果要扫描的是单一端口,形式可以为"80"。如果为多个端口,可以用逗号分开,例如"80,443,3389"。如果要扫描的是连续的端口范围,可以用横线,例如“1-5000” 。
-
参数arguments的值也是字符串类型,这个参数实际上就是Nmap扫描所用的参数。
参数 作用
-O 系统扫描
-V,-v,-D,-d,-p debug信息
–fuzzy 推测操作系统检测结果
-sT TCP端口扫描(完整三次握手)
-sU UDP端口扫描(不回应可能打开,回应则关闭)
-sL DNS反向解析
-sS 隐藏扫描(半开SYN)
-sP 发现存活主机(直连arp,非直连TCP80,ICMP)
-sO 确定主机协议扫描
-sW 对滑动窗口的扫描
-sA TCP ACK扫描
-sN 关闭主机扫描(不管是否存活直接扫描)
-sF fin扫描
-sX Xmas扫描(fin psh urg为置位)
-sI 完全隐藏(以一个跳板为主机(无流量)扫描另一台主机)
-sV 服务器版本
-sC 跟安全有关的脚本
-PN 扫描自己
以上就是我常用的指令==参数,还有很多很多,就不一一列举了。 all_hosts()函数:返回一个被扫描的所有主机列表。 如果要对192.168.1.101的 探测确认主机是否存活,可以使用以下命令。
import nmap
nm = nmap.PortScanner()
nm.scan(hosts='192.168.1.0/24',arguments='-n -sP -PE') # 返回JSON信息,包含扫描的主机IP、状态等
nm.all_hosts() # 返回存活主机IP 列表
3.2 python telnet模块
SSH端口存活扫描,判断主机列表是否属于Liunx服务器
Liunx命令: telnet IP 端口
import re
from telnetlib import Telnet
tn = Telnet(host, port=23, timeout=10)
tn.read_until("\n", timeout=5) # 读取返回ssh结果,直到有\n就结束
# 正则匹配ssh字符,判断是否为Liunx服务器
3.3 主机登录探测
登录服务器:
- ssh -l 用户名 IP -p 端口
- 配置公钥私钥 ssh -i 密钥文件路径 -l 用户名 IP -p 端口
3.4 python SSH模块
pexpect
用来通过启动子程序,使用正则表达式对程序输出做出特定响应(此方式有缺陷,可了解,可跳过) 以此实现与其自动交互的Python模块。Pexpect的基本工作流程,基本可以分为以下三个步骤:
- 1. 首先用spawn来执行一个程序;
- 2. 然后用expect方法来等待指定的关键字,这个关键字是被执行的程序打印到标准输出上面的;
- 3. 最后当发现这个关键字以后,使用send/sendline方法发送字符串给这个程序。
通常在程序中第一步只需要做一次,第二步和第三步会不停的循环来完成整个工作。当然在Pexpect中还有很多其他方法,编写程序时可以根据自己的需求选择使用。
# run()函数 run功能相对简单,只能实现简单交互
import pexpect
pexpect.run("ls /tmp", withexitstatus=1) # withexitstatus 判断命令是否执行成功,返回元组包括命令执行的内容及状态 0代表成功
# spawn()函数:启动子程序,有丰富的方法实现对子程序的控制
import pexpect
ssh_k = pexpect.spawn("ssh root@192.168.0.11 -p22")
# expect()方法
当使用spawn()方法启动了一个程序并返回程序控制句柄后,就可以使用expect()方法来等待指定的关键字了。关键字可以是字符串、正则表达式、EOF、TIMEOUT或者以上类型组成的列表,用来匹配子程序返回的结果。如果只提供字符串等非列表,则匹配成功后返回0,如果提供列表,则返回匹配成功的列表元素的索引,匹配失败会抛出异常。
ssh_k.expect("password") # 返回0 代表匹配成功,匹配失败会报错timeout
匹配超时错误结果,可单独或多个匹配
ssh_k.expect([pexpect.TIMEOUT, pexpect.EOF] # 匹配结果返回列表内的索引
注意:正则表达式$在expect代表就是$符号,不是-一个-一个正则表达式
\r\n代表行结束
# send()/sendline()方法 ,发送命令
# sendline()和send()的区别就是sendline()发送的是带回车符的字符串
- 模拟登录
import pexpect
def login_ssh_passwd(port="",user="",host="",passwd=""):
'''函数:用于实现pexepect实现ssh的自动化用户密码登录'''
# print 'ssh -p %s %s@%s' % (port,user, host)
if port and user and host and passwd:
ssh = pexpect.spawn('ssh -p %s %s@%s' % (port,user, host))
i = ssh.expect(['password:', 'continue connecting (yes/no)?'], timeout=5)
if i == 0 :
ssh.sendline(passwd)
elif i == 1:
ssh.sendline('yes\n')
ssh.expect('password: ')
ssh.sendline(passwd)
index = ssh.expect (["#", pexpect.EOF, pexpect.TIMEOUT])
if index == 0:
print "logging in as root!"
ssh.interact()
elif index == 1:
print "logging process exit!"
elif index == 2:
print "logging timeout exit"
else:
print "Parameter error!"
def login_ssh_key(keyfile="",user="",host="",port=""):
'''函数:用于实现pexepect实现ssh的自动化密钥登录'''
if port and user and host and keyfile:
ssh = pexpect.spawn('ssh -i %s -p %s %s@%s' % (keyfile,port,user, host))
i = ssh.expect( [pexpect.TIMEOUT,'continue connecting (yes/no)?'], timeout=2)
# print '...................................',0
if i == 1:
ssh.sendline('yes\n')
index = ssh.expect (["#", pexpect.EOF, pexpect.TIMEOUT])
else:
index = ssh.expect (["#", pexpect.EOF, pexpect.TIMEOUT])
if index == 0:
print "logging in as root!"
ssh.interact()
elif index == 1:
print "logging process exit!"
elif index == 2:
print "logging timeout exit"
else:
print "Parameter error!"
def main():
'''主函数:实现两种方式分别的登录'''
# login_ssh_passwd(port='22',user='root',host='192.168.1.101',passwd='imooccs')
login_ssh_key(keyfile="/tmp/id_rsa",port='22',user='root',host='192.168.1.101')
if __name__ == "__main__":
main()
pexpect缺点: 1、依赖终端命令的方式 2、不同的ssh登录环境兼容较差
paramiko
基于Python实现的SSH远程安全连接,用于SSH远程执行命令、文件传输等功能的ssh客户端模块。(采用)
基于用户名和密码实现SSH功能
import paramiko
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在known_hosts文件上的主机
# 即允许将信任的主机自动加入到host_allow 列表,此方法必须放在connect方法的前面
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器,没有返回结果说明建立连接,存在返回结果表示错误信息显示
ssh.connect(hostname="192.168.0.99", port=22, username="root", password="rootroot")
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 结果放到stdout中,如果有错误将放到stderr中
result = stdout.read().decode()
# 获取错误提示(stdout、stderr只会输出其中一个)
err = stderr.read()
# 关闭连接
ssh.close()
print(stdin, result, err)
使用秘钥实现SSH功能
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('id_rsa31')
# 创建SSH对象
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='192.168.79.9', port=22, username='root', pkey=private_key) # 返回三个对象,操作系统标准输入,标准输出,错误输出
stdin, stdout, stderr = ssh.exec_command('ifconfig') # 执行命令后返回结果分别赋值给三个变量
res_out = stdout.read() # 获取返回结果
print(res_out.decode())
ssh.close()
4. 通过操作系统获取主机资产信息
4.1 获取主机名命令
hostname、uname -a、cat /etc/sysconfig/network等
4.2 获取系统版本
cat /etc/issue、cat /etc/redhat-release、uname、 lsb_ release
4.3 获取Mac地址
获取mac地址
linux系统:
cat /sys/class/net/eth0/address 或 所有cat /sys/class/net/e*/address 或正则匹配 cat /sys/class/net/[^vtlsb]*/address
ifconfig eth0
ip a
ESXI:esxcfg-vmknic -| 或 esxcfg-vmknic -1 |awk '{print $8}' | grep ':'
# 通用方式命令
cat /sys/class/net/[^vtlsb]*/address||esxcfg-vmknic -l|awk '{print $8}' | grep ':'
4.4 获取服务器硬件机型
dmidecode -s system-manufacturer、dmidecode -s system-product-name
4.5 获取序列号信息
dmidecode -s system-serial-number
4.6 网络设备SNMP资产扫描
网络设备只需要开启配置:
snmp-server enable traps
服务器则需要安装和配置:
1、apt-get install snmpd snmp snmp-mibs-downloader
2、配置修改: agentAddress
网络设备snmp客户端
# -v 版本 指定版本号
# -c 指定密码认证标识,默认public
# iso.3.6.1.2.1.1.1.0 获取某一项值,可加可不加
snmpwalk -v 2c -c public IP iso.3.6.1.2.1.1.1.0
Centos安装:yuminstall net-snmp-utils
ubuntu:apt-get install snmp
python模块: pip install pysnmp
python示例:
SNMP标准引入一组ASN.1语言元素,称之为SMI(Structure of Management Information)。由SMI描述的相互关联的被管对象(Managed Objects)组成MIB(Management Information Base)模块。
核心MIB中经常用到的Managed Objects成为SNMP标准的一部分。剩下的MIB一般由设备生产商在其设备中创建。(也就是说这些MIB是生产商和设备相关的)
PySNMP是一个纯粹用Python实现的SNMP。
用PySNMP的最抽象的API为One-line Applications。其中有两类API:同步的和非同步的,都在模块pysnmp.entity.rfc3413.oneliner.cmdgen 中实现。
from pysnmp.entity.rfc3413.oneliner import cmdgen然后用cg = cmdgen.CommandGenerator()来产生一个CommandGenerator对象,以后调用cg的getCmd等方法来获取或者设置网络设备信息。
getCmd()需要三个参数:
-
1.cmdgen.CommunityData() 社区信息 传入三个数据,安全my-agent、社区名public、snmp协议版本,之间用逗号隔开,例如 cmdgen.CommunityData('my-agent', 'public', 1)**
-
2.cmdgen.UdpTransportTarget() 通道参数,传入一个元组,包含主机IP/** 域名和端口,例如:cmdgen.UdpTransportTarget(('192.168.70.237', 161)
-
- OID mib值,例如 '.1.3.6.1.4.1.1800.5.13.2'
-
注意:三个参数之间用 ","隔开。
下面上个例子是获得设备snmp数据:
from pysnmp.entity.rfc3413.oneliner import cmdgen
def snmpget():
cg = cmdgen.CommandGenerator() ##获得CommandGenerator对象
errorIndication, errorStatus, errorIndex, varBinds = cg.getCmd(
#0代表v1,1代表v2c
cmdgen.CommunityData('my-agent', 'public', 1), ##社区信息,my-agent ,public 表示社区名,1表示snmp v2c版本,0为v1版本
cmdgen.UdpTransportTarget(('192.168.70.237', 161)),##这是传输的通道,传输到IP 192.168.70.237, 端口 161上(snmp标准默认161 UDP端口)
'.1.3.6.1.4.1.1800.5.13.2' ##传送的OID,个人认为MIB值
)
print str(varBinds[0][1]); ##varBinds返回是一个stulp,含有MIB值和获得值
def runit(loop=1):
for i in range(loop):
snmpget()
#print i
if __name__ == "__main__":
runit(loop=1)
4.7 docker扫描
关键信息命令
docker ps |awk -F '->' '{print $1}'|grep -v 'CONTAINER'|awk 'BEGIN{FS~/s+/;}{print $NF" "$1" "$2;}'|sed s/0.0.0.0://
4.8 kvm物理机资产探测扫描
宿主机获取到虚拟机的mac地址
cat /sys/class/net/vnet*/address
优点: 1、mac地址的唯一性 2、不容易修改
4.9 ESX物理机资产探测扫描
ESXI的资产SDK调用
官方网址: https://www.vmware.com/support/pubs/sdk_pubs.html
Python模块: pyvmomi
持续更新~