Tag: apache

  • find-a-bot.sh – a nice little script to ID bots bugging your website site

    a nice little script to ID bots bugging your websiteOriginally published on May 30, 2008, made some modifications & bumped it up in the display queue.

    Already demonstrating earlier this week how to block spambots and rogue spiders. Today I’m completing the lesson with a nice little bash script sample that can help you identify some of these non-browser ‘candidates’ by parsing your access logs and placing the results in an easy-to-read text file.

    In other words, this script will selectively find most non-browser user agents that appear in your access logs like this:

    24.190.239.220 - - [29/May/2008:05:16:19 -0700] "GET /about HTTP/1.1" 200 628 "-" "Java/1.6.0_06"
    79.71.205.134 - - [29/May/2008:00:56:34 -0700] "GET / HTTP/1.1" 200 12888 "-" "Site Sniper Pro"

    And turns it into a slightly saner and sorted output like this:

    24.190.239.220 [29/May/2008:05:16:19 "Java/1.6.0_06"
    79.71.205.134 [29/May/2008:00:56:34 "Site Sniper Pro"

    Here is what your bash script might look like on a site running WordPress on shared host like DreamHost … I’ll explain some of the mechanics afterwards:

    #!/bin/bash
    #
    # step 1 - modify these so you get paths like this:
    #   /home/YOURROOT/YOURDOMAIN.coM/...
    #
    myroot="YOURROOT"
    mydomain="YOURDOMAIN.COM"
    
    #
    # step 2 - leave alone if these days & formats work for you:
    #
    TERM=linux
    export TERM
    tdy=`date +%d%b%y`
    ydy=`date -d '1 day ago' +%Y-%m-%d`
    dby=`date -d '7 day ago' +%Y-%m-%d`
    logfile="access.log.$ydy"
    
    #
    # step 3 - modify if you're using something other
    #           than  WordPress on DreamHost
    #
    outfile="/home/$myroot/$mydomain/findabot"
    logpath="/home/$myroot/logs/$mydomain/http/"
    csspath="/home/$myroot/$mydomain/wp-content"
    
    #
    # step 4 - mother of all parsing statements, parse to taste
    #	(note this version DOES sort)
    #
    # 	remember \ at the very end of line equals
    #	bash line continuation of a command set
    #
    grep "$csspath" -v $logpath$logfile | \
      egrep " \"(Mozilla|Opera)\/[0-9]| \"BlackBerry[0-9]{4}" -v | \
      perl -l -a -n -e 'print $F[0]," ",$F[3]," ",$F[11]," ",$F[12]," ",$F[13]' | \
      sort -n > $outfile/$ydy.txt
    
    #
    # step 5 - maintain a manageable archive
    #
    if [ -e $outfile/$dby.txt ]; then
    	mv -f $outfile/$dby.txt $outfile/bak.txt
    fi
    

    Okay, step 1 basically means you login to your site either SSH or even FTP and before navigating anywhere, issue the “pwd” command so you can determine your YOURROOT and YOURDOMAIN (though the latter may likely be your website’s url).

    Step 2 is how we get date stamps for our input and output files. I found a nice simple example of date variable formatting of these over on an ExpressionEngine manual – but they’ll work in your bash script just fine.

    Also, that line containing “7 day ago” can be modified to indicate how many days worth of logs you want to keep active. Similarly, the prior line containing “1 day ago” means you want to parse yesterday’s logs.

    Step 3 is basically how I use variables to define file and directory paths based on what I coded for steps 1 and 2.

    Step 4 combines all the elements from the above steps and taking a page out of my April 2nd article entitled ‘How to quickly check your error logs for oddities‘ issues a consecutive stream of grep and/or egrep commands.

    Sometimes leveraging the ‘-v’ command to exclude elements, most noteably when I’m excluding known user agent strings for browsers.

    This done, a bit of PERL command line magic is used to parse out the fields we want, where afterwards the selected data is sorted and piped into the output file defined in step 3.

    Step 5 takes into account that logs can get big, so this is where we manage an archive … based on step 2 … for 7 days worth of entries.

    find-a-bot gets into the bits and bytes of web site bottageIf you’re not familiar with creating bash scripts, you may encounter situations where you need to “chmod” or even “chown” the file to get it to work.

    The next step – though not documented above – is to test the script and when you’re sure it’s working, modify your crontab file so your batch runs every night, like say 2:15 AM while you and everyone else are sleeping. Here’s what my crontab entry looks like:

    15 2 * * * /home/YOURROOT/find-a-bot.sh > /dev/null

    I’ve provided a .txt version of the file you can simply download from here.

    Moreover, I’ve created a slightly more complex version to download of the above for use on a system running a something like vBulletin on a root or virtual private server operating with Fedora or RedHat.

    The point is, while the above appears a bit complex, I can assure you it’s worth running as it can help you quickly discern over the course of a few days:

    • how often and how hard spambots are sniffing your system
    • how much of your bandwidth is consumed by feed readers versus browsers
    • which feed readers are hammering away at your site, ignoring your <skiphours /> and/or <skipdays /> data
    • how much bandwidth you might save by exporting your sermon’s RSS feeds to a service like FeedBurner
    • what spiders are ignoring your robots.txt file
    • tips on unusual visitors from interesting places from unique user agents
    • whether or not some of the comment spam is via “Mozilla-like”agents who botch their user agent string
    • how many of your visitors are infected with spyware
    • how many of your visitors are trying to hide their tracks by visiting you with an anonymous proxy firing blank user agent strings
    • how many spamblogs are leaching your compelling content

    Like I said, it will require just a little bash script know how, so with that, I leave you with these tutorials:

    Oh and if you’re nice and leave a comment, I might even email you a link to my own archive of greatest bot hits over the past few days.

    Especially if you share your own scripting recipes for spotting bots.

  • How to block spambots by user agent using .htaccess

    How to block spambots by user agent using .htaccess .Originally published May 27, 2008, I’ve bumped this up a bit in the queue after some edits.

    Spambots and spiders that ignore robots exclusion file can kill your site both in bandwidth and by potentially exposing information you don’t want ‘harvested.’ With that in mind, here is a quick-n-dirty guide to blocking spambots and rogue search engine spiders by using .htaccess. First the essential example codeblock, followed by a working example:

    essential example codeblock

    # redirect spambots & rogue spiders to the end of the internet
    Options +FollowSymlinks
    RewriteEngine On
    RewriteBase /
    RewriteEngine on
    RewriteCond %{HTTP_USER_AGENT} ^spambot
    RewriteRule ^(.*)$ http://www.shibumi.org/eoti.htm#$1 [R=301,L]

    Next is to read my article on how to quickly check your error logs for oddities … which should provide you with a list of all sorts of unusual user agents worth blocking.

    With said list, all that is left to do is create a working version that instead of sending people to the end of the internet, blocks them outright – which is probably a better move then sending the traffic elsewhere:

    real-world/working example

    # redirect spambots & rogue spiders to the end of the internet
    Options +FollowSymlinks
    RewriteEngine On
    RewriteBase /
    RewriteEngine on
    RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EmailSearch [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Microsoft\ URL [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Web\ Image\ Collector
    RewriteRule .* - [F,L]

    Note I provide 4 examples:

    1. ^$,
    2. ^EmailSearch
    3. ^Microsoft\ URL
    4. ^Web\ Image\ Collector

    All to demonstrate how to use perl-like regular expressions parse out the user agent. For example:

    1. ^ – identifies the beginning of the user agent string
    2. $ – identifies the end of the user agent string
    3. \ – that is a slash with a space afterwards tells the parser to include the space between words
    4. [OR] – is placed after each of the multiple entries, except the last
    5. [NC,…] – is sometimes placed after an entry to scan it w/out concern to upper or lower case

    In the process, I’m intentionally blocking empty user agents using .htaccess – “^$” – a search string that uses a regular express to test for nothing between the beginning “^” and end “$” of a user agent token. Sorry, but if you’re not willing to tell me who/what you are, I’m not willing to show you my content.

    Also, be aware the above requires that you have mod_rewrite installed on your Apache server, and that you have privileges to create your own rewrite rules in your own .htaccess file. If you’re not sure, check with your hosting service and/or system administrator.

    In most cases, such privs & access exists – but your mileage may vary – as they might in how your particular .htaccess file actually works in-the-wild.

    That said, more tomorrow or Thursday on how to create cron job to list those “unusual user agents” ‘automagically‘ for easy identification – and if needed -anti-spam remediation.

  • Setting up multiple test sites in XAMPP via virtual sites

    It’s NEVER a good idea to test new designs, programs and/or learn new stuff on a production website. This article describes how to create multiple virtual servers on a Windows 7 platform using XAMPP to create a perfect Linux/Apache like test bed.XAMPP + Win7 = great platform to test WordPress, MovableType and   Drupal

    Some Context

    I’m in the process of re-factoring some websites I’ve let go fallow far too long. Part of this process includes setting up a Linux-like test site on my brand new Windows7-driven Lenovo U350 via XAMPP.

    Yeah, I know, that was a lot all at once, so let’s break some of this down for those of you who don’t code for a living:

    What’s XAMPP?

    The WikiPedia defines XAMPPas follows:

    (pronounced /ˈzæmp/ or /ˈɛks.æmp/[1]) is a free and open source cross-platform web server package, consisting mainly of the Apache HTTP Server, MySQL database, and interpreters for scripts written in the PHP and Perl programming languages …

    … The program is released under the terms of the GNU General Public License and acts as a free web server capable of serving dynamic pages. XAMPP is available for Microsoft Windows, Linux, Solaris, and Mac OS X, and is mainly used for web development projects..

    In short, XAMPP gives me a Linux/LAMP development platform on a Windows based machine.

    My Situation

    Whether it’s learning something for work, or working on a church website, often find myself jumping between languages such as Perl, PHP and Python … and content ‘manglement’ systems such as WordPress, Drupal and MovableType, I find it’s easier to keep things organized if I:

    1. keep each project in its own path
    2. establish a virtual server for each project
    3. enter the project name in the address bar of my browser

    Getting it done

    By default, “localhost” is the default domain name for your PC. It resolves to IP address 127.0.0.1.

    But just as a hosting provider can support several domain names on a single IP address, so too can your Windows system.

    Below are the steps to get this done:

    Step 1 – identify the new host

    Unlike Windows XP or Vista,  for Windows 7 you’ll need to right click on the NotePad program and “Run as Administrator” as pictured below:

    Notepad - Open as Admin

    This is because the file we want to edit is now protected. That file is located at:

    
    C:\Windows\System32\drivers\etc\hosts
    
    

    Once you’ve opened the file and on or about line 23, edit your file so it reads:

    
    127.0.0.1       localhost
    127.0.0.1       drupal
    
    

    Save it, close your notepad editor, so you don’t shoot yourself in the foot in admin mode.

    Step 2 – establish the virtual host

    Keep in mind, the primary purpose of XAMPP is to give you an Apache server that runs on your local machine.

    That in mind, you’ll need to edit one more file:

    
    notepad C:\xampp\apache\conf\extra\httpd-vhosts.conf
    
    

    Once in, you’ll want to modify it so it reads:

    
    NameVirtualHost *:80
    <VirtualHost *:80>
     ServerAdmin postmaster@dummy-host.localhost
     DocumentRoot "C:/xampp/htdocs"
     ServerName localhost:80
     ServerAlias localhost
     ErrorLog "logs/dummy-host.localhost-error.log"
     CustomLog "logs/dummy-host.localhost-access.log" combined
    </VirtualHost>
    <VirtualHost *:80>
     ServerAdmin postmaster@drupal-host.localhost
     DocumentRoot "C:/xampp/htdocs/drupal"
     ServerName drupal:80
     ServerAlias drupal
     ErrorLog "logs/drupal-host.localhost-error.log"
     CustomLog "logs/drupal-host.localhost-access.log" combined
    </VirtualHost>
    
    

    Note, in the default XAMPP install, the above is commented out, and the hosts are dummy and dummy2. I simply un-commented everything and renamed dummy2 to drupal.

    Step 3

    Restart your Apache server. The easiest way to do this is stop and start the server through the can be done through the console as pictured below:

    XAMPP Console

    Step 4 – Test It

    Finally, you’ll want to test it by entering “drupal” in the address bar of the browser of your choice.

    Before you do that, you may want to create the directory C:\xampp\htdocs\drupal …

    … and then add an index.html, .php, .pl OR .py file to provide the ubiquitous “Hello World!” to demonstrate everything is running as planned.

    Wrap-up

    Additional Resources

    I’m not the first person to write on this topic, nor will I be the last. That said, here are some other sites that offer similar tutorials in case the one above is still as clear as mud.

    Why Bother?

    Some of you may be wondering why bother at all? Why not just work on your live site.

    Personally, as an IT professional with a couple of decades experience, I can say with utter certainty – backed-up with copious examples – that this is a recipe for disaster.

    Instead, why not simply take an old box and install a Linux distribution such as Ubuntu or Fedora … or do what I did, took a new box an added XAMPP.

    Either way, you’ll be glad you did when one of your tests or learning experiences fries your non-production site.

  • How to block a range of IPs from spamming your church website

    Using a blog to manage a website’s content is a flexible and affordable solution more and more churches are employing to effectively present their message online. There is however one drawback – in that some of the open source blogging solutions used as content management on the cheap also tend to attract attention from nere-do-wells who attack the comment and content functions of application such as WordPress and MovableType with robotic floods of advertisements offering anything from enlarging various appendages to curing male baldness all while losing your life’s saving playing poker online.

    What’s worse is that many of these attacks these days come from servers in countries where you have absolutely no legal, let alone social, recourse to stop said attacks. Take for example a recent slam of attacks on a new dedicated server I’ve been working on – all which failed due to recent preventative security endeavors – but all incoming from a block of related IP addresses from a server in China all of whose addresses had 218.25.161… in common.

    And while these unwanted advances were successfully thwarted by various server hardening practices implementations – the best way to avoid trouble from said attacker is to just deny access to anything on the server by denying the range of IP addresses indicated in my security logs.

    With that in mind, I thought I’d share two approaches to blocking a range of IP addresses. One solution at the firewall level – the path I prefer on dedicated servers, the other solution is blocking IP blocks via the .htaccess file, which are employed on sites hosted on a shared server.

    Using APF firewall, I simply create an entry that defines the block – in this case:

    218.25.161.0/24

    In the .htaccess file:

    <Limit GET HEAD POST>
    order allow,deny
    deny from 218.25.161
    allow from all
    </LIMIT>

    Both implementations block IP addresses from 218.25.161.0 through 218.25.161.255. But what happens if I only want to block addresses from a smaller set of addresses? Like those coming from someone abusing their DSL services whose range of dynamically assigned IPs may only be a range of 216.12.201.150 through 216.12.201.200.

    That becomes trickier as is requires both a knowledge of the ‘CIDR notation’ and the bit mapping that goes along with it. Which is why I recommend instead using this nifty little online tool from Mikero.com. An easy-to-use service which performs all the bit-blasting, while also “aligning” the range so it can be expressed in correct CIDR notation.

    Or in laymen’s terms, I add the following generated range to my firewall:

    216.12.201.128/25

    Or where no such firewall access is available, the following line in my .htaccess file:

    deny from 216.12.201.128/25

    Below are some tools and links on the topic of how to block a range of IP addresses if you want to dig into it a bit further.

    Online tools to calculate an IP address range (CIDR):

    Online tools to check/verify your CIDR notation:

    Tutorials on blocking IP addresses and CIDR subnet masks:

    Pre-fabricated blacklists to block IP addresses of entire countries:

    A bit more on .htaccess and mod_access:

    Just remember to keep good backups of whatever files you’re working on – and try not to lock yourself out while experimenting with changes!