Monday, November 03, 2008

fixed 404s

[Mon Nov 3 11:18:58 2008] [error] [client 169.229.192.166] File does not exist: /usr/local/apache/htdocs/newsletter/01-4/2001-4.pdf
FIXED: -> 01-4.pdf

[Mon Nov 3 11:21:37 2008] [error] [client 169.229.192.166] File does not exist: /usr/local/apache/htdocs/aviation/2003/download.php
FIXED: -> /aviation2003downloads/
in /aviation/2003/index.php

also:
/aviation2000downloads/
FIXED: -> /aviation/2000/
in /aviation/2004/index.php, /aviation/2005/index.php


[Sun Nov 2 01:57:47 2008] [error] [client 169.229.192.166] File does not exist: /usr/local/apache/htdocs/sitemap/2004techtopics.pdf
[Sun Nov 2 01:57:47 2008] [error] [client 169.229.192.166] File does not exist: /usr/local/apache/htdocs/sitemap/2002techtopics.pdf
[Sun Nov 2 01:57:50 2008] [error] [client 169.229.192.166] File does not exist: /usr/local/apache/htdocs/sitemap/2006techtopics.pdf
[Sun Nov 2 01:58:17 2008] [error] [client 169.229.192.166] File does not exist: /usr/local/apache/htdocs/sitemap/1999techtopics.pdf
[Sun Nov 2 01:59:22 2008] [error] [client 169.229.192.166] File does not exist: /usr/local/apache/htdocs/sitemap/1998techtopics.pdf
[Sun Nov 2 01:59:22 2008] [error] [client 169.229.192.166] File does not exist: /usr/local/apache/htdocs/sitemap/2005techtopics.pdf
[Sun Nov 2 01:59:23 2008] [error] [client 169.229.192.166] File does not exist: /usr/local/apache/htdocs/sitemap/2001techtopics.pdf

fixed in: /sitemap/index.php

Newsletter



I also fixed a LOT of broken links in older newsletter folders (.html instead of .php, old paths that were replaced 3 or 4 years ago...)

Newsletters from late 2006 and all of 2007 didn't have index.php pages, so I copied HTML from the newsletter/archive page into new index pages for each issue in 2007. Still need to do 2006.

Labels: , , , , ,

Wednesday, October 15, 2008

Finding 404s

Today I once again tail'ed the error log, and fixed a bunch of broken links to /freestuff/store.php

Then there are a lot of SSL errors...

Ooh! and I fixed some broken image links in the 2003 Summer newsletter...

Labels: , , , , ,

Tuesday, May 20, 2008

sed and grep: "Stories" of web visitors

I've been thinking for a long time about crunching the web logs to produce "stories" showing how visitors navigate our site. We don't get so many visitors that it would be overwhelming to look at a day or two.

So I've started writing shell scripts to do the crunching.

They are located at /home/steve/webstats/trunk

The plan is, starting from a raw log file:
1. find just requests for pages (.php, .html, .pdf) with result code 200.

