#!/usr/bin/perl -w
#
# IPFA 1.1 IP-Address-Fake-Anonymiser for (apache) log files
# Copyright (C) 2005 Wolfram Riedel <taisto@web.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA.
#
####################################################################
#
# mode configuration
# 0: mode off
# 1: mode on

$mode_swapping   = 0;                   # swap byte order
$mode_winding    = 0;                   # wind bytes
$mode_impossible = 0;                   # impossible bytes > 255
$mode_cutoff     = 1;                   # first byte always "1"

# Modes 'swapping', 'winding' and 'impossible' are reversible in
# theory and therefore not anonymous. Mode 'cutoff' is data lossy
# and provides partial anonymity. All four modes can be used in
# combination.
#
####################################################################

$| = 1;                                 # unbuffered output

# help message
if ( $ARGV[0] && ($ARGV[0] eq "-h" || $ARGV[0] eq "--help")) {
print <<HELP;
IPFA 1.1 IP-Address-Fake-Anonymiser for (apache) log files
Copyright (C) 2005 Wolfram Riedel <taisto\@web.de>

Usage: ipfa [LOGFILE]
HELP
exit 0;
}

while($log_line = <STDIN>) {

  ($hostip) = split (/\s/, $log_line);  # read old ip from log line
  @ipbytes = split (/\./, $hostip,4);   # split ip into bytes


  # mode for cutting off
  if ($mode_cutoff) {
   $ipbytes[0] = 1;
#   $ipbytes[1] = 1;
   $ipbytes[2] = 1;
#   $ipbytes[3] = 1;
  }


  # mode for swapping,
  # provides array mapping (0-3 => 1-4) for other modes
  $ipbytes[11] = $ipbytes[0];
  $ipbytes[12] = $ipbytes[1];
  $ipbytes[13] = $ipbytes[2];
  $ipbytes[14] = $ipbytes[3];
  if ($mode_swapping) {
    $ipbytes[1] = $ipbytes[13];
    $ipbytes[2] = $ipbytes[11];
    $ipbytes[3] = $ipbytes[14];
    $ipbytes[4] = $ipbytes[12];
  } else {
    $ipbytes[1] = $ipbytes[11];
    $ipbytes[2] = $ipbytes[12];
    $ipbytes[3] = $ipbytes[13];
    $ipbytes[4] = $ipbytes[14];
  }


  # mode for winding
  if ($mode_winding) {
    $ipbytes[1] = ($ipbytes[1] + 32) % 255;
    $ipbytes[2] = ($ipbytes[2] + 128) % 255;
    $ipbytes[3] = ($ipbytes[3] + 64) % 255;
    $ipbytes[4] = ($ipbytes[4] + 192) % 255;
  }


  # mode for impossible bytes
  if ($mode_impossible) {
    $ipbytes[1] *= 2;
    $ipbytes[2] += 256;
    $ipbytes[3] *= 2;
    $ipbytes[4] += 128;
  }


  # compose new ip
  $newip = $ipbytes[1].".".$ipbytes[2].".".$ipbytes[3].".".$ipbytes[4];

  $log_line =~ s/^\S*\s+//;             # cut old ip from log line

  if ($ARGV[0]) {
    $logfile = "$ARGV[0]";                # first arg: name of log file
    open(LOG, ">>$logfile")               # open log file for append
	or die "cannot open log file";
    print LOG $newip." ".$log_line;       # compose line and write to logfile
    close(LOG)                            # close log file
	or die "cannot close log file";
  } else {
    print $newip." ".$log_line;           # compose and output line
  }
}

