App-SilverSplash

 view release on metacpan or  search on metacpan

lib/App/SilverSplash/IPTables.pm  view on Meta::CPAN

package App::SilverSplash::IPTables;

use strict;
use warnings;

use base 'App::SilverSplash';

use Data::Dumper qw(Dumper);

use Config::SL  ();
use URI::Escape ();

use constant DEBUG => $ENV{SL_DEBUG} || 0;

our (
    $Config,     $Iptables,     $Wan_if,  %tables_chains,
    $Lan_if,     $Perlbal_port, $Mark_op, $Lease_file,
    $Gateway_ip, $Wan_ip,       $Wan_mac,
);

BEGIN {
    $Config       = Config::SL->new;
    $Iptables     = $Config->sl_iptables || die 'oops';
    $Perlbal_port = $Config->sl_perlbal_port || die 'oops';

    # wan and lan interfaces
    $Wan_if = $Config->sl_wan_if || die 'oops';
    $Lan_if = $Config->sl_lan_if || die 'oops';

    ($Gateway_ip) = `/sbin/ifconfig $Lan_if` =~ m/inet addr:(\S+)/;
    ($Wan_ip)     = `/sbin/ifconfig $Wan_if` =~ m/inet addr:(\S+)/;
    ($Wan_mac)    = `/sbin/ifconfig $Wan_if` =~ m/HWaddr\s(\S+)/;

    $Mark_op    = $Config->sl_mark_op         || die 'oops';
    $Lease_file = $Config->sl_dhcp_lease_file || die 'oops';

    %tables_chains = (
        filter => [qw( slAUT slAUTads slNET slRTR )],
        mangle => [qw( slBLK slINC slOUT slTRU )],
        nat    => [qw( slOUT )],
    );

}

our $Blocked_mark = '0x100';
our $Trusted_mark = '0x200';
our $Paid_mark    = '0x400';
our $Ads_mark     = '0x500';

