1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-06-19 00:17:51 +02:00
Files
jc/jc/parsers/iptables.py

284 lines
7.4 KiB
Python
Raw Normal View History

2019-10-22 15:42:29 -07:00
"""jc - JSON CLI output utility ipables Parser
Usage:
2019-12-12 09:47:14 -08:00
2019-10-22 15:42:29 -07:00
Specify --iptables as the first argument if the piped input is coming from iptables
2019-11-12 07:01:36 -08:00
Supports -vLn and --line-numbers for all tables
2019-10-22 15:42:29 -07:00
2019-12-12 09:21:20 -08:00
Compatibility:
2019-12-12 09:47:14 -08:00
2019-12-12 09:21:20 -08:00
'linux'
2019-10-22 15:42:29 -07:00
Examples:
2019-11-11 18:30:46 -08:00
$ sudo iptables --line-numbers -v -L -t nat | jc --iptables -p
[
2019-10-22 16:40:27 -07:00
{
2019-11-11 18:30:46 -08:00
"chain": "PREROUTING",
"rules": [
{
"num": 1,
"pkts": 2183,
"bytes": 186000,
"target": "PREROUTING_direct",
"prot": "all",
"opt": null,
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere"
},
{
"num": 2,
"pkts": 2183,
"bytes": 186000,
"target": "PREROUTING_ZONES_SOURCE",
"prot": "all",
"opt": null,
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere"
},
{
"num": 3,
"pkts": 2183,
"bytes": 186000,
"target": "PREROUTING_ZONES",
"prot": "all",
"opt": null,
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere"
},
{
"num": 4,
"pkts": 0,
"bytes": 0,
"target": "DOCKER",
"prot": "all",
"opt": null,
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere",
"options": "ADDRTYPE match dst-type LOCAL"
}
]
2019-10-22 16:40:27 -07:00
},
2019-11-11 18:30:46 -08:00
...
2019-10-22 16:40:27 -07:00
]
2019-11-11 18:30:46 -08:00
$ sudo iptables --line-numbers -v -L -t nat | jc --iptables -p -r
[
2019-10-22 16:40:27 -07:00
{
2019-11-11 18:30:46 -08:00
"chain": "PREROUTING",
"rules": [
{
"num": "1",
"pkts": "2183",
"bytes": "186K",
"target": "PREROUTING_direct",
"prot": "all",
"opt": "--",
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere"
},
{
"num": "2",
"pkts": "2183",
"bytes": "186K",
"target": "PREROUTING_ZONES_SOURCE",
"prot": "all",
"opt": "--",
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere"
},
{
"num": "3",
"pkts": "2183",
"bytes": "186K",
"target": "PREROUTING_ZONES",
"prot": "all",
"opt": "--",
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere"
},
{
"num": "4",
"pkts": "0",
"bytes": "0",
"target": "DOCKER",
"prot": "all",
"opt": "--",
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere",
"options": "ADDRTYPE match dst-type LOCAL"
}
]
2019-10-22 16:40:27 -07:00
},
2019-11-11 18:30:46 -08:00
...
2019-10-22 16:40:27 -07:00
]
2019-10-22 15:42:29 -07:00
"""
2019-11-07 08:07:43 -08:00
import jc.utils
2019-10-22 15:42:29 -07:00
2019-12-13 20:01:51 -08:00
class info():
2020-06-22 10:48:51 -07:00
version = '1.4'
2020-02-13 09:47:40 -05:00
description = 'iptables command parser'
2019-12-13 20:01:51 -08:00
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
2020-02-11 18:09:21 -08:00
magic_commands = ['iptables']
2019-12-13 20:01:51 -08:00
2020-02-03 16:11:58 -08:00
__version__ = info.version
2019-11-04 16:59:14 -08:00
def process(proc_data):
2019-11-11 18:30:46 -08:00
"""
2019-11-12 11:28:10 -08:00
Final processing to conform to the schema.
Parameters:
2019-11-14 16:36:00 -08:00
2019-11-13 08:04:40 -08:00
proc_data: (dictionary) raw structured data to process
2019-11-12 11:28:10 -08:00
Returns:
2019-12-17 09:56:09 -08:00
List of dictionaries. Structured data with the following schema:
2019-12-12 09:21:20 -08:00
2019-11-11 18:30:46 -08:00
[
2019-11-04 16:59:14 -08:00
{
2019-11-11 18:30:46 -08:00
"chain": string,
"rules": [
{
"num" integer,
"pkts": integer,
"bytes": integer, # converted based on suffix
"target": string,
"prot": string,
"opt": string, # "--" = Null
"in": string,
"out": string,
"source": string,
"destination": string,
"options": string
}
]
2019-11-04 16:59:14 -08:00
}
]
2019-11-11 18:30:46 -08:00
"""
2019-11-04 16:59:14 -08:00
for entry in proc_data:
for rule in entry['rules']:
int_list = ['num', 'pkts']
for key in int_list:
if key in rule:
try:
key_int = int(rule[key])
rule[key] = key_int
2019-11-06 08:47:54 -06:00
except (ValueError):
2019-11-04 16:59:14 -08:00
rule[key] = None
if 'bytes' in rule:
multiplier = 1
if rule['bytes'][-1] == 'K':
2020-06-22 10:47:34 -07:00
multiplier = 10 ** 3
2019-11-04 16:59:14 -08:00
rule['bytes'] = rule['bytes'].rstrip('K')
elif rule['bytes'][-1] == 'M':
2020-06-22 10:47:34 -07:00
multiplier = 10 ** 6
2019-11-04 16:59:14 -08:00
rule['bytes'] = rule['bytes'].rstrip('M')
elif rule['bytes'][-1] == 'G':
2020-06-22 10:47:34 -07:00
multiplier = 10 ** 9
2019-11-04 16:59:14 -08:00
rule['bytes'] = rule['bytes'].rstrip('G')
elif rule['bytes'][-1] == 'T':
2020-06-22 10:47:34 -07:00
multiplier = 10 ** 12
2019-11-04 16:59:14 -08:00
rule['bytes'] = rule['bytes'].rstrip('T')
elif rule['bytes'][-1] == 'P':
2020-06-22 10:47:34 -07:00
multiplier = 10 ** 15
2019-11-04 16:59:14 -08:00
rule['bytes'] = rule['bytes'].rstrip('P')
try:
bytes_int = int(rule['bytes'])
rule['bytes'] = bytes_int * multiplier
2019-11-06 08:47:54 -06:00
except (ValueError):
2019-11-04 16:59:14 -08:00
rule['bytes'] = None
if 'opt' in rule:
if rule['opt'] == '--':
rule['opt'] = None
return proc_data
2019-11-07 08:07:43 -08:00
def parse(data, raw=False, quiet=False):
2019-11-11 18:30:46 -08:00
"""
2019-11-12 11:17:33 -08:00
Main text parsing function
2019-11-11 18:30:46 -08:00
2019-11-12 11:17:33 -08:00
Parameters:
2019-11-14 16:36:00 -08:00
2019-11-12 11:17:33 -08:00
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
2019-11-11 18:30:46 -08:00
2019-11-12 11:17:33 -08:00
Returns:
2019-12-17 10:09:19 -08:00
List of dictionaries. Raw or processed structured data.
2019-11-11 18:30:46 -08:00
"""
2019-11-07 08:07:43 -08:00
if not quiet:
2019-12-13 20:01:51 -08:00
jc.utils.compatibility(__name__, info.compatible)
2019-11-05 22:42:48 -06:00
2019-11-04 16:59:14 -08:00
raw_output = []
2019-10-22 15:42:29 -07:00
chain = {}
headers = []
if jc.utils.has_data(data):
2019-10-22 15:42:29 -07:00
2020-06-22 10:47:34 -07:00
for line in list(filter(None, data.splitlines())):
2019-10-22 15:42:29 -07:00
if line.startswith('Chain'):
2020-06-22 10:47:34 -07:00
if chain:
raw_output.append(chain)
chain = {}
headers = []
2019-10-22 15:42:29 -07:00
parsed_line = line.split()
2019-10-22 15:42:29 -07:00
chain['chain'] = parsed_line[1]
chain['rules'] = []
2019-10-22 15:42:29 -07:00
continue
2019-10-22 15:42:29 -07:00
elif line.startswith('target') or line.find('pkts') == 1 or line.startswith('num'):
headers = []
headers = [h for h in ' '.join(line.lower().strip().split()).split() if h]
headers.append("options")
2019-10-22 15:42:29 -07:00
continue
2019-10-22 15:42:29 -07:00
else:
rule = line.split(maxsplit=len(headers) - 1)
temp_rule = dict(zip(headers, rule))
if temp_rule:
chain['rules'].append(temp_rule)
if chain:
raw_output.append(chain)
2019-11-04 16:59:14 -08:00
if raw:
return raw_output
else:
return process(raw_output)