#!/usr/bin/perl -w

# This Squid redirector checks a given URL for containing an IP address
# instead of a hostname. If it does, the address will be tried to resolve
# to a suitable hostname, which will be used in place of the IP address.
# If this is not possible, redirect to an error page (most likely on a
# local web server).

# All this is necessary because Squid, in its current version (probably
# due to the latest DNS-spoofing patch) crashes if an URL with an IP address
# is requested.

# THIS IS A HACK. USE AT YOUR OWN RISK.

use strict;
use warnings;
use Net::hostent;
use Socket;
use Sys::Syslog;

my @parts; # Array with URL compnents (protocol, server, path)
my $proto; # protocol
my $ip; # IP address
my $urlpath; # path
my $dnsname; # DNS name of $ip
my $validip; # return value of inet_aton (if $ip is valid)

# use unbuffered output
$|=1;

# enable syslog
openlog ("redirector", "nowait", "user");


# URL format: <proto>://<server>[:port][/[pfad]]

while (<>) {
	# does URL contain a numeric IP adress?
	if ($_ =~ m"://\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$" or
	    $_ =~ m"://\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}[:/]" ) {
		
		# extract the parts of the URL
		@parts = split m"://(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", $_;
		$proto = $parts[0];
		$ip = $parts[1];
		$urlpath = $parts[2] ? $parts[2] : "";
		$validip = Socket::inet_aton($ip);
		#syslog ("info", "Proto: %s Server: %s Path: %s", $proto, $ip, $urlpath);
		
		# IP address valid?
		if ($validip) {
			syslog ("info", "IP Adress %s valid", $ip);
			# try to resolve to a DNS name
			$dnsname = gethostbyaddr($validip);
			# found?
			if ($dnsname) {
				syslog ("info", "OK, new URL: %s://%s%s", $proto, $dnsname->name, $urlpath);
				# output new URL (replace IP adress with DNS name)
				print "$proto://".$dnsname->name."$urlpath";
			} else {
				undef $validip;
			}
		}
		if (!$validip) {
			syslog ("info", "Failed, redirecting to http://www.example.com/badurl/%s/%s/%s", $proto, $ip, $urlpath);
			# redirect to error page (adjust this to your needs!)
			print "http://www.example.com/badurl/$proto/$ip/$urlpath";
		}

	} else {
		# empty line -> Squid will use original URL
		print "\n";
	}
}
