BSD-Ipfwgen

 view release on metacpan or  search on metacpan

Ipfwgen.pm  view on Meta::CPAN

my $ipfw = "/sbin/ipfw";

use vars qw($VERSION);
$VERSION = 1.5;

require Exporter;

@ISA = qw(Exporter);
@EXPORT = qw(
	outside leaf 
	us not_us consolidate symmetric
	count_by_interface count_by_address 
	count_by_udp count_by_tcp 
	no_looping no_spoofing_us no_spoofing_by_us no_leaf_spoofing
	generate 
	drop_unwanted 
	tcp_from_rules udp_from_rules 
	tcp_to_rules udp_to_rules 
	from_net_rules to_net_rules 
	to_me_rules from_me_rules
	not_to_me_rules not_from_me_rules
	in_interface_rules out_interface_rules
	from_us to_us
	);

my @from_us;
my @to_us;
my @outside;
my @leaf;
my @us;
my @not_us;
my @symmetric;
my @interesting;
my %consolidate;
my $if0; # first interface

use Carp;

# BEGIN { use IO::Handle; open(DEBUG, ">&STDERR"); autoflush DEBUG 1; }
BEGIN { open(DEBUG, ">/dev/null"); };

Ipfwgen.pm  view on Meta::CPAN

	}
}

# interfaces
sub outside { push(@outside, @_); }
sub leaf { push(@leaf, @_); };

# networks
sub interesting { push(@interesting, @_); watch(@_); }
sub us { push(@us, @_); watch(@_); };
sub not_us { push(@not_us, @_); watch(@_); };
sub symmetric { push(@symmetric, @_); watch(@_); };
sub from_us { push(@from_us, @_); watch(@_); };
sub to_us { push(@to_us, @_); watch(@_); };

sub mark_addresses
{
	my ($aref, $network, $bits, $value, $rem) = @_;
	die "can only consolidate class Bs or smaller" 
		if $bits < 16;

Ipfwgen.pm  view on Meta::CPAN

	my @r = @{$interfaces{$interface}->{'ROUTES'}};
	my %r;
	my @dn = get_direct_nets($interface);
	@r{@r} = @r;
	@r{@dn} = @dn;
	return @r;
}

