Bison

 view release on metacpan or  search on metacpan

lib/Bison.pm  view on Meta::CPAN

    chain('new', { name => $bopts->{firewall}, jump => 'drop' });
    log_setup($bopts->{firewall});

    # now the catchall filter, known as dropwall
    chain('new', { name => 'dropwall', jump => 'drop'});
    log_setup('dropwall', { prefix => 'Bison DropWall'});

    # silent logging chain for all those annoying things
    chain('new', { name => 'silent', jump => 'drop'});
}

sub has_ip_address {
    if (! defined $bopts->{ip_address}) {
        die "Can't continue. No IP Address set. Please set one with override_globals({ip_address => '0.0.0.0'})\n";
    }
}

=head2 forward

Handles all forwarding related stuff. ie: Forward packets from an internal network (eth1) to the internet (eth0).

    # generate something like iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT
    forward({
        from => 'eth1',
        to => 'eth0',
        type => 'related'
    });

    # .. or simply just forward the packets from eth1 to eth0
    forward({ from => 'eth1', to => 'eth0' });

=cut

sub forward {
    my $args = shift;

    my ($from, $to, $type);
    for(keys %$args) {
        $from = $args->{$_} if $_ eq 'from';
        $to = $args->{$_} if $_ eq 'to';
        $type = $args->{$_} if $_ eq 'type';
    }

    if (! $from || ! $to) {
        log_error('forward(): From and To need to be set to forward packets');
        return 0;
    }

    ipt("-A FORWARD -i $from -o $to -j ACCEPT");
    if ($type) {
        if ($type eq 'related' || $type eq 'established') {
            ipt("-A FORWARD -i $to -o $from -m state --state ESTABLISHED,RELATED -j ACCEPT");
            ipt("-A INPUT -i $to -m state --state ESTABLISHED,RELATED -j ACCEPT");
        }
    }
}

=head2 drop_bad_tcp_flags

Catches any malicious TCP packets into a badflags chain, then prefixes the log as that chain.
Should help prevent force fragment and XMAS packets. Also checks to make sure new TCP connections 
are SYN packets.
This section could do with a bit more work, but this is still a beta release :)

=cut

sub drop_bad_tcp_flags {
    my ($chain, $prefix) = @_;

    $chain = $chain||'badflags';
    $prefix = $prefix||'Bison BadFlags';
    ($bopts->{badflags}, $bopts->{badflags_prefix}) = ($chain, $prefix);
    # create a chain to handle them
    chain('new', { name => $chain, jump => 'drop' });

    # add alert options with defaults
    log_setup($chain, { prefix => $prefix});

    ipt("-A INPUT -p tcp ! --syn -m state --state NEW -j $chain");
    ipt("-A INPUT -f -j $chain");
    ipt("-A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j $chain");
    ipt("-A INPUT -p tcp --tcp-flags ALL ALL -j $chain");
    ipt("-A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j $chain");
    ipt("-A INPUT -p tcp --tcp-flags ALL NONE -j $chain");
    ipt("-A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j $chain");
    ipt("-A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j $chain");
    return 1;
}

=head2 open_service

Open ports to a service by name (www, ssh, ftp). If no arguments are passed 
it will open access to everyone. If you pass a hash with to => then the port 
will be only available to that ip address.

    open_service('ssh', { to => '10.1.1.5' }); # open 22 to 10.1.1.5 only
    open_service('www'); # open port 80 to all

=cut

sub open_service {
    my ($service, $args) = @_;

    my @services = qw/ssh www ftp/;
    if (! grep { $_ eq $service } @services) {
        log_error("open_service: No such service $service");
        return 0;
    }

    my ($to, $port);
    for(keys %$args) {
        $to = $args->{$_} if $_ eq 'to';
    }

    given(lc $service) {
        when ('ssh') { $port = 22; }   
        when ('www') { $port = 80; }
        when ('ftp') { $port = '20:21'; }
    }
    
    if ($to) { ipt("-A INPUT -i $bopts->{iface} -s $to -d 0/0 -p tcp --dport $port -j ACCEPT"); }



( run in 1.390 second using v1.01-cache-2.11-cpan-b16cb0d3907 )