sub load_allows {
    my ( $class, $file ) = @_;

    my $fh;
    open( $fh, '<', $Config->sl_root . "/conf/$file" ) or die $!;
    my $ct = do { local $/; <$fh> };
    close($fh) or die $!;

    my @lines = split( /\n/, $ct );
    @lines = grep { $_ =~ m/\S/ }
      grep { $_ !~ /#/ }             # skip comments
      grep { defined $_ } @lines;    # skip undef

    return \@lines;
}

sub init_firewall {
    my $class = shift;

    `echo 1 > /proc/sys/net/ipv4/ip_forward`;

    # flush the existing firewall
    $class->clear_firewall();

    # create the chains
    foreach my $table ( sort keys %tables_chains ) {
        foreach my $chain ( @{ $tables_chains{$table} } ) {

            iptables("-t $table -N $chain");
        }
    }

    # walled garden exceptions
    my $hosts_allow    = $class->load_allows('cp_hosts_allow.txt');
    my $sslhosts_allow = $class->load_allows('cp_sslhosts_allow.txt');
    my $accept         = "slNET -d %s -p tcp -m tcp --dport %d -j ACCEPT";

    my $slout = "slOUT -d %s -p tcp -m tcp --dport %d -j ACCEPT";

    my $hosts_accept =
      join( "\n", map { sprintf( $accept, $_, 80 ) } @{$hosts_allow} );

    my $sslhosts_accept =
      join( "\n", map { sprintf( $accept, $_, 443 ) } @{$sslhosts_allow} );

    my $hosts_slout =
      join( "\n", map { sprintf( $slout, $_, 80 ) } @{$hosts_allow} );

    my $sslhosts_slout =
      join( "\n", map { sprintf( $slout, $_, 443 ) } @{$sslhosts_allow} );

    ##############################
    # add the filter default chains
    my $filters = <<"FILTERS";
INPUT -i $Lan_if -j slRTR

FORWARD -i $Lan_if -j slNET

slAUT --protocol tcp --source-port ! 25 -j ACCEPT

slAUTads -m state --state RELATED,ESTABLISHED -j ACCEPT
slAUTads -p tcp -m tcp --dport 22 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 80 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 110 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 143 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 443 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 465 -j ACCEPT 
slAUTads -p udp -m udp --dport 500 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 587 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 993 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 995 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 1723 -j ACCEPT 
slAUTads -p udp -m udp --dport 1701 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 3389 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 5050 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 5190 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 5222 -j ACCEPT 
slAUTads -p tcp -m tcp --dport 5223 -j ACCEPT 

slNET -m mark --mark $Blocked_mark/0x700 -j DROP
slNET -m state --state INVALID -j DROP
slNET -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
slNET -m mark --mark $Trusted_mark/0x700 -j ACCEPT
slNET -m mark --mark $Paid_mark/0x700 -j slAUT
slNET -m mark --mark $Ads_mark/0x700 -j slAUTads
slNET -p icmp -j REJECT  --reject-with icmp-port-unreachable
$hosts_accept
$sslhosts_accept
slNET -j DROP

slRTR -m mark --mark $Blocked_mark/0x700 -j DROP
slRTR -m state --state INVALID -j DROP
slRTR -m state --state RELATED,ESTABLISHED -j ACCEPT
slRTR -p tcp -m tcp ! --tcp-option 2 --tcp-flags SYN SYN -j DROP
slRTR -p tcp -m tcp --dport $Perlbal_port -j ACCEPT
slRTR -m mark --mark $Trusted_mark/0x700 -j ACCEPT
slRTR -p udp -m udp -s 10.69.0.1/16 --dport 53 -j ACCEPT
slRTR -p udp -m udp -s 10.69.0.1/16 --dport 67 -j ACCEPT
slRTR -p udp -m udp -s 10.69.0.1/16 --dport 68 -j ACCEPT
slRTR -p tcp -m tcp -s 10.69.0.1/16 --dport 20022 -j ACCEPT
slRTR -p icmp -s 10.69.0.1/16 -j ACCEPT
FILTERS

    add_rules( 'filter', $filters );

    #############################
    # default mangle chains
    my $mangles = <<"MANGLES";
PREROUTING -i $Lan_if -j slOUT
PREROUTING -i $Lan_if -j slBLK
PREROUTING -i $Lan_if -j slTRU
POSTROUTING -o $Lan_if -j slINC
MANGLES

    add_rules( 'mangle', $mangles );

    #############################
    # default nat chains
    my $nats = <<"NATS";
PREROUTING -i $Lan_if -j slOUT
POSTROUTING -o $Wan_if -j MASQUERADE

slOUT -m mark --mark $Trusted_mark/0x700 -j ACCEPT
slOUT -m mark --mark $Paid_mark/0x700 -j ACCEPT
slOUT -m mark --mark $Ads_mark/0x700 -j ACCEPT
$hosts_slout
$sslhosts_slout
slOUT -p tcp -m tcp --dport 80 -j DNAT --to-destination $Gateway_ip:$Perlbal_port
slOUT -p tcp -m tcp --dport 443 -j DNAT --to-destination $Gateway_ip:$Perlbal_port
slOUT -p udp --dport 53 -d $Gateway_ip -j ACCEPT
slOUT -p udp --dport 67 -j ACCEPT
slOUT -p udp --dport 68 -j ACCEPT
slOUT -p tcp --dport 20022 -d $Gateway_ip -j ACCEPT
slOUT -p tcp --dport $Perlbal_port -d $Gateway_ip -j ACCEPT
slOUT -j DROP
NATS

    add_rules( 'nat', $nats );

    # trusted hosts
    my $trusted_hosts = $class->load_allows('trusted_hosts.txt');
    my $out_rule =
"-t mangle -A slTRU -m mac --mac-source %s -j MARK $Mark_op $Trusted_mark";

    # TODO - arp translation
    #my $out_rule = "-t mangle -A slTRU -s %s -m mac --mac-source %s -j MARK $Mark_op $Trusted_mark";
    #my $in_rule = "-t mangle -A slINC -d %s -j ACCEPT";

    foreach my $mac ( @{$trusted_hosts} ) {

        # TODO - arp translation



( run in 2.488 seconds using v1.01-cache-2.11-cpan-302cb4679cc )