Complete.Org: Mailing Lists: Archives: discussion: August 1999:
[aclug-L] ipchains firewall packet
Home

[aclug-L] ipchains firewall packet

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: aclug-L@xxxxxxxxxxxx
Subject: [aclug-L] ipchains firewall packet
From: Jeff <schaller@xxxxxxxxxxxxx>
Date: Tue, 17 Aug 1999 18:43:24 -0500 (CDT)
Reply-to: aclug-L@xxxxxxxxxxxx

Here's what we (hopefully) had copies of at the meeting,
and what I based my presentation off of. I wrote it for a security
tools review.

-jeff
-- 
"It's not just the apocalypse, it's the humidity." - Joel of MST3K




Title: Using ipchains to set up a packet-filtering firewall.
Author: Jeff Schaller <schaller@xxxxxxxxxxxxx>
Date: Aug 15, 1999

keywords: ipchains, packet filtering, firewall
Rating (out of 5): 4
Why: powerful utility to tighten down a box; wish there was an easier way
     to delete rules

Introduction:
The ipchains utility (which is used in the 2.* kernels instead of
ipfwadm), can be used to set up a simple yet powerful packet-filtering
firewall.  The situation:
- To connect to the internet, I have a dialup account (and am thus
  assigned a random IP each time)
- I want to set up a policy which blocks any incoming connections
- I then want to allow back in certain connections

Overview of the solution:
We'll use ipchains to set up a default DENY policy for all incoming
connections to any port or address, from any port or address, and using
any protocol.  We'll then decide what we need to allow back in to provide
the services we want to use.  We'll use the ipchains "-l" flag to log to
syslog when a rule matches; by watching the syslog, we can see what
patterns emerge.

Specifics of the solution:
Each time we reboot, the rules get cleared, so we'll put the ipchains
commands into one of the system startup scripts (I appended them to
/etc/rc.d/rc.local).  The paranoid may want to put them in a separate
script that gets executed immediately after the network interface(s) are
brought up.  So first, the "DENY all" command:

# deny all, log
/sbin/ipchains -I input -j DENY -l

This tells ipchains to insert into the 'input' chain the rule to deny
every packet, and then log if the rule matches.  You now have an airtight
box. Trouble is, you've lost quite a bit of functionality from your side
as well.  Things like X which try to make local connections, DNS replies,
pings, http, etc.  So we start allowing these back in (I'll start letting 
the comments speak for the commands):

# allow all sourced from me, don't log
/sbin/ipchains -I input -s 127.0.0.1 -j ACCEPT

# allow pings, log
/sbin/ipchains -I input -p icmp -j ACCEPT -l

# allow onyx's [ my ISP ] telnetd connect back to us on tcp, don't log
/sbin/ipchains -I input -s 206.53.103.2 23:23 -d 0/0 1024: \
  -p tcp -j ACCEPT

# allow remote httpds to connect back on tcp, don't log
/sbin/ipchains -I input -s 0/0 80:80 -d 0/0 1024: -p tcp -j ACCEPT

(Side note: logging http packets _quickly_ fills up your syslog -- beware)

# allow rlogin from LAN
ipchains -I input -s 192.168.0.0/24 -d 0/0 513:513 -p tcp -j ACCEPT

You'll want to think about what other services you want to allow to
connect back and add rules for each.  Helpful hints for creating the
ipchains rules:
- start off by adding the "-l" flag to each rule and watching the syslog;
  if the matches are uninteresting (or too numerous), you can go back and
  remove the "-l" flag.
- I use "-j DENY"; you could use "-j REJECT" to send an ICMP reject
  message back, if you're feeling nice.
- the "-s" flag specifies the source address (CIDR notation accepted) and
  source port; similarly for the "-d" flag.  The port specification can be
  a single port (80), or a range of ports (1024: or 20-21). Of course, see
  the manpage for ipchains(8) for other options.


As an added bonus, here is a small perl script I wrote to parse the syslog
entries for ipchains.  By default it looks in /var/log/kernel, which is
where my ipchains logs end up.  You can specify a different file on the
command line.  By default, the script prints only the "DENY" packets, and
attempts to resolve the IP address to a name.  It then translates any
known port numbers into service names according to /etc/services. The "-f"
flag is available to continuously update (ala 'tail -f').


#!/usr/bin/perl

# firewall interpreter
# searches /var/log/kernel for firewall entries
# deciphers them according to /etc/services
#

# have option to sort by ip [then date]
# have option to sort by src port
# ... dest port
# ... show time deltas between same-IP hits

use Socket;
use Getopt::Std;
getopts('anf') or die "Usage: $0 [ -a ] [ -n ] [ -f ] [ file ]
# A firewall reporting script
-a      print all packets, not just DENY
-n      do not do DNS lookups on IP addresses
-f      continually update
file    provide alternate file to read entries from; default is /var/log/kernel
";

sub read_services;
sub parse_line;

%services = ();
&read_services;
$file = $ARGV[0] || '/var/log/kernel';

open D, "<$file" or die "hrm, $!";
while (<D>) {
  &parse_line($_);
}

while ($opt_f) {
  sleep 3;
  seek D, 0, 1;
  while (<D>) {
    &parse_line($_);
  }
}

close D;

sub read_services {
  open S, "</etc/services" or die "ack";
  while (<S>) {
    next if /^#/ or /^$/;
    next unless /tcp/;
    ($name, $port) = ($_ =~ /^(.*?)\s+(\d+)\//);
    $services{$port} = $name;
  }
  close S;
}

sub parse_line {
  $_ = $_[0];
  my $status;

  return unless /Packet log:/;
  chomp;
  my ($date, $proto, $srcip, $srcport, $meip, $meport) =
    ($_ =~ /^(.{15}) .+ PROTO=(\d+)\s
             (\d+\.\d+.\d+\.\d+):(\d+)\s
             (\d+\.\d+.\d+\.\d+):(\d+)
           /x);

  if (/DENY/) {
    $status = '!';
  } elsif (/ACCEPT/) {
    $status = 'o';
  } else {
    $status = '?';
  }

  next if ($status eq 'o' && !$opt_a);

  $proto = (getprotobynumber($proto))[0];
  $srcname = $services{$srcport} || $srcport;
  $destname = $services{$meport} || $meport;


  if ($opt_n) {
    $src = $srcip;
  } else {
    $src = gethostbyaddr(inet_aton($srcip), AF_INET) || $srcip;
  }

  printf "%s %15s %10s -> %-s /%s/ %s\n",
         $status, $date, $srcname, $destname, $proto, $src;
}


[Prev in Thread] Current Thread [Next in Thread]
  • [aclug-L] ipchains firewall packet, Jeff <=