[pve-devel] [PATCH firewall 5/5] Add hostname resolving to corosync firewall rule generation

Stefan Reiter s.reiter at proxmox.com
Mon Jul 1 10:49:24 CEST 2019


All ringX_addr entries that cannot be parsed as an IP address will be
best-effort resolved as hostnames. This has to happen in the exact same
way as corosync does internally, to ensure consistency with firewall
rules.

Includes changes to the testing corosync.conf to trigger resolving
codepaths during test runs.

Source for corosync behaviour:
http://people.redhat.com/ccaulfie/docs/KnetCorosync.pdf

Signed-off-by: Stefan Reiter <s.reiter at proxmox.com>
---
 src/PVE/Firewall.pm | 68 +++++++++++++++++++++++++++++++++++++++++++--
 test/corosync.conf  |  4 +++
 2 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index ea714db..a4cd846 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -10,7 +10,7 @@ use File::Path;
 use IO::File;
 use Net::IP;
 use POSIX;
-use Socket qw(AF_INET6 inet_ntop inet_pton);
+use Socket qw(AF_INET AF_INET6 inet_ntop inet_pton);
 use Storable qw(dclone);
 
 use PVE::Cluster;
@@ -23,6 +23,7 @@ use PVE::ProcFSTools;
 use PVE::SafeSyslog;
 use PVE::Tools qw($IPV4RE $IPV6RE);
 use PVE::Tools qw(run_command lock_file dir_glob_foreach);
+use PVE::Tools qw(unpack_sockaddr_in46 getaddrinfo_all);
 
 my $pvefw_conf_dir = "/etc/pve/firewall";
 my $clusterfw_conf_filename = "$pvefw_conf_dir/cluster.fw";
@@ -2564,13 +2565,74 @@ sub for_all_corosync_addresses {
 		my $node_ip = $node_config->{$node_key};
 		my $testip = Net::IP->new($node_ip);
 
-		$lambda->($node_name, $node_ip, $testip->version, $node_key)
-		    if defined($testip);
+		if (defined($testip)) {
+		    $lambda->($node_name, $node_ip, $testip->version, $node_key);
+		} else {
+		    # invalid ip, assume hostname and try resolving (best-effort)
+		    my $resolver_result = resolve_hostname_like_corosync($node_ip, $corosync_conf);
+
+		    $testip = Net::IP->new($resolver_result)
+			if defined($resolver_result);
+		    $lambda->($node_name, $testip->ip, $testip->version, $node_key)
+			if defined($testip);
+		}
 	    }
 	}
     }
 }
 
+# NOTE: Corosync actually only resolves on startup or config change, but we
+# currently do not have an easy way to synchronize our behaviour to that.
+sub resolve_hostname_like_corosync {
+    my ($hostname, $corosync_conf) = @_;
+
+    my $corosync_strategy = $corosync_conf->{main}->{totem}->{ip_version};
+    if (defined($corosync_strategy)) {
+	$corosync_strategy = lc $corosync_strategy;
+    } else {
+	$corosync_strategy = "ipv6-4"; # corosync default
+    }
+
+    my $resolved_ip4;
+    my $resolved_ip6;
+
+    my @resolved_raw;
+    eval { @resolved_raw = getaddrinfo_all($hostname); };
+    return undef if $@ || !@resolved_raw; # ignore errors in resolving
+
+    foreach my $socket_info (@resolved_raw) {
+	next if !$socket_info->{addr};
+
+	my ($family, undef, $host) = unpack_sockaddr_in46($socket_info->{addr});
+
+	if ($family == AF_INET && !defined($resolved_ip4)) {
+	    $resolved_ip4 = inet_ntop(AF_INET, $host);
+	} elsif ($family == AF_INET6 && !defined($resolved_ip6)) {
+	    $resolved_ip6 = inet_ntop(AF_INET6, $host);
+	}
+
+	last if defined($resolved_ip4) && defined($resolved_ip6);
+    }
+
+    # corosync_strategy specifies the order in which IP addresses are resolved
+    # by corosync. We need to match that order, to ensure we create firewall
+    # rules for the correct address family.
+    my $resolved_ip;
+    if ($corosync_strategy eq "ipv4") {
+	$resolved_ip = $resolved_ip4;
+    } elsif ($corosync_strategy eq "ipv6") {
+	$resolved_ip = $resolved_ip6;
+    } elsif ($corosync_strategy eq "ipv6-4") {
+	$resolved_ip = $resolved_ip6;
+	$resolved_ip = $resolved_ip4 if !defined($resolved_ip);
+    } elsif ($corosync_strategy eq "ipv4-6") {
+	$resolved_ip = $resolved_ip4;
+	$resolved_ip = $resolved_ip6 if !defined($resolved_ip);
+    }
+
+    return $resolved_ip;
+}
+
 sub generate_group_rules {
     my ($ruleset, $cluster_conf, $group, $ipversion) = @_;
 
diff --git a/test/corosync.conf b/test/corosync.conf
index 3e8cb10..75385ec 100644
--- a/test/corosync.conf
+++ b/test/corosync.conf
@@ -10,6 +10,7 @@ nodelist {
     quorum_votes: 1
     ring0_addr: 172.16.1.11
     ring1_addr: 172.16.2.11
+    ring2_addr: hostname1
   }
   node {
     name: prox2
@@ -17,6 +18,7 @@ nodelist {
     quorum_votes: 1
     ring0_addr: 172.16.1.12
     ring1_addr: 172.16.2.12
+    ring2_addr: hostname2
   }
   node {
     name: prox3
@@ -24,6 +26,7 @@ nodelist {
     quorum_votes: 1
     ring0_addr: 172.16.1.3
     ring1_addr: 172.16.2.3
+    ring2_addr: hostname3
   }
   node {
     name: proxself
@@ -31,6 +34,7 @@ nodelist {
     quorum_votes: 1
     ring0_addr: 172.16.1.2
     ring1_addr: 172.16.2.2
+    ring2_addr: proxself
   }
 }
 
-- 
2.20.1





More information about the pve-devel mailing list