Author: arkurth
Date: Fri May 26 23:06:03 2017
New Revision: 1796358
URL: http://svn.apache.org/viewvc?rev=1796358&view=rev
Log:
VCL-971
Updated ufw.pm::save_configuration to add the '*<table>' lines as it finds them
which could be intermingled with lines containing 'vcl'. It was previously
assuming everything belonged in 'filter'.
Updated iptables.pm::get_table_info to handle text in the jump section of a
rule that contains special characters such as square brackets. The code was
previously passing what it found to a s/// regex. This was failing if the text
contained special regex characters. Rewrote regex which locates the jump
section to exclude any part of a subsequent match section.
Tested using Ubuntu/ufw for both a NAT host and client and it worked fine.
Modified:
vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/firewalld.pm
vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm
vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/ufw.pm
Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/firewalld.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/firewalld.pm?rev=1796358&r1=1796357&r2=1796358&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/firewalld.pm
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/firewalld.pm Fri
May 26 23:06:03 2017
@@ -174,7 +174,7 @@ sub get_all_direct_rules {
# ipv4 filter INPUT 0 --jump vcl-pre_capture --match comment --comment
'VCL: jump to rules added during the pre-capture stage (2017-04-07 17:19:21)'
my @rules = grep(/^(ipv4|ipv6|eb)/, @$output);
- #notify($ERRORS{'DEBUG'}, 0, "retrieved all firewalld direct rules
defined on $computer_name:\n" . join("\n", @rules));
+ notify($ERRORS{'DEBUG'}, 0, "retrieved all firewalld direct rules
defined on $computer_name:\n" . join("\n", @rules));
return @rules;
}
Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm?rev=1796358&r1=1796357&r2=1796358&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm Fri
May 26 23:06:03 2017
@@ -1704,12 +1704,12 @@ sub get_table_info {
# Be sure to check for ! enclosed in quotes:
# -A POSTROUTING '!' --destination 10.10.0.0/20
--jump MASQUERADE
my $parameters = {
- 'protocol' =>
'\s*\'?(\!?)\'?\s*(-p|--protocol)\s+([^\s]+)',
- 'source' =>
'\s*\'?(\!?)\'?\s*(-s|--source)\s+([\d\.\/]+)',
- 'destination' =>
'\s*\'?(\!?)\'?\s*(-d|--destination)\s+([\d\.\/]+)',
- 'in-interface' =>
'\s*\'?(\!?)\'?\s*(-i|--in-interface)\s+([^\s]+)',
- 'out-interface' =>
'\s*\'?(\!?)\'?\s*(-o|--out-interface)\s+([^\s]+)',
- 'fragment' =>
'\s*\'?(\!?)\'?\s*(-f|--fragment)',
+ 'protocol' =>
'(?:\'?(\!?)\'?\s)?(-p|--protocol)\s+([^\s]+)',
+ 'source' =>
'(?:\'?(\!?)\'?\s)?(-s|--source)\s+([\d\.\/]+)',
+ 'destination' =>
'(?:\'?(\!?)\'?\s)?(-d|--destination)\s+([\d\.\/]+)',
+ 'in-interface' =>
'(?:\'?(\!?)\'?\s)?(-i|--in-interface)\s+([^\s]+)',
+ 'out-interface' =>
'(?:\'?(\!?)\'?\s)?(-o|--out-interface)\s+([^\s]+)',
+ 'fragment' =>
'(?:\'?(\!?)\'?\s)?(-f|--fragment)',
};
PARAMETER: for my $parameter (keys %$parameters) {
@@ -1726,28 +1726,35 @@ sub get_table_info {
# Remove the matching pattern from the rule
specification string
# This is done to make it easier to parse the
match extension parts of the specification later on
- $rule_specification_string =~
s/(^\s+|$pattern|\s+$)//ig;
+ my $rule_specification_string_before =
$rule_specification_string;
+ $rule_specification_string =~
s/(^\s+|$pattern|\s+$)//igx;
+ #notify($ERRORS{'DEBUG'}, 0, "trimmed
$parameter parameter:\n" .
+ # "before :
'$rule_specification_string_before'\n" .
+ # "after : '$rule_specification_string'"
+ #);
}
-
- # Parse the target rule parameters
- my $target_parameters = {
- 'jump' => '\s*(-j|--jump)\s+([^\s]+)\s*(.*)',
- 'goto' => '\s*(-g|--goto)\s+([^\s]+)\s*(.*)',
- };
-
+
# -j ACCEPT
# -j REJECT --reject-with icmp-host-prohibited
+ # -j LOG --log-prefix "[UFW BLOCK] "
- # Parse the parameters which specify targets
- TARGET_PARAMETER: for my $target_parameter (keys
%$target_parameters) {
- my $pattern =
$target_parameters->{$target_parameter};
- my ($target_parameter_match, $target,
$target_extension_option_string) = $rule_specification_string =~ /$pattern/ig;
- next TARGET_PARAMETER unless
$target_parameter_match;
-
- # Assemble a regex to remove the target
specification from the overall specification
- my $target_parameter_regex =
"\\s*$target_parameter_match\\s+$target\\s*";
-
- $rule->{parameters}{$target_parameter} =
$target;
+ my $target_section_regex = <<'EOF';
+(
+ (-[jg]|--(?:jump|goto))
+ \s+
+ ([^\s]+)
+ (
+ (?:
+ (?!\s+(?:-m|--match)\s+)
+ .
+ )*
+ )
+)
+EOF
+ my ($target_section_match, $target_parameter_match,
$target, $target_extension_option_string) = $rule_specification_string =~
/$target_section_regex/ix;
+ if ($target_parameter_match) {
+ my $target_parameter_type =
($target_parameter_match =~ /j/ ? 'jump' : 'goto');
+ $rule->{parameters}{$target_parameter_type} =
$target;
my $target_extension_option_name;
@@ -1764,13 +1771,6 @@ sub get_table_info {
/gx;
TARGET_OPTION_SECTION: for my
$target_extension_option_section (@target_extension_option_sections) {
- # Stop parsing if the start of a match
extension specification if found
- if ($target_extension_option_section =~
/^(-m|--match)$/) {
- last TARGET_OPTION_SECTION;
- }
-
-
-
# Check if this is the beginning of a
target extension option
if ($target_extension_option_section =~
/^[-]+(\w[\w-]+)/) {
$target_extension_option_name =
$1;
@@ -1781,8 +1781,7 @@ sub get_table_info {
# If here, the section should
be a target extension option value
notify($ERRORS{'WARNING'}, 0,
"failed to parse iptables rule on $computer_name, target extension option name
was not detected before this section: '$target_extension_option_section'\n" .
"output line: $line\n" .
- "preceeding target
parameter: $target_parameter\n" .
- "target value: $target"
+ "target section:
$target_section_match"
);
next LINE;
}
@@ -1791,29 +1790,36 @@ sub get_table_info {
$rule->{target_extensions}{$target}{$target_extension_option_name} =
$target_extension_option_section;
$target_extension_option_name =
undef;
}
-
- # Add the section to the regex so it
will be removed
- $target_parameter_regex .=
"$target_extension_option_section\\s*";
} # TARGET_OPTION_SECTION
my $rule_specification_string_before =
$rule_specification_string;
- $rule_specification_string =~
s/$target_parameter_regex//g;
- #notify($ERRORS{'DEBUG'}, 0, "parsed iptables
target parameter:\n" .
- # "target parameter:
$target_parameter_match\n" .
- # "target: $target\n" .
- # "target specification removal regex:
$target_parameter_regex\n" .
- # "rule specification before:
$rule_specification_string_before\n" .
- # "rule specification after:
$rule_specification_string"
- #);
- } # TARGET_PARAMETER
-
+ $rule_specification_string =~
s/(^\s+|$target_section_regex|\s+$)//igx;
+ if ($rule_specification_string_before ne
$rule_specification_string) {
+ #notify($ERRORS{'DEBUG'}, 0, "trimmed
$target_parameter_type target section:\n" .
+ # "before :
'$rule_specification_string_before'\n" .
+ # "after :
'$rule_specification_string'"
+ #);
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "regex
failed to remove target section from rule specification:\n" .
+ "line
: $line\n" .
+ "remaining rule specification
before : $rule_specification_string_before\n" .
+ "remaining rule specification
after : $rule_specification_string\n" .
+ "target section
regex:\n$target_section_regex"
+ );
+ }
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "target section
was not found in rule specification: '$rule_specification_string', line:
'$line'");
+ }
# The only text remaining in $rule_specification_string
should be match extension information
+ # Make sure space exists between match extension module
name (comment) and the option
# --match comment--comment 'my comment'
# --match tcp--destination-port
$rule_specification_string =~ s/(--match [^\s-]+)--/$1
--/g;
-
+
# Split the remaining string by spaces or sections
enclosed in quotes
my @match_extension_sections =
$rule_specification_string =~
/
@@ -1831,8 +1837,6 @@ sub get_table_info {
my $match_extension_option_inverted = 0;
my $comment;
-
-
MATCH_EXTENSION_SECTION: for my
$match_extension_section (@match_extension_sections) {
next MATCH_EXTENSION_SECTION if
!$match_extension_section;
@@ -1855,10 +1859,9 @@ sub get_table_info {
}
else {
notify($ERRORS{'WARNING'}, 0,
"failed to parse iptables rule in $table_name table on $computer_name\n" .
- "match extension module
name was not detected before this section:\n" .
- "match extension
section:\n$match_extension_section\n" .
- "iptables rule
specification:\n$rule_specification_string\n" .
- "iptables command:
\n$line"
+ "match extension module
name was not detected before this section: '$match_extension_section'\n" .
+ "iptables rule
specification: '$rule_specification_string'\n" .
+ "iptables command:
'$line'"
);
next LINE;
}
Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/ufw.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/ufw.pm?rev=1796358&r1=1796357&r2=1796358&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/ufw.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/ufw.pm Fri May 26
23:06:03 2017
@@ -151,7 +151,7 @@ sub save_configuration {
# Call iptables-save
# All lines added by vcl should contain a 'vcl-'
- my $command = "iptables-save |grep 'vcl-'";
+ my $command = "iptables-save";
my ($exit_status, $output) = $self->os->execute($command);
if (!defined($output)) {
notify($ERRORS{'WARNING'}, 0, "failed to execute command to
retrieve iptables rules containing 'vcl-' from $computer_name: $command");
@@ -167,18 +167,43 @@ sub save_configuration {
# Note: Do not use "WARNING" in the message or else it will show up in
vcld.log, creating noise when searching for WARNING messages
push @updated_lines, <<EOF;
+
# DISCLAIMER: The remainder of this file has been automatically configured by
VCL ($timestamp)
# Do not modify this line or any lines below
# Custom firewall configuration lines may be added to this file but must be
located above this line
-*filter
EOF
- push @updated_lines, @$output;
- push @updated_lines, 'COMMIT';
+ my @vcl_lines;
+ my $current_table;
+ my $last_table_written = '';
+ LINE: for my $line (@$output) {
+ # Find lines that specify a table name:
+ # *nat
+ # *filter
+ if ($line =~ /^\s*\*(.+)$/) {
+ $current_table = $1;
+ }
+ elsif ($line =~ /(vcl|$PROCESSNAME)-/) {
+ if ($last_table_written ne $current_table) {
+ if ($last_table_written) {
+ push @vcl_lines, "COMMIT\n";
+ }
+
+ push @vcl_lines, "*$current_table";
+ $last_table_written = $current_table;
+ }
+
+ push @vcl_lines, $line;
+ }
+ }
+ push @vcl_lines, 'COMMIT';
+ my $vcl_string = join("\n", @vcl_lines);
+ push @updated_lines, @vcl_lines;
my $updated_string = join("\n", @updated_lines);
+
if ($self->os->create_text_file($rules_file_path, $updated_string)) {
- notify($ERRORS{'OK'}, 0, "saved ufw firewall configuration on
$computer_name to $rules_file_path:\n$updated_string");
+ notify($ERRORS{'OK'}, 0, "added VCL-specific lines to
$rules_file_path on $computer_name:\n$vcl_string");
}
else {
notify($ERRORS{'WARNING'}, 0, "failed to save ufw firewall
configuration on $computer_name, $rules_file_path could not be updated");