BSD-Ipfwgen
view release on metacpan or search on metacpan
Ipfwgen.pod view on Meta::CPAN
=head1 NAME
BSD::Ipfwgen - Module to aid in the creation of ipfw-based firewalls
=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()
no_spoofing_us()
no_spoofing_by_us()
no_leaf_spoofing()
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.
**interface list** is a list of interface names. de0, fxp1 etc
**options** is a list of the valid options: DEFAULT-ACCEPT, INSECURE
$rules is a newline separated set of L<ipfw> rules.
=head1 DESCRIPTION
Ipfwgen is designed to make writing complex firewalls easier and
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
The declaritive commands must preceed all others.
=over 25
=item B<outside>(INTERFACEs)
Specifies that an interface is connected to the Internet at large
and that the packets coming in from that interface should not be from
"us".
=item B<leaf>(INTERFACEs)
Specifies that an interface leads to a network with no other
connections. Routing to a leaf can be assumed to be symmetric.
=item B<consolidate>(NETWORKSs)
Specifies that addresses within the network specified should be ignored
and that the network address should be used instead when a list of
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.
=item B<symmetric>(NETWORKs)
Specifies that the routes to a network are expected to be symmetric.
=back
=head1 COUNTING SPECIFICATIONS
These are all optional.
=over 25
=item B<count_by_interface>()
Requests that traffic be counted by interface. Both incoming and
outgoing will be counted.
=item B<count_by_address>(NETWORKs)
Requests that traffic be tracked on a per NETWORK bases.
=item B<count_by_udp>(PORTs)
Requests that traffic be tracked on a per PORT basis for udp.
=item B<count_by_tcp>(PORTs)
Requests that traffic be tracked on a per PORT basis for udp.
=back
=head1 SPOOFING AND LOOPING
Ipfwgen makes an attempt to generate all the anti-looping and anti-spoofing
rules. These are all optional, but anti land-attack rules will be
added automatically.
=over 25
=item B<no_looping>()
Specifies that obvious packet loops should be prevented. For example,
do not route packets meant for us out and outside interface.
=item B<no_spoofing_us>()
Specifies that if there is an "outside" interface, the packets arriving
on it should be checked to make sure that they don't claim to come from
ourselves.
Ipfwgen.pod view on Meta::CPAN
=head1 FILTER BY ADDRESSES RULES
These are all optional.
=over 25
=item B<from_net_rules>(network,rules)
Apply the specified ruleset to packets that came from an address
with the network specified.
=item B<to_net_rules>(network,rules)
Apply the specified ruleset to packets that are destined for an address
with the network specified.
=item B<drop_unwanted>(networks)
A quick way to list the networks that you do not with to communicate
with.
=back
=head1 FITLER BY PORT
These are all optional.
=over 25
=item B<tcp_from_rules>(port,rules)
Apply the rules specified to tcp packets that came from the specified port.
=item B<tcp_to_rules>(port,rules)
Apply the rules specified to tcp packets that are destined for the
specified port.
=item B<udp_from_rules>(port,rules)
Apply the rules specified to udp packets that came from the specified port.
=item B<udp_to_rules>(port,rules)
Apply the rules specified to udp packets that are destined for the
specified port.
=back
=head1 ORIGINATION AND TERMINATION
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.
=over 25
=item B<in_interface_rules>(interface,rules)
Apply the specified rules to packets that arrived on the specified
interface.
=item B<out_interface_rules>(interface,rules)
Apply the specified rules to packets that are departing over the
specified interface.
=back
=head1 GENERATE OPTIONS
Once the rules have been declared, they must be compiled into
actual firewall commands. The command to compile them is
B<generate>(options). The B<generate> command should be given
last.
The compiled rules are dumped on STDOUT. They are not automatically
executed. Running B<generate()> cannot harm your system. Running the
output from a program that includes B<generate()> can harm your system
so be careful!
The following options are understood.
=over 25
=item DEFAULT-ACCEPT
Specifies that unless packets are specifically rejected, they should be
accepted. The default is that packets that are not specifically accpeted
are rejected.
=item INSECURE
When building the firewall, add in a rule to accept all packets
as a temporary measure. When the firewall is completely built, remove
the rule. This creates a window of opportunity for attack. On the
other hand, it helps prevent accididental computer death when rebuilding
the firewall. It's a good idea to use INSECURE while testing your
firewall, but not to use it for final deployment.
=item LOG_DENIES
Specifies that in general, when packets are denied, they should be
logged. Some rules will still not log: the anti-looping rules tend
to deny a lot of packets and logging those is both boring and wasteful.
Ipfwgen.pod view on Meta::CPAN
The =US specifier will be replaced by the network defined by the
B<us>() command. If more than one network was defined, then the rule
with the =US specifier will be replicated as necessary to put them all
in. =skiprule still works.
=item =TOUS
The =US specifier will be replaced by the network defined by the
B<to_us>() command. If more than one network was defined, then the rule
with the =US specifier will be replicated as necessary to put them all
in. =skiprule still works.
=item =FROMUS
The =FROMUS specifier will be replaced by the network defined by the
B<from_us>() command. If more than one network was defined, then the rule
with the =US specifier will be replicated as necessary to put them all
in. =skiprule still works.
=item =IN
The =IN specifier will be replaced by the interfaces that the firewall
system has. This will likely require replicating the rule with the specifier.
=skiprule still works.
=item =host:I<hostname>
The =host:I<hostname> specifier will be replaced with the IP address of
the hosthame given. Only one IP address will be substituted in so do not
use this with hosts that have multiple IP addresses. The =host:I<hostname>
specifier is the only specifier that can be used more than once in a
rule and the only one that can be combined with other specifiers.
=item =IF0
FreeBSD treats the first interface a specially. The =IF0 specifier will
be replaced by the name of the first interface. =IF0 can be combined with
other meta specifiers.
=back
=head1 SEQUENCE
The rules generated by Ipfwgen are processed in the following sequence:
=over 6
=item 1.
Counting rules. Count packets in by interfaces; count
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.
Apply filters for packets that are going out via a particular interface
(B<out_interface_rules>). This includes loop prevention on outside
interfaces and on broadcast networks. This also includes preventing
us from spoofing others.
=item 6.
Accept packets that are part of established TCP connections.
=item 7.
Apply filters for packets that are coming from a particular
network (B<from_net_rules>). This includes preventing anyone from spoofing
traffic from leaf nodes.
=item 8.
Apply filters for packets that are going to a particular
network (B<to_net_rules>). This includes dropping unwanted networks.
=item 9.
Apply filters for packets that are coming from a particular udp port.
=item 10.
Apply filters for packets that are going to a particular udp port.
=item 11.
Apply filters for packets that are coming from a particular tcp port.
=item 12.
Apply filters for packets that are going to a particular tcp port.
=item 13.
Accept or deny the rest as per the DEFAULT-ACCEPT option.
=back
=head1 EXAMPLE
#/usr/local/bin/perl -w
use strict;
use BSD::Ipfwgen;
use IO::Handle;
outside 'fxp0';
leaf 'etha32';
consolidate '209.66.121.128/25';
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();
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
);
no_looping();
no_spoofing_us();
no_spoofing_by_us();
no_leaf_spoofing();
to_me_rules <<'';
=deny udp from not 140.174.82.0/26 to any 111,2049 # portmap, NFS
=deny tcp from not 140.174.82.0/26 to any 111 # portmap
from_me_rules <<'';
=deny udp from any 111,2049 to not 140.174.82.0/26 # portmap, NFS
=deny tcp from any 111 to not 140.174.82.0/26 # portmap
to_net_rules ('=host:mac84', <<'');
=skiprule tcp from 140.174.82.32/27 to =host:mac84 6000 # mac84
=deny tcp from any to =host:mac84 6000
generate qw(INSECURE DEFAULT-ACCEPT);
=head1 REQUIREMENTS
Ipfwgen generates commands that work with FreeBSD 2.2.5's
firewall program: L<ipfw>. Ipfwgen makes use of features that were
only recently added to ipfw: skipto, xmit, recv.
=head1 BUGS
Ipfwgen cannot currently deal non-exclusive thru traffic. For ISPs
this means that it cannot deal with customers that have redundent
connections. Fixing this is not terribly hard.
The firewalls generated by Ipfwgen are often not optimal. If anyone
wishes to write an optimizer, that would be great!
The firewalls generated by Ipfwgen can be hard to read.
Ipfwgen expects the netmasks on point to point links to be accurate.
Nothing else really cares about such netmasks so this may lead to some
problems.
Some of the internal structures aren't very enlightened. For example,
everything having to do with get_netmask() and mark_addresses() could be
redone for clarity and speed.
( run in 1.830 second using v1.01-cache-2.11-cpan-364913b4093 )