diff options
Diffstat (limited to 'lib/Vyatta')
-rw-r--r-- | lib/Vyatta/Conntrack/RuleCT.pm | 351 |
1 files changed, 25 insertions, 326 deletions
diff --git a/lib/Vyatta/Conntrack/RuleCT.pm b/lib/Vyatta/Conntrack/RuleCT.pm index 594c784..421b746 100644 --- a/lib/Vyatta/Conntrack/RuleCT.pm +++ b/lib/Vyatta/Conntrack/RuleCT.pm @@ -58,6 +58,21 @@ my %dummy_rule = ( my $DEBUG = 'false'; +sub rule { + my ( $self ) = @_; + my ($rule, $srcrule, $dstrule, $err_str); + my $tcp_and_udp = 0; + # set CLI rule num as comment + my @level_nodes = split (' ', $self->{_comment}); + $rule .= "-m comment --comment \"$level_nodes[2]-$level_nodes[5]\" "; + ($srcrule, $err_str) = $src->rule(); + return ($err_str, ) if (!defined($srcrule)); + ($dstrule, $err_str) = $dst->rule(); + return ($err_str, ) if (!defined($dstrule)); + $rule .= " $srcrule $dstrule "; + print "rule is $rule\n"; +} + sub new { my $that = shift; my $class = ref ($that) || $that; @@ -110,8 +125,18 @@ sub setup_base { $self->{_other} = $config->$val_func("protocol other"); } + #FIXME: AddressFilter.pm needs a change to accomodate other and + # icmp protocols as it does port checks unconditionally. $src->$addr_setup("$level source"); + $src->{_protocol} = $self->{_protocol};#needed to use address filter + if ( (($src->{_protocol} eq 'icmp') or ($src->{_protocol} eq 'other')) and (defined($src->{_port})) ) { + die "Error: Cannot specify port with protocol $src->{_protocol}\n"; + } $dst->$addr_setup("$level destination"); + $dst->{_protocol} = $self->{_protocol};#needed to use address filter + if ( (($dst->{_protocol} eq 'icmp') or ($dst->{_protocol} eq 'other')) and (defined($dst->{_port})) ) { + die "Error: Cannot specify port with protocol $dst->{_protocol}\n"; + } return 0; } @@ -187,340 +212,14 @@ sub get_policy_command { $command .= " stream $self->{_udp}->{_stream}"; } } elsif ($self->{_protocol} eq 'icmp') { - $command .= " icmp"; $command .= " icmp $self->{_icmp}"; } elsif ($self->{_protocol} eq 'other') { - $command .= " other"; $command .= " other $self->{_other}"; } print "\n $command\n\n"; return $command; } -sub rule { - my ( $self ) = @_; - my ($rule, $srcrule, $dstrule, $err_str); - my $tcp_and_udp = 0; - - # set CLI rule num as comment - my @level_nodes = split (' ', $self->{_comment}); - $rule .= "-m comment --comment \"$level_nodes[2]-$level_nodes[5]\" "; - print "rule is $rule\n"; - - # set the protocol - if (defined($self->{_protocol})) { - my $str = $self->{_protocol}; - my $negate = ''; - if ($str =~ /^\!(.*)$/) { - $str = $1; - $negate = '! '; - } - if ($str eq 'tcp_udp') { - $tcp_and_udp = 1; - $rule .= " $negate -p tcp "; # we'll add the '-p udp' to 2nd rule later - } else { - $rule .= " $negate -p $str "; - } - } - - my $state_str = uc (get_state_str($self)); - if ($state_str ne "") { - $rule .= "-m state --state $state_str "; - } - - # set tcp flags if applicable - my $tcp_flags = undef; - if (defined $self->{_tcp_flags}) { - if (($self->{_protocol} eq "tcp") || ($self->{_protocol} eq "6")) { - $tcp_flags = get_tcp_flags_string($self->{_tcp_flags}); - } else { - return ("TCP flags can only be set if protocol is set to TCP", ); - } - } - if (defined($tcp_flags)) { - $rule .= " -m tcp --tcp-flags $tcp_flags "; - } - - # set the icmp code and type if applicable - if (($self->{_protocol} eq "icmp") || ($self->{_protocol} eq "1")) { - if (defined $self->{_icmp_name}) { - if (defined($self->{_icmp_type}) || defined($self->{_icmp_code})){ - return ("Cannot use ICMP type/code with ICMP type-name", ); - } - $rule .= "--icmp-type $self->{_icmp_name} "; - } elsif (defined $self->{_icmp_type}) { - $rule .= "--icmp-type $self->{_icmp_type}"; - if (defined $self->{_icmp_code}) { - $rule .= "/$self->{_icmp_code}"; - } - $rule .= " "; - } elsif (defined $self->{_icmp_code}) { - return ("ICMP code can only be defined if ICMP type is defined", ); - } - } elsif (defined($self->{_icmp_type}) || defined($self->{_icmp_code}) - || defined($self->{_icmp_name})) { - return ("ICMP type/code or type-name can only be defined if protocol is ICMP", ); - } - - # Setup ICMPv6 rule if configured - # ICMPv6 parameters are only valid if the rule is matching on the - # ICMPv6 protocol ID. - # - if (($self->{_protocol} eq "icmpv6") || - ($self->{_protocol} eq "ipv6-icmp") || - ($self->{_protocol} eq "58")) { - if (defined($self->{_icmpv6_type})) { - $rule .= "-m icmpv6 --icmpv6-type $self->{_icmpv6_type}"; - } - } - - # add the source and destination rules - ($srcrule, $err_str) = $src->rule(); - return ($err_str, ) if (!defined($srcrule)); - ($dstrule, $err_str) = $dst->rule(); - return ($err_str, ) if (!defined($dstrule)); - if ((grep /multiport/, $srcrule) ^ (grep /multiport/, $dstrule)) { - if ((grep /sport/, $srcrule) && (grep /dport/, $dstrule)) { - return ('Cannot specify multiple ports when both ' - . 'source and destination ports are specified', ); - } - } - $rule .= " $srcrule $dstrule "; - - return ('Cannot specify both "match-frag" and "match-non-frag"', ) - if (defined($self->{_frag}) && defined($self->{_non_frag})); - if (defined($self->{_frag})) { - $rule .= ' -f '; - } elsif (defined($self->{_non_frag})) { - $rule .= ' ! -f '; - } - - # note: "out" is not valid in the INPUT chain. - return ('Cannot specify both "match-ipsec" and "match-none"', ) - if (defined($self->{_ipsec}) && defined($self->{_non_ipsec})); - if (defined($self->{_ipsec})) { - $rule .= ' -m policy --pol ipsec --dir in '; - } elsif (defined($self->{_non_ipsec})) { - $rule .= ' -m policy --pol none --dir in '; - } - - my $p2p = undef; - if (defined($self->{_p2p}->{_all})) { - $p2p = '--apple --bit --dc --edk --gnu --kazaa '; - } else { - my @apps = qw(apple bit dc edk gnu kazaa); - foreach (@apps) { - if (defined($self->{_p2p}->{"_$_"})) { - $p2p .= "--$_ "; - } - } - } - if (defined($p2p)) { - $rule .= " -m ipp2p $p2p "; - } - - my $time = undef; - if (defined($self->{_time}->{_utc})) { - $time .= " --utc "; - } - if (defined($self->{_time}->{_startdate})) { - my $check_date = validate_date($self->{_time}->{_startdate}, "startdate"); - if (!($check_date eq "")) { - return ($check_date, ); - } - $time .= " --datestart $self->{_time}->{_startdate} "; - } - if (defined($self->{_time}->{_stopdate})) { - my $check_date = validate_date($self->{_time}->{_stopdate}, "stopdate"); - if (!($check_date eq "")) { - return ($check_date, ); - } - $time .= " --datestop $self->{_time}->{_stopdate} "; - } - if (defined($self->{_time}->{_starttime})) { - return ("Invalid starttime $self->{_time}->{_starttime}. -Time should use 24 hour notation hh:mm:ss and lie in between 00:00:00 and 23:59:59", ) - if (!validate_timevalues($self->{_time}->{_starttime}, "time")); - $time .= " --timestart $self->{_time}->{_starttime} "; - } - if (defined($self->{_time}->{_stoptime})) { - return ("Invalid stoptime $self->{_time}->{_stoptime}. -Time should use 24 hour notation hh:mm:ss and lie in between 00:00:00 and 23:59:59", ) - if (!validate_timevalues($self->{_time}->{_stoptime}, "time")); - $time .= " --timestop $self->{_time}->{_stoptime} "; - } - if (defined($self->{_time}->{_monthdays})) { - my $negate = " "; - if ($self->{_time}->{_monthdays} =~ m/^!/) { - $negate = "! "; - $self->{_time}->{_monthdays} = substr $self->{_time}->{_monthdays}, 1; - } - return ("Invalid monthdays value $self->{_time}->{_monthdays}. -Monthdays should have values between 1 and 31 with multiple days separated by commas -eg. 2,12,21 For negation, add ! in front eg. !2,12,21", ) - if (!validate_timevalues($self->{_time}->{_monthdays}, "monthdays")); - $time .= " $negate --monthdays $self->{_time}->{_monthdays} "; - } - if (defined($self->{_time}->{_weekdays})) { - my $negate = " "; - if ($self->{_time}->{_weekdays} =~ m/^!/) { - $negate = "! "; - $self->{_time}->{_weekdays} = substr $self->{_time}->{_weekdays}, 1; - } - return ("Invalid weekdays value $self->{_time}->{_weekdays}. -Weekdays should be specified using the first three characters of the day with the -first character capitalized eg. Mon,Thu,Sat For negation, add ! in front eg. !Mon,Thu,Sat", ) - if (!validate_timevalues($self->{_time}->{_weekdays}, "weekdays")); - $time .= " $negate --weekdays $self->{_time}->{_weekdays} "; - } - if (defined($time)) { - $rule .= " -m time $time "; - } - - my $limit = undef; - if (defined $self->{_limit}->{_rate}) { - my $rate_integer = $self->{_limit}->{_rate}; - $rate_integer =~ s/\/(second|minute|hour|day)//; - if ($rate_integer < 1) { - return ("integer value in rate cannot be less than 1", ); - } - $limit = "--limit $self->{_limit}->{_rate} --limit-burst $self->{_limit}->{_burst}"; - } - $rule .= " -m limit $limit " if defined $limit; - - # recent match condition SHOULD BE DONE IN THE LAST so - # all options in $rule are copied to $recent_rule below - my $recent_rule = undef; - if (defined($self->{_recent_time}) || defined($self->{_recent_cnt})) { - my $recent_rule1 = undef; - my $recent_rule2 = undef; - $recent_rule1 .= ' -m recent --update '; - $recent_rule2 .= ' -m recent --set '; - if (defined($self->{_recent_time})) { - $recent_rule1 .= " --seconds $self->{_recent_time} "; - } - if (defined($self->{_recent_cnt})) { - $recent_rule1 .= " --hitcount $self->{_recent_cnt} "; - } - - $recent_rule = $rule; - - if ($rule =~ m/\-m\s+set\s+\-\-match\-set/) { - # firewall group being used in this rule. iptables complains if recent - # match condition is placed after group match conditions [see bug 5744] - # so instead of appending recent match place it before group match - my @split_rules = (); - - @split_rules = split(/(\-m\s+set\s+\-\-match\-set)/, $rule, 2); - $rule = $split_rules[0] . $recent_rule1 . - $split_rules[1] . $split_rules[2]; - - @split_rules = split(/(\-m\s+set\s+\-\-match\-set)/, $recent_rule, 2); - $recent_rule = $split_rules[0] . $recent_rule2 . - $split_rules[1] . $split_rules[2]; - } else { - # append recent match conditions to the two rules needed for recent match - $rule .= $recent_rule1; - $recent_rule .= $recent_rule2; - } - } - - my $chain = $self->{_name}; - my $rule_num = $self->{_rule_number}; - my $rule2 = undef; - # set the jump target. Depends on action and log - if ("$self->{_log}" eq "enable") { - $rule2 = $rule; - my $log_prefix = get_log_prefix($chain, $rule_num, $self->{_action}); - $rule2 .= "-j LOG --log-prefix \"$log_prefix\" "; - } - if ("$self->{_action}" eq "drop") { - $rule .= "-j DROP "; - } elsif ("$self->{_action}" eq "accept") { - $rule .= "-j RETURN "; - } elsif ("$self->{_action}" eq "reject") { - $rule .= "-j REJECT "; - } elsif ("$self->{_action}" eq 'inspect') { - my $target = ipt_get_queue_target('SNORT'); - return ('Undefined target for inspect', ) if ! defined $target; - $rule .= "-j $target "; - } elsif ("$self->{_action}" eq 'modify') { - # mangle actions - my $count = 0; - if (defined($self->{_mod_mark})) { - # MARK - $rule .= "-j MARK --set-mark $self->{_mod_mark} "; - $count++; - } - if (defined($self->{_mod_dscp})) { - # DSCP - $rule .= "-j DSCP --set-dscp $self->{_mod_dscp} "; - $count++; - } - if (defined($self->{_mod_tcpmss})) { - # TCP-MSS - # check for SYN flag - if (!defined $self->{_tcp_flags} || - !(($self->{_tcp_flags} =~ m/SYN/) && !($self->{_tcp_flags} =~ m/!SYN/))) { - return ('need to set TCP SYN flag to modify TCP MSS', ); - } - - if ($self->{_mod_tcpmss} =~ m/\d/) { - $rule .= "-j TCPMSS --set-mss $self->{_mod_tcpmss} "; - } else { - $rule .= "-j TCPMSS --clamp-mss-to-pmtu "; - } - $count++; - } - - # others - - if ($count == 0) { - return ('Action "modify" requires more specific configuration under ' - . 'the "modify" node', ); - } elsif ($count > 1) { - return ('Cannot define more than one modification under ' - . 'the "modify" node', ); - } - } else { - return ("\"action\" must be defined", ); - } - if (defined($rule2)) { - my $tmp = $rule2; - $rule2 = $rule; - $rule = $tmp; - } elsif (defined($recent_rule)) { - $rule2 = $recent_rule; - $recent_rule = undef; - } - - return (undef, undef) if defined $self->{_disable}; - - my ($udp_rule, $udp_rule2, $udp_recent_rule) = (undef, undef, undef); - if ($tcp_and_udp == 1) { - # create udp rules - $udp_rule = $rule; - $udp_rule2 = $rule2 if defined $rule2; - $udp_recent_rule = $recent_rule if defined $recent_rule; - foreach my $each_udprule ($udp_rule, $udp_rule2, $udp_recent_rule) { - $each_udprule =~ s/ \-p tcp / -p udp / if defined $each_udprule; - } - } - - if ($DEBUG eq 'true') { - # print all potential iptables rules that could be formed for - # a single CLI rule. see get_num_ipt_rules to see exact count - print "rule :\n$rule\n" if defined $rule; - print "rule2 :\n$rule2\n" if defined $rule2; - print "recent rule :\n$recent_rule\n" if defined $recent_rule; - print "udp rule :\n$udp_rule\n" if defined $udp_rule; - print "udp rule2 :\n$udp_rule2\n" if defined $udp_rule2; - print "udp recent rule :\n$udp_recent_rule\n" if defined $udp_recent_rule; - } - - return (undef, $rule, $rule2, $recent_rule, $udp_rule, $udp_rule2, $udp_recent_rule); -} - 1; |