BSD-Ipfwgen
view release on metacpan or search on metacpan
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"); };
}
}
# 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;
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);
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
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
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);
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");
}
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 )