cleanups
authorDietmar Maurer <dietmar@proxmox.com>
Fri, 10 Aug 2012 10:14:33 +0000 (12:14 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Fri, 10 Aug 2012 10:14:33 +0000 (12:14 +0200)
PVE/Firewall.pm
README
pvefw

index 7ff4ddf..8eb277c 100644 (file)
@@ -5,6 +5,9 @@ use strict;
 use Data::Dumper;
 use PVE::Tools;
 use PVE::QemuServer;
+use File::Path;
+use IO::File;
+use Data::Dumper;
 
 my $macros;
 sub get_shorewall_macros {
@@ -82,7 +85,7 @@ my $generate_output_rule = sub {
 # we need complete VM configuration of all VMs (openvz/qemu)
 # in vmdata
 
-sub compile {
+my $compile_shorewall = sub {
     my ($targetdir, $vmdata, $rules) = @_;
 
     # remove existing data ?
@@ -318,12 +321,151 @@ sub compile {
     }
 
     PVE::Tools::file_set_contents("$targetdir/rules", $out);
+};
+
+
+sub parse_fw_rules {
+    my ($filename, $fh) = @_;
+
+    my $section;
+
+    my $res = { in => [], out => [] };
+
+    my $macros = PVE::Firewall::get_shorewall_macros();
+
+    while (defined(my $line = <$fh>)) {
+       next if $line =~ m/^#/;
+       next if $line =~ m/^\s*$/;
+
+       if ($line =~ m/^\[(in|out)\]\s*$/i) {
+           $section = lc($1);
+           next;
+       }
+       next if !$section;
+
+       my ($action, $iface, $source, $dest, $proto, $dport, $sport) =
+           split(/\s+/, $line);
+
+       if (!$action) {
+           warn "skip incomplete line\n";
+           next;
+       }
+
+       my $service;
+       if ($action =~ m/^(ACCEPT|DROP|REJECT)$/) {
+           # OK
+       } elsif ($action =~ m/^(\S+)\((ACCEPT|DROP|REJECT)\)$/) {
+           ($service, $action) = ($1, $2);
+           if (!$macros->{$service}) {
+               warn "unknown service '$service'\n";
+               next;
+           }
+       } else {
+           warn "unknown action '$action'\n";
+           next;
+       }
+
+       $iface = undef if $iface && $iface eq '-';
+       if ($iface && $iface !~ m/^(net0|net1|net2|net3|net4|net5)$/) {
+           warn "unknown interface '$iface'\n";
+           next;
+       }
+
+       $proto = undef if $proto && $proto eq '-';
+       if ($proto && $proto !~ m/^(icmp|tcp|udp)$/) {
+           warn "unknown protokol '$proto'\n";
+           next;
+       }
+
+       $source = undef if $source && $source eq '-';
+
+#      if ($source !~ m/^(XYZ)$/) {
+#          warn "unknown source '$source'\n";
+#          next;
+#      }
+
+       $dest = undef if $dest && $dest eq '-';
+#      if ($dest !~ m/^XYZ)$/) {
+#          warn "unknown destination '$dest'\n";
+#          next;
+#      }
+
+       $dport = undef if $dport && $dport eq '-';
+       $sport = undef if $sport && $sport eq '-';
+
+       my $rule = {
+           action => $action,
+           service => $service,
+           iface => $iface,
+           source => $source,
+           dest => $dest,
+           proto => $proto,
+           dport => $dport,
+           sport => $sport,
+       };
+
+       push @{$res->{$section}}, $rule;
+    }
+
+    return $res;
+}
+
+sub read_local_vm_config {
+
+    my $openvz = {};
+
+    my $qemu = {};
+
+    my $list = PVE::QemuServer::config_list();
+
+    foreach my $vmid (keys %$list) {
+       # next if $vmid ne '100';
+       my $cfspath = PVE::QemuServer::cfs_config_path($vmid);
+       if (my $conf = PVE::Cluster::cfs_read_file($cfspath)) {
+           $qemu->{$vmid} = $conf;
+       }
+    }
+
+    my $vmdata = { openvz => $openvz, qemu => $qemu };
+
+    return $vmdata;
+};
+
+sub read_vm_firewall_rules {
+    my ($vmdata) = @_;
+    my $rules = {};
+    foreach my $vmid (keys %{$vmdata->{qemu}}, keys %{$vmdata->{openvz}}) {
+       my $filename = "/etc/pve/firewall/$vmid.fw";
+       my $fh = IO::File->new($filename, O_RDONLY);
+       next if !$fh;
+
+       $rules->{$vmid} = parse_fw_rules($filename, $fh);
+    }
+
+    return $rules;
+}
+
+sub compile {
+
+    my $vmdata = read_local_vm_config();
+    my $rules = read_vm_firewall_rules($vmdata);
+
+    # print Dumper($vmdata);
+
+    my $swdir = '/etc/shorewall';
+    mkdir $swdir;
+
+    &$compile_shorewall($swdir, $vmdata, $rules);
 
+    PVE::Tools::run_command(['shorewall', 'compile']);
 }
 
+sub compile_and_start {
+    my ($restart) = @_;
 
-sub activate {
+    compile();
 
+    PVE::Tools::run_command(['shorewall', $restart ? 'restart' : 'start']);
 }
 
 
diff --git a/README b/README
index b9a9da7..41c7c19 100644 (file)
--- a/README
+++ b/README
@@ -1,13 +1,38 @@
 Experimental software, only used for testing.
 
+Note: you need to change values in /etc/sysctl.d/pve.conf to:
+
+net.bridge.bridge-nf-call-ip6tables = 1
+net.bridge.bridge-nf-call-iptables = 1
+net.bridge.bridge-nf-call-arptables = 1
+net.bridge.bridge-nf-filter-vlan-tagged = 1
+
+and reboot after that change.
+
+
 VM firewall rules are read from /etc/pve/firewall/<VMID>.fw
 
 You can find examples in the example/ dir
 
+Note: All commands overwrites /etc/shorewall/, so don't use if you have
+and existing shorewall config you want to keep.
+
 Use the following command to generate shorewall configuration:
 
 ./pvefw compile
 
-That command overwrites /etc/shorewall/, so don't use if you have
-and existing shorewall config you want to keep.
+To compile and start the firewall:
+
+./pvefw start
+
+To compile and restart the firewall:
+
+./pvefw restart
+
+To stop the firewall:
+
+./pvefw stop
+
+To clear all iptable rules:
 
+./pvefw clear
\ No newline at end of file
diff --git a/pvefw b/pvefw
index 4ac9679..b10895e 100755 (executable)
--- a/pvefw
+++ b/pvefw
@@ -3,15 +3,11 @@
 use strict;
 use lib qw(.);
 use PVE::Firewall;
-use File::Path;
-use IO::File;
-use Data::Dumper;
 
 use PVE::SafeSyslog;
 use PVE::Cluster;
 use PVE::INotify;
 use PVE::RPCEnvironment;
-use PVE::QemuServer;
 
 use PVE::JSONSchema qw(get_standard_option);
 
@@ -34,127 +30,6 @@ $rpcenv->set_language($ENV{LANG});
 $rpcenv->set_user('root@pam');
 
 
-sub parse_fw_rules {
-    my ($filename, $fh) = @_;
-
-    my $section;
-
-    my $res = { in => [], out => [] };
-
-    my $macros = PVE::Firewall::get_shorewall_macros();
-
-    while (defined(my $line = <$fh>)) {
-       next if $line =~ m/^#/;
-       next if $line =~ m/^\s*$/;
-
-       if ($line =~ m/^\[(in|out)\]\s*$/i) {
-           $section = lc($1);
-           next;
-       }
-       next if !$section;
-
-       my ($action, $iface, $source, $dest, $proto, $dport, $sport) =
-           split(/\s+/, $line);
-
-       if (!$action) {
-           warn "skip incomplete line\n";
-           next;
-       }
-
-       my $service;
-       if ($action =~ m/^(ACCEPT|DROP|REJECT)$/) {
-           # OK
-       } elsif ($action =~ m/^(\S+)\((ACCEPT|DROP|REJECT)\)$/) {
-           ($service, $action) = ($1, $2);
-           if (!$macros->{$service}) {
-               warn "unknown service '$service'\n";
-               next;
-           }
-       } else {
-           warn "unknown action '$action'\n";
-           next;
-       }
-
-       $iface = undef if $iface && $iface eq '-';
-       if ($iface && $iface !~ m/^(net0|net1|net2|net3|net4|net5)$/) {
-           warn "unknown interface '$iface'\n";
-           next;
-       }
-
-       $proto = undef if $proto && $proto eq '-';
-       if ($proto && $proto !~ m/^(icmp|tcp|udp)$/) {
-           warn "unknown protokol '$proto'\n";
-           next;
-       }
-
-       $source = undef if $source && $source eq '-';
-
-#      if ($source !~ m/^(XYZ)$/) {
-#          warn "unknown source '$source'\n";
-#          next;
-#      }
-
-       $dest = undef if $dest && $dest eq '-';
-#      if ($dest !~ m/^XYZ)$/) {
-#          warn "unknown destination '$dest'\n";
-#          next;
-#      }
-
-       $dport = undef if $dport && $dport eq '-';
-       $sport = undef if $sport && $sport eq '-';
-
-       my $rule = {
-           action => $action,
-           service => $service,
-           iface => $iface,
-           source => $source,
-           dest => $dest,
-           proto => $proto,
-           dport => $dport,
-           sport => $sport,
-       };
-
-       push @{$res->{$section}}, $rule;
-    }
-
-    return $res;
-}
-
-sub read_local_vm_config {
-
-    my $openvz = {};
-
-    my $qemu = {};
-
-    my $list = PVE::QemuServer::config_list();
-
-    foreach my $vmid (keys %$list) {
-       # next if $vmid ne '100';
-       my $cfspath = PVE::QemuServer::cfs_config_path($vmid);
-       if (my $conf = PVE::Cluster::cfs_read_file($cfspath)) {
-           $qemu->{$vmid} = $conf;
-       }
-    }
-
-    my $vmdata = { openvz => $openvz, qemu => $qemu };
-
-    return $vmdata;
-};
-
-sub read_vm_firewall_rules {
-    my ($vmdata) = @_;
-    my $rules = {};
-    foreach my $vmid (keys %{$vmdata->{qemu}}, keys %{$vmdata->{openvz}}) {
-       my $filename = "/etc/pve/firewall/$vmid.fw";
-       my $fh = IO::File->new($filename, O_RDONLY);
-       next if !$fh;
-
-       $rules->{$vmid} = parse_fw_rules($filename, $fh);
-    }
-
-    return $rules;
-}
-
 __PACKAGE__->register_method ({
     name => 'compile',
     path => 'compile',
@@ -169,27 +44,35 @@ __PACKAGE__->register_method ({
     code => sub {
        my ($param) = @_;
 
-       my $vmdata = read_local_vm_config();
-       my $rules = read_vm_firewall_rules($vmdata);
+       PVE::Firewall::compile();
 
-       # print Dumper($vmdata);
+       return undef;
+    }});
 
-       my $swdir = '/etc/shorewall';
-       mkdir $swdir;
+__PACKAGE__->register_method ({
+    name => 'start',
+    path => 'start',
+    method => 'POST',
+    description => "Start firewall.",
+    parameters => {
+       additionalProperties => 0,
+       properties => {},
+    },
+    returns => { type => 'null' },
 
-       PVE::Firewall::compile($swdir, $vmdata, $rules);
+    code => sub {
+       my ($param) = @_;
 
-       PVE::Tools::run_command(['shorewall', 'compile']);
+       PVE::Firewall::compile_and_start();
 
        return undef;
-
     }});
 
 __PACKAGE__->register_method ({
-    name => 'start',
-    path => 'start',
+    name => 'restart',
+    path => 'restart',
     method => 'POST',
-    description => "Start firewall.",
+    description => "Restart firewall.",
     parameters => {
        additionalProperties => 0,
        properties => {},
@@ -199,7 +82,7 @@ __PACKAGE__->register_method ({
     code => sub {
        my ($param) = @_;
 
-       PVE::Tools::run_command(['shorewall', 'start']);
+       PVE::Firewall::compile_and_start(1);
 
        return undef;
     }});
@@ -247,6 +130,7 @@ my $nodename = PVE::INotify::nodename();
 my $cmddef = {
     compile => [ __PACKAGE__, 'compile', []],
     start => [ __PACKAGE__, 'start', []],
+    restart => [ __PACKAGE__, 'restart', []],
     stop => [ __PACKAGE__, 'stop', []],
     clear => [ __PACKAGE__, 'clear', []],
 };