Using Gource to Visualize SSH Attempts...Because Why Not?

As with most endeavours related to the question "I wonder if I can do X?", this one started off on a day where I was very VERY bored.
The question "Can I use Gource to Visualize SSH Logs?" was quickly answered when I remembered Gource can take any logs that I can get to follow the custom
format.
Custom Log Format
If you want to use Gource with something other than the supported systems, there is a pipe ('|') delimited custom log format:
timestamp - A unix timestamp of when the update occured.
username - The name of the user who made the update.
type - Single character for the update type - (A)dded, (M)odified or (D)eleted.
file - Path of the file updated.
colour - A colour for the file in hex (FFFFFF) format. Optional.
Most of that should be easy enough to map to something that would make sense from a logline for an ssh attempt. OH! I should mention the source log is RFC3164 formatted. An example of that is:
<86>Aug 22 15:00:54 sooper-awesome-host sshd[18525]: Failed password for root from SOURCE_IP port 42865 ssh2
Lets cover each item in the custom log format one at a time.
- timestamp
- Our auth log has a timestamp, but we will need to convert it to a UNIX timestamp.
- username
- This one we will map to the IP that made the SSH attempt
- type
- We only have 2 types to consider. 'Accepted' and 'Failed'. Lets map 'Failed' to (M)odified and 'Accepted' to (A)dded.
- file
- This one will affect how the visualization with look. This one I played around with a lot...still not 100% satisfied with it.
So, from the RFC3164 log example above, once the data has been parsed, we get something like this to feed to Gource:
1500280628|BAD_GUY_IP|M|/M/root/BAD_GUY_IP/1500280628.0.root
Fair warning: I'm just now learning python so this may make a few (all?) of you seasoned Python Veterans throw up a little. That said, here is a quick and dirty python3 script I wrote that will read STDIN, parse, then spit out a formatted line to STDOUT.
import time
import datetime
import datefinder
import re
import sys
for line in sys.stdin:
if ("Failed" in line) or ("Accepted" in line):
date_stamp_found = re.findall(r'[A-Za-z]{3}\s\d{1,2}\s(?:\d{1,2}:){2}\d{1,2}', line)
date_stamp = datefinder.find_dates(str(date_stamp_found))
if "Failed password for" or "Failed none for" in line:
if "invalid user" in line:
line_list = line.split()
user = line_list[10]
ip = line_list[12]
else:
line_list = line.split()
user = line_list[8]
ip = line_list[10]
elif "Accepted password for" in line:
line_list = line.split()
user = line_list[8]
ip = line_list[10]
elif "Accepted publickey for" in line:
line_list = line.split()
user = line_list[8]
ip = line_list[10]
for match in date_stamp:
unix_stamp = time.mktime(datetime.datetime.strptime(str(match), "%Y-%m-%d %H:%M:%S").timetuple())
if "Failed" in line:
event="M"
event_print="Failed"
elif "Accepted" in line:
event="A"
event_print="Accepted"
else:
event="M"
event_print="Unknown"
sys.stdout.write('%s|%s|%s|/%s/%s/%s/%s.%s\r\n' % (int(unix_stamp),ip,event,event_print,user,ip,unix_stamp,user))
sys.stdout.flush()
A simple usage of this would be to cat an RFC3164 ssh log and pipe it into this python script. Then one more pipe into gource
.
cat /var/log/secure | python ./secure2gource.py | gource --log-format custom --key --max-files 0 --file-idle-time 0 -
You can even watch a logfile in near realtime!
tail -f /var/log/secure | python ./secure2gource.py | gource --realtime --log-format custom --key --max-files 0 --file-idle-time 0 -
Finally, an example video. Not much different than a normal gource video, except it is visualizing SSH attempts.
Once the dust settles on the video, orbs to the left are all failed attempts and the 15 some-odd orbs down there at the bottom right are actual accepted logins.
Also, since I chose to use the id of the user who is attempting to log in as the file extension, I can use --key
in gource to keep a running count of attempts!
Using Gource to Visualize SSH Attempts...Because Why Not? from Micheal Quinn on Vimeo.