X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=blobdiff_plain;f=src%2FPVE%2FFirewall.pm;h=be81778c97d8f5503c2dcca5421fe5055c6f6eba;hp=73005ab7bced11f6d5bb37b4de3066e7fecc87ed;hb=eb399cef4838774a16964cc5d11e4bcbfb07fbd2;hpb=56f313f75c4e204a687073079b5682ab4ab622f4 diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm index 73005ab..be81778 100644 --- a/src/PVE/Firewall.pm +++ b/src/PVE/Firewall.pm @@ -438,8 +438,8 @@ my $pve_fw_macros = { { action => 'PARAM', proto => 'icmp', dport => 'echo-request' }, ], 'VNC' => [ - "VNC traffic for VNC display's 0 - 9", - { action => 'PARAM', proto => 'tcp', dport => '5900:5909' }, + "VNC traffic for VNC display's 0 - 99", + { action => 'PARAM', proto => 'tcp', dport => '5900:5999' }, ], 'VNCL' => [ "VNC traffic from Vncservers to Vncviewers in listen mode", @@ -687,6 +687,58 @@ sub get_etc_protocols { return $etc_protocols; } +my $ipv4_mask_hash_clusternet = { + '255.255.0.0' => 16, + '255.255.128.0' => 17, + '255.255.192.0' => 18, + '255.255.224.0' => 19, + '255.255.240.0' => 20, + '255.255.248.0' => 21, + '255.255.252.0' => 22, + '255.255.254.0' => 23, + '255.255.255.0' => 24, + '255.255.255.128' => 25, + '255.255.255.192' => 26, + '255.255.255.224' => 27, + '255.255.255.240' => 28, + '255.255.255.248' => 29, + '255.255.255.252' => 30, +}; + +my $__cluster_network; + +sub cluster_network { + my ($new_value) = @_; + + $__cluster_network = $new_value if defined($new_value); + + return $__cluster_network if defined($__cluster_network); + + eval { + my $nodename = PVE::INotify::nodename(); + + my $ip = PVE::Cluster::remote_node_ip($nodename); + + my $testip = Net::IP->new($ip); + + my $routes = PVE::ProcFSTools::read_proc_net_route(); + foreach my $entry (@$routes) { + my $mask = $ipv4_mask_hash_clusternet->{$entry->{mask}}; + next if !defined($mask); + return if $mask eq '0.0.0.0'; + my $cidr = "$entry->{dest}/$mask"; + my $testnet = Net::IP->new($cidr); + if ($testnet->overlaps($testip)) { + $__cluster_network = $cidr; + return; + } + } + }; + warn $@ if $@; + + return $__cluster_network; +} + sub parse_address_list { my ($str) = @_; @@ -1635,10 +1687,6 @@ sub enable_host_firewall { ruleset_chain_add_conn_filters($ruleset, $chain, 'ACCEPT'); ruleset_chain_add_input_filters($ruleset, $chain, $options, $cluster_conf, $loglevel); - ruleset_addrule($ruleset, $chain, "-m addrtype --dst-type MULTICAST -j ACCEPT"); - ruleset_addrule($ruleset, $chain, "-p udp -m conntrack --ctstate NEW --dport 5404:5405 -j ACCEPT"); - ruleset_addrule($ruleset, $chain, "-p udp -m udp --dport 9000 -j ACCEPT"); #corosync - # we use RETURN because we need to check also tap rules my $accept_action = 'RETURN'; @@ -1654,6 +1702,22 @@ sub enable_host_firewall { delete $rule->{iface_in}; } + # allow standard traffic for management ipset (includes cluster network) + my $mngmntsrc = "-m set --match-set PVEFW-management src"; + ruleset_addrule($ruleset, $chain, "$mngmntsrc -p tcp --dport 8006 -j $accept_action"); # PVE API + ruleset_addrule($ruleset, $chain, "$mngmntsrc -p tcp --dport 5900:5999 -j $accept_action"); # PVE VNC Console + ruleset_addrule($ruleset, $chain, "$mngmntsrc -p tcp --dport 3128 -j $accept_action"); # SPICE Proxy + ruleset_addrule($ruleset, $chain, "$mngmntsrc -p tcp --dport 22 -j $accept_action"); # SSH + + my $clusternet = cluster_network(); + + # corosync + if ($clusternet) { + my $corosync_rule = "-p udp --dport 5404:5405 -j $accept_action"; + ruleset_addrule($ruleset, $chain, "-s $clusternet -d $clusternet $corosync_rule"); + ruleset_addrule($ruleset, $chain, "-s $clusternet -m addrtype --dst-type MULTICAST $corosync_rule"); + } + # implement input policy my $policy = $cluster_options->{policy_in} || 'DROP'; # allow nothing by default ruleset_add_chain_policy($ruleset, $chain, 0, $policy, $loglevel, $accept_action); @@ -1668,10 +1732,6 @@ sub enable_host_firewall { ruleset_chain_add_conn_filters($ruleset, $chain, 'ACCEPT'); - ruleset_addrule($ruleset, $chain, "-m addrtype --dst-type MULTICAST -j ACCEPT"); - ruleset_addrule($ruleset, $chain, "-p udp -m conntrack --ctstate NEW --dport 5404:5405 -j ACCEPT"); - ruleset_addrule($ruleset, $chain, "-p udp -m udp --dport 9000 -j ACCEPT"); #corosync - # we use RETURN because we may want to check other thigs later $accept_action = 'RETURN'; @@ -1687,6 +1747,18 @@ sub enable_host_firewall { delete $rule->{iface_out}; } + # allow standard traffic on cluster network + if ($clusternet) { + ruleset_addrule($ruleset, $chain, "-d $clusternet -p tcp --dport 8006 -j $accept_action"); # PVE API + ruleset_addrule($ruleset, $chain, "-d $clusternet -p tcp --dport 22 -j $accept_action"); # SSH + ruleset_addrule($ruleset, $chain, "-d $clusternet -p tcp --dport 5900:5999 -j $accept_action"); # PVE VNC Console + ruleset_addrule($ruleset, $chain, "-d $clusternet -p tcp --dport 3128 -j $accept_action"); # SPICE Proxy + + my $corosync_rule = "-p udp --dport 5404:5405 -j $accept_action"; + ruleset_addrule($ruleset, $chain, "-d $clusternet $corosync_rule"); + ruleset_addrule($ruleset, $chain, "-m addrtype --dst-type MULTICAST $corosync_rule"); + } + # implement output policy $policy = $cluster_options->{policy_out} || 'ACCEPT'; # allow everything by default ruleset_add_chain_policy($ruleset, $chain, 0, $policy, $loglevel, $accept_action); @@ -1900,7 +1972,7 @@ sub parse_clusterfw_option { return ($opt, $value); } -sub parse_clusterfw_alias { +sub parse_alias { my ($line) = @_; # we can add single line comments to the end of the line @@ -1924,7 +1996,11 @@ sub parse_clusterfw_alias { sub parse_vm_fw_rules { my ($filename, $fh) = @_; - my $res = { rules => [], options => {}}; + my $res = { + rules => [], + options => {}, + aliases => {}, + }; my $section; @@ -1956,6 +2032,15 @@ sub parse_vm_fw_rules { next; } + if ($section eq 'aliases') { + eval { + my $data = parse_alias($line); + $res->{aliases}->{lc($data->{name})} = $data; + }; + warn "$prefix: $@" if $@; + next; + } + my $rule; eval { $rule = parse_fw_rule($line, 1, 1); }; if (my $err = $@) { @@ -2088,7 +2173,7 @@ sub parse_cluster_fw_rules { warn "$prefix: $@" if $@; } elsif ($section eq 'aliases') { eval { - my $data = parse_clusterfw_alias($line); + my $data = parse_alias($line); $res->{aliases}->{lc($data->{name})} = $data; }; warn "$prefix: $@" if $@; @@ -2299,6 +2384,9 @@ sub save_vmfw_conf { my $options = $vmfw_conf->{options}; $raw .= &$format_options($options) if scalar(keys %$options); + my $aliases = $vmfw_conf->{aliases}; + $raw .= &$format_aliases($aliases) if scalar(keys %$aliases); + my $rules = $vmfw_conf->{rules} || []; if (scalar(@$rules)) { $raw .= "[RULES]\n\n"; @@ -2532,11 +2620,9 @@ sub compile { if ($vmdata) { # test mode my $testdir = $vmdata->{testdir} || die "no test directory specified"; my $filename = "$testdir/cluster.fw"; - die "missing test file '$filename'\n" if ! -f $filename; $cluster_conf = load_clusterfw_conf($filename); $filename = "$testdir/host.fw"; - die "missing test file '$filename'\n" if ! -f $filename; $hostfw_conf = load_hostfw_conf($filename); $vmfw_configs = read_vm_firewall_configs($vmdata, $testdir); @@ -2551,7 +2637,10 @@ sub compile { $cluster_conf->{ipset}->{venet0} = []; - + + my $clusternet = cluster_network() || '127.0.0.0/8'; + push @{$cluster_conf->{ipset}->{management}}, { cidr => $clusternet }; + my $ruleset = {}; ruleset_create_chain($ruleset, "PVEFW-INPUT"); @@ -2596,7 +2685,7 @@ sub compile { my $conf = $vmdata->{qemu}->{$vmid}; my $vmfw_conf = $vmfw_configs->{$vmid}; next if !$vmfw_conf; - next if defined($vmfw_conf->{options}->{enable}) && ($vmfw_conf->{options}->{enable} == 0); + next if !$vmfw_conf->{options}->{enable}; foreach my $netid (keys %$conf) { next if $netid !~ m/^net(\d+)$/; @@ -2618,7 +2707,7 @@ sub compile { my $vmfw_conf = $vmfw_configs->{$vmid}; next if !$vmfw_conf; - next if defined($vmfw_conf->{options}->{enable}) && ($vmfw_conf->{options}->{enable} == 0); + next if !$vmfw_conf->{options}->{enable}; if ($conf->{ip_address} && $conf->{ip_address}->{value}) { my $ip = $conf->{ip_address}->{value}; @@ -2928,6 +3017,16 @@ sub remove_pvefw_chains { iptables_restore_cmdlist($cmdlist); } +sub init { + my $cluster_conf = load_clusterfw_conf(); + my $cluster_options = $cluster_conf->{options}; + my $enable = $cluster_options->{enable}; + + return if !$enable; + + # load required modules here +} + sub update { my ($verbose) = @_; @@ -2956,5 +3055,4 @@ sub update { run_locked($code); } - 1;