Monday, May 13, 2013

Bash One Liner to Get a Frequency Count for IP Connections with Netstat

So you want to see how many connections a given IP has open with netstat? Here's a quick Bash one-liner to get a frequency count for each IP. Note, this is for the external IP / foreign address, and it ignores what port they're connecting on, so 8.8.8.8:443 and 8.8.8.8:80 will be treated as two connections from 8.8.8.8.

So we run netstat with the -pan flags (word-ish sounding and easy to remember, shows the Program that's using the connection, All connections, Numeric version (instead of hostnames / URLs) ) and then we pipe it to awk, and print the 5th field (Foreign Address), then to cut where we discard the port numbers by telling it to print the first field before a colon (which separates the IP from the port). Then we pipe it to sort to organize it, pipe it to unique with the -c flag to get a count of how many times each IP shows up and then to sort again with the -n (sort numeric, very important) and -r flags so the highest count is at the op. And we're done!



netstat -pan | awk '{print $5}' | cut -d ":" -f 1 | sort | uniq -c | sort -nr 


You'll get something like this (IPs changed to protect the guilty): 



[root@example ~]# netstat -pan | awk '{print $5}' | cut -d ":" -f 1 | sort | uniq -c | sort -nr 
    483 127.0.0.1
    119 8.8.8.8
    104 8.8.8.9
     84 8.8.8.10
     70 8.8.8.11
...
[root@example ~]#

You can see the connection count on the left, 483 current connections from 8.8.8.8, 119 from 8.8.8.9 and so on.

Wednesday, May 8, 2013

A Bash Script for Logging Into a Website and Checking a Page

Let's say you want to monitor a page. And to get to the page, you have to log into the website. And you just want something quick without having to set up proper monitoring. 

That was the problem that I faced this afternoon. So I came up with this handy Bash script:

(Note: You can also view the most up-to-date version of this script on my Github page here)

 
#!/bin/bash

# --------------------------
# Simple Page Check Utility
# --------------------------
# Written by James Berger
# Last updated: May 22nd 2013


# Description:
# ------------
# This runs a quick check to see if our user can log in
# Curl logs into the site and places the result into a file,
# Then we grep the file and see if a string that shows up
# when you're logged in is present. The results with a time
# stamp are echoed out and stored in a log file as well
# so you can run this with a cron job every x number of
# minutes to see if the site goes down at a specific time.
 
# Setting our variables
results_file="/home/YourUserName/page-check-results.html"
target_url="https://www.YourSiteHere.com/logon"
phrase_to_check_for="PhraseOnLoggedInPage"
log_file="/home/YourUserNameHere/page-check-server-status.txt"

# A function for checking the contents of the results file, this
# is for testing purposes to make sure that the bits of the script
# that work with that file are functioning correctly. If the script
# isn't working like you think it should, you can call this at
# different points in the script to see if the file is being
# updated, cleared out, etc.
check_results_file() {
echo -e "HERE ARE YOUR RESULTS:"
echo -e "--------------------------------------------"
cat $results_file
echo -e "--------------------------------------------\n"
}

# Quick function to create a new line, little easier than typing
# all of the below out each time.
newline() {
echo -e "\n"
}

# Quick function to print out a separator line
dashline() {
echo -e "---------------------------------"
}

# Run clear to keep things tidy
clear


echo -e "#############################"
echo -e "# Simple Page Check Utility #"
echo -e "#############################\n"

echo -e " Current variables:"
dashline;
echo -e "The target URL is: "$target_url
echo -e "The phrase to check for is: \""$phrase_to_check_for"\""
echo -e "The file the results are stored in is: "$results_file
echo -e "The status of each check is being logged to: "$log_file
dashline;
newline;


echo -e " Results file:"
dashline;
# Create our results file if it doesn't already exist
echo -e "Checking to see if there's a file to store the results in."
if [ ! -f $results_file ]
  then
echo -e "No results file found."
    echo -e "Creating results file" $results_file
    touch $results_file
  else
echo -e "Results file currently exists."
    # Remove our previous results if they exist
    echo -e "Clearing out previous contents of results file."
    echo -e "" > $results_file
fi
dashline;
newline;


#check_results_file;
echo -e " HTTP status code of target URL"
dashline;
# This just makes sure that the page shows up to begin with by getting the HTTP status code of the login page.
# If it's something other than 200, then we won't be able to log in anyway.

echo -e "Running HTTP status check... "
http_status="$(curl -sL -w "%{http_code}\\n" $target_url -o /dev/null)"
echo -e "HTTP status code for the page at the target URL is: "$http_status
dashline;
newline;


echo -e " Phrase check:"
dashline;
# This logs into the site using the creds they've provided for us and the form fields from their login form.
echo -e "Running curl on the target URL."
# You can set the user agent differently if need be.
curl -A "Mozilla/4.73 [en] (X11; U; Linux 2.2.15 i686)" \
--cookie cjar --cookie-jar cjar \
--data "userName=YourUserNameHere" \
--data "password=YourPasswordHere" \
--data "login=Login" \
--location $target_url>$results_file

newline;
#check_results_file;
echo -e "Checking the contents of the results file."

if cat $results_file | grep -q "$phrase_to_check_for"
  then
echo -e "Checking for the phrase \""$phrase_to_check_for"\""
    dashline;
    newline;
    echo -e " Result:"
    dashline;
    echo -e "Found the specified phrase in the results file.\n"
    echo -e "Able to successfully log in."
    echo -e "\r\nLogin successful for $(date) with the HTTP status code $http_status" >> $log_file
    echo -e "Updating the log file now with the result for $(date)."
  else
echo -e "Checking for the phrase " $phrase_to_check_for
    echo -e " Result:"
    dashline;
    echo -e "Did not find it in " $results_file
    echo "Failed to log in."
    echo -e "\r\nLogin failed for $(date) with the HTTP status code $http_status" >> $log_file
    echo -e "Updating the log file now with the result for $(date)."
fi
dashline;
newline;
newline;
newline;
newline;
newline;


There's a few small changes I've made that aren't in this version (The latest version will be on my Github page here) and a few more things that I have planned for this.

1. Log the results to a file with a time and date stamp (done).
2. Add in a section that will email you if it registers a failure (in progress).
3. Allow the user to set the variables interactively from the command line so they don't actually have to edit the script, making it a bit more user friendly.
4. Possibly setting it so that the variables can be specified as command line arguments.
5. Sticking in a bit that will tell you what the usage is for the script if you don't specify any arguments.

The one thing I don't like about the email option is that it requires you to having a working mail server on the box that you're running this script on. That's not going to be all servers out there, so I may need to see if there's some alternative mechanism that can be used to email basic alerts to people.