X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=blobdiff_plain;f=pvefw;h=e33518de64c13db1e7463a8382505bd47a8afab6;hp=4ac96796e7331f32bbd293fafce45692f4f93478;hb=de2a57cdcf099c30feecb5c095328a82d1d154e1;hpb=9a4644fa5560e9087b50e5f9c11699590ad8966e diff --git a/pvefw b/pvefw index 4ac9679..e33518d 100755 --- 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); @@ -33,133 +29,143 @@ $rpcenv->init_request(); $rpcenv->set_language($ENV{LANG}); $rpcenv->set_user('root@pam'); +__PACKAGE__->register_method({ + name => 'enablevmfw', + path => 'enablevmfw', + method => 'POST', + parameters => { + additionalProperties => 0, + properties => { + vmid => get_standard_option('pve-vmid'), + netid => { + type => 'string', + optional => 1 + }, + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; -sub parse_fw_rules { - my ($filename, $fh) = @_; + # test if VM exists + my $vmid = $param->{vmid}; + my $netid = $param->{netid}; - my $section; + my $code = sub { + my $conf = PVE::QemuServer::load_config($vmid); - my $res = { in => [], out => [] }; + foreach my $opt (keys %$conf) { + next if $opt !~ m/^net(\d+)$/; + my $net = PVE::QemuServer::parse_net($conf->{$opt}); + next if !$net; + next if $netid && $opt != $netid; + PVE::Firewall::generate_tap_rules($net, $opt, $vmid); + } + }; - my $macros = PVE::Firewall::get_shorewall_macros(); + PVE::Firewall::run_locked($code); + + return undef; + }}); - while (defined(my $line = <$fh>)) { - next if $line =~ m/^#/; - next if $line =~ m/^\s*$/; +__PACKAGE__->register_method({ + name => 'disablevmfw', + path => 'disablevmfw', + method => 'POST', + parameters => { + additionalProperties => 0, + properties => { + vmid => get_standard_option('pve-vmid'), + netid => { + type => 'string', + optional => 1 + }, + + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; - if ($line =~ m/^\[(in|out)\]\s*$/i) { - $section = lc($1); - next; - } - next if !$section; + # test if VM exists + my $vmid = $param->{vmid}; + my $netid = $param->{netid}; - my ($action, $iface, $source, $dest, $proto, $dport, $sport) = - split(/\s+/, $line); - if (!$action) { - warn "skip incomplete line\n"; - next; - } + my $code = sub { + my $conf = PVE::QemuServer::load_config($vmid); - 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; + foreach my $opt (keys %$conf) { + next if $opt !~ m/^net(\d+)$/; + my $net = PVE::QemuServer::parse_net($conf->{$opt}); + next if !$net; + next if $netid && $opt != $netid; + PVE::Firewall::flush_tap_rules($net, $opt, $vmid); } - } 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; -} + PVE::Firewall::run_locked($code); -sub read_local_vm_config { - - my $openvz = {}; + return undef; + }}); - my $qemu = {}; +__PACKAGE__->register_method({ + name => 'enablegroup', + path => 'enablegroup', + method => 'POST', + parameters => { + additionalProperties => 0, + properties => { + securitygroup => { + type => 'string', + }, + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; - my $list = PVE::QemuServer::config_list(); + my $code = sub { + my $group = $param->{securitygroup}; + PVE::Firewall::enable_group_rules($group); + }; - 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; - } - } + PVE::Firewall::run_locked($code); + + return undef; + }}); - my $vmdata = { openvz => $openvz, qemu => $qemu }; +__PACKAGE__->register_method({ + name => 'disablegroup', + path => 'disablegroup', + method => 'POST', + parameters => { + additionalProperties => 0, + properties => { + securitygroup => { + type => 'string', + }, - return $vmdata; -}; + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; -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; + my $code = sub { + my $group = $param->{securitygroup}; + PVE::Firewall::disable_group_rules($group); + }; - $rules->{$vmid} = parse_fw_rules($filename, $fh); - } + PVE::Firewall::run_locked($code); - return $rules; -} + return undef; + }}); -__PACKAGE__->register_method ({ - name => 'compile', - path => 'compile', +__PACKAGE__->register_method({ + name => 'enablehostfw', + path => 'enablehostfw', method => 'POST', - description => "Compile firewall rules.", parameters => { additionalProperties => 0, properties => {}, @@ -169,27 +175,42 @@ __PACKAGE__->register_method ({ code => sub { my ($param) = @_; - my $vmdata = read_local_vm_config(); - my $rules = read_vm_firewall_rules($vmdata); + my $code = sub { + PVE::Firewall::enablehostfw(); + }; - # print Dumper($vmdata); + PVE::Firewall::run_locked($code); - my $swdir = '/etc/shorewall'; - mkdir $swdir; + return undef; + }}); - PVE::Firewall::compile($swdir, $vmdata, $rules); +__PACKAGE__->register_method({ + name => 'disablehostfw', + path => 'disablehostfw', + method => 'POST', + parameters => { + additionalProperties => 0, + properties => {}, + }, + returns => { type => 'null' }, + + code => sub { + my ($param) = @_; + + my $code = sub { + PVE::Firewall::disablehostfw(); + }; - PVE::Tools::run_command(['shorewall', 'compile']); + PVE::Firewall::run_locked($code); return undef; - }}); __PACKAGE__->register_method ({ - name => 'start', - path => 'start', + name => 'compile', + path => 'compile', method => 'POST', - description => "Start firewall.", + description => "Compile firewall rules.", parameters => { additionalProperties => 0, properties => {}, @@ -199,16 +220,20 @@ __PACKAGE__->register_method ({ code => sub { my ($param) = @_; - PVE::Tools::run_command(['shorewall', 'start']); + my $code = sub { + PVE::Firewall::compile(); + }; + + PVE::Firewall::run_locked($code); return undef; }}); __PACKAGE__->register_method ({ - name => 'stop', - path => 'stop', + name => 'start', + path => 'start', method => 'POST', - description => "Stop firewall.", + description => "Start (or restart if already active) firewall.", parameters => { additionalProperties => 0, properties => {}, @@ -218,16 +243,20 @@ __PACKAGE__->register_method ({ code => sub { my ($param) = @_; - PVE::Tools::run_command(['shorewall', 'stop']); + my $code = sub { + PVE::Firewall::compile_and_start(); + }; + + PVE::Firewall::run_locked($code); return undef; }}); __PACKAGE__->register_method ({ - name => 'clear', - path => 'clear', + name => 'stop', + path => 'stop', method => 'POST', - description => "Clear will remove all rules installed by this script. The host is then unprotected.", + description => "Stop firewall. This will remove all rules installed by this script. The host is then unprotected.", parameters => { additionalProperties => 0, properties => {}, @@ -237,7 +266,11 @@ __PACKAGE__->register_method ({ code => sub { my ($param) = @_; - PVE::Tools::run_command(['shorewall', 'clear']); + my $code = sub { + die "implement me"; + }; + + PVE::Firewall::run_locked($code); return undef; }}); @@ -247,8 +280,14 @@ my $nodename = PVE::INotify::nodename(); my $cmddef = { compile => [ __PACKAGE__, 'compile', []], start => [ __PACKAGE__, 'start', []], + restart => [ __PACKAGE__, 'restart', []], stop => [ __PACKAGE__, 'stop', []], - clear => [ __PACKAGE__, 'clear', []], + enablevmfw => [ __PACKAGE__, 'enablevmfw', []], + disablevmfw => [ __PACKAGE__, 'disablevmfw', []], + enablehostfw => [ __PACKAGE__, 'enablehostfw', []], + disablehostfw => [ __PACKAGE__, 'disablehostfw', []], + enablegroup => [ __PACKAGE__, 'enablegroup', []], + disablegroup => [ __PACKAGE__, 'disablegroup', []], }; my $cmd = shift;