使用nmap扫描外租机开放的端口并识别
使用nmap扫描外租机开放的端口并识别 需要用到pubapi来写入数据库 不适用于所有环境,脚本只做技术储备
from requests.packages import urllib3
from BasicInterface import executeMysqlData
from base64 import b64encode
import json, time,re,requests,datetime
urllib3.disable_warnings()
#将cmdb的ip地址提交到gcp的nmap接口去扫描开放端口
def isPublicIpv4(ip):
pattern = r'^(?:(?:(?:[1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.){3}{?:[1-9]?\d|1\d\d|2[0-4]\d|25[θ-5]))$'
private_pattern = r'^(?:(?:10|127)\.\d{1,3}\.\d{1,3}\.\d{1,3}|(?:172\.(?:1[6-9]|2\d|3[01]))\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}}$'
return re.match(pattern,ip) is not None and re.match(private_pattern,ip) is None
#只要7天内有扫过的 ip就不会再扫描了,所以这里抓出7天内有扫描过的
ipqueryIPExist = "SELECT ip FROM ScanResult WHERE ScanTime >= CURDATE() - INTERVAL 6 DAY AND ScanTime <=CURDATE() GROUP BY ip;"
resultQuery = executeMysqlData(1,'read',queryIPExist)
resultList = []
for q in resultQuery:
for r in q:
resultList.append(r)
cookies = {'sso' : '<ssoKey>'}
#脚本中的接口有多页,所以做了一个遍历,n为页面编号
n=1
ipListJson = {}
#本地手动添加的ip列表,如果有需要增加的,则按格式添加即可
ipList = ['<ipaddress>']
while 1:
response = requests.get('<serverUrl>'%n, cookies= cookies , verify= False)
status_code = response.status_code
response = json.loads(response.text)
if status_code != 404:
for m in range (θ,len(response['result'])):
name = response['result'][m]['name']
ip = response['result'][m]['ip']
user = response['result'][m]['user']
app = response['result'][m]['app']
#有些ip地址栏里写了乱七八糟的东西,所以为了确保获取到正确的 ip,所以限制了长度
if isPublicIpv4(ip) == True and ip != '0.0.0.0' and ip != '1.1.1.1' and ip != 'N/a' and ip!='θ' and ip !' and ip !='127.0.0.1':
ipListJson[name] = {}
ipListJson[name]['ip'] = ip
ipListJson[name]['user'] = user
ipListJson[name]['app'] = app
else:
break
n += 1
for i in ipList:
ipListJson[i] = {}
ipListJson[i]['ip'] = i
ipListJson[i]['user'] = ''
#外租机的 ip和端口,外租机上使用 flask开放了1080端口用来接收数据,只能接收文本 text格式的数据
url='<serverurl>'
#使用 for循环进行发送数据,每个 ip发送一次
for j in ipListJson:
currentDatetime = datetime.datetime.now()
mysqlDateFormat = "'" + currentDatetime.strftime('%Y-%m-%d %H:%M:%S') + "'"
ip = ipListJson[j]['ip']
if ip.split('.')[-1] == '255':
print (f'该ip地址{ip}无法进行扫描, 忽略。。。')
else:
if ip not in resultList:
print (f'{ip}提交到接口进行扫描')
n=θ
while 1:
try:
if n != 3:
response = requests.post(url, data= ip, timeout=1800)
break
else:
print (f'重试{n}次失败, 跳过。。。。')
break
except:
n += 1
print (f'扫描失败, 正在进行第{n}次重试')
time.sleep(30)
if ipListJson[j][' user'] is not None:
#这里有的时候会扫描失败,造成返回不了 json数据,所以 try一下,无法格式化的 ip默认扫描失败,跳过
if isinstance(ipListJson[j]['user'], str):
userStr = "'" + ipListJson[j]['user'] + "'"
elif isinstance(ipListJson[j]['user'],list):
userStr = "'" + ", ". join(ipListJson[j][' user']) + "'"
else:
print (ipListJson[j]['user'])
else:
userStr = "'" + ' unknown' + "'"
try:
scanResultJson = response.json()
for k in scanResultJson:
#有些 ip地址所有的端口都是关闭的,所以扫描的时候返回的 portstatus的 key是没有的导致出问题,所以 try一下,如果失败的就当作扫描失败,跳过
try:
portStr = scanResultJson[k]['portstatus']
except:
sql= f"""INSERT INTO ScanResult (ScanTime, ip, user) VALUES ({mysqlDateFormat},{"'" + k + "'"},{userStr})"""
print (f'no port scaned open, will insert into sql through {sql}')
executeMysqlData(1,'write', sql)
#使用 for循环进行行放的端口读取并写入到数据库,按端口进行存入
for l in scanResultJson[k]['portstatus']:
applicationStr = scanResultJson[k]['portstatus'][l]['application']
if applicationStr == '':
applicationStr = "'" + 'Unknown' + "'"
serviceStr = "'" + scanResultJson[k]['portstatus'][l]['service'] + "'"
sql= f"""INSERT INTO ScanResult (ScanTime, application, ip, name, openport, service, user) VALUES 〔{mysqlDateFormat},{applicationStr},{"'" + k + "'"},{"'" + j + "'"},{"'" + l + "'"},{serviceStr},{userStr})"""
executeMysqlData(1,'write', sql)
except:
sql= f"""INSERT INTO ScanResult (ScanTime, ip, user) VALUES〔{mysqlDateFormat},{"'" + ip + "'"},{userStr})"""
executeMysqlData(1,'write', sql)
#这里使用 for循环去读取 json数据,将数据提取出来以后,再写入数据库
else:
print (fˈip:{ip}已经扫描完毕, 忽略。。。')