--- loncom/configuration/Firewall.pm 2019/06/09 02:35:45 1.18 +++ loncom/configuration/Firewall.pm 2024/09/13 03:52:03 1.28 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Firewall configuration to allow internal LON-CAPA communication between servers # -# $Id: Firewall.pm,v 1.18 2019/06/09 02:35:45 raeburn Exp $ +# $Id: Firewall.pm,v 1.28 2024/09/13 03:52:03 raeburn Exp $ # # The LearningOnline Network with CAPA # @@ -51,7 +51,7 @@ sub uses_firewalld { if ($1 >= 18) { $checkfirewalld = 1; } - } elsif ($distro =~ /^(?:centos|rhes|scientific)(\d+)/) { + } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) { if ($1 >= 7) { $checkfirewalld = 1; } @@ -82,10 +82,11 @@ sub firewall_open_port { return 'inactive firewall' if (!&firewall_is_active()); return 'port number unknown' if !$lond_port; return 'invalid firewall chain' unless (ref($fw_chains) eq 'ARRAY'); - my (@opened,@okchains,$zone); + my (@opened,@okchains,$zone,$firewalld_num_opened); if ($firewalld) { $zone = &get_default_zone(); return 'invalid zone' if ($zone eq ''); + $firewalld_num_opened = 0; } else { my @badchains; foreach my $chain (@{$fw_chains}) { @@ -119,6 +120,10 @@ sub firewall_open_port { @lond_port_curropen); if (ref($iphost) eq 'HASH') { if (keys(%{$iphost}) > 0) { + my $count = scalar(keys(%{$iphost})); + if ($count > 1) { + print "Please be patient. Checking $count IPs.\n"; + } my %curropen; if ($firewalld) { &firewall_close_anywhere($iptables,$zone,$port,$firewalld); @@ -132,6 +137,7 @@ sub firewall_open_port { $lond_port,$iphost,\%curropen); } } + my $countok = 0; foreach my $key (keys(%{$iphost})) { my $ip = ''; if ($key =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) { @@ -156,6 +162,7 @@ sub firewall_open_port { close(PIPE); if ($result eq 'success') { push(@lond_port_open,$ip); + $firewalld_num_opened ++; } else { push(@port_error,$ip); } @@ -179,12 +186,27 @@ sub firewall_open_port { } } } + if ($count > 1) { + $countok ++; + print '.'; + if ($countok%40 == 0) { + print "\n"; + } + } + } + if ($count > 1) { + if ($countok%40) { + print "\n"; + } } } else { - print "no key found in $iphost hash ref\n"; + print "no key found in \$iphost hash ref.\n". + "Domain Name Service (DNS) may not be available.\n". + "If this LON-CAPA node is standalone, then you can fix this issue by modifying /etc/hosts.\n". + "Use a text editor to add: IPaddress Hostname\n"; } } else { - print "$iphost is not a reference to a hash\n"; + print "\$iphost is not a reference to a hash\n"; } if (@lond_port_curropen) { unless (grep(/^\Q$port\E$/,@opened)) { @@ -222,6 +244,7 @@ sub firewall_open_port { close(PIPE); if ($result eq 'success') { push(@opened,$port); + $firewalld_num_opened ++; } else { $port_error = $port; } @@ -262,6 +285,9 @@ sub firewall_open_port { } } } + if ($firewalld && $firewalld_num_opened) { + system('firewall-cmd --runtime-to-permanent'); + } foreach my $port (@{$ports}) { if (!grep(/^\Q$port\E$/,@opened)) { return 'Required port not open: '.$port."\n"; @@ -276,6 +302,7 @@ sub firewall_is_port_open { # for other ports returns 1 if the firewall port is open, 0 if not. # if firewalld is in use, checks for rich rules only. my $count = 0; + # check if firewall is active or installed return $count if (! &firewall_is_active()); if ($firewalld) { my $zone = &get_default_zone(); @@ -307,16 +334,11 @@ sub firewall_is_port_open { close(PIPE); } } - return $count; - } - return $count unless ($fw_chain !~ /^[\w-]+$/); - if (open(PIPE,"$iptables -L $fw_chain -n |")) { - # check if firewall is active or installed - return if (! &firewall_is_active()); + } elsif (($fw_chain =~ /^[\w-]+$/) && (open(PIPE,"$iptables -L $fw_chain -n |"))) { while() { if ($port eq $lond_port) { if (ref($iphost) eq 'HASH') { - if (/^ACCEPT\s+tcp\s+\-{2}\s+(\S+)\s+\S+\s+tcp\s+dpt\:\Q$port\E/) { + if (/^ACCEPT\s+(?:tcp|6)\s+\-{2}\s+(\S+)\s+\S+\s+tcp\s+dpt\:\Q$port\E/) { my $ip = $1; if ($iphost->{$ip}) { $count ++; @@ -349,6 +371,18 @@ sub firewall_is_active { } close(PIPE); } + unless ($status) { + if (open(PIPE,'nft list tables |')) { + while() { + chomp(); + if (/filter$/) { + $status = 1; + last; + } + } + close(PIPE); + } + } } unless ($status) { $status = &uses_firewalld(); @@ -361,10 +395,11 @@ sub firewall_close_port { return 'inactive firewall' if (!&firewall_is_active()); return 'port number unknown' if !$lond_port; return 'invalid firewall chain' unless (ref($fw_chains) eq 'ARRAY'); - my (@okchains,$zone); + my (@okchains,$zone,$firewalld_num_closed); if ($firewalld) { $zone = &get_default_zone(); return 'no default zone' if ($zone eq ''); + $firewalld_num_closed = 0; } else { my @badchains; foreach my $chain (@{$fw_chains}) { @@ -421,6 +456,7 @@ sub firewall_close_port { close(PIPE); if ($result eq 'success') { push(@lond_port_close,$ip); + $firewalld_num_closed ++; } else { push(@port_error,$ip); } @@ -442,7 +478,7 @@ sub firewall_close_port { while () { chomp(); next unless (/dpt:\Q$port\E/); - if (/^ACCEPT\s+tcp\s+\-{2}\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+/) { + if (/^ACCEPT\s+(?:tcp|6)\s+\-{2}\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+/) { my $ip = $1; my $keepopen = 0; if (ref($iphost) eq 'HASH') { @@ -509,6 +545,7 @@ sub firewall_close_port { close(PIPE); if ($result eq 'success') { print "Port: $port closed in zone: $zone.\n"; + $firewalld_num_closed ++; } else { print "Error closing port: $port in zone: $zone.\n"; } @@ -549,6 +586,9 @@ sub firewall_close_port { } } } + if ($firewalld && $firewalld_num_closed) { + system('firewall-cmd --runtime-to-permanent'); + } return; } @@ -586,6 +626,7 @@ sub firewall_close_anywhere { close(PIPE); if ($result eq 'success') { print 'Port '.$port.' closed for source "anywhere"'."\n"; + system('firewall-cmd --runtime-to-permanent'); } else { print 'Error closing port '.$port.' for source "anywhere".'."\n"; } @@ -597,7 +638,7 @@ sub firewall_close_anywhere { while () { next unless (/dpt:\Q$port\E/); chomp(); - if (/^(\d+)\s+ACCEPT\s+tcp\s+\-{2}\s+0\.0\.0\.0\/0\s+0\.0\.0\.0\/0/) { + if (/^(\d+)\s+ACCEPT\s+(?:tcp|6)\s+\-{2}\s+0\.0\.0\.0\/0\s+0\.0\.0\.0\/0/) { my $firewall_command = "$iptables -D $fw_chain $1"; system($firewall_command); my $return_status = $?>>8; @@ -639,9 +680,9 @@ sub get_fw_chains { my $ubuntu_config = "/etc/ufw/ufw.conf"; my $firewalld = &uses_firewalld($distro); if ($firewalld) { - my ($dist,$version) = ($distro =~ /^([\D]+)(\d+)$/); - if ((($dist eq 'rhes') || ($dist eq 'centos')) && - ($version >= 8)) { + my ($dist,$version) = ($distro =~ /^([\D]+)(\d+)(?:|\-stream)$/); + if (((($dist eq 'rhes') || ($dist eq 'centos') || ($dist eq 'rocky') || ($dist eq 'alma')) && + ($version >= 8)) || (($dist eq 'oracle') && ($version >= 7))) { push(@fw_chains,'INPUT'); } else { my $zone = &get_default_zone(); @@ -660,7 +701,7 @@ sub get_fw_chains { } else { if ($distro =~ /^(debian|ubuntu|suse|sles)/) { @posschains = ('INPUT'); - } elsif ($distro =~ /^(fedora|rhes|centos|scientific)(\d+)$/) { + } elsif ($distro =~ /^(fedora|rhes|centos|scientific|oracle|rocky|alma)(\d+)(?:|\-stream)$/) { if ((($1 eq 'fedora') && ($2 > 15)) || (($1 ne 'fedora') && ($2 >= 7))) { @posschains = ('INPUT'); } else { @@ -673,7 +714,7 @@ sub get_fw_chains { print("Unable to find iptables file containing static definitions.\n"); } } - if ($distro =~ /^(fedora|rhes|centos|scientific)(\d+)$/) { + if ($distro =~ /^(fedora|rhes|centos|scientific|oracle|rocky|alma)(\d+)(?:|\-stream)$/) { unless ((($1 eq 'fedora') && ($2 > 15)) || (($1 ne 'fedora') && ($2 >= 7))) { push(@fw_chains,'RH-Firewall-1-INPUT'); }