William Safire's rules for writing as seen in the New York Times
Do not put statements in the negative form.
And don't start sentences with a conjunction.
If you reread your work, you will find on rereading that a great
deal of repetition can be avoided by rereading and editing.
Never use a long word when a diminutive one will do.
Unqualified superlatives are the worst of all.
If any word is improper at the end of a sentence, a linking verb is.
Avoid trendy locutions that sound flaky.
Never, ever use repetitive redundancies.
Also, avoid awkward or affected alliteration.
Last, but not least, avoid cliche's like the plague.
You will be writing some basic Perl that will parse incoming real-time log entries to the AUTH and AUTHPRIV logging facilities within syslog. You will be maintaining a database of IP addresses from where valid users login. When a new IP address is encountered for a user, you will perform a reverse DNS lookup, a geographical IP address lookup, and will send an email to the 'root' user (of whom email is redirected to your user on your machine).
This lab is heavy on the regular expressions within Perl, so don't skimp on them! You will also touch a little syslog to configure the named pipe, but the big focus is Perl. Read up on the following links, they have a lot of good information, especially the first one, the 'Perl Intro'.
All of the information in this lab was built from the following websites:
This lab is due at 9:30am, Tuesday April 27th, 2007.
You must complete all the following tasks for this lab.
libdbd-mysql-perl/var/log/auth.pipe' using the mkfifo command.
/etc/syslog.conf file and add the following line:
auth.*,authpriv.* |/var/log/auth.pipe
/usr/local/sbin called 'logscan.pl'.
/var/log/auth.pipe' using Perl regular expressions to look for any lines where a user logs into the system using either 'password' or 'publickey'. Specifically you want to look for lines like the following:
Apr 11 13:53:14 coolname sshd[19693]: Accepted password for chris from 128.138.242.249 port 54113 ssh Apr 11 13:57:38 coolname sshd[19931]: Accepted publickey for chris from 128.138.242.249 port 54531 ssh
logins table within your login_monitor database created in the previous lab. You need to capture the date, username and ip address to insert into the database. Note that you must format the date and time properly for MySQL to accept it. You must use prepared statements when inserting into the database.From: New Login Report <root@[yourmachine].cs.colorado.edu> To: root <root@[yourmachine].cs.colorado.edu> Subject: New IP address seen for user '[username]' A new username/ipaddress combination was seen: timestamp: [timestamp] username: [username] IP address: [IP addres] Reverse DNS: [reverse DNS lookup] Country Code: [Geo IP data country code] Country Name: [Geo IP data country name] Sincerely, The simple log scanner.Let's take an example email from the first coolname log entry from above as it were the first time we saw user 'chris' login from 128.138.242.249:
Apr 11 13:53:14 coolname sshd[19693]: Accepted password for chris from 128.138.242.249 port 54113 ssh...
From: New Login Report <root@coolname.cs.colorado.edu> To: root <root@coolname.cs.colorado.edu> Subject: New IP address seen for user 'chris' A new username/ipaddress combination was seen: timestamp: Apr 11 13:53:14 username: chris IP address: 128.138.242.249 Reverse DNS: supervillian.cs.colorado.edu. Country Code: "US" Country Name: "United States" Sincerely, The simple log scanner.To see how to do a reverse DNS lookup within Perl, see the clarifications section below.
/etc/rc.local file:
perl /usr/local/sbin/logscan.pl &
Let's say I have a log file with lines as follows:
Cron started doing shit. User bob logged in from 128.138.242.247 at 11:47am User chris logged in from 128.138.242.247 at 12:00pm Cron started doing shit. User johannes logged in from 128.138.202.19 at 12:06pm Cron is still spamming the logs
I want to pull out the username and hostname of lines that tell me about logins:
#open the file up here
while(<HANDLE>) {
#each line is in $_
#regular expressions without an explicit variable work on $_
if(/^User (\S+) logged in from (\S+) at (\S+)/) {
#$1 now has the username
#$2 now has the ip address
#$3 now has the time
print "$3 - $1 - $2\n";
}
#ignore other lines that don't match the regular expression
}
#close file here
The above script would output the following from the above simulated log:
11:47am - bob - 128.138.242.247 12:00pm - chris - 128.138.242.247 12:06pm - johannes - 128.138.202.19
Perl has an interesting way of spawning a shell command and giving you access to the output. You do this with file handles, just as if you're reading and writing from a file. You can see an example of this in the previous email lab (Lab 07) to see how I read output from the 'w' command. Here's an example of how I read the output of 'ls':
open(CMD, "ls -l /tmp |")
while(<CMD>) {
#each line of output is in $_
...
}
close(CMD);
See how the command output is 'piped' to the file handle? You can then read it like you would any other file. I would recommend you 'man dig' and look at the options to see how to get terse output with the '+short' option.
logins.db or geo-ip database files)It's super easy. Open a file for reading, and then use the 'split' function to split on a character. You can see examples of this in one of the links at the top of the lab.
open(LOGINS, "<", "/var/local/logins.db")
while(<LOGINS>) {
#each line is in $_
#split works on $_ without an explicit variable
my @values = split(/,/);
#$values[0] ... $values[n] -- now contain each thing that was separated by commas
}
close(LOGINS);
Read the comments at the top of the geoip database file, as it has all the info you need to calculate what the integer values for IP addresses are. Basically you want to convert an IP address like 128.138.202.19 to an integer. Doing this is simple:
128.138.202.19 == (128 * 256 * 256 * 256) + (138 * 256 * 256) + (202 * 256) + (19) == 2156579347
Now take this number and find within which range it falls, and you have the entry for where that IP address lives. The entry for the above address is on line 11449 of the file:
"2156527616","2156593151","ARIN","521683200","US","USA","UNITED STATES"
We know that the IP address falls in this range because the first two numbers on the line are a range of IP addresses.
2156527616 < 2156579347 < 2156593151 128.138.0.0 < 128.138.202.19 < 128.138.255.255