From: Dietmar Maurer Date: Mon, 6 Aug 2012 08:10:45 +0000 (+0200) Subject: write real files X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=commitdiff_plain;h=f789653a8b50676bb269fa1fd117e1913d54dec4;ds=sidebyside write real files And use short zone names --- diff --git a/PVE/Firewall.pm b/PVE/Firewall.pm index 6565212..cf53afc 100644 --- a/PVE/Firewall.pm +++ b/PVE/Firewall.pm @@ -3,22 +3,36 @@ package PVE::Firewall; use warnings; use strict; use Data::Dumper; - +use PVE::Tools; use PVE::QemuServer; # we need complete VM configuration of all VMs (openvz/qemu) # in vmdata sub compile { - my ($vmdata) = @_; + my ($targetdir, $vmdata) = @_; my $netinfo; - my $bridges = {}; my $zoneinfo = { fw => { type => 'firewall' }, }; + my $register_bridge = sub { + my ($bridge) = @_; + + my $zone = 'z' . $bridge; + + return $zone if $zoneinfo->{$zone}; + + $zoneinfo->{$zone} = { + type => 'bridge', + bridge => $bridge, + }; + + return $zone; + }; + foreach my $vmid (keys %{$vmdata->{qemu}}) { $netinfo->{$vmid} = {}; my $conf = $vmdata->{qemu}->{$vmid}; @@ -29,20 +43,17 @@ sub compile { next if !$net; die "implement me" if !$net->{bridge}; my $bridge = $net->{bridge}; - $bridges->{$bridge} = 1; - $zoneinfo->{$bridge}->{type} = 'ipv4'; - $zoneinfo->{$bridge}->{ifaces}->{$bridge} = 1; + my $bridge_zone = &$register_bridge($bridge); if (defined($net->{tag})) { $bridge = $bridge .= "v$net->{tag}"; - $bridges->{$bridge} = 1; - $zoneinfo->{$bridge}->{type} = 'ipv4'; - $zoneinfo->{$bridge}->{ifaces}->{$bridge} = 1; + $bridge_zone = &$register_bridge($bridge); } - my $zone = $bridge . ($conf->{zone} || "vm$vmid"); + my $vmzone = $conf->{zone} || "vm$vmid"; + my $zone = "$bridge_zone$vmzone"; $net->{zone} = $zone; $zoneinfo->{$zone}->{type} = 'bport'; - $zoneinfo->{$zone}->{bridge} = $bridge; + $zoneinfo->{$zone}->{bridge_zone} = $bridge_zone; $zoneinfo->{$zone}->{ifaces}->{"tap${vmid}i${netid}"} = 1; $netinfo->{$vmid}->{$netid} = $net; } @@ -50,40 +61,84 @@ sub compile { #print Dumper($netinfo); - # TODO: zone names have length limit, so we need to + # NOTE: zone names have length limit, so we need to # translate them into shorter names + my $zoneid = 0; + my $zonemap = { fw => 'fw' }; + + my $lookup_zonename = sub { + my ($zone) = @_; + + return $zonemap->{$zone} if defined($zonemap->{$zone}); + $zonemap->{$zone} = 'z' . $zoneid++; + + return $zonemap->{$zone}; + }; + # dump zone file - print "DUMP: zones\n"; - my $format = "%-15s %-10s %s\n"; - printf($format, '#ZONE', 'TYPE', 'OPTIONS'); + my $out; + my $format = "%-15s %-10s %s\n"; + $out = sprintf($format, '#ZONE', 'TYPE', 'OPTIONS'); + foreach my $z (sort keys %$zoneinfo) { - printf($format, $z, $zoneinfo->{$z}->{type}, ''); + my $zid = &$lookup_zonename($z); + if ($zoneinfo->{$z}->{type} eq 'firewall') { + $out .= sprintf($format, $zid, $zoneinfo->{$z}->{type}, ''); + } elsif ($zoneinfo->{$z}->{type} eq 'bridge') { + $out .= sprintf($format, &$lookup_zonename($z), 'ipv4', ''); + } elsif ($zoneinfo->{$z}->{type} eq 'bport') { + my $bridge_zone = $zoneinfo->{$z}->{bridge_zone} || die "internal error"; + my $bzid = &$lookup_zonename($bridge_zone); + $out .= sprintf($format, "$zid:$bzid", 'bport', ''); + } else { + die "internal error"; + } } - print "#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE\n"; + $out .= sprintf("#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE\n"); + + PVE::Tools::file_set_contents("$targetdir/zones", $out); - print "\n"; - print "DUMP: interfaces\n"; + # dump interfaces $format = "%-15s %-20s %-10s %s\n"; - printf($format, '#ZONE', 'INTERFACE', 'BROADCAST', 'OPTIONS'); + $out = sprintf($format, '#ZONE', 'INTERFACE', 'BROADCAST', 'OPTIONS'); + foreach my $z (sort keys %$zoneinfo) { - my $ifaces = $zoneinfo->{$z}->{ifaces}; - foreach my $iface (sort keys %$ifaces) { - my $broadcast = $zoneinfo->{$z}->{type} eq 'ipv4' ? 'detect' : ''; - my $options = $bridges->{$iface} ? 'bridge' : ''; - my $bridge = $zoneinfo->{$z}->{bridge} || ''; - my $iftxt = $zoneinfo->{$z}->{bridge} ? "$zoneinfo->{$z}->{bridge}:$iface" : $iface; - printf($format, $z, $iftxt, $broadcast, $options); + my $zid = &$lookup_zonename($z); + if ($zoneinfo->{$z}->{type} eq 'firewall') { + # do nothing; + } elsif ($zoneinfo->{$z}->{type} eq 'bridge') { + my $bridge = $zoneinfo->{$z}->{bridge} || die "internal error"; + $out .= sprintf($format, $zid, $bridge, 'detect', 'bridge'); + + } elsif ($zoneinfo->{$z}->{type} eq 'bport') { + my $ifaces = $zoneinfo->{$z}->{ifaces}; + foreach my $iface (sort keys %$ifaces) { + my $bridge_zone = $zoneinfo->{$z}->{bridge_zone} || die "internal error"; + my $bridge = $zoneinfo->{$bridge_zone}->{bridge} || die "internal error"; + my $iftxt = "$bridge:$iface"; + $out .= sprintf($format, $zid, $iftxt, '', ''); + } + } else { + die "internal error"; } } - print "#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE\n"; + $out .= sprintf("#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE\n"); + + PVE::Tools::file_set_contents("$targetdir/interfaces", $out); + + # dump policy + + $format = "%-15s %-15s %-15s %s\n"; + $out = sprintf($format, '#SOURCE', 'DEST', 'POLICY', 'LOG'); + $out .= sprintf($format, 'all', 'all', 'REJECT', 'info'); - print "\n"; + PVE::Tools::file_set_contents("$targetdir/policy", $out); } diff --git a/fwtest.pl b/fwtest.pl index f04b67e..867e21b 100755 --- a/fwtest.pl +++ b/fwtest.pl @@ -3,6 +3,7 @@ use strict; use lib qw(.); use PVE::Firewall; +use File::Path; my $vmdata = { qemu => { @@ -15,6 +16,7 @@ my $vmdata = { 102 => { zone => 'z1', net0 => 'rtl8139=0E:9D:ED:CC:AA:ED,bridge=vmbr0', + net1 => 'rtl8139=0E:9D:ED:CC:CC:ED,bridge=vmbr1', }, 103 => { zone => 'z1', @@ -24,6 +26,12 @@ my $vmdata = { }, }; -PVE::Firewall::compile($vmdata); +my $testdir = "./testdir"; +rmtree($testdir); +mkdir $testdir; + +PVE::Firewall::compile($testdir, $vmdata); + +PVE::Tools::run_command(['shorewall', 'check', $testdir]); exit(0);