(Hmmm...
right now I am using grep -v to get rid of certain things that aren't (1.) above.
is it simpler to use something like:
grep '] "GET [^ ]*[php|pdf|html][^ ]* HTTP/1.." 200 '
or
sed '/] "GET [^ ]*[php|pdf|html][^ ]* HTTP\/1.." 200 /!d'
to get "successful requests for pages?"

sed doesn't do aaa OR bbb OR ccc very well; it looks like
sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d    # most seds
gsed '/AAA\|BBB\|CCC/!d' # GNU sed only
sed is very fast, though.

This works at about 10,000 raw log lines/sec:
sed '/" 200 /!d' $logfilename | \
sed -e '/"GET [^ ]*\.php/b' \
-e '/"GET [^ ]*\.pdf/b' \
-e '/"GET [^ ]*\.ppt/b' \
-e '/"GET [^ ]*\.avi/b' \
-e '/"GET [^ ]*\.doc/b' \
-e '/"GET [^ ]*\.mpg/b' \
-e '/"GET [^ ]*\.flv/b' \
-e '/"GET [^ ]*\.html/b' \
-e '/"GET [^ ]*\/ HTTP/b' \
-e d > $temporary_story_file
More importantly, if I specify good files, then I have to modify the script every time we add a new file type. And if I forget, it's not easy to notice the absence of the overlooked file type.

grep, grep, grep takes a while to process one log file, about 15 minutes so far...

Tue May 20 20:44:19 PDT 2008
Lines in apache access log:
636818 /export/www/htdocs/weblogs/2008/Q2/access_log_200804

Dropping requests for images:

Tue May 20 20:54:32 PDT 2008
Lines left in temporary work file:
214027 /tmp/stories_14566

Dropping requests for javascripts:

Tue May 20 20:55:01 PDT 2008
Lines left in temporary work file:
203919 /tmp/stories_2_14566

Dropping requests for css:

Tue May 20 20:55:39 PDT 2008
Lines left in temporary work file:
192682 /tmp/stories_14566

Dropping partial or unsuccessful requests:

Tue May 20 20:59:28 PDT 2008
Lines left in temporary work file:
140429 /tmp/stories_2_14566


anyway, next is:
(1.5. weed out search / h@x0r bots)
2. sort by IP address and time
3. clean up the lines to make a tab-delimited table with these fields:
IP address datestamp URL requested referring URL Browser type

Of course you can buy tools that claim to do this...

Labels: , , , , , ,

Tuesday, April 01, 2008

Web Server Stats: What to do with hax0r traffic

In my ongoing quest to produce a measure of real human use of the site, I now come to malicious traffic.

First thing: how to identify malicious traffic?

In an earlier post I describe creating Fake hacker targets like /_vti_bin/owssvr.dll (on our LAMP server). I could grep access logs for known malicious URLs like that. Problem: high maintenance. The bad guys are always discovering and trying new vulnerabilities, and I would have to somehow keep up.

I could look for large numbers of 404s per host, since probes for vulnerabilities will fail. (Well, they would if I removed the fake targets.)

Labels: , , , ,

Wednesday, February 27, 2008

Checking my web server for errors

My Apache error logs don't tell me enough about 404s. They don't tell me:

User-agent:
If the user-agent is a web crawler, I don't care about bad links on our site; they're probably already fixed and the crawler still has the bad link in their index.

Referrer:
If the 404 is from a bad link on our site, I want to know the originating page.

Query:
Most 404s come from cross-site scripting (XSS) attacks. Without the query part of the URL, it's impossible to distinguish these.

Today I am using tail and grep to check the last few days' worth of 404s:

$ tail -20000 access_log_www | grep -F '" 404'

As it happens, we get about 10,000 requests/day, so to see n days' log entries I just look at the last n0,000 lines in the access logs (tail -20000).

Only 0.2% of requests are 404s, so grep has to winnow through a lot of chaff to find them. To speed it up, I use grep -F, which turns off the regular expression engine.

The string 404 can appear in other places (the file size field, the user-agent field) so I grab the double quote in the last position of the URL field. Naturally that means I have to single-quote the search pattern.

Statistical aside:
How much time does grep -F save?

Here are the results of 10 greps on 20,000 lines, 5 with and 5 without the -F arg:

grep real 0.486 user 0.460 sys 0.070
grep real 0.493 user 0.460 sys 0.020
grep real 0.507 user 0.430 sys 0.080
grep real 0.510 user 0.490 sys 0.010
grep real 0.541 user 0.500 sys 0.130
grep -F real 0.455 user 0.480 sys 0.040
grep -F real 0.458 user 0.420 sys 0.050
grep -F real 0.458 user 0.430 sys 0.050
grep -F real 0.458 user 0.470 sys 0.040
grep -F real 0.523 user 0.600 sys 0.050


grep (no -F) costs:
7.87% in real time
-2.50% in user time (saves time?)
34.78% in system time (big percentage of a small number)
more than grep -F

put another way, grep -F saves:
7.29% in real time
-2.56% in user time (costs time?)
25.81% in system time (big percentage of a small number)
versus grep

Labels: , , ,