14
14
from attack import Attack , Fingerprint
15
15
from analysis import infer_target , extract_attack_vectors , compute_summary
16
16
from util import parquet_files_to_view , FileType , determine_filetype , determine_source_filetype , \
17
- print_logo , parse_config
17
+ print_logo , parse_config , is_executable_present
18
18
from graphs import create_line_graph , create_bar_graph
19
19
20
20
DOCKERIZED : bool = 'DISSECTOR_DOCKER' in os .environ
21
21
22
22
23
23
def parse_arguments () -> Namespace :
24
24
parser = ArgumentParser ()
25
- parser .add_argument ('-f' , '--file' , type = Path , help = 'Path to Flow / PCAP file(s)' , nargs = '+' , required = True ,
26
- dest = 'files' )
27
- parser .add_argument ('--summary' , action = 'store_true' , help = 'Optional: print fingerprint without source addresses' )
28
- parser .add_argument ('-r' , action = 'store_true' , help = 'Optional: use experimental Rust pcap-converter' )
29
- parser .add_argument ('--output' , type = Path , help = 'Path to directory in which to save the fingerprint '
30
- f'(default { "/data" if DOCKERIZED else "." } /fingerprints)' ,
31
- default = Path ('/data/fingerprints' ) if DOCKERIZED else Path ('./fingerprints' ))
32
- parser .add_argument ('--config' , type = Path , help = 'Path to DDoS-DB and/or MISP config file (default /etc/config.ini)' ,
33
- default = Path ('/etc/config.ini' ))
34
- parser .add_argument ('--nprocesses' , dest = 'n' , type = int , help = 'Number of processes used to concurrently read PCAPs '
35
- '(default is the number of CPU cores)' ,
36
- default = os .cpu_count ())
25
+ parser .add_argument ('-f' , '--file' , type = Path , nargs = '+' , required = True , dest = 'files' ,
26
+ help = 'Path to Flow / PCAP file(s)' )
27
+ parser .add_argument ('--summary' , action = 'store_true' ,
28
+ help = 'Optional: print fingerprint without source addresses' )
29
+ # parser.add_argument('-r', action='store_true', help='Optional: use experimental Rust pcap-converter')
30
+ parser .add_argument ('--output' , type = Path ,
31
+ default = Path ('/data/fingerprints' ) if DOCKERIZED else Path ('./fingerprints' ),
32
+ help = 'Path to directory in which to save the fingerprint '
33
+ f'(default: { "/data" if DOCKERIZED else "." } /fingerprints)' )
34
+ parser .add_argument ('--config' , type = Path , default = Path ('/etc/config.ini' ),
35
+ help = 'Path to DDoS-DB and/or MISP config file (default: /etc/config.ini)' )
36
+ parser .add_argument ('--nprocesses' , dest = 'n' , type = int , default = os .cpu_count (),
37
+ help = 'Number of processes used to read and process PCAPs '
38
+ f'(default: number of CPU cores ({ os .cpu_count ()} ))' )
37
39
parser .add_argument ('--target' , type = str , dest = 'target' ,
38
- help = 'Optional: target IP address of this attack (subnet currently unsupported)' )
39
- parser .add_argument ('--ddosdb' , action = 'store_true' , help = 'Optional: directly upload fingerprint to DDoS-DB' )
40
- parser .add_argument ('--misp' , action = 'store_true' , help = 'Optional: directly upload fingerprint to MISP' )
40
+ help = 'Optional: Specify target IP address of this attack (subnet currently unsupported)' )
41
+ parser .add_argument ('--ddosdb' , action = 'store_true' ,
42
+ help = 'Optional: Directly upload fingerprint to DDoS-DB' )
43
+ parser .add_argument ('--misp' , action = 'store_true' ,
44
+ help = 'Optional: Directly upload fingerprint to MISP' )
41
45
parser .add_argument ('--graph' , action = 'store_true' ,
42
46
help = 'Optional: Create graphs of the attack, stored alongside the fingerprint' )
43
- parser .add_argument ('--noverify' , action = 'store_true' , help = "Optional: Don't verify TLS certificates" )
44
- parser .add_argument ('--debug' , action = 'store_true' , help = 'Optional: show debug messages' )
45
- parser .add_argument ('--show-target' , action = 'store_true' , help = 'Optional: Do NOT anonymize the target IP address '
46
- '/ network in the fingerprint' )
47
+ parser .add_argument ('--noverify' , action = 'store_true' ,
48
+ help = "Optional: Do not verify TLS certificates (accept self-signed certificates)" )
49
+ parser .add_argument ('--show-target' , action = 'store_true' ,
50
+ help = 'Optional: Do NOT anonymize the target IP address/network in the fingerprint' )
51
+ parser .add_argument ('--tshark' , action = 'store_true' ,
52
+ help = 'Optional: Force use of tshark/tcpdump over pcap-converter, even if it is present' )
53
+ parser .add_argument ('--debug' , action = 'store_true' ,
54
+ help = 'Optional: Show debug messages' )
55
+
47
56
return parser .parse_args ()
48
57
49
58
@@ -65,6 +74,32 @@ def parse_arguments() -> Namespace:
65
74
66
75
filetype = determine_filetype (args .files )
67
76
77
+ # Determine which of pcap-converter, tcpdump, tshark or nfdump are installed
78
+ pcap_converter_ok = is_executable_present ('pcap-converter' )
79
+ tcpdump_ok = is_executable_present ('tcpdump' )
80
+ tshark_ok = is_executable_present ('tshark' )
81
+ nfdump_ok = is_executable_present ('nfdump' )
82
+
83
+ # Error out early if one of the required executables (for the specified file type) is not present
84
+ if filetype == FileType .PCAP and args .tshark and not tshark_ok :
85
+ LOGGER .error ("Use of tshark requested, but tshark cannot be found. Is it installed properly?" )
86
+ exit (1 )
87
+
88
+ if filetype == FileType .PCAP and args .tshark and not tcpdump_ok :
89
+ LOGGER .error ("Use of tshark requested, but tcpdump is needed as well and cannot be found. Is it installed properly?" )
90
+ exit (1 )
91
+
92
+ if filetype == FileType .PCAP and not args .tshark and not pcap_converter_ok and (not tshark_ok or not tcpdump_ok ):
93
+ tshark = ' nor tshark' if not tshark_ok else ''
94
+ tcpdump = ' nor tcpdump' if not tcpdump_ok else ''
95
+ LOGGER .error (f"Pcap file supplied, but neither pcap-converter{ tshark } { tcpdump } can be found." )
96
+ LOGGER .error (f"Please ensure that either pcap-converter OR tcpdump and tshark are installed" )
97
+ exit (1 )
98
+
99
+ if filetype == FileType .FLOW and not nfdump_ok :
100
+ LOGGER .error ("Flow file supplied, but nfdump cannot be found. Is it installed properly?" )
101
+ exit (1 )
102
+
68
103
start = time .time ()
69
104
if filetype == FileType .PQT :
70
105
# If parquet files: check all contain data from either pcap or flow, but not both
@@ -79,8 +114,12 @@ def parse_arguments() -> Namespace:
79
114
pqt_files = [str (f ) for f in args .files ]
80
115
else :
81
116
# Convert the file(s) to parquet
82
- dst_dir = tempfile .gettempdir () if DOCKERIZED else f"{ os .getcwd ()} /parquet"
83
- pqt_files = read_files (args .files , dst_dir = dst_dir , filetype = filetype , nr_processes = args .n , rust_converter = args .r )
117
+ dst_dir = Path (tempfile .gettempdir ()) if DOCKERIZED else Path (f"{ os .getcwd ()} /parquet" )
118
+ pqt_files = read_files (args .files ,
119
+ dst_dir = dst_dir ,
120
+ filetype = filetype ,
121
+ nr_processes = args .n ,
122
+ rust_converter = pcap_converter_ok and not args .tshark )
84
123
duration = time .time ()- start
85
124
LOGGER .info (f"Conversion took { duration :.2f} s" )
86
125
LOGGER .debug (pqt_files )
0 commit comments