-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathdenylog.py
108 lines (91 loc) · 2.76 KB
/
denylog.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#!/usr/bin/env python
# file: denylog.py
# vim:fileencoding=utf-8:ft=python
#
# Copyright © 2015-2018 R.F. Smith <[email protected]>.
# SPDX-License-Identifier: MIT
# Created: 2015-09-03T08:47:30+02:00
# Last modified: 2020-03-31T23:43:48+0200
"""
Summarize the deny log messages from ipfw.
Use the given file names, or /var/log/security if no filenames are given.
This program can handle compressed files like /var/log/security.?.bz2.
"""
import argparse
import bz2
import logging
import re
import sys
__version__ = "2020.03.31"
def main():
"""
Entry point for denylog.py.
"""
args = setup()
if not args.files:
args.files = ["/var/log/security"]
reps = " IP: {:16s} port: {:10s} rule: {}"
serv = services()
for f in args.files:
print("File:", f)
try:
matches = parselogfile(f)
except FileNotFoundError as e:
print(e)
continue
if not matches:
print(" Nothing to report.")
continue
for rule, IP, port in matches:
print(reps.format(IP + ",", serv[int(port)] + ",", rule))
def setup():
"""Parse command-line arguments."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("-v", "--version", action="version", version=__version__)
parser.add_argument(
"--log",
default="warning",
choices=["debug", "info", "warning", "error"],
help="logging level (defaults to 'warning')",
)
parser.add_argument(
"files", metavar="file", nargs="*", help="one or more files to process"
)
args = parser.parse_args(sys.argv[1:])
logging.basicConfig(
level=getattr(logging, args.log.upper(), None),
format="%(levelname)s: %(message)s",
)
return args
def services(filename="/etc/services"):
"""
Generate a dictionary of the available services from /etc/services.
Arguments:
filename: Name of the services file.
Returns:
A dict in the form of {25: 'smtp', 80: 'http', ...}
"""
with open(filename) as serv:
data = serv.read()
matches = re.findall("\n" + r"(\S+)\s+(\d+)/", data)
return {int(num): name for name, num in set(matches)}
def parselogfile(filename):
"""
Extract deny rules for incoming packets from file and parse them.
Arguments:
filename: Name of the file to read.
Returns:
A tuple of (rule, source IP, port) tuples
"""
if filename.endswith(".bz2"):
df = bz2.open(filename, "rt")
else:
df = open(filename)
data = df.read()
df.close()
patt = (
r"ipfw: (\d+) Deny (?:\S+) " r"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d+).*in"
)
return tuple(set(re.findall(patt, data)))
if __name__ == "__main__":
main()