Added nmap testing
This commit is contained in:
parent
9481934a5b
commit
4086f344e4
2 changed files with 97 additions and 33 deletions
30
README.md
30
README.md
|
@ -25,7 +25,7 @@ to stdout
|
||||||
usage: logging_tox_savefile.py [-h] [--output OUTPUT]
|
usage: logging_tox_savefile.py [-h] [--output OUTPUT]
|
||||||
[--command {info,decrypt,nodes}]
|
[--command {info,decrypt,nodes}]
|
||||||
[--indent INDENT]
|
[--indent INDENT]
|
||||||
[--info {info,repr,yaml,json,pprint}]
|
[--info {info,repr,yaml,json,pprint,nmap_udp,nmap_tcp}]
|
||||||
[--nodes {select_tcp,select_udp,select_version,nmap_tcp,nmap_udp}]
|
[--nodes {select_tcp,select_udp,select_version,nmap_tcp,nmap_udp}]
|
||||||
[--download_nodes_url DOWNLOAD_NODES_URL]
|
[--download_nodes_url DOWNLOAD_NODES_URL]
|
||||||
[profile]
|
[profile]
|
||||||
|
@ -40,7 +40,7 @@ Optional arguments:
|
||||||
--command {info,decrypt,nodes}
|
--command {info,decrypt,nodes}
|
||||||
Action command - default: info
|
Action command - default: info
|
||||||
--output OUTPUT Destination for info/decrypt/nodes - defaults to stdout
|
--output OUTPUT Destination for info/decrypt/nodes - defaults to stdout
|
||||||
--info {info,repr,yaml,json,pprint}
|
--info {info,repr,yaml,json,pprint,nmap_udp,nmap_tcp}
|
||||||
Format for info command
|
Format for info command
|
||||||
--nodes {select_tcp,select_udp,select_version,nmap_tcp,nmap_udp}
|
--nodes {select_tcp,select_udp,select_version,nmap_tcp,nmap_udp}
|
||||||
Action for nodes command (requires jq)
|
Action for nodes command (requires jq)
|
||||||
|
@ -48,6 +48,32 @@ Optional arguments:
|
||||||
--download_nodes_url DOWNLOAD_NODES_URL
|
--download_nodes_url DOWNLOAD_NODES_URL
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### --command info
|
||||||
|
|
||||||
|
```info``` will output the profile on stdout, or to a file with ```--output```
|
||||||
|
|
||||||
|
Choose one of ```{info,repr,yaml,json,pprint}```
|
||||||
|
for the format for info command.
|
||||||
|
|
||||||
|
Choose one of ```{nmap_udp,nmap_tcp}```
|
||||||
|
to run tests using ```nmap``` for the ```DHT``` and ```TCP_RELAY```
|
||||||
|
sections of the profile. Reguires ```nmap``` and uses ```sudo```.
|
||||||
|
|
||||||
|
### --command nodes
|
||||||
|
|
||||||
|
Takes a DHTnodes.json file as an argument.
|
||||||
|
Choose one of ```{select_tcp,select_udp,select_version}```
|
||||||
|
for ```--nodes``` to select TCP nodes, UDP nodes or nodes with the latest version.
|
||||||
|
Requires ```jq```.
|
||||||
|
|
||||||
|
Choose one of ```{nmap_tcp,nmap_udp}```
|
||||||
|
to run tests using ```nmap``` for the ```tcp``` and ```udp```
|
||||||
|
nodes. Reguires ```nmap``` and uses ```sudo```.
|
||||||
|
|
||||||
|
### --command decrypt
|
||||||
|
|
||||||
|
Decrypt a profile.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
If you want to read encrypted profiles, you need to download
|
If you want to read encrypted profiles, you need to download
|
||||||
|
|
|
@ -30,7 +30,8 @@ commands, or the filename of the nodes file for the nodes command.
|
||||||
choices=['select_tcp', 'select_udp', 'nmap_tcp', 'select_version', 'nmap_udp']
|
choices=['select_tcp', 'select_udp', 'nmap_tcp', 'select_version', 'nmap_udp']
|
||||||
select_udp - select udp nodes
|
select_udp - select udp nodes
|
||||||
select_tcp - select tcp nodes
|
select_tcp - select tcp nodes
|
||||||
nmap_tcp - test tcp nodes with namp
|
nmap_udp - test UDP nodes with nmap
|
||||||
|
nmap_tcp - test TCP nodes with nmap
|
||||||
select_version - select nodes that are the latest version
|
select_version - select nodes that are the latest version
|
||||||
download - download nodes from --download_nodes_url
|
download - download nodes from --download_nodes_url
|
||||||
--download_nodes_url https://nodes.tox.chat/json
|
--download_nodes_url https://nodes.tox.chat/json
|
||||||
|
@ -335,17 +336,17 @@ The Node Info data structure contains a Transport Protocol, a Socket
|
||||||
af = 'IPv6'
|
af = 'IPv6'
|
||||||
alen = 16
|
alen = 16
|
||||||
ipaddr = inet_ntop(AF_INET6, result[delta+1:delta+1+alen])
|
ipaddr = inet_ntop(AF_INET6, result[delta+1:delta+1+alen])
|
||||||
total = 1 + alen + 2 + 32
|
total = 1 + alen + 2 + 32
|
||||||
port = int(struct.unpack_from(">H", result, delta+1+alen)[0])
|
port = int(struct.unpack_from(">H", result, delta+1+alen)[0])
|
||||||
pk = bin_to_hex(result[delta+1+alen+2:delta+1+alen+2+32], 32)
|
pk = bin_to_hex(result[delta+1+alen+2:delta+1+alen+2+32], 32)
|
||||||
LOG.info(f"DHTnode #{relay} bytes={length} status={status} ip={ipv} af={af} ip={ipaddr} port={port} pk={pk}")
|
LOG.info(f"DHTnode #{relay} bytes={length} status={status} ip={ipv} af={af} ip={ipaddr} port={port} pk={pk}")
|
||||||
lIN += [{"Bytes": length,
|
lIN += [{"Bytes": length,
|
||||||
"Status": status,
|
"Status": status,
|
||||||
"Ip": ipv,
|
"Ip": ipv,
|
||||||
"Af": af,
|
"Af": af,
|
||||||
"Ip": ipaddr,
|
"Ip": ipaddr,
|
||||||
"Port": port,
|
"Port": port,
|
||||||
"Pk": pk}]
|
"Pk": pk}]
|
||||||
if bUSE_NMAP:
|
if bUSE_NMAP:
|
||||||
cmd = f"nmap -Pn -n -sT -p T:{port} {ipaddr}"
|
cmd = f"nmap -Pn -n -sT -p T:{port} {ipaddr}"
|
||||||
|
|
||||||
|
@ -400,7 +401,7 @@ def lProcessDHTnodes(state, index, length, result):
|
||||||
return lIN
|
return lIN
|
||||||
|
|
||||||
def process_chunk(index, state):
|
def process_chunk(index, state):
|
||||||
global lOUT, bOUT, iTOTAL
|
global lOUT, bOUT, iTOTAL, aOUT
|
||||||
|
|
||||||
length = struct.unpack_from("<H", state, index)[0]
|
length = struct.unpack_from("<H", state, index)[0]
|
||||||
data_type = struct.unpack_from("<H", state, index + 4)[0]
|
data_type = struct.unpack_from("<H", state, index + 4)[0]
|
||||||
|
@ -423,29 +424,29 @@ def process_chunk(index, state):
|
||||||
aIN = {"Nospam": f"{nospam}",
|
aIN = {"Nospam": f"{nospam}",
|
||||||
"Public_key": f"{public_key}",
|
"Public_key": f"{public_key}",
|
||||||
"Private_key": f"{private_key}"}
|
"Private_key": f"{private_key}"}
|
||||||
lOUT += [{"Nospam_keys": aIN}]
|
lOUT += [{"NOSPAMKEYS": aIN}]; aOUT.update({"NOSPAMKEYS": aIN})
|
||||||
|
|
||||||
elif data_type == MESSENGER_STATE_TYPE_DHT:
|
elif data_type == MESSENGER_STATE_TYPE_DHT:
|
||||||
LOG.debug(f"process_chunk {dSTATE_TYPE[data_type]} length={length}")
|
LOG.debug(f"process_chunk {dSTATE_TYPE[data_type]} length={length}")
|
||||||
lIN = lProcessDHTnodes(state, index, length, result)
|
lIN = lProcessDHTnodes(state, index, length, result)
|
||||||
if lIN: lOUT += [{"DHT_nodes": lIN}]
|
if lIN: lOUT += [{"DHT": lIN}]; aOUT.update({"DHT": lIN})
|
||||||
|
|
||||||
elif data_type == MESSENGER_STATE_TYPE_FRIENDS:
|
elif data_type == MESSENGER_STATE_TYPE_FRIENDS:
|
||||||
LOG.debug(f"TODO process_chunk {length // 2216} FRIENDS {length} {length % 2216}")
|
LOG.debug(f"TODO process_chunk {length // 2216} FRIENDS {length} {length % 2216}")
|
||||||
lIN = lProcessFriends(state, index, length, result)
|
lIN = lProcessFriends(state, index, length, result)
|
||||||
if lIN: lOUT += [{"Friends": lIN}]
|
if lIN: lOUT += [{"FRIENDS": lIN}]; aOUT.update({"FRIENDS": lIN})
|
||||||
|
|
||||||
elif data_type == MESSENGER_STATE_TYPE_NAME:
|
elif data_type == MESSENGER_STATE_TYPE_NAME:
|
||||||
name = str(state[index + 8:index + 8 + length], 'utf-8')
|
name = str(state[index + 8:index + 8 + length], 'utf-8')
|
||||||
LOG.info("Nick_name = " +name)
|
LOG.info("Nick_name = " +name)
|
||||||
aIN = {"Nick_name": name}
|
aIN = {"NAME": name}
|
||||||
lOUT += [{"Nick_name": aIN}]
|
lOUT += [{"Nick_name": aIN}]; aOUT.update({"Nick_name": aIN})
|
||||||
|
|
||||||
elif data_type == MESSENGER_STATE_TYPE_STATUSMESSAGE:
|
elif data_type == MESSENGER_STATE_TYPE_STATUSMESSAGE:
|
||||||
mess = str(state[index + 8:index + 8 + length], 'utf-8')
|
mess = str(state[index + 8:index + 8 + length], 'utf-8')
|
||||||
LOG.info(f"StatusMessage = " +mess)
|
LOG.info(f"StatusMessage = " +mess)
|
||||||
aIN = {"Status_message": mess}
|
aIN = {"Status_message": mess}
|
||||||
lOUT += [{"Status_message": aIN}]
|
lOUT += [{"STATUSMESSAGE": aIN}]; aOUT.update({"STATUSMESSAGE": aIN})
|
||||||
|
|
||||||
elif data_type == MESSENGER_STATE_TYPE_STATUS:
|
elif data_type == MESSENGER_STATE_TYPE_STATUS:
|
||||||
# 1 uint8_t status (0 = online, 1 = away, 2 = busy)
|
# 1 uint8_t status (0 = online, 1 = away, 2 = busy)
|
||||||
|
@ -454,25 +455,27 @@ def process_chunk(index, state):
|
||||||
status = dStatus[status]
|
status = dStatus[status]
|
||||||
LOG.info(f"{dSTATE_TYPE[data_type]} = " +status)
|
LOG.info(f"{dSTATE_TYPE[data_type]} = " +status)
|
||||||
aIN = {f"Online_status": status}
|
aIN = {f"Online_status": status}
|
||||||
lOUT += [{"Online_status": aIN}]
|
lOUT += [{"STATUS": aIN}]; aOUT.update({"STATUS": aIN})
|
||||||
|
|
||||||
elif data_type == MESSENGER_STATE_TYPE_GROUPS:
|
elif data_type == MESSENGER_STATE_TYPE_GROUPS:
|
||||||
lIN = lProcessGroups(state, index, length, result)
|
lIN = lProcessGroups(state, index, length, result)
|
||||||
if lIN: lOUT += [{"Groups": lIN}]
|
if lIN: lOUT += [{"GROUPS": lIN}]; aOUT.update({"GROUPS": lIN})
|
||||||
|
|
||||||
elif data_type == MESSENGER_STATE_TYPE_TCP_RELAY:
|
elif data_type == MESSENGER_STATE_TYPE_TCP_RELAY:
|
||||||
lIN = lProcessTcpRelay(state, index, length, result)
|
lIN = lProcessTcpRelay(state, index, length, result)
|
||||||
if lIN: lOUT += [{"Tcp_relays": lIN}]
|
if lIN: lOUT += [{"TCP_RELAY": lIN}]; aOUT.update({"TCP_RELAY": lIN})
|
||||||
|
|
||||||
elif data_type == MESSENGER_STATE_TYPE_PATH_NODE:
|
elif data_type == MESSENGER_STATE_TYPE_PATH_NODE:
|
||||||
LOG.debug(f"TODO process_chunk {dSTATE_TYPE[data_type]} bytes={length}")
|
LOG.debug(f"TODO process_chunk {dSTATE_TYPE[data_type]} bytes={length}")
|
||||||
|
lIN = []
|
||||||
|
if lIN: lOUT += [{"PATH_NODE": lIN}]; aOUT.update({"PATH_NODE": lIN})
|
||||||
|
|
||||||
elif data_type == MESSENGER_STATE_TYPE_CONFERENCES:
|
elif data_type == MESSENGER_STATE_TYPE_CONFERENCES:
|
||||||
if length > 0:
|
if length > 0:
|
||||||
LOG.debug(f"TODO process_chunk {dSTATE_TYPE[data_type]} bytes={length}")
|
LOG.debug(f"TODO process_chunk {dSTATE_TYPE[data_type]} bytes={length}")
|
||||||
else:
|
else:
|
||||||
LOG.info(f"NO {dSTATE_TYPE[data_type]}")
|
LOG.info(f"NO {dSTATE_TYPE[data_type]}")
|
||||||
lOUT += [{"Conferences": []}]
|
lOUT += [{"CONFERENCES": []}]; aOUT.update({"CONFERENCES": []})
|
||||||
|
|
||||||
elif data_type != MESSENGER_STATE_TYPE_END:
|
elif data_type != MESSENGER_STATE_TYPE_END:
|
||||||
LOG.warn("UNRECOGNIZED datatype={datatype}")
|
LOG.warn("UNRECOGNIZED datatype={datatype}")
|
||||||
|
@ -518,7 +521,7 @@ jq '.|with_entries(select(.key|match("nodes"))).nodes[]|select(.status_tcp)|sele
|
||||||
else
|
else
|
||||||
echo INFO $ip "${ports[*]}"
|
echo INFO $ip "${ports[*]}"
|
||||||
cmd="nmap -Pn -n -sT -p T:"`echo "${ports[*]}" |sed -e 's/ /,/g'`
|
cmd="nmap -Pn -n -sT -p T:"`echo "${ports[*]}" |sed -e 's/ /,/g'`
|
||||||
dbug $cmd $ip
|
echo DBUG $cmd $ip
|
||||||
$cmd $ip | grep /tcp
|
$cmd $ip | grep /tcp
|
||||||
fi
|
fi
|
||||||
ip=""
|
ip=""
|
||||||
|
@ -552,6 +555,31 @@ def vBashFileNmapUdp():
|
||||||
os.chmod(sFile, 0o0775)
|
os.chmod(sFile, 0o0775)
|
||||||
return sFile
|
return sFile
|
||||||
|
|
||||||
|
def vOsSystemNmapUdp(l, oArgs):
|
||||||
|
iErrs = 0
|
||||||
|
for elt in aOUT["DHT"]:
|
||||||
|
cmd = f"sudo nmap -Pn -n -sU -p U:{elt['port']} {elt['ipaddr']}"
|
||||||
|
iErrs += os.system(cmd +f" >> {oArgs.output} 2>&1")
|
||||||
|
if iErrs:
|
||||||
|
LOG.warn(f"{oArgs.info} {iErrs} ERRORs to {oArgs.output}")
|
||||||
|
print(f"{oArgs.info} {iErrs} ERRORs to {oArgs.output}")
|
||||||
|
else:
|
||||||
|
LOG.info(f"{oArgs.info} NO errors to {oArgs.output}")
|
||||||
|
print(f"{oArgs.info} NO errors to {oArgs.output}")
|
||||||
|
|
||||||
|
def vOsSystemNmapTcp(l, oArgs):
|
||||||
|
iErrs = 0
|
||||||
|
for elt in l:
|
||||||
|
cmd = f"sudo nmap -Pn -n -sT -p T:{elt['port']} {elt['ipaddr']}"
|
||||||
|
print(f"{oArgs.info} NO errors to {oArgs.output}")
|
||||||
|
iErrs += os.system(cmd +f" >> {oArgs.output} 2>&1")
|
||||||
|
if iErrs:
|
||||||
|
LOG.warn(f"{oArgs.info} {iErrs} ERRORs to {oArgs.output}")
|
||||||
|
print(f"{oArgs.info} {iErrs} ERRORs to {oArgs.output}")
|
||||||
|
else:
|
||||||
|
LOG.info(f"{oArgs.info} NO errors to {oArgs.output}")
|
||||||
|
print(f"{oArgs.info} NO errors to {oArgs.output}")
|
||||||
|
|
||||||
def vSetupLogging(loglevel=logging.DEBUG):
|
def vSetupLogging(loglevel=logging.DEBUG):
|
||||||
global LOG
|
global LOG
|
||||||
if coloredlogs:
|
if coloredlogs:
|
||||||
|
@ -588,7 +616,7 @@ def oMainArgparser(_=None):
|
||||||
parser.add_argument('--indent', type=int, default=2,
|
parser.add_argument('--indent', type=int, default=2,
|
||||||
help='Indent for yaml/json/pprint')
|
help='Indent for yaml/json/pprint')
|
||||||
parser.add_argument('--info', type=str, default='info',
|
parser.add_argument('--info', type=str, default='info',
|
||||||
choices=['info', 'repr', 'yaml','json', 'pprint'],
|
choices=['info', 'repr', 'yaml','json', 'pprint', 'nmap_tcp', 'nmap_udp'],
|
||||||
help='Format for info command')
|
help='Format for info command')
|
||||||
choices = []
|
choices = []
|
||||||
if bHAVE_JQ:
|
if bHAVE_JQ:
|
||||||
|
@ -702,26 +730,36 @@ if __name__ == '__main__':
|
||||||
# toxEsave
|
# toxEsave
|
||||||
assert bSAVE[:8] == bOUT, "Not a Tox profile"
|
assert bSAVE[:8] == bOUT, "Not a Tox profile"
|
||||||
|
|
||||||
lOUT = []
|
iErrs = 0
|
||||||
|
lOUT = []; aOUT = {}
|
||||||
process_chunk(len(bOUT), bSAVE)
|
process_chunk(len(bOUT), bSAVE)
|
||||||
if lOUT:
|
if lOUT:
|
||||||
if oArgs.output:
|
if oArgs.output:
|
||||||
oStream = open(oArgs.output, 'rb')
|
oStream = open(oArgs.output, 'wb')
|
||||||
else:
|
else:
|
||||||
oStream = sys.stdout
|
oStream = sys.stdout
|
||||||
if oArgs.info == 'yaml' and yaml:
|
if oArgs.info == 'yaml' and yaml:
|
||||||
yaml.dump(lOUT, stream=oStream, indent=oArgs.indent)
|
yaml.dump(aOUT, stream=oStream, indent=oArgs.indent)
|
||||||
oStream.write('\n')
|
oStream.write('\n')
|
||||||
elif oArgs.info == 'json' and json:
|
elif oArgs.info == 'json' and json:
|
||||||
json.dump(lOUT, oStream, indent=oArgs.indent)
|
json.dump(aOUT, oStream, indent=oArgs.indent)
|
||||||
oStream.write('\n')
|
oStream.write('\n')
|
||||||
elif oArgs.info == 'repr':
|
elif oArgs.info == 'repr':
|
||||||
oStream.write(repr(lOUT))
|
oStream.write(repr(aOUT))
|
||||||
oStream.write('\n')
|
oStream.write('\n')
|
||||||
elif oArgs.info == 'pprint':
|
elif oArgs.info == 'pprint':
|
||||||
pprint(lOUT, stream=oStream, indent=oArgs.indent, width=80)
|
pprint(aOUT, stream=oStream, indent=oArgs.indent, width=80)
|
||||||
elif oArgs.info == 'info':
|
elif oArgs.info == 'info':
|
||||||
pass
|
pass
|
||||||
|
elif oArgs.info == 'nmap_tcp':
|
||||||
|
assert oArgs.output, "--output required for this command"
|
||||||
|
oStream.close()
|
||||||
|
vOsSystemNmapTcp(aOUT["TCP_RELAY"], oArgs)
|
||||||
|
elif oArgs.info == 'nmap_udp':
|
||||||
|
assert oArgs.output, "--output required for this command"
|
||||||
|
oStream.close()
|
||||||
|
vOsSystemNmapUdp(aOUT["DHT"], oArgs)
|
||||||
|
|
||||||
# were short repacking as we read - 446 bytes missing
|
# were short repacking as we read - 446 bytes missing
|
||||||
LOG.debug(f"len bSAVE={len(bSAVE)} bOUT={len(bOUT)} delta={len(bSAVE) - len(bOUT)} iTOTAL={iTOTAL}")
|
LOG.debug(f"len bSAVE={len(bSAVE)} bOUT={len(bOUT)} delta={len(bSAVE) - len(bOUT)} iTOTAL={iTOTAL}")
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue