From 9d31b4186cf5107ff15ec8fa89e98c776b37a5ff Mon Sep 17 00:00:00 2001 From: Alexandre Derumier Date: Fri, 7 Feb 2014 16:22:32 +0100 Subject: [PATCH] add support for security groups pvefw disablegroup -securitygroup [OPTIONS] pvefw enablegroup -securitygroup [OPTIONS] (pool permissions is not yet implemented) /etc/pve/firewall/groups.fw [IN:group1] ACCEPT - - - tcp 22 - ACCEPT - - - icmp - - [OUT:group1] ACCEPT - - - tcp 80 - ACCEPT - - - icmp - - Signed-off-by: Alexandre Derumier --- PVE/Firewall.pm | 84 +++++++++++++++++++++++++++++++++++++++++++++++-- pvefw | 47 +++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 2 deletions(-) diff --git a/PVE/Firewall.pm b/PVE/Firewall.pm index 5396bcd..ff5cadf 100644 --- a/PVE/Firewall.pm +++ b/PVE/Firewall.pm @@ -463,6 +463,80 @@ sub generate_proxmoxfwoutput { } +sub enable_group_rules { + my ($group) = @_; + + generate_group_rules($group); + iptables_restore(); +} + +sub generate_group_rules { + my ($group) = @_; + + my $filename = "/etc/pve/firewall/groups.fw"; + my $fh = IO::File->new($filename, O_RDONLY); + return if !$fh; + + my $rules = parse_fw_rules($filename, $fh, $group); + my $inrules = $rules->{in}; + my $outrules = $rules->{out}; + + my $chain = "GROUP-".$group."-IN"; + + iptables_addrule(":$chain - [0:0]"); + + if (scalar(@$inrules)) { + foreach my $rule (@$inrules) { + iptables_generate_rule($chain, $rule); + } + } + + $chain = "GROUP-".$group."-OUT"; + + iptables_addrule(":$chain - [0:0]"); + + if(!iptables_chain_exist("BRIDGEFW-OUT")){ + iptables_addrule(":BRIDGEFW-OUT - [0:0]"); + } + + if(!iptables_chain_exist("BRIDGEFW-IN")){ + iptables_addrule(":BRIDGEFW-IN - [0:0]"); + } + + if (scalar(@$outrules)) { + foreach my $rule (@$outrules) { + #we go the BRIDGEFW-IN because we need to check also other tap rules + #(and group rules can be set on any bridge, so we can't go to VMBRXX-IN) + $rule->{action} = 'BRIDGEFW-IN' if $rule->{action} eq 'ACCEPT'; + iptables_generate_rule($chain, $rule); + } + } + +} + +sub disable_group_rules { + my ($group) = @_; + + my $chain = "GROUP-".$group."-IN"; + + if(iptables_chain_exist($chain)){ + iptables_addrule("-F $chain"); + iptables_addrule("-X $chain"); + } + + $chain = "GROUP-".$group."-OUT"; + + if(iptables_chain_exist($chain)){ + iptables_addrule("-F $chain"); + iptables_addrule("-X $chain"); + } + + #iptables_restore will die if security group is linked in a tap chain + #maybe can we improve that, parsing each vm config, or parsing iptables -S + #to see if the security group is linked or not + iptables_restore(); +} + my $generate_input_rule = sub { my ($zoneinfo, $rule, $net, $netid) = @_; @@ -777,9 +851,11 @@ my $compile_shorewall = sub { sub parse_fw_rules { - my ($filename, $fh) = @_; + my ($filename, $fh, $group) = @_; my $section; + my $securitygroup; + my $securitygroupexist; my $res = { in => [], out => [] }; @@ -790,11 +866,14 @@ sub parse_fw_rules { next if $line =~ m/^#/; next if $line =~ m/^\s*$/; - if ($line =~ m/^\[(in|out)\]\s*$/i) { + if ($line =~ m/^\[(in|out)(:(\S+))?\]\s*$/i) { $section = lc($1); + $securitygroup = lc($3) if $3; + $securitygroupexist = 1 if $securitygroup && $securitygroup eq $group; next; } next if !$section; + next if $group && $securitygroup ne $group; my ($action, $iface, $source, $dest, $proto, $dport, $sport) = split(/\s+/, $line); @@ -873,6 +952,7 @@ sub parse_fw_rules { push @{$res->{$section}}, $rule; } + die "security group $group don't exist" if $group && !$securitygroupexist; return $res; } diff --git a/pvefw b/pvefw index 2d4d450..70a2bee 100755 --- a/pvefw +++ b/pvefw @@ -100,6 +100,51 @@ __PACKAGE__->register_method({ return undef; }}); +__PACKAGE__->register_method({ + name => 'enablegroup', + path => 'enablegroup', + method => 'POST', + parameters => { + additionalProperties => 0, + properties => { + securitygroup => { + type => 'string', + }, + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $group = $param->{securitygroup}; + PVE::Firewall::enable_group_rules($group); + + return undef; + }}); + +__PACKAGE__->register_method({ + name => 'disablegroup', + path => 'disablegroup', + method => 'POST', + parameters => { + additionalProperties => 0, + properties => { + securitygroup => { + type => 'string', + }, + + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $group = $param->{securitygroup}; + PVE::Firewall::disable_group_rules($group); + + return undef; + }}); + __PACKAGE__->register_method({ name => 'enablehostfw', path => 'enablehostfw', @@ -243,6 +288,8 @@ my $cmddef = { disablevmfw => [ __PACKAGE__, 'disablevmfw', []], enablehostfw => [ __PACKAGE__, 'enablehostfw', []], disablehostfw => [ __PACKAGE__, 'disablehostfw', []], + enablegroup => [ __PACKAGE__, 'enablegroup', []], + disablegroup => [ __PACKAGE__, 'disablegroup', []], }; my $cmd = shift; -- 2.39.2