sub get_routes 
{
	for my $net (@us, @symmetric, @interesting, @not_us, @from_us, @to_us) {
		my ($base, $mask) = get_netmask($net);
		if ($mask >= 24) {
			$base =~ m/^(\d+\.\d+\.\d+)\.\d+$/
				or die "parse dest $net ($base)";
			$track_net{$1} = $net;
		} else {
			die if $mask < 16;
			$base =~ /^(\d+\.\d+)\.(\d+)\.\d+$/
				or die "parse dest $net ($base)";
			my ($netbase, $ext) = ($1, $2);

Ipfwgen.pm  view on Meta::CPAN

my %tcp_from_rules;
my %udp_to_rules;
my %tcp_to_rules;
my %from_net_rules;
my %to_net_rules;
my $begun = 0;

my @from_me_rules;
my @to_me_rules;

my @not_from_me_rules;
my @not_to_me_rules;

my %count_in;
my %count_out;
my %count_udp_from;
my %count_tcp_from;
my %count_udp_to;
my %count_tcp_to;
my @count;

sub must_exist

Ipfwgen.pm  view on Meta::CPAN

sub udp_from_rules { my($port, $rules) = @_; push(@{$udp_from_rules{$port}}, clean_rules($rules)); }
sub tcp_from_rules { my($port, $rules) = @_; push(@{$tcp_from_rules{$port}}, clean_rules($rules)); }
sub udp_to_rules { my($port, $rules) = @_; push(@{$udp_to_rules{$port}}, clean_rules($rules)); }
sub tcp_to_rules { my($port, $rules) = @_; push(@{$tcp_to_rules{$port}}, clean_rules($rules)); }

sub from_net_rules { my($net, $rules) = @_; push(@{$from_net_rules{$net}}, clean_rules($rules)); }
sub to_net_rules { my($net, $rules) = @_; push(@{$to_net_rules{$net}}, clean_rules($rules)); }

sub from_me_rules { my($rules) = @_; push(@from_me_rules, clean_rules($rules)); }
sub to_me_rules { my($rules) = @_; push(@to_me_rules, clean_rules($rules)); }
sub not_from_me_rules { my($rules) = @_; push(@not_from_me_rules, clean_rules($rules)); }
sub not_to_me_rules { my($rules) = @_; push(@not_to_me_rules, clean_rules($rules)); }

#sub modload
#	modload /lkm/ipfw_mod.o
#	XXX
#

my $genlabel = "genlabel00000";
my @rules;

sub gensect

Ipfwgen.pm  view on Meta::CPAN

	push(@rules, "=label not-counting-tcp");
	push(@rules, "=gap");

	push(@rules, @count);
	push(@rules, "=gap");

	push(@rules, "=rulenum 10000");
	push(@rules, "=gap");

	# recv only happens on packets that we didn't generate
	if (@from_us_fules || @not_from_me_rules) {
		push(@rules,
			"=skipto done-from-us all from any to any in recv =IN",
			@from_me_rules,
			"=skipto done-not-from-us all from any to any",
			"=label done-from-us",
			@not_from_me_rules,
			"=label done-not-from-us");
		push(@rules, "=gap");
	}

	if (@to_me_rules || @not_to_me_rules) {
		push(@rules,
			"=skipto done-to-us all from any to =ME",
			@not_to_me_rules,
			"=skipto done-not-to-us all from any to any",
			"=label done-to-us",
			@to_me_rules,
			"=label done-not-to-us");
		push(@rules, "=gap");
	}

	gensect(undef, 0, "all from any to any in <recv =KEY>", %in_rules);
	push(@rules, "=gap");
	gensect(undef, 0, "all from any to any out <xmit =KEY>", %out_rules);

Ipfwgen.pm  view on Meta::CPAN

				push(@n, $y);
			}
		} elsif ($x =~ /=TOUS/) {
			for my $n (@to_us) {
				my $y = $x;
				$y =~ s/=TOUS/$n/g;
				push(@n, $y);
			}
		} elsif ($x =~ /=US/) {
			my $l2 = $genlabel++;
			for my $n (@not_us) {
				my $y = remove_action($x);
				$y =~ s/=US/$n/g;
				push(@n, "=skipto $l2 $y");
			}
			for my $n (@us) {
				my $y = $x;
				$y =~ s/=US/$n/g;
				push(@n, $y);
			}
			push(@n, "=label $l2");

Ipfwgen.pm  view on Meta::CPAN

	}
	print "$ipfw delete 1\n";
	print "$ipfw zero\n";
}

sub generate
{
	my (@opt) = @_;

	# don't allow others to pretend that they are us
	unshift(@not_from_me_rules, 
		"=skiprule all from any to any in recv 'lo*'",
		"=deny_log all from =ME to any # ns-op");

	my @legal = qw(
		LOG_DENIES
		DEFAULT-ACCEPT
		INSECURE
	);
	my %legal;
	@legal{@legal} = @legal;

Ipfwgen.pod  view on Meta::CPAN


=head1 SYNOPSIS

	use BSD::Ipfwgen;

	outside qw(**interface list**);
	leaf qw(**interface list**);

	consolidate qw(**network list**);
	us qw(**network list**);
	not_us qw(**network list**);
	to_us qw(**network list**);
	from_us qw(**network list**);
	symmetric qw(**network list**);

	count_by_interface();
	count_by_address qw(**network list**);
	count_by_udp qw(**port list**);
	count_by_tcp qw(**port list**);

	no_looping()

Ipfwgen.pod  view on Meta::CPAN


	tcp_from_rules($port, $rules);
	tcp_to_rules($port, $rules);
	udp_from_rules($port, $rules);
	udp_to_rules($port, $rules);

	from_net_rules($network, $rules);
	to_net_rules($network, $rules);

	to_me_rules($rules)
	not_to_me_rules($rules)
	from_me_rules($rules)
	not_from_me_rules($rules)

	in_interface_rules($interface, $rules);
	out_interface_rules($interface, $rules);

	drop_unwanted qw(**network list**);

	generate qw(**options**)

	**port list** is a list of integers.  80, 23, etc.
	**network list** is a list of network address.  207.33.90.32/27 etc.

Ipfwgen.pod  view on Meta::CPAN

safer.  It handles generating some of the harder rulesets: anti-spoofing,
anti-looping, and anti land-attack.

Ipfwgen does not try to reduce the complexity of firewall building.  
What it does do is allow you to write a perl program which generates
a firewal.  It's expected that the firewalls generated by Ipfwgen will
be examined by a human and installed manually.  

Ipfwgen commands must be given in a particular sequence.  First are
the declaritive commands: B<outside>, B<leaf>, B<consolidate>, B<us>, 
B<not_us>, and B<symmetric>.

Then the rule-specification commands: almost everything else.  Ipfwgen
keeps an internal database of the rules that are in progress.  After all
the rule-specification commands are done, then the firewall gets 
compiled.

The B<generate> command compiles the specifications into actuall L<ipfw> 
commands and dumps them on STDOUT.

=head1 DECLARATIVE COMMANDS

Ipfwgen.pod  view on Meta::CPAN

IP addresses for the firewall system is needed.  This is primarily
used to avoid needing to list a large number of IP addresses on 
web servers with many virtual hosts.

=item B<us>(NETWORKs)

Specifies network ranges that comprise the address space that is routed
by "us".  The B<us> command implies that we are the only source of routes
for the addresses specifed.

=item B<not_us>(NETWORKs)

Specifies networks that are within "us" but should not be.  For example,
"us" may claim to include 209.66.121.0/24, but in reality, the first few
addresses aren't ours.  This situation can be handled using "not_us".

=item B<to_us>(NETWORKs)

Specifies networks that we may legitimately receive traffic on 
behalf of.  Don't filter it when incomming at the edges.

=item B<from_us>(NETWORKs)

Specifies networks that we may legitimately send traffic on 
behalf of.  Don't filter it when outgoing at the edges.

Ipfwgen.pod  view on Meta::CPAN


These are all optional.  These filters will be generated anyway to
handle the anti land-attack rules.

=over 25

=item B<to_me_rules>(rules)

Apply the specified rules to packets that are destined for this machine.

=item B<not_to_me_rules>(rules)

Apply the specified rules to packets that are not destined for this machine.

=item B<from_me_rules>(rules)

Apply the specified rules to packets that are sent from this machine.

=item B<not_from_me_rules>(rules)

Apply the specified rules to packets that came from some other machine.

=back

=head1 FILTER BY INTERFACE

These are all optional, but these filters will be generated anyway
to do the anti-looping and anti-spoofing rules.

Ipfwgen.pod  view on Meta::CPAN

packets out by interface; count packets from udp ports;
count packets to udp ports; count packets from tcp ports;
count packets to tcp pots; count packets from and to particular
networks.

=item 2.

Apply filters on packets that are from the firewall system
(B<to_me_rules>).  Apply
filters on packets that are not from the firewall system
(B<not_to_me_rules>).

=item 3.

Apply filters on packets that are to the firewall system
(B<from_me_rules>).  Apply filters
on packets that are not to the firewall system
(B<not_from_me_rules>).

=item 4.

Apply filters for packets that came in via a particular interface.
(B<in_interface_rules>).  This includes loop prevention on point-to-point
interfaces.  This also includes preventing others from spoofing us and
leaf nodes from spoofing anyone.

=item 5.

Ipfwgen.pod  view on Meta::CPAN

	us qw(
		140.174.82.0/24 
		207.33.232.0/22 
		207.33.184.0/22 
		207.33.240.0/21 
		209.157.64.0/19 
		140.174.154.0/24 
		207.33.66.0/24 
		209.66.121.0/24
	    );
	not_us qw(
		209.66.121.0/29
	);
	symmetric qw(
		209.66.121.0/27
	    );


	count_by_interface();
	count_by_tcp qw(80 119 21 53 25 871 513 23 6667);
	count_by_address qw();

examples/gen-another  view on Meta::CPAN

us qw(
	140.174.82.0/24 
	207.33.232.0/22 
	207.33.184.0/22 
	207.33.240.0/21 
	209.157.64.0/19 
	140.174.154.0/24 
	207.33.66.0/24 
	209.66.121.0/24
    );
not_us qw(
	209.66.121.0/29
);

# count_by_interface();
# count_by_tcp qw(80 119 21 53 25 871 513 23 6667);
# count_by_address qw();
drop_unwanted qw(
	192.168.0.0:255.255.0.0
	172.16.0.0:255.240.0.0
	10.0.0.0:255.0.0.0



( run in 0.265 second using v1.01-cache-2.11-cpan-26ccb49234f )