Re: [pve-devel] Firewall hooks

2018-03-23 Thread Tom Weber
Am Donnerstag, den 22.03.2018, 12:28 +0100 schrieb Harald Leithner:
> Hi,
> 
> it seams that there are no firewall hooks in pve-firewall is this
> correct?

IIRC, yes.

> I would like to add my own action before, after the firewall 
> configuration for a VM is stop,started or reloaded.
[..]
> Is there any point I could attach my own script?

when I was dealing with the firewall code cleanups last year, I had
ideas like this in the back of my head. Or at least ideas that would
make implementing such hooks easier.
My plans to further work on this still exist - free time doesn't
currently :(

  Tom


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] pve-firewall : can't have log on drop/reject rules

2018-11-22 Thread Tom Weber
Am Mittwoch, den 21.11.2018, 18:40 +0100 schrieb Alexandre DERUMIER:
> Hi,
> 
> I'm not sure it was working before,
> 
> but I can't get any log for a vm rule with a drop/reject.
> 
> It's only works with default vm drop/reject action.

Yes.

> I found an old patch about adding log by rules 
> https://pve.proxmox.com/pipermail/pve-devel/2017-September/028816.htm
> l
> 
> But I don't see anywhere how to define it in rules.
> 
> any idea ?

Yes, this was a preparing patch towards the features you're looking
for. Unfortunately real life work caught me up all year, so I couldn't
spent more time on this. This isn't implemented (though still somewhere
on my todo).

  Tom

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] Request for improvement of Network handling regarding LXC

2017-07-20 Thread Tom Weber
Hi there,

i'm currently evaluating the PVE environment as a replacement for my
custom KVM+LXC+DRBD setup I'm running so far.

Playing with (privileged) containers I figured that IP configuration is
always done from inside the container.

My usual setup is setting the (static) IP of the container from the
outside (and applying firewall rules) and dropping capabilities for the
container itself so this can't be changed from inside the container.

Currently this seems to be impossible with PVE as it comes.

Attached is a little patch that sets the IP from the 'outside' (if
defined as a static one). Once I manually add the lxc.cap.drop lines to
the CT config, I can't change this from the inside anymore.

It's only for IPv4 (can't test v6 on this setup) but I think it's
rather trivial to add this.

Unless you drop net_admin the CT will still be able to change
networking and behave like before - or work with DHCP.

Regards,
  Tom

--- /usr/share/perl5/PVE/LXC.pm.orig2017-07-20 12:03:52.949344829 +0200
+++ /usr/share/perl5/PVE/LXC.pm 2017-07-20 14:12:09.022119871 +0200
@@ -428,6 +428,11 @@
    $raw .= "lxc.network.type = veth\n";
    $raw .= "lxc.network.veth.pair = veth${vmid}i${ind}\n";
    $raw .= "lxc.network.hwaddr = $d->{hwaddr}\n" if defined($d->{hwaddr});
+   if (defined($d->{ip}) and ($d->{ip} ne "dhcp")) {
+   $raw .= "lxc.network.ipv4 = $d->{ip}\n";
+   $raw .= "lxc.network.ipv4.gateway = $d->{gw}\n" if 
defined($d->{gw});
+   $raw .= "lxc.network.flags = up\n" if defined($d->{ip});
+   }
    $raw .= "lxc.network.name = $d->{name}\n" if defined($d->{name});
    $raw .= "lxc.network.mtu = $d->{mtu}\n" if defined($d->{mtu});
 }


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] Request for improvement of Network handling regarding LXC

2017-07-20 Thread Tom Weber
Am Donnerstag, den 20.07.2017, 13:31 +0200 schrieb Michael Rasmussen:
> On Thu, 20 Jul 2017 13:22:58 +0200
> Tom Weber  wrote:
> 
> > 
> > +   if (defined($d->{ip}) and ($d->{ip} ne "dhcp")) {
> > +   $raw .= "lxc.network.ipv4 = $d->{ip}\n";
> > +   $raw .= "lxc.network.ipv4.gateway = $d->{gw}\n" if
> > defined($d->{gw});
> > +   $raw .= "lxc.network.flags = up\n" if defined($d-
> > >{ip});
> The if defined($d->{ip}) in this line is not needed since this is
> already true when entering this condition. 

Indeed.
restover from the first version which didn't have the bigger if block
with dhcp checking.

thanks,
  Tom
___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] Request for improvement of Network handling regarding LXC

2017-07-20 Thread Tom Weber
Am Donnerstag, den 20.07.2017, 15:00 +0200 schrieb Wolfgang Bumiller:
> On Thu, Jul 20, 2017 at 01:22:58PM +0200, Tom Weber wrote:
> > 
> > Hi there,
> > 
> > i'm currently evaluating the PVE environment as a replacement for
> > my
> > custom KVM+LXC+DRBD setup I'm running so far.
> > 
> > Playing with (privileged) containers I figured that IP
> > configuration is
> > always done from inside the container.
> > 
> > My usual setup is setting the (static) IP of the container from the
> > outside (and applying firewall rules) and dropping capabilities for
> > the
> > container itself so this can't be changed from inside the
> > container.
> > 
> > Currently this seems to be impossible with PVE as it comes.
> > 
> > Attached is a little patch that sets the IP from the 'outside' (if
> > defined as a static one). Once I manually add the lxc.cap.drop
> > lines to
> > the CT config, I can't change this from the inside anymore.
> > 
> > It's only for IPv4 (can't test v6 on this setup) but I think it's
> > rather trivial to add this.
> > 
> > Unless you drop net_admin the CT will still be able to change
> > networking and behave like before - or work with DHCP.
> No objection to adding this as a separate option.
> 
> There's still the idea of adding feature flags to containers floating
> around (initially for allowing things like fuse or mounting of
> network
> shares (nfs, cifs)), and this would definitely be another useful flag
> to add.
> 
> Note that dropping net_admin also prevents containers from
> configuring
> their inner firewall or using tunnels/vpns/etc., so it would
> definitely
> need to be a separate option rather than a general change of behavior
> like in this patch, but you probably know that.

As far as I can see this patch alone wouldn't change the normal
behavior: 
step 1) lxc sets the IP from outside
step 2) container itself sets/overrides the IP from the inside.

Only if I manually add lxc.cap.drop = net_admin to the config of the
container it will prevent step 2.

Preventing the container from messing with networking/firewall settings
is exactly why I want/need this.

A feature switch for this (maybe even in the UI would be nice too) but
thats far beyond my 2 days knowledge of playing with pve :)

  Tom

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] debian 9.1 LXC unsupported

2017-07-24 Thread Tom Weber
With debian bumping it's stretch Version Number to 9.1, the check in
/usr/share/perl5/PVE/LXC/Setup/Debian.pm
fails.

# lxc-start -F -n 14433
unsupported debian version '9.1'
...

I fixed it for me like this:

--- /usr/share/perl5/PVE/LXC/Setup/Debian.pm.orig   2017-07-24 
11:25:37.601390691 +0200
+++ /usr/share/perl5/PVE/LXC/Setup/Debian.pm2017-07-24 11:25:59.305206733 
+0200
@@ -28,7 +28,7 @@
 $version = $1;
 
 die "unsupported debian version '$version'\n"
-   if !($version >= 4 && $version <= 9);
+   if !($version >= 4 && $version < 10);
 
 my $self = { conf => $conf, rootdir => $rootdir, version => $version };


  Tom
___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH Storage] LVM Striping

2017-07-27 Thread Tom Weber
Am Mittwoch, den 26.07.2017, 20:44 +0200 schrieb Martin Lablans:
> Dear all,
> 
> this patch will change the LVM storage plugin to create striped
> rather
> than linear logical volumes, which can multiply the throughput for 
> volume groups backed by several controllers or network paths.
> 
> The number of stripes is set equal to the number of physical volumes
> in 
> the volume group (which is determined using vgs). If this number is
> 1 
> (one), linear volumes are used as before.

You're making an assumption that wouldn't hold on most of my machines
(event though they're not converted to pve yet).
- I often have SSD and HDD based physical volumes in a volume group, so
I can decide which LV I put on which PV - speed vs space
- Huge drives - esp. HDD based ones, I usually partition to get smaller
PVs (each partition a PV) for 2 reasons: 1) the PVs at the beginning of
the disk are usually faster than the ones at the end - this makes it
easier to place a LV 2) Handling of PVs (think about pvmove) is easier.

This might or might not be of interest for the regular pve user (and I
guess I'll end up hand-optimizing for my setup anyway when using pve ;)
) but I don't think automatic striping by default, just based on the
number of PVs is a good idea.

Regards,
  Tom

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH Storage] Newly created LVM volumes are now created with a number of stripes equal to the number of physical volumes in a volume group.

2017-07-31 Thread Tom Weber
Am Sonntag, den 30.07.2017, 10:52 +0200 schrieb Martin Lablans:
> Of course it would be preferable to leave this in the admin's hand
> via 
> system-wide LVM configuration. This would also give Tom the
> flexibility 
> for his setup. However, I don't know a way to achieve striping in
> LVM 
> without using the -i option. raid_stripe_all_devices=1 does not
> achieve 
> that result, cf. https://serverfault.com/questions/849088
> 
> If someone knows how to configure striping in LVM, then I'll be happy
> to 
> write a few lines for the Proxmox documentation or wiki. If not,
> using 
> -i seems to be the only way to achieve striping.
> 
> Basically, we are discussing to change the current behaviour from
> "use 1 
> stripe" to "use  stripes". The latter option seems to 
> make a lot more sense to me, although I can see that there are
> special 
> setups requiring exactly one stripe.

I think huge (and affordable) Server SSDs and approaches like ceph etc.
will move storage back from external solutions into the local servers
again (hyper converged servers). And that will make local storage
setups way more complex and maybe the rule (and my setups not so
special anymore ;-) ).

> I see three options:
> 1) We find a way to configure that using LVM; I'll contribute
> documentation
> 2) We add a "-stripes" option to pct create, with options
>   0   ==> old behaviour (no -i)
>   n>0 ==> n stripes
>   auto==> number of pvs
> 3) Like 2), but define it as an option of the PVE storage 
> (/etc/pve/storage.cfg)

I don't know what the design goals are for pve (still new to it) but I
personally would prefer to have such an option well documented (with or
without UI) over a (silent) default for the whole lvm setup.
So i'd prefer 2) (maybe 3) but that will be difficult in complex
setups).

Regards,
  Tom
___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] better firewall logging possible?

2017-09-05 Thread Tom Weber
Hi there,

today I had to figure the hard way that the Firewall Option 'IP filter'
(at least in PVE 5.0 for Containers) drops packets silently without any
logging at all, even if the log_level_* is set.

If I set the log_level, I'd expect to see _all_ dropped packets in the
Log. (This gave me a hell of a time today with a DHCP Server inside a
container).

Regards,
  Tom

ps: is this the right place for such a feature request?


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] better firewall logging possible?

2017-09-06 Thread Tom Weber
Hi, 

thanks for the quick reply.
it doesn't seem to be that easy though.

this one compiles:

--- Firewall.pm.ORIG2017-09-06 11:27:00.158674622 +0200
+++ Firewall.pm 2017-09-06 11:39:07.801620128 +0200
@@ -2119,8 +2119,13 @@
    if ($ipversion == 6 && !$options->{radv}) {
    ruleset_addrule($ruleset, $chain, '-p icmpv6 --icmpv6-type 
router-advertisement -j DROP');
    }
+# XXX
    if ($ipfilter_ipset) {
    ruleset_addrule($ruleset, $chain, "-m set ! --match-set 
$ipfilter_ipset src -j DROP");
+   my $lc_direction = lc($direction);
+   my $loglevel = get_option_log_level($options, 
"log_level_${lc_direction}");
+   #ruleset_addlog($ruleset, $chain, $vmid, "policy $policy: ", 
$loglevel);
+   ruleset_addlog($ruleset, $chain, "FIXME-vmid", "policy: 
FIXME-policy", $loglevel);
    }
    ruleset_addrule($ruleset, $chain, "-j MARK --set-mark 
$FWACCEPTMARK_OFF"); # clear mark
 }


- $vmid and $policy are not (yet) available in ruleset_create_vm_chain
- $direction is always OUT in this block
- It doesn't produce anything in the log (doesn't it stop processing
after the DROP?) 

this is the generated chain:

Chain veth144010i2-OUT (1 references)
 pkts bytes target prot opt in out source   destination 

0 0 DROP   all  --  anyany anywhere anywhere
 ! match-set PVEFW-1DB4EE2A src
0 0 NFLOG  all  --  anyany anywhere anywhere
 nflog-prefix  ":FIXME-vmid:4:veth144010i2-OUT: policy: FIXME-policy"
0 0 MARK   all  --  anyany anywhere anywhere
 MARK and 0x7fff
0 0 GROUP-dns-server-OUT  all  --  anyany anywhere 
anywhere
0 0 RETURN all  --  anyany anywhere anywhere
 mark match 0x8000/0x8000
0 0 GROUP-default-guests-OUT  all  --  anyany anywhere  
   anywhere
0 0 RETURN all  --  anyany anywhere anywhere
 mark match 0x8000/0x8000
0 0 GROUP-dhcp-server-OUT  all  --  anyany anywhere 
anywhere
0 0 RETURN all  --  anyany anywhere anywhere
 mark match 0x8000/0x8000
0 0 GROUP-mail-sender-OUT  all  --  anyany anywhere 
anywhere
0 0 RETURN all  --  anyany anywhere anywhere
 mark match 0x8000/0x8000
0 0 PVEFW-SET-ACCEPT-MARK  udp  --  anyany anywhere 
anywhere[goto]  udp dpt:discard
0 0 PVEFW-Reject  all  --  anyany anywhere anywhere 
   
0 0 NFLOG  all  --  anyany anywhere anywhere
 nflog-prefix  ":144010:4:veth144010i2-OUT: policy REJECT: "
0 0 PVEFW-reject  all  --  anyany anywhere anywhere 
   [goto] 
0 0all  --  anyany anywhere anywhere
 /* PVESIG:j/bfq13umaUL2xMG35f2FLY+hPU */



  Tom

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] better firewall logging possible?

2017-09-06 Thread Tom Weber
Hi,

this patch compiles, but it won't work.

it still DROPs without logging.

Now it logs the packets that don't get dropped.
The first DROP stops the evaluation of the chain. Everything else gets
logged.

Chain veth144010i2-OUT (1 references)
 pkts bytes target prot opt in out source   destination 

0 0 DROP   all  --  anyany anywhere anywhere
 ! match-set PVEFW-1DB4EE2A src
0 0 NFLOG  all  --  anyany anywhere anywhere
 nflog-prefix  ":144010:4:veth144010i2-OUT: policyXXX: DROP"

changing the order will make it log everything.

I think the blacklist Option does it right:

sub ruleset_chain_add_input_filters {
my ($ruleset, $chain, $ipversion, $options, $cluster_conf, $loglevel) = @_;

if ($cluster_conf->{ipset}->{blacklist}){
if (!ruleset_chain_exist($ruleset, "PVEFW-blacklist")) {
ruleset_create_chain($ruleset, "PVEFW-blacklist");
ruleset_addlog($ruleset, "PVEFW-blacklist", 0, "DROP: ", $loglevel) 
if $loglevel;
ruleset_addrule($ruleset, "PVEFW-blacklist", "-j DROP");
}
my $ipset_chain = compute_ipset_chain_name(0, 'blacklist', $ipversion);
ruleset_addrule($ruleset, $chain, "-m set --match-set ${ipset_chain} 
src -j PVEFW-blacklist");
}

Unfortunately I'm too short on time right now to create a proper patch
myself. 


this is the non working version so far:

--- Firewall.pm.ORIG2017-09-06 11:27:00.158674622 +0200
+++ Firewall.pm 2017-09-06 15:51:27.850452259 +0200
@@ -2081,8 +2081,9 @@
 }
 }
 
+#XXX
 sub ruleset_create_vm_chain {
-my ($ruleset, $chain, $ipversion, $options, $macaddr,
$ipfilter_ipset, $direction) = @_;
+my ($ruleset, $chain, $ipversion, $options, $macaddr,
$ipfilter_ipset, $direction, $vmid) = @_;
 
 ruleset_create_chain($ruleset, $chain);
 my $accept = generate_nfqueue($options);
@@ -2119,8 +2120,11 @@
    if ($ipversion == 6 && !$options->{radv}) {
    ruleset_addrule($ruleset, $chain, '-p icmpv6 --icmpv6-type 
router-advertisement -j DROP');
    }
+# XXX
    if ($ipfilter_ipset) {
    ruleset_addrule($ruleset, $chain, "-m set ! --match-set
$ipfilter_ipset src -j DROP");
+   my $loglevel = get_option_log_level($options,
"log_level_out");
+   ruleset_addlog($ruleset, $chain, $vmid, "policyXXX: DROP",
$loglevel);
    }
    ruleset_addrule($ruleset, $chain, "-j MARK --set-mark
$FWACCEPTMARK_OFF"); # clear mark
 }
@@ -2232,7 +2236,8 @@
    if $options->{ipfilter} || $vmfw_conf->{ipset}-
>{$ipfilter_name};
 
 # create chain with mac and ip filter
-ruleset_create_vm_chain($ruleset, $tapchain, $ipversion, $options,
$macaddr, $ipfilter_ipset, $direction);
+#XXX
+ruleset_create_vm_chain($ruleset, $tapchain, $ipversion, $options,
$macaddr, $ipfilter_ipset, $direction, $vmid);
 
 if ($options->{enable}) {
    ruleset_generate_vm_rules($ruleset, $rules, $cluster_conf,
$vmfw_conf, $tapchain, $netid, $direction, $options, $ipversion);


Am Mittwoch, den 06.09.2017, 13:39 +0200 schrieb Alexandre DERUMIER:
> > 
> > > 
> > > - $vmid and $policy are not (yet) available in
> > > ruleset_create_vm_chain 
> for $vmid,
> --
> edit
> 
> # create chain with mac and ip filter
> ruleset_create_vm_chain($ruleset, $tapchain, $ipversion,
> $options, $macaddr, $ipfilter_ipset, $direction);
> 
> ->
> 
> # create chain with mac and ip filter
> ruleset_create_vm_chain($ruleset, $tapchain, $ipversion,
> $options, $macaddr, $ipfilter_ipset, $direction, $vmid);
> 
> 
> 
> 
> then
> 
> sub ruleset_create_vm_chain {
> my ($ruleset, $chain, $ipversion, $options, $macaddr,
> $ipfilter_ipset, $direction) = @_;
> 
> 
> ->
> 
> sub ruleset_create_vm_chain {
> my ($ruleset, $chain, $ipversion, $options, $macaddr,
> $ipfilter_ipset, $direction, $vmid) = @_;
> 
> 
> 
> 
> 
> for
> "policy $policy: "
> ---
> it's just a string, keep it empty for now, or "policy DROP"
> 
> 
> 
> 
> > 
> > > 
> > > - $direction is always OUT in this block 
> yes, but it need to be use lowercase for the rule
> 
> I think this should be ok
> + my $lc_direction = lc($direction); 
> + my $loglevel = get_option_log_level($options,
> "log_level_${lc_direction}"); 
> 
> 
> or
> 
> my $loglevel = "log_level_out";
> 
> 
> > 
> > > 
> > > - It doesn't produce anything in the log (doesn't it stop
> > > processing 
> > > after the DROP?) 
> in others rules it's added after the DROP.
> try to add it before to test.  (but I think that the missing $vmid
> was the problem, to log in correct logfile)
> 

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] better firewall logging possible?

2017-09-06 Thread Tom Weber
Attached patch works for me regarding and tested with ipfilter Option.
I also added logging for the 2 other silent DROPs above - untested
though.

Maybe someone could verify and even commit (no git repository for pve
over here - yet)

  Tom


Am Mittwoch, den 06.09.2017, 16:24 +0200 schrieb Tom Weber:
> 
> 
> Hi,
> 
> this patch compiles, but it won't work.
> 
> it still DROPs without logging.
> 
> Now it logs the packets that don't get dropped.
> The first DROP stops the evaluation of the chain. Everything else
> gets
> logged.
> 
> Chain veth144010i2-OUT (1 references)
>  pkts bytes target prot opt
> in out source   destination 
> 0 0 DROP   all  
> --  anyany anywhere anywhere ! match-
> set PVEFW-1DB4EE2A src
> 0 0 NFLOG  all  
> --  anyany anywhere anywhere nflog-
> prefix  ":144010:4:veth144010i2-OUT: policyXXX: DROP"
> 
> changing the order will make it log everything.
> 
> I think the blacklist Option does it right:
> 
> sub ruleset_chain_add_input_filters {
> my ($ruleset, $chain, $ipversion, $options, $cluster_conf,
> $loglevel) = @_;
> 
> if ($cluster_conf->{ipset}->{blacklist}){
> if (!ruleset_chain_exist($ruleset, "PVEFW-blacklist")) {
> ruleset_create_chain($ruleset, "PVEFW-blacklist");
> ruleset_addlog($ruleset, "PVEFW-blacklist", 0, "DROP: ",
> $loglevel) if $loglevel;
> ruleset_addrule($ruleset, "PVEFW-blacklist", "-j DROP");
> }
> my $ipset_chain = compute_ipset_chain_name(0, 'blacklist',
> $ipversion);
> ruleset_addrule($ruleset, $chain, "-m set --match-set
> ${ipset_chain} src -j PVEFW-blacklist");
> }
[...]
___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH] add log for ipfilter, macfilter && ipv6 router-advertisement

2017-09-07 Thread Tom Weber
Hi Alexandre,

i can test it later, thanks. 2 comments though.

Am Donnerstag, den 07.09.2017, 03:22 +0200 schrieb Alexandre Derumier:
> +my ($ruleset, $chain, $ipversion, $options, $macaddr,
> $ipfilter_ipset, $direction, $vmid) = @_;
> +
> +my $lc_direction = lc($direction);
> +my $loglevel = get_option_log_level($options,
> "log_level_${lc_direction}");

in this function we're only logging for outgoing. it's always
log_level_out if we need it.
 
> - ruleset_addrule($ruleset, $chain, "-m mac ! --mac-
> source 
> $macaddr -j DROP");
> + my $rule = "-m mac ! --mac-source $macaddr";
> + ruleset_addlog($ruleset, $chain, $vmid, "policy DROP: ",
> $loglevel, $rule);
> + ruleset_addrule($ruleset, $chain, "$rule -j DROP");

you are aware that $rule is used elsewhere and in a totally different
way? just look in ruleset_add_group_rule. Thats why I named it
$matchrule initially to avoid confusion.

  Tom
___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH] add log for ipfilter, macfilter && ipv6 router-advertisement

2017-09-07 Thread Tom Weber
Am Donnerstag, den 07.09.2017, 09:30 +0200 schrieb Alexandre DERUMIER:
> > 
> > > 
> > > you are aware that $rule is used elsewhere and in a totally
> > > different 
> > > way? just look in ruleset_add_group_rule. Thats why I named it 
> > > $matchrule initially to avoid confusion. 
> we already used it  like this in:
> 
> 
> 
> sub ruleset_addlog {
>  ...
> $logrule = "$rule $logrule" if defined($rule);
> }
> 
> so I think it's fine.

well.. do a
$ grep '$rule->' Firewall.pm


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH] Firewall Improvements

2017-09-14 Thread Tom Weber
See mail Firewall Improvements

Tom Weber (1):
  prepare code for more generic firewall logging

 src/PVE/Firewall.pm | 168 +++-

 1 file changed, 99 insertions(+), 69 deletions(-)

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] Firewall Improvements

2017-09-14 Thread Tom Weber
Hi all,

last week I reported a problem with firewall logging.
After looking deeper into Firewall.pm I have a better understanding of
the problems I first had with using the Firewall as a rather fresh PVE
User:

- the different levels of log_level_in / out don't make sense to me.
Firewall.pm uses them as boolean to decide wether to log or not. The
level is is never ever used (which i'd expect from the UI and the
docs). Or did I miss something?

- I don't see a clear consistent way on how packets are getting logged
(and in what direction). From a user point of view i was expecting more
logging with increasing log levels up to logging accepted packets for a
loglevel of debug. Now I know that this asumption is wrong.

- Macros can't be edited or extended since they are hardwired in the
code.

- Same for the Standard Set of Rules


I was thinking on how to improve the situation. My first thought was to
give the log_levels a better meaning (like start logging drops at a
certain log_level and accepts a the highest loglevel). But I think,
with lots of chains used by all guests, this is no good approach.


IMHO a flag to toggle logging for a rule or security group in general
would be the most usefull thing to have. This would even make it
possible to log accepted packages.

I'd also like the Idea of having the macro definitions outside the
code, where an admin can change them (same for the standard set of
rules).

But before I start putting too much time into this I'd like to ask for
comments and if there is interest at all :-).


I'll also send a first patch that makes all (except for one place)
iptables rule generation in Firewall.pm differenciate between the match
and the action part of the rule, which gives us one central place to
generate logging rules.
This is meant as an interim patch on the way to the final goal - so
some of the code probably looks clumsy - but the goal was to generate
exactly the same rules as before - which appears to work on my setups
(comparing pve-firewall compile outputs) except for a few additional
spaces sometimes.
And since this is my first patch here, I'd appreciate feedback for the
patch in any case :)

  Tom




___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH] prepare code for more generic firewall logging

2017-09-14 Thread Tom Weber
making ruleset generation aware of a match and action
part in iptable rules.
code will generate the same iptables as before! (except for
a few additional spaces between match and action).
---
 src/PVE/Firewall.pm | 168 +++-
 1 file changed, 99 insertions(+), 69 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index cc81325..61f07e0 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1648,8 +1648,6 @@ sub enable_bridge_firewall {
 $bridge_firewall_enabled = 1;
 }
 
-my $rule_format = "%-15s %-30s %-30s %-15s %-15s %-15s\n";
-
 sub iptables_restore_cmdlist {
 my ($cmdlist) = @_;
 
@@ -1778,7 +1776,7 @@ sub ipset_get_chains {
 return $res;
 }
 
-sub ruleset_generate_cmdstr {
+sub ruleset_generate_match {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
 
 return if defined($rule->{enable}) && !$rule->{enable};
@@ -1909,6 +1907,14 @@ sub ruleset_generate_cmdstr {
 
 push @cmd, "-m addrtype --dst-type $rule->{dsttype}" if $rule->{dsttype};
 
+return scalar(@cmd) ? join(' ', @cmd) : undef;
+}
+
+sub ruleset_generate_action {
+my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
+
+my @cmd = ();
+
 if (my $action = $rule->{action}) {
    $action = $actions->{$action} if defined($actions->{$action});
    $goto = 1 if !defined($goto) && $action eq 'PVEFW-SET-ACCEPT-MARK';
@@ -1918,6 +1924,17 @@ sub ruleset_generate_cmdstr {
 return scalar(@cmd) ? join(' ', @cmd) : undef;
 }
 
+sub ruleset_generate_cmdstr {
+my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
+my $match = ruleset_generate_match($ruleset, $chain, $ipversion, $rule, 
$actions, $goto, $cluster_conf, $fw_conf);
+my $action = ruleset_generate_action($ruleset, $chain, $ipversion, $rule, 
$actions, $goto, $cluster_conf, $fw_conf);
+
+return undef if !(defined($match) or defined($action));
+my $ret = defined($match) ? $match : "";
+$ret = "$ret $action" if defined($action);
+return $ret;
+}
+
 sub ruleset_generate_rule {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
 
@@ -1931,15 +1948,19 @@ sub ruleset_generate_rule {
 
 # update all or nothing
 
-my @cmds = ();
+my @mstrs = ();
+my @astrs = ();
 foreach my $tmp (@$rules) {
-   if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain, $ipversion, 
$tmp, $actions, $goto, $cluster_conf, $fw_conf)) {
-   push @cmds, $cmdstr;
+   my $m = ruleset_generate_match($ruleset, $chain, $ipversion, $tmp, 
$actions, $goto, $cluster_conf, $fw_conf);
+   my $a = ruleset_generate_action($ruleset, $chain, $ipversion, $tmp, 
$actions, $goto, $cluster_conf, $fw_conf);
+   if (defined $m or defined $a) {
+   push @mstrs, defined($m) ? $m : "";
+   push @astrs, defined($a) ? $a : "";
    }
 }
 
-foreach my $cmdstr (@cmds) {
-   ruleset_addrule($ruleset, $chain, $cmdstr);
+for my $i (0 .. $#mstrs) {
+   ruleset_addrule($ruleset, $chain, $mstrs[$i], $astrs[$i]);
 }
 }
 
@@ -1948,8 +1969,10 @@ sub ruleset_generate_rule_insert {
 
 die "implement me" if $rule->{macro}; # not implemented, because not 
needed so far
 
-if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain, $ipversion, 
$rule, $actions, $goto)) {
-   ruleset_insertrule($ruleset, $chain, $cmdstr);
+my $match = ruleset_generate_match($ruleset, $chain, $ipversion, $rule, 
$actions, $goto);
+my $action = ruleset_generate_action($ruleset, $chain, $ipversion, $rule, 
$actions, $goto);
+if (defined $match && defined $action) {
+   ruleset_insertrule($ruleset, $chain, $match, $action);
 }
 }
 
@@ -1970,7 +1993,7 @@ sub ruleset_chain_exist {
 return $ruleset->{$chain} ? 1 : undef;
 }
 
-sub ruleset_addrule {
+sub ruleset_addrule_old {
my ($ruleset, $chain, $rule) = @_;
 
die "no such chain '$chain'\n" if !$ruleset->{$chain};
@@ -1978,12 +2001,20 @@ sub ruleset_addrule {
push @{$ruleset->{$chain}}, "-A $chain $rule";
 }
 
+sub ruleset_addrule {
+   my ($ruleset, $chain, $match, $action, $log) = @_;
+
+   die "no such chain '$chain'\n" if !$ruleset->{$chain};
+
+   push @{$ruleset->{$chain}}, "-A $chain $match $action";
+}
+
 sub ruleset_insertrule {
-   my ($ruleset, $chain, $rule) = @_;
+   my ($ruleset, $chain, $match, $action, $log) = @_;
 
die "no such chain '$chain'\n" if !$ruleset->{$chain};
 
-   unshift @{$ruleset->{$chain}}, "-A $chain $rule";
+   unshift @{$ruleset->{$chain}}, "-A $chain $match $action";
 }
 
 sub get_log_rule_base {
@@ -2000,15 +2031,14 @@ sub get_log_rule_base {
 }
 
 sub ruleset_addlog {
-my ($ruleset, $chain, $vmid, $msg, $loglevel, $rule) = @_;
+my ($ruleset, $chain, $vmid, $msg, $loglevel, $match) = @_;
 
 return if !defined($loglevel);
 
-my $logrule = get_log_rule_ba

Re: [pve-devel] [PATCH] prepare code for more generic firewall logging

2017-09-18 Thread Tom Weber
Am Montag, den 18.09.2017, 12:21 +0200 schrieb Wolfgang Bumiller:
> Improving logging makes sense, the current state might be confuse for
> some (given that drop-rules simply generate a `-j DROP` iptables
> rules
> and therefore don't get logged).
> This seems to be a good first step, although I'd be much happier if
> iptables would allow setting the log-prefix and performing the log
> action separately, then we could simply introduce a log-drop chain
> instead.

well, once we have one single place that actually creates the rules, it
should be way easier to implement there.
My intention is to get away from hardwired "rulegeneration" which we
have in the code on several places to separate ruledefinitions and code
that only generates the rules from that definitions.

> I'm assuming your intention is to be able to duplicate the matching
> part
> of a rule so that you can first add it with `-j NFLOG` and afterwards
> its `-j DROP` action (or whatever action was requested). In this
> case,
> also note that with groups the actions may not be executed
> immediately
> and instead set a mark and return out of the current chain.

yes thats the idea.
And I'm aware of the marks.

> With that in mind, I have no objections to this patch (or a version
> of
> it, see the inline comments below).
> 
> But first things first: please read https://pve.proxmox.com/wiki/Deve
> loper_Documentation
> for details about patches and CLA (which is required for us to apply
> external patches).

Martin already has the signed CLA.

> Also, the spaces in your patch have been replaced by non-breaking-
> space
> characters, causing git-am to fail on it. You should check your
> mailer
> settings to avoid this.

if you don't mind i'll send the next version to you directly just to
let you verify the cosmetic things before cluttering the list again :) 

> On Thu, Sep 14, 2017 at 07:08:54PM +0200, Tom Weber wrote:
> > 
> > making ruleset generation aware of a match and action
> > part in iptable rules.
> > code will generate the same iptables as before! (except for
> > a few additional spaces between match and action).
> Note that these spaces are currently not accepted by the testcases
> and
> requires:
> -$rule =~ s/^-A $chain // || die "got strange rule: $rule";
> +$rule =~ s/^-A $chain +// || die "got strange rule: $rule";
> in FirewallSimulator.pm's rule_match()
> 
> Please use `make check` in the future to check your changes ;-)

To be honest, I didn't catch what the use of FirewallSimumlator
actually was/is :-)
It's not that there's much comments or dokumentation at all.

> > ---
> >  src/PVE/Firewall.pm | 168 +++-
> > 
> >  1 file changed, 99 insertions(+), 69 deletions(-)
> > 
> > diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
> > index cc81325..61f07e0 100644
> > --- a/src/PVE/Firewall.pm
> > +++ b/src/PVE/Firewall.pm
> > @@ -1648,8 +1648,6 @@ sub enable_bridge_firewall {
> >  $bridge_firewall_enabled = 1;
> >  }
> >  
> > -my $rule_format = "%-15s %-30s %-30s %-15s %-15s %-15s\n";
> > -
> Removes an unrelated unused variable. Such cleanups are preferred as
> separate patches.

ok. 
 
> > -my @cmds = ();
> > +my @mstrs = ();
> > +my @astrs = ();
> >  foreach my $tmp (@$rules) {
> > -   if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain,
> > $ipversion, $tmp, $actions, $goto, $cluster_conf, $fw_conf)) {
> > -   push @cmds, $cmdstr;
> > +   my $m = ruleset_generate_match($ruleset, $chain,
> > $ipversion, $tmp, $actions, $goto, $cluster_conf, $fw_conf);
> > +   my $a = ruleset_generate_action($ruleset, $chain,
> > $ipversion, $tmp, $actions, $goto, $cluster_conf, $fw_conf);
> > +   if (defined $m or defined $a) {
> > +   push @mstrs, defined($m) ? $m : "";
> > +   push @astrs, defined($a) ? $a : "";
> While this is all part of a small chunk of code, I'd prefer a single
> array containing pairs of [$match, $action] as elements, rather than
> worrying about future changes possibly bringing @mstrs and @astrs out
> of
> sync.

agreed. I consider this ugly too, but this is code that will probably
be replaced in further steps.
The intention of this patch was to only separate match and action and
show where i'm heading to with as few changes as possible to the actual
logic.

> > -sub ruleset_addrule {
> > +sub ruleset_addrule_old {
> The name suggests that you plan on removing this later on. If this is

yes. Only one place in the code where I couldn't easily split action
from match, hence I had to keep it. Will also be eliminated in a later
step.


thanks for your feedback!
  Tom

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH] prepare code for more generic firewall logging

2017-09-18 Thread Tom Weber
Am Montag, den 18.09.2017, 13:34 +0200 schrieb Dietmar Maurer:
> > 
> > With that in mind, I have no objections to this patch (or a version
> > of
> > it, see the inline comments below).
> But logging all Dropped package would produce an incredible amount of
> logs?

That's why I'd like to have a flag to turn logging on/off for every
single rule, security group, etc..
see my other mail.

  Tom


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH container] Fix restore with multiple mountpoints

2017-09-26 Thread Tom Weber
If you use mountpoints inside a container, and change ownership of
these, a restore of the CT will reset them to root:root again.

That's because the whole CT FS gets prepared and mounted together with
(of course) an owner of root:root for the mp.
As tar uses the option --skip-old-files it won't touch these dirs then.

I don't see why one would need --skip-old-files for a restore job (or
did I miss something?)


Tom Weber (1):
  remove --skip-old-files from tar restore options

 src/PVE/LXC/Create.pm | 5 -
 1 file changed, 5 deletions(-)

-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH container] remove --skip-old-files from tar restore options

2017-09-26 Thread Tom Weber
this breaks ownership of mountpoints in containers
(leaves them at root:root)
---
 src/PVE/LXC/Create.pm | 5 -
 1 file changed, 5 deletions(-)

diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm
index 1f21e06..ac632de 100644
--- a/src/PVE/LXC/Create.pm
+++ b/src/PVE/LXC/Create.pm
@@ -77,11 +77,6 @@ sub restore_archive {
@PVE::Storage::Plugin::COMMON_TAR_FLAGS,
'-C', $rootdir];
 
-# skip-old-files doesn't have anything to do with time (old/new), but is
-# simply -k (annoyingly also called --keep-old-files) without the 'treat
-# existing files as errors' part... iow. it's bsdtar's interpretation of -k
-# *sigh*, gnu...
-push @$cmd, '--skip-old-files';
 push @$cmd, '--anchored';
 push @$cmd, '--exclude' , './dev/*';
 
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 firewall 4/4] convert string based rule definitions to hashes

2017-09-26 Thread Tom Weber
---
 src/PVE/Firewall.pm | 220 
 1 file changed, 117 insertions(+), 103 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index f8a9300..179617a 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -142,6 +142,20 @@ my $log_level_hash = {
 emerg => 0,
 };
 
+# %rule
+#
+# name => optional
+# action =>
+# proto =>
+# sport =>
+# dport =>
+# log => optional, loglevel
+# logmsg => optional, logmsg - overwrites default
+# iface_in
+# iface_out
+# match => optional, overwrites generation of match
+# target => optional, overwrites action
+
 # we need to overwrite some macros for ipv6
 my $pve_ipv6fw_macros = {
 'Ping' => [
@@ -536,7 +550,7 @@ my $FWACCEPTMARK_OFF = "0x/0x8000";
 my $pve_std_chains = {};
 $pve_std_chains->{4} = {
 'PVEFW-SET-ACCEPT-MARK' => [
-   "-j MARK --set-mark $FWACCEPTMARK_ON",
+   { target => "-j MARK --set-mark $FWACCEPTMARK_ON" },
 ],
 'PVEFW-DropBroadcast' => [
# same as shorewall 'Broadcast'
@@ -552,10 +566,10 @@ $pve_std_chains->{4} = {
{ action => 'DROP', dsttype => 'BROADCAST' },
{ action => 'DROP', source => '224.0.0.0/4' },
{ action => 'DROP', proto => 'icmp' },
-   "-p tcp -j REJECT --reject-with tcp-reset",
-   "-p udp -j REJECT --reject-with icmp-port-unreachable",
-   "-p icmp -j REJECT --reject-with icmp-host-unreachable",
-   "-j REJECT --reject-with icmp-host-prohibited",
+   { match => '-p tcp', target => '-j REJECT --reject-with tcp-reset' },
+   { match => '-p udp', target => '-j REJECT --reject-with 
icmp-port-unreachable' },
+   { match => '-p icmp', target => '-j REJECT --reject-with 
icmp-host-unreachable' },
+   { target => '-j REJECT --reject-with icmp-host-prohibited' },
 ],
 'PVEFW-Drop' => [
# same as shorewall 'Drop', which is equal to DROP,
@@ -568,7 +582,7 @@ $pve_std_chains->{4} = {
{ action => 'ACCEPT', proto => 'icmp', dport => 'fragmentation-needed' 
},
{ action => 'ACCEPT', proto => 'icmp', dport => 'time-exceeded' },
# Drop packets with INVALID state
-   "-m conntrack --ctstate INVALID -j DROP",
+   { action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
{ action => 'DROP', proto => 'udp', dport => '135,445', nbdport => 2 },
{ action => 'DROP', proto => 'udp', dport => '137:139'},
@@ -576,7 +590,7 @@ $pve_std_chains->{4} = {
{ action => 'DROP', proto => 'tcp', dport => '135,139,445', nbdport => 
3 },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
-   "-p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -j DROP",
+   { action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
# Drop DNS replies
{ action => 'DROP', proto => 'udp', sport => 53 },
 ],
@@ -591,7 +605,7 @@ $pve_std_chains->{4} = {
{ action => 'ACCEPT', proto => 'icmp', dport => 'fragmentation-needed' 
},
{ action => 'ACCEPT', proto => 'icmp', dport => 'time-exceeded' },
# Drop packets with INVALID state
-   "-m conntrack --ctstate INVALID -j DROP",
+   { action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
{ action => 'PVEFW-reject', proto => 'udp', dport => '135,445', nbdport 
=> 2 },
{ action => 'PVEFW-reject', proto => 'udp', dport => '137:139'},
@@ -599,111 +613,115 @@ $pve_std_chains->{4} = {
{ action => 'PVEFW-reject', proto => 'tcp', dport => '135,139,445', 
nbdport => 3 },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
-   "-p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -j DROP",
+   { action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
# Drop DNS replies
{ action => 'DROP', proto => 'udp', sport => 53 },
 ],
 'PVEFW-tcpflags' => [
# same as shorewall tcpflags action.
# Packets arriving on this interface are checked for som illegal 
combinations of TCP flags
-   "-p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -g 
PVEFW-logflags",
-   "-p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -g 
PVEFW-logflags",
-   "-p tcp -m tcp --tcp-flags SYN,RST SYN,RST -g PVEFW-logflags",
-   "-p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -g PVEFW-logflags",
-   "-p tcp -m tcp --sport 0 --tcp-flags FIN,SYN,RST,ACK SYN -g 
PVEFW-logflags",
+   { match => '-p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG 
FIN,PSH,URG', target => '-g PVEFW-logflags' },
+   { match => '-p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE', 
target => '-g PVEFW-logflags' },
+   { match => '-p tcp -m tcp --tcp-flags SYN,RST SYN,RST', target => '-g 
PVEFW-logflags' },
+   { match => '-p 

[pve-devel] [PATCH v2 firewall 2/4] prepare code for more generic firewall logging

2017-09-26 Thread Tom Weber
making ruleset generation aware of a match and action
part in iptable rules.
code will generate the same iptables as before! (except for
a few additional spaces between match and action).
---
 src/PVE/Firewall.pm  | 166 ++-
 src/PVE/FirewallSimulator.pm |   2 +-
 2 files changed, 100 insertions(+), 68 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 5d78686..f1aecef 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1776,7 +1776,7 @@ sub ipset_get_chains {
 return $res;
 }
 
-sub ruleset_generate_cmdstr {
+sub ruleset_generate_match {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
 
 return if defined($rule->{enable}) && !$rule->{enable};
@@ -1907,6 +1907,14 @@ sub ruleset_generate_cmdstr {
 
 push @cmd, "-m addrtype --dst-type $rule->{dsttype}" if $rule->{dsttype};
 
+return scalar(@cmd) ? join(' ', @cmd) : undef;
+}
+
+sub ruleset_generate_action {
+my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
+
+my @cmd = ();
+
 if (my $action = $rule->{action}) {
$action = $actions->{$action} if defined($actions->{$action});
$goto = 1 if !defined($goto) && $action eq 'PVEFW-SET-ACCEPT-MARK';
@@ -1916,6 +1924,17 @@ sub ruleset_generate_cmdstr {
 return scalar(@cmd) ? join(' ', @cmd) : undef;
 }
 
+sub ruleset_generate_cmdstr {
+my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
+my $match = ruleset_generate_match($ruleset, $chain, $ipversion, $rule, 
$actions, $goto, $cluster_conf, $fw_conf);
+my $action = ruleset_generate_action($ruleset, $chain, $ipversion, $rule, 
$actions, $goto, $cluster_conf, $fw_conf);
+
+return undef if !(defined($match) or defined($action));
+my $ret = defined($match) ? $match : "";
+$ret = "$ret $action" if defined($action);
+return $ret;
+}
+
 sub ruleset_generate_rule {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
 
@@ -1929,15 +1948,19 @@ sub ruleset_generate_rule {
 
 # update all or nothing
 
-my @cmds = ();
+my @mstrs = ();
+my @astrs = ();
 foreach my $tmp (@$rules) {
-   if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain, $ipversion, 
$tmp, $actions, $goto, $cluster_conf, $fw_conf)) {
-   push @cmds, $cmdstr;
+   my $m = ruleset_generate_match($ruleset, $chain, $ipversion, $tmp, 
$actions, $goto, $cluster_conf, $fw_conf);
+   my $a = ruleset_generate_action($ruleset, $chain, $ipversion, $tmp, 
$actions, $goto, $cluster_conf, $fw_conf);
+   if (defined $m or defined $a) {
+   push @mstrs, defined($m) ? $m : "";
+   push @astrs, defined($a) ? $a : "";
}
 }
 
-foreach my $cmdstr (@cmds) {
-   ruleset_addrule($ruleset, $chain, $cmdstr);
+for my $i (0 .. $#mstrs) {
+   ruleset_addrule($ruleset, $chain, $mstrs[$i], $astrs[$i]);
 }
 }
 
@@ -1946,8 +1969,10 @@ sub ruleset_generate_rule_insert {
 
 die "implement me" if $rule->{macro}; # not implemented, because not 
needed so far
 
-if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain, $ipversion, 
$rule, $actions, $goto)) {
-   ruleset_insertrule($ruleset, $chain, $cmdstr);
+my $match = ruleset_generate_match($ruleset, $chain, $ipversion, $rule, 
$actions, $goto);
+my $action = ruleset_generate_action($ruleset, $chain, $ipversion, $rule, 
$actions, $goto);
+if (defined $match && defined $action) {
+   ruleset_insertrule($ruleset, $chain, $match, $action);
 }
 }
 
@@ -1968,7 +1993,7 @@ sub ruleset_chain_exist {
 return $ruleset->{$chain} ? 1 : undef;
 }
 
-sub ruleset_addrule {
+sub ruleset_addrule_old {
my ($ruleset, $chain, $rule) = @_;
 
die "no such chain '$chain'\n" if !$ruleset->{$chain};
@@ -1976,12 +2001,20 @@ sub ruleset_addrule {
push @{$ruleset->{$chain}}, "-A $chain $rule";
 }
 
+sub ruleset_addrule {
+   my ($ruleset, $chain, $match, $action, $log) = @_;
+
+   die "no such chain '$chain'\n" if !$ruleset->{$chain};
+
+   push @{$ruleset->{$chain}}, "-A $chain $match $action";
+}
+
 sub ruleset_insertrule {
-   my ($ruleset, $chain, $rule) = @_;
+   my ($ruleset, $chain, $match, $action, $log) = @_;
 
die "no such chain '$chain'\n" if !$ruleset->{$chain};
 
-   unshift @{$ruleset->{$chain}}, "-A $chain $rule";
+   unshift @{$ruleset->{$chain}}, "-A $chain $match $action";
 }
 
 sub get_log_rule_base {
@@ -1998,15 +2031,14 @@ sub get_log_rule_base {
 }
 
 sub ruleset_addlog {
-my ($ruleset, $chain, $vmid, $msg, $loglevel, $rule) = @_;
+my ($ruleset, $chain, $vmid, $msg, $loglevel, $match) = @_;
 
 return if !defined($loglevel);
 
-my $logrule = get_log_rule_base($chain, $vmid, $msg, $loglevel);
-
-$logrule = "$rule $logrule" if defined($rule);
+my $logaction = get_log_rule_base($chain, $vmid, $msg, $loglevel);
 
-ru

[pve-devel] [PATCH v2 firewall 0/4] Firewall improvements

2017-09-26 Thread Tom Weber
second version, far from finished but trying to reorganize things
without breaking what exists. generates the same rules as before.

feedback welcome.


Tom Weber (4):
  remove unused $rule_format
  prepare code for more generic firewall logging
  integrate logging into ruleset_addrule
  convert string based rule definitions to hashes

 src/PVE/Firewall.pm  | 387 +++
 src/PVE/FirewallSimulator.pm |   2 +-
 2 files changed, 210 insertions(+), 179 deletions(-)

-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 firewall 3/4] integrate logging into ruleset_addrule

2017-09-26 Thread Tom Weber
---
 src/PVE/Firewall.pm | 33 ++---
 1 file changed, 10 insertions(+), 23 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index f1aecef..f8a9300 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -2002,10 +2002,14 @@ sub ruleset_addrule_old {
 }
 
 sub ruleset_addrule {
-   my ($ruleset, $chain, $match, $action, $log) = @_;
+   my ($ruleset, $chain, $match, $action, $log, $logmsg, $vmid) = @_;
 
die "no such chain '$chain'\n" if !$ruleset->{$chain};
 
+   if (defined($log) && $log) {
+   my $logaction = get_log_rule_base($chain, $vmid, $logmsg, $log);
+   push @{$ruleset->{$chain}}, "-A $chain $match $logaction";
+   }
push @{$ruleset->{$chain}}, "-A $chain $match $action";
 }
 
@@ -2020,27 +2024,15 @@ sub ruleset_insertrule {
 sub get_log_rule_base {
 my ($chain, $vmid, $msg, $loglevel) = @_;
 
-die "internal error - no log level" if !defined($loglevel);
-
 $vmid = 0 if !defined($vmid);
+$msg = "" if !defined($msg);
 
 # Note: we use special format for prefix to pass further
-# info to log daemon (VMID, LOGVELEL and CHAIN)
+# info to log daemon (VMID, LOGLEVEL and CHAIN)
 
 return "-j NFLOG --nflog-prefix \":$vmid:$loglevel:$chain: $msg\"";
 }
 
-sub ruleset_addlog {
-my ($ruleset, $chain, $vmid, $msg, $loglevel, $match) = @_;
-
-return if !defined($loglevel);
-
-my $logaction = get_log_rule_base($chain, $vmid, $msg, $loglevel);
-
-$match = "" if !defined $match;
-ruleset_addrule($ruleset, $chain, $match, $logaction);
-}
-
 sub ruleset_add_chain_policy {
 my ($ruleset, $chain, $ipversion, $vmid, $policy, $loglevel, 
$accept_action) = @_;
 
@@ -2053,15 +2045,11 @@ sub ruleset_add_chain_policy {
 
ruleset_addrule($ruleset, $chain, "", "-j PVEFW-Drop");
 
-   ruleset_addlog($ruleset, $chain, $vmid, "policy $policy: ", $loglevel);
-
-   ruleset_addrule($ruleset, $chain, "", "-j DROP");
+   ruleset_addrule($ruleset, $chain, "", "-j DROP", $loglevel, "policy 
$policy: ", $vmid);
 } elsif ($policy eq 'REJECT') {
ruleset_addrule($ruleset, $chain, "", "-j PVEFW-Reject");
 
-   ruleset_addlog($ruleset, $chain, $vmid, "policy $policy: ", $loglevel);
-
-   ruleset_addrule($ruleset, $chain, "", "-g PVEFW-reject");
+   ruleset_addrule($ruleset, $chain, "", "-g PVEFW-reject", $loglevel, 
"policy: $policy", $vmid);
 } else {
# should not happen
die "internal error: unknown policy '$policy'";
@@ -2093,8 +2081,7 @@ sub ruleset_chain_add_input_filters {
 if ($cluster_conf->{ipset}->{blacklist}){
if (!ruleset_chain_exist($ruleset, "PVEFW-blacklist")) {
ruleset_create_chain($ruleset, "PVEFW-blacklist");
-   ruleset_addlog($ruleset, "PVEFW-blacklist", 0, "DROP: ", $loglevel) 
if $loglevel;
-   ruleset_addrule($ruleset, "PVEFW-blacklist", "", "-j DROP");
+   ruleset_addrule($ruleset, "PVEFW-blacklist", "", "-j DROP", 
$loglevel, "DROP: ");
}
my $ipset_chain = compute_ipset_chain_name(0, 'blacklist', $ipversion);
ruleset_addrule($ruleset, $chain, "-m set --match-set ${ipset_chain} 
src", "-j PVEFW-blacklist");
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 firewall 1/4] remove unused $rule_format

2017-09-26 Thread Tom Weber
---
 src/PVE/Firewall.pm | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index cc81325..5d78686 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1648,8 +1648,6 @@ sub enable_bridge_firewall {
 $bridge_firewall_enabled = 1;
 }
 
-my $rule_format = "%-15s %-30s %-30s %-15s %-15s %-15s\n";
-
 sub iptables_restore_cmdlist {
 my ($cmdlist) = @_;
 
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH v2 firewall 4/4] convert string based rule definitions to hashes

2017-09-27 Thread Tom Weber
First of all, this all is work in progress. I thought I commit for
easier understanding of the way i'm heading - instead of one huge
commit which turns everything inside out. and for feedback of course.

My goal are defined structures for rules, chains, macros (which i think
are just arrays of "rule templates") etc and code which deals with
these structures instead of printing out iptables commands in various
places.
While doing this, keeping "input" and "output" identical to whats there
doesn't make this an easy task and therefore I sometimes use these
'temporary ugliness' approaches at places that I intend to replace
anyway.


Am Mittwoch, den 27.09.2017, 09:53 +0200 schrieb Wolfgang Bumiller:
> On Wed, Sep 27, 2017 at 12:02:33AM +0200, Tom Weber wrote:
> > 
> > ---
> >  src/PVE/Firewall.pm | 220 --
> > --
> >  1 file changed, 117 insertions(+), 103 deletions(-)
> > 
> > diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
> > index f8a9300..179617a 100644
> > --- a/src/PVE/Firewall.pm
> > +++ b/src/PVE/Firewall.pm
> > @@ -142,6 +142,20 @@ my $log_level_hash = {
> >  emerg => 0,
> >  };
> >  
> > +# %rule
> > +#
> +1 for the documentation, but what happened to the right sides of
> most
> of these arrows? ;-) (yeah some of these options are being abused a
> bit...)

still in the progress of defining this :-).. Right now it's more like a
scratchpad where I collect what I encounter.

> > +# name => optional
> > +# action =>
> > +# proto =>
> > +# sport =>
> > +# dport =>
> > +# log => optional, loglevel
> Why not call it loglevel then? Also, with this being new it should be
> mentioned in the commit message.

this is for now and for backward compatibility. I'd prefer this as a
boolean, but I'm still carrying the loglevel around since it's used in
the frontend and the logformat for the pvefw-logger.

Do we really need the loglevel as it is or would a boolean be
sufficient? And how would we get rid of it? 

> > +# logmsg => optional, logmsg - overwrites default
> And this.
> > 
> > +# iface_in
> > +# iface_out
> > +# match => optional, overwrites generation of match
> > +# target => optional, overwrites action
> > +
> >  # we need to overwrite some macros for ipv6
> >  my $pve_ipv6fw_macros = {
> >  'Ping' => [
> > @@ -536,7 +550,7 @@ my $FWACCEPTMARK_OFF = "0x/0x8000";
> 
> 
> > 
> > @@ -1948,19 +1970,24 @@ sub ruleset_generate_rule {
> >  
> >  # update all or nothing
> >  
> > +# fixme: lots of temporary ugliness
> +1 for the 'temporary' in there ;-)
> 
> > 
> >  my @mstrs = ();
> >  my @astrs = ();
> > +my @logging = ();
> > +my @logmsg = ();
> >  foreach my $tmp (@$rules) {
> >     my $m = ruleset_generate_match($ruleset, $chain,
> > $ipversion, $tmp, $actions, $goto, $cluster_conf, $fw_conf);
> >     my $a = ruleset_generate_action($ruleset, $chain,
> > $ipversion, $tmp, $actions, $goto, $cluster_conf, $fw_conf);
> >     if (defined $m or defined $a) {
> >     push @mstrs, defined($m) ? $m : "";
> >     push @astrs, defined($a) ? $a : "";
> > +   push @logging, $tmp->{log};
> > +   push @logmsg, $tmp->{logmsg};
> >     }
> >  }
> >  
> >  for my $i (0 .. $#mstrs) {
> > -   ruleset_addrule($ruleset, $chain, $mstrs[$i], $astrs[$i]);
> > +   ruleset_addrule($ruleset, $chain, $mstrs[$i], $astrs[$i],
> > $logging[$i], $logmsg[$i]);
> >  }
> >  }
> >  
> > @@ -1993,14 +2020,6 @@ sub ruleset_chain_exist {
> >  return $ruleset->{$chain} ? 1 : undef;
> >  }
> >  
> > -sub ruleset_addrule_old {
> > -   my ($ruleset, $chain, $rule) = @_;
> > -
> > -   die "no such chain '$chain'\n" if !$ruleset->{$chain};
> > -
> > -   push @{$ruleset->{$chain}}, "-A $chain $rule";
> > -}
> > -
> >  sub ruleset_addrule {
> > my ($ruleset, $chain, $match, $action, $log, $logmsg, $vmid) =
> > @_;
> >  
> > @@ -3127,26 +3146,21 @@ sub generate_std_chains {
> >  my $std_chains = $pve_std_chains->{$ipversion} || die
> > "internal error";
> >  
> >  my $loglevel = get_option_log_level($options,
> > 'smurf_log_level');
> > -
> > -my $chain;
> > -
> > -if ($ipversion == 4) {
> > -   # same as shorewall

Re: [pve-devel] [PATCH v2 firewall 4/4] convert string based rule definitions to hashes

2017-09-27 Thread Tom Weber
Am Mittwoch, den 27.09.2017, 11:53 +0200 schrieb Wolfgang Bumiller:
> On Wed, Sep 27, 2017 at 12:02:33AM +0200, Tom Weber wrote:
> > 
> > ---
> > +'PVEFW-smurflog' => [
> > +   { action => 'DROP', logmsg => 'DROP: ' },
> > +],
> > +'PVEFW-logflags' => [
> > +   { action => 'DROP', logmsg => 'DROP: ' },
> >  ],
> >  };
> 
> Just noticed this is missing in the ipv6 part below it (my ip6tables
> aren't updating anymore).

yes, missed it. but only the PVEFW-logflags? smurflog has never been
part of ipv6.

  Tom
___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH v2 firewall 4/4] convert string based rule definitions to hashes

2017-09-27 Thread Tom Weber
Am Mittwoch, den 27.09.2017, 11:51 +0200 schrieb Wolfgang Bumiller:
> On Wed, Sep 27, 2017 at 11:09:29AM +0200, Tom Weber wrote:
> > 
> > My goal are defined structures for rules, chains, macros (which i
> > think
> > are just arrays of "rule templates") etc and code which deals with
> > these structures instead of printing out iptables commands in
> > various
> > places.
> That's long overdue anyway and might be useful later on when we want
> to
> start using nftables.
> 
> > 
> > While doing this, keeping "input" and "output" identical to whats
> > there
> > doesn't make this an easy task and therefore I sometimes use these
> > 'temporary ugliness' approaches at places that I intend to replace
> > anyway.
> That's fine.
> 
> > 
> > > 
> > > > 
> > > > @@ -3127,26 +3146,21 @@ sub generate_std_chains {
> > > >  my $std_chains = $pve_std_chains->{$ipversion} || die
> > > > "internal error";
> > > >  
> > > >  my $loglevel = get_option_log_level($options,
> > > > 'smurf_log_level');
> > > > -
> > > > -my $chain;
> > > > -
> > > > -if ($ipversion == 4) {
> > > > -   # same as shorewall smurflog.
> > > > -   $chain = 'PVEFW-smurflog';
> > > > -   $std_chains->{$chain} = [];
> > > > -   
> > > > -   push @{$std_chains->{$chain}},
> > > > get_log_rule_base($chain,
> > > > 0, "DROP: ", $loglevel) if $loglevel;
> > > > -   push @{$std_chains->{$chain}}, "-j DROP";
> > > > +my $chain = 'PVEFW-smurflog';
> > > > +if ( $loglevel && $std_chains->{$chain} ) {
> > > This shouldn't check for $loglevel as it can also have changed
> > > from
> > > non-zero to zero in which case the change would happen. Iow. you
> > > cannot
> > > turn off the smurf logs anymore.
> > huh? if $loglevel == 0 it will not turn on logging.
> This modifies the fields in the global $pve_std_chains, so it doesn't
> need to not turn it on, it needs to turn if off. Such modifications
> are
> something I'd prefer to reduce if possible.

yes you're right - didn't look at it as running service.
so, the ultimate solution would be to have the std_chains template
defined in external config files (which i have in mind from the
beginning) from which we'll generate our working internal tree which
we'd then manipulate according to various settings?

> > > > +   foreach my $r (@{$std_chains->{$chain}}) {
> > > > +     $r->{log} = $loglevel;
> > > Wouldn't it be better to just give ruleset_generate_rule an
> > > optional
> > > default loglevel parameter for when rules don't define their own
> > > {log}?
> > how would this help with turning smurf / tcpflags logging
> > separately on
> > and off then? (not that I like the current way of setting these -
> > but
> > that's what's in the frontend right now)
> Could be passed depending on $chain in the loop below, then we could
> avoid touching the global hashes entirely.
> The function would still prefer the rule's ->{log} member over the
> default if it exists.

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v3 firewall 08/13] implement ipt_rule_to_cmds, ruleset_add_ipt_cmd

2017-10-09 Thread Tom Weber
ipt_rule_to_cmds converts a %rule to an array of iptables commands
ruleset_add_ipt_cmd adds such an iptables command to a chain
ruleset_generate_rule uses these now
ruleset_generate_rule_old is an interim workaround
---
 src/PVE/Firewall.pm | 151 
 1 file changed, 140 insertions(+), 11 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 89a8ef3..b492086 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -146,14 +146,15 @@ my $log_level_hash = {
 # %rule
 #
 # name => optional
+# enable => [0|1]
 # action =>
 # proto =>
-# sport =>
-# dport =>
+# sport => port[,port[,port]].. or port:port
+# dport => port[,port[,port]].. or port:port
 # log => optional, loglevel
 # logmsg => optional, logmsg - overwrites default
-# iface_in
-# iface_out
+# iface_in => incomin interface
+# iface_out => outgoing interface
 # match => optional, overwrites generation of match
 # target => optional, overwrites action
 
@@ -1844,6 +1845,104 @@ sub ipt_gen_src_or_dst_match {
 return $match;
 }
 
+# convert a %rule to an array of iptables commands
+sub ipt_rule_to_cmds {
+my ($rule, $chain, $ipversion, $cluster_conf, $fw_conf, $vmid) = @_;
+
+die "ipt_rule_to_cmds unable to handle macro" if $rule->{macro}; #should 
not happen
+
+my @match = ();
+
+if (defined $rule->{match}) {
+   push @match, $rule->{match};
+} else {
+   push @match, "-i $rule->{iface_in}" if $rule->{iface_in};
+   push @match, "-o $rule->{iface_out}" if $rule->{iface_out};
+
+   if ($rule->{source}) {
+   push @match, ipt_gen_src_or_dst_match($rule->{source}, 's', 
$ipversion, $cluster_conf, $fw_conf);
+   }
+   if ($rule->{dest}) {
+   push @match, ipt_gen_src_or_dst_match($rule->{dest}, 'd', 
$ipversion, $cluster_conf, $fw_conf);
+   }
+
+   if (my $proto = $rule->{proto}) {
+   push @match, "-p $proto";
+
+   my $nbdport = defined($rule->{dport}) ? 
parse_port_name_number_or_range($rule->{dport}, 1) : 0;
+   my $nbsport = defined($rule->{sport}) ? 
parse_port_name_number_or_range($rule->{sport}, 0) : 0;
+
+   my $multiport = 0;
+   $multiport++ if $nbdport > 1;
+   $multiport++ if $nbsport > 1;
+
+   push @match, "--match multiport" if $multiport;
+
+   die "multiport: option '--sports' cannot be used together with 
'--dports'\n"
+   if ($multiport == 2) && ($rule->{dport} ne $rule->{sport});
+
+   if ($rule->{dport}) {
+   if ($proto eq 'icmp') {
+   # Note: we use dport to store --icmp-type
+   die "unknown icmp-type '$rule->{dport}'\n"
+   if $rule->{dport} !~ /^\d+$/ && 
!defined($icmp_type_names->{$rule->{dport}});
+   push @match, "-m icmp --icmp-type $rule->{dport}";
+   } elsif ($proto eq 'icmpv6') {
+   # Note: we use dport to store --icmpv6-type
+   die "unknown icmpv6-type '$rule->{dport}'\n"
+   if $rule->{dport} !~ /^\d+$/ && 
!defined($icmpv6_type_names->{$rule->{dport}});
+   push @match, "-m icmpv6 --icmpv6-type $rule->{dport}";
+   } elsif (!$PROTOCOLS_WITH_PORTS->{$proto}) {
+   die "protocol $proto does not have ports\n";
+   } else {
+   if ($nbdport > 1) {
+   if ($multiport == 2) {
+   push @match,  "--ports $rule->{dport}";
+   } else {
+   push @match, "--dports $rule->{dport}";
+   }
+   } else {
+   push @match, "--dport $rule->{dport}";
+   }
+   }
+   }
+
+   if ($rule->{sport}) {
+   die "protocol $proto does not have ports\n"
+   if !$PROTOCOLS_WITH_PORTS->{$proto};
+   if ($nbsport > 1) {
+   push @match, "--sports $rule->{sport}" if $multiport != 2;
+   } else {
+   push @match, "--sport $rule->{sport}";
+   }
+   }
+   } elsif ($rule->{dport} || $rule->{sport}) {
+   die "destination port '$rule->{dport}', but no protocol 
specified\n" if $rule->{dport};
+   die "source port '$rule->{sport}', but no protocol specified\n" if 
$rule->{sport};
+   }
+
+   push @match, "-m addrtype --dst-type $rule->{dsttype}" if 
$rule->{dsttype};
+}
+my $matchstr = scalar(@match) ? join(' ', @match) : "";
+
+my $targetstr;
+if (defined $rule->{target}) {
+   $targetstr = $rule->{target};
+} else {
+   my $action = (defined $rule->{action}) ? $rule->{action} : "";
+   my $goto = 1 if $action eq 'PVEFW-SET-ACCEPT-MARK';
+   $targetstr = ($goto) ? "-g $action" : "-j $action";
+}
+
+my @iptcmds;
+if (defined $rule->{log} && $rule->{log}) {

[pve-devel] [PATCH v3 firewall 12/13] remove unused ruleset_generate_rule_insert

2017-10-09 Thread Tom Weber
---
 src/PVE/Firewall.pm | 12 
 1 file changed, 12 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index d249f7a..65ea132 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -2070,18 +2070,6 @@ sub ruleset_generate_rule {
 }
 }
 
-sub ruleset_generate_rule_insert {
-my ($ruleset, $chain, $ipversion, $rule, $actions, $goto) = @_;
-
-die "implement me" if $rule->{macro}; # not implemented, because not 
needed so far
-
-my $match = ruleset_generate_match($ruleset, $chain, $ipversion, $rule, 
$actions, $goto);
-my $action = ruleset_generate_action($ruleset, $chain, $ipversion, $rule, 
$actions, $goto);
-if (defined $match && defined $action) {
-   ruleset_insertrule($ruleset, $chain, $match, $action);
-}
-}
-
 sub ruleset_create_chain {
 my ($ruleset, $chain) = @_;
 
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v3 firewall 13/13] remove ruleset_generate_match, ruleset_generate_action

2017-10-09 Thread Tom Weber
ruleset_generate_match and ruleset_generate_action not used anymore
---
 src/PVE/Firewall.pm | 97 -
 1 file changed, 97 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 65ea132..9b78acb 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1952,103 +1952,6 @@ sub ipt_rule_to_cmds {
 return @iptcmds;
 }
 
-sub ruleset_generate_match {
-my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
-
-return if defined($rule->{enable}) && !$rule->{enable};
-return if $rule->{errors};
-
-return $rule->{match} if defined $rule->{match};
-
-die "unable to emit macro - internal error" if $rule->{macro}; # should 
not happen
-
-my $nbdport = defined($rule->{dport}) ? 
parse_port_name_number_or_range($rule->{dport}, 1) : 0;
-my $nbsport = defined($rule->{sport}) ? 
parse_port_name_number_or_range($rule->{sport}, 0) : 0;
-
-my @cmd = ();
-
-push @cmd, "-i $rule->{iface_in}" if $rule->{iface_in};
-push @cmd, "-o $rule->{iface_out}" if $rule->{iface_out};
-
-my $source = $rule->{source};
-my $dest = $rule->{dest};
-
-push @cmd, ipt_gen_src_or_dst_match($source, 's', $ipversion, 
$cluster_conf, $fw_conf) if $source;
-push @cmd, ipt_gen_src_or_dst_match($dest, 'd', $ipversion, $cluster_conf, 
$fw_conf) if $dest;
-
-if (my $proto = $rule->{proto}) {
-   push @cmd, "-p $proto";
-
-   my $multiport = 0;
-   $multiport++ if $nbdport > 1;
-   $multiport++ if $nbsport > 1;
-
-   push @cmd, "--match multiport" if $multiport;
-
-   die "multiport: option '--sports' cannot be used together with 
'--dports'\n"
-   if ($multiport == 2) && ($rule->{dport} ne $rule->{sport});
-
-   if ($rule->{dport}) {
-   if ($proto eq 'icmp') {
-   # Note: we use dport to store --icmp-type
-   die "unknown icmp-type '$rule->{dport}'\n"
-   if $rule->{dport} !~ /^\d+$/ && 
!defined($icmp_type_names->{$rule->{dport}});
-   push @cmd, "-m icmp --icmp-type $rule->{dport}";
-   } elsif ($proto eq 'icmpv6') {
-   # Note: we use dport to store --icmpv6-type
-   die "unknown icmpv6-type '$rule->{dport}'\n"
-   if $rule->{dport} !~ /^\d+$/ && 
!defined($icmpv6_type_names->{$rule->{dport}});
-   push @cmd, "-m icmpv6 --icmpv6-type $rule->{dport}";
-   } elsif (!$PROTOCOLS_WITH_PORTS->{$proto}) {
-   die "protocol $proto does not have ports\n";
-   } else {
-   if ($nbdport > 1) {
-   if ($multiport == 2) {
-   push @cmd,  "--ports $rule->{dport}";
-   } else {
-   push @cmd, "--dports $rule->{dport}";
-   }
-   } else {
-   push @cmd, "--dport $rule->{dport}";
-   }
-   }
-   }
-
-   if ($rule->{sport}) {
-   die "protocol $proto does not have ports\n"
-if !$PROTOCOLS_WITH_PORTS->{$proto};
-   if ($nbsport > 1) {
-   push @cmd, "--sports $rule->{sport}" if $multiport != 2;
-   } else {
-   push @cmd, "--sport $rule->{sport}";
-   }
-   }
-} elsif ($rule->{dport} || $rule->{sport}) {
-   die "destination port '$rule->{dport}', but no protocol specified\n" if 
$rule->{dport};
-   die "source port '$rule->{sport}', but no protocol specified\n" if 
$rule->{sport};
-}
-
-push @cmd, "-m addrtype --dst-type $rule->{dsttype}" if $rule->{dsttype};
-
-return scalar(@cmd) ? join(' ', @cmd) : undef;
-}
-
-sub ruleset_generate_action {
-my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
-
-return $rule->{target} if defined $rule->{target};
-
-my @cmd = ();
-
-if (my $action = $rule->{action}) {
-   $action = $actions->{$action} if defined($actions->{$action});
-   $goto = 1 if !defined($goto) && $action eq 'PVEFW-SET-ACCEPT-MARK';
-   push @cmd, $goto ? "-g $action" : "-j $action";
-}
-
-return scalar(@cmd) ? join(' ', @cmd) : undef;
-}
-
 sub ruleset_generate_rule {
 my ($ruleset, $chain, $ipversion, $rule, $cluster_conf, $fw_conf) = @_;
 
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v3 firewall 10/13] rule_substitude_action, remove ruleset_generate_rule_old

2017-10-09 Thread Tom Weber
implement rule_substitude_action
eliminate use of ruleset_genereate_rule_old and remove it
---
 src/PVE/Firewall.pm | 73 ++---
 1 file changed, 24 insertions(+), 49 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 633aa7a..d9c2347 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1800,6 +1800,15 @@ sub ipset_get_chains {
 return $res;
 }
 
+# substitude action of rule according to action hash
+sub rule_substitude_action {
+my ($rule, $actions) = @_;
+
+if (my $action = $rule->{action}) {
+   $rule->{action} = $actions->{$action} if defined($actions->{$action});
+}  
+}
+
 # generate a src or dst match
 # $dir(ection) is either d or s
 sub ipt_gen_src_or_dst_match {
@@ -2061,40 +2070,6 @@ sub ruleset_generate_rule {
 }
 }
 
-sub ruleset_generate_rule_old {
-my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
-
-my $rules;
-
-if ($rule->{macro}) {
-   $rules = &$apply_macro($rule->{macro}, $rule, 0, $ipversion);
-} else {
-   $rules = [ $rule ];
-}
-
-# update all or nothing
-
-# fixme: lots of temporary ugliness
-my @mstrs = ();
-my @astrs = ();
-my @logging = ();
-my @logmsg = ();
-foreach my $tmp (@$rules) {
-   my $m = ruleset_generate_match($ruleset, $chain, $ipversion, $tmp, 
$actions, $goto, $cluster_conf, $fw_conf);
-   my $a = ruleset_generate_action($ruleset, $chain, $ipversion, $tmp, 
$actions, $goto, $cluster_conf, $fw_conf);
-   if (defined $m or defined $a) {
-   push @mstrs, defined($m) ? $m : "";
-   push @astrs, defined($a) ? $a : "";
-   push @logging, $tmp->{log};
-   push @logmsg, $tmp->{logmsg};
-   }
-}
-
-for my $i (0 .. $#mstrs) {
-   ruleset_addrule($ruleset, $chain, $mstrs[$i], $astrs[$i], $logging[$i], 
$logmsg[$i]);
-}
-}
-
 sub ruleset_generate_rule_insert {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto) = @_;
 
@@ -2170,8 +2145,9 @@ sub ruleset_add_chain_policy {
 
 if ($policy eq 'ACCEPT') {
 
-   ruleset_generate_rule_old($ruleset, $chain, $ipversion, { action => 
'ACCEPT' },
- { ACCEPT =>  $accept_action});
+   my $rule = { action => 'ACCEPT' };
+   rule_substitude_action($rule, { ACCEPT =>  $accept_action});
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule);
 
 } elsif ($policy eq 'DROP') {
 
@@ -2317,12 +2293,12 @@ sub ruleset_generate_vm_rules {
next if $rule->{type} ne $lc_direction;
eval {
if ($direction eq 'OUT') {
-   ruleset_generate_rule_old($ruleset, $chain, $ipversion, 
$rule,
- { ACCEPT => "PVEFW-SET-ACCEPT-MARK", 
REJECT => "PVEFW-reject" },
+   rule_substitude_action($rule, { ACCEPT => 
"PVEFW-SET-ACCEPT-MARK", REJECT => "PVEFW-reject" });
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
  undef, $cluster_conf, $vmfw_conf);
} else {
-   ruleset_generate_rule_old($ruleset, $chain, $ipversion, 
$rule,
- { ACCEPT => $in_accept , REJECT => 
"PVEFW-reject" },
+   rule_substitude_action($rule, { ACCEPT => $in_accept , 
REJECT => "PVEFW-reject" });
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
  undef, $cluster_conf, $vmfw_conf);
}
};
@@ -2451,8 +2427,8 @@ sub enable_host_firewall {
if ($rule->{type} eq 'group') {
ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, 
'IN', $accept_action, $ipversion);
} elsif ($rule->{type} eq 'in') {
-   ruleset_generate_rule_old($ruleset, $chain, $ipversion, $rule,
- { ACCEPT => $accept_action, REJECT => 
"PVEFW-reject" },
+   rule_substitude_action($rule, { ACCEPT => $accept_action, 
REJECT => "PVEFW-reject" });
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
  undef, $cluster_conf, $hostfw_conf);
}
};
@@ -2508,8 +2484,8 @@ sub enable_host_firewall {
if ($rule->{type} eq 'group') {
ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, 
'OUT', $accept_action, $ipversion);
} elsif ($rule->{type} eq 'out') {
-   ruleset_generate_rule_old($ruleset, $chain, $ipversion,
- $rule, { ACCEPT => $accept_action, REJECT 
=> "PVEFW-reject" },
+   rule_substitude_action($rule, { ACCEPT => $accept_action, 
REJECT => "PVEFW-reject" });
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
 

[pve-devel] [PATCH v3 firewall 09/13] remove unused ruleset_generate_cmdstr

2017-10-09 Thread Tom Weber
---
 src/PVE/Firewall.pm | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index b492086..633aa7a 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -2040,17 +2040,6 @@ sub ruleset_generate_action {
 return scalar(@cmd) ? join(' ', @cmd) : undef;
 }
 
-sub ruleset_generate_cmdstr {
-my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
-my $match = ruleset_generate_match($ruleset, $chain, $ipversion, $rule, 
$actions, $goto, $cluster_conf, $fw_conf);
-my $action = ruleset_generate_action($ruleset, $chain, $ipversion, $rule, 
$actions, $goto, $cluster_conf, $fw_conf);
-
-return undef if !(defined($match) or defined($action));
-my $ret = defined($match) ? $match : "";
-$ret = "$ret $action" if defined($action);
-return $ret;
-}
-
 sub ruleset_generate_rule {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
 
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v3 firewall 00/13] Firewall code cleanups

2017-10-09 Thread Tom Weber
third version. mostly converting rules into structures.
reorganized ruleset_generate_rule and everything around it.
please note that some of the stuff implemented in the first patches
gets eliminated later. So maybe it's worth reading all patches before
flaming me ;-)


Tom Weber (13):
  remove unused $rule_format
  prepare code for more generic firewall logging
  integrate logging into ruleset_addrule
  convert string based rule definitions to hashes
  make $pve_std_chains a copy of $pve_std_chains_conf
  eliminate unused nbdport in pve_std_chains_conf
  iptables address matching in own subroutine
  implement ipt_rule_to_cmds, ruleset_add_ipt_cmd
  remove unused ruleset_generate_cmdstr
  rule_substitude_action, remove ruleset_generate_rule_old
  cleanup parameters to ruleset_generate_rule
  remove unused ruleset_generate_rule_insert
  remove ruleset_generate_match, ruleset_generate_action

 src/PVE/Firewall.pm  | 674 ++-
 src/PVE/FirewallSimulator.pm |   2 +-
 2 files changed, 342 insertions(+), 334 deletions(-)

-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v3 firewall 06/13] eliminate unused nbdport in pve_std_chains_conf

2017-10-09 Thread Tom Weber
---
 src/PVE/Firewall.pm | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index c7ddd10..f009e58 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -586,10 +586,10 @@ $pve_std_chains_conf->{4} = {
# Drop packets with INVALID state
{ action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
-   { action => 'DROP', proto => 'udp', dport => '135,445', nbdport => 2 },
-   { action => 'DROP', proto => 'udp', dport => '137:139'},
+   { action => 'DROP', proto => 'udp', dport => '135,445' },
+   { action => 'DROP', proto => 'udp', dport => '137:139' },
{ action => 'DROP', proto => 'udp', dport => '1024:65535', sport => 137 
},
-   { action => 'DROP', proto => 'tcp', dport => '135,139,445', nbdport => 
3 },
+   { action => 'DROP', proto => 'tcp', dport => '135,139,445' },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
{ action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
@@ -609,10 +609,10 @@ $pve_std_chains_conf->{4} = {
# Drop packets with INVALID state
{ action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
-   { action => 'PVEFW-reject', proto => 'udp', dport => '135,445', nbdport 
=> 2 },
+   { action => 'PVEFW-reject', proto => 'udp', dport => '135,445' },
{ action => 'PVEFW-reject', proto => 'udp', dport => '137:139'},
{ action => 'PVEFW-reject', proto => 'udp', dport => '1024:65535', 
sport => 137 },
-   { action => 'PVEFW-reject', proto => 'tcp', dport => '135,139,445', 
nbdport => 3 },
+   { action => 'PVEFW-reject', proto => 'tcp', dport => '135,139,445' },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
{ action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
@@ -682,10 +682,10 @@ $pve_std_chains_conf->{6} = {
# Drop packets with INVALID state
{ action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
-   { action => 'DROP', proto => 'udp', dport => '135,445', nbdport => 2 },
+   { action => 'DROP', proto => 'udp', dport => '135,445' },
{ action => 'DROP', proto => 'udp', dport => '137:139'},
{ action => 'DROP', proto => 'udp', dport => '1024:65535', sport => 137 
},
-   { action => 'DROP', proto => 'tcp', dport => '135,139,445', nbdport => 
3 },
+   { action => 'DROP', proto => 'tcp', dport => '135,139,445' },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
{ action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
@@ -706,10 +706,10 @@ $pve_std_chains_conf->{6} = {
# Drop packets with INVALID state
{ action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
-   { action => 'PVEFW-reject', proto => 'udp', dport => '135,445', nbdport 
=> 2 },
-   { action => 'PVEFW-reject', proto => 'udp', dport => '137:139'},
+   { action => 'PVEFW-reject', proto => 'udp', dport => '135,445' },
+   { action => 'PVEFW-reject', proto => 'udp', dport => '137:139' },
{ action => 'PVEFW-reject', proto => 'udp', dport => '1024:65535', 
sport => 137 },
-   { action => 'PVEFW-reject', proto => 'tcp', dport => '135,139,445', 
nbdport => 3 },
+   { action => 'PVEFW-reject', proto => 'tcp', dport => '135,139,445' },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
{ action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v3 firewall 07/13] iptables address matching in own subroutine

2017-10-09 Thread Tom Weber
put generation of iptables source/destination address matching
in own subroutine and use this in ruleset_generate_match
---
 src/PVE/Firewall.pm | 104 
 1 file changed, 47 insertions(+), 57 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index f009e58..89a8ef3 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1799,6 +1799,51 @@ sub ipset_get_chains {
 return $res;
 }
 
+# generate a src or dst match
+# $dir(ection) is either d or s
+sub ipt_gen_src_or_dst_match {
+my ($adr, $dir, $ipversion, $cluster_conf, $fw_conf) = @_;
+
+my $srcdst;
+if ($dir eq 's') {
+   $srcdst = "src";
+} elsif ($dir eq 'd') {
+   $srcdst = "dst";
+} else {
+   die "ipt_gen_src_or_dst_match: invalid direction $dir \n";
+}
+
+my $match;
+if ($adr =~ m/^\+/) {
+   if ($adr =~ m/^\+(${ipset_name_pattern})$/) {
+   my $name = $1;
+   my $ipset_chain;
+   if ($fw_conf && $fw_conf->{ipset}->{$name}) {
+   $ipset_chain = compute_ipset_chain_name($fw_conf->{vmid}, 
$name, $ipversion);
+   } elsif ($cluster_conf && $cluster_conf->{ipset}->{$name}) {
+   $ipset_chain = compute_ipset_chain_name(0, $name, $ipversion);
+   } else {
+   die "no such ipset '$name'\n";
+   }
+   $match = "-m set --match-set ${ipset_chain} ${srcdst}";
+   } else {
+   die "invalid security group name '$adr'\n";
+   }
+} elsif ($adr =~ m/^${ip_alias_pattern}$/){
+   my $alias = lc($adr);
+   my $e = $fw_conf ? $fw_conf->{aliases}->{$alias} : undef;
+   $e = $cluster_conf->{aliases}->{$alias} if !$e && $cluster_conf;
+   die "no such alias '$adr'\n" if !$e;
+   $match = "-${dir} $e->{cidr}";
+} elsif ($adr =~ m/\-/){
+   $match = "-m iprange --${srcdst}-range $adr";
+} else {
+   $match = "-${dir} $adr";
+}
+
+return $match;
+}
+
 sub ruleset_generate_match {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
 
@@ -1820,63 +1865,8 @@ sub ruleset_generate_match {
 my $source = $rule->{source};
 my $dest = $rule->{dest};
 
-if ($source) {
-if ($source =~ m/^\+/) {
-   if ($source =~ m/^\+(${ipset_name_pattern})$/) {
-   my $name = $1;
-   if ($fw_conf && $fw_conf->{ipset}->{$name}) {
-   my $ipset_chain = 
compute_ipset_chain_name($fw_conf->{vmid}, $name, $ipversion);
-   push @cmd, "-m set --match-set ${ipset_chain} src";
-   } elsif ($cluster_conf && $cluster_conf->{ipset}->{$name}) {
-   my $ipset_chain = compute_ipset_chain_name(0, $name, 
$ipversion);
-   push @cmd, "-m set --match-set ${ipset_chain} src";
-   } else {
-   die "no such ipset '$name'\n";
-   }
-   } else {
-   die "invalid security group name '$source'\n";
-   }
-   } elsif ($source =~ m/^${ip_alias_pattern}$/){
-   my $alias = lc($source);
-   my $e = $fw_conf ? $fw_conf->{aliases}->{$alias} : undef;
-   $e = $cluster_conf->{aliases}->{$alias} if !$e && $cluster_conf;
-   die "no such alias '$source'\n" if !$e;
-   push @cmd, "-s $e->{cidr}";
-} elsif ($source =~ m/\-/){
-   push @cmd, "-m iprange --src-range $source";
-   } else {
-   push @cmd, "-s $source";
-}
-}
-
-if ($dest) {
-if ($dest =~ m/^\+/) {
-   if ($dest =~ m/^\+(${ipset_name_pattern})$/) {
-   my $name = $1;
-   if ($fw_conf && $fw_conf->{ipset}->{$name}) {
-   my $ipset_chain = 
compute_ipset_chain_name($fw_conf->{vmid}, $name, $ipversion);
-   push @cmd, "-m set --match-set ${ipset_chain} dst";
-   } elsif ($cluster_conf && $cluster_conf->{ipset}->{$name}) {
-   my $ipset_chain = compute_ipset_chain_name(0, $name, 
$ipversion);
-   push @cmd, "-m set --match-set ${ipset_chain} dst";
-   } else {
-   die "no such ipset '$name'\n";
-   }
-   } else {
-   die "invalid security group name '$dest'\n";
-   }
-   } elsif ($dest =~ m/^${ip_alias_pattern}$/){
-   my $alias = lc($dest);
-   my $e = $fw_conf ? $fw_conf->{aliases}->{$alias} : undef;
-   $e = $cluster_conf->{aliases}->{$alias} if !$e && $cluster_conf;
-   die "no such alias '$dest'\n" if !$e;
-   push @cmd, "-d $e->{cidr}";
-} elsif ($dest =~ 
m/^(\d+)\.(\d+).(\d+).(\d+)\-(\d+)\.(\d+).(\d+).(\d+)$/){
-   push @cmd, "-m iprange --dst-range $dest";
-   } else {
-   push @cmd, "-d $dest";
-}
-}
+push @cmd, ipt_gen_src_or_dst_match($source, 's', $ipversion, 
$cluster_conf, $fw_conf) if $source;
+pus

[pve-devel] [PATCH v3 firewall 05/13] make $pve_std_chains a copy of $pve_std_chains_conf

2017-10-09 Thread Tom Weber
create a new $pve_std_chains with $pve_std_chains_conf as template on
every compilation of the rules. This avoids persitant changes to the
$pve_std_chains and makes it easier to read the std_chains configuration
from external config files (later to implement).
---
 src/PVE/Firewall.pm | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 634ff90..c7ddd10 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -20,6 +20,7 @@ use IO::File;
 use Net::IP;
 use PVE::Tools qw(run_command lock_file dir_glob_foreach);
 use Encode;
+use Storable qw(dclone);
 
 my $hostfw_conf_filename = "/etc/pve/local/host.fw";
 my $pvefw_conf_dir = "/etc/pve/firewall";
@@ -548,7 +549,8 @@ my $FWACCEPTMARK_ON  = "0x8000/0x8000";
 my $FWACCEPTMARK_OFF = "0x/0x8000";
 
 my $pve_std_chains = {};
-$pve_std_chains->{4} = {
+my $pve_std_chains_conf = {};
+$pve_std_chains_conf->{4} = {
 'PVEFW-SET-ACCEPT-MARK' => [
{ target => "-j MARK --set-mark $FWACCEPTMARK_ON" },
 ],
@@ -641,7 +643,7 @@ $pve_std_chains->{4} = {
 ],
 };
 
-$pve_std_chains->{6} = {
+$pve_std_chains_conf->{6} = {
 'PVEFW-SET-ACCEPT-MARK' => [
{ target => "-j MARK --set-mark $FWACCEPTMARK_ON" },
 ],
@@ -3354,6 +3356,9 @@ sub compile {
 
 my $vmfw_configs;
 
+# fixme: once we read standard chains from config this needs to be put in 
test/standard cases below
+$pve_std_chains = dclone($pve_std_chains_conf);
+
 if ($vmdata) { # test mode
my $testdir = $vmdata->{testdir} || die "no test directory specified";
my $filename = "$testdir/cluster.fw";
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v3 firewall 01/13] remove unused $rule_format

2017-10-09 Thread Tom Weber
---
 src/PVE/Firewall.pm | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index cc81325..5d78686 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1648,8 +1648,6 @@ sub enable_bridge_firewall {
 $bridge_firewall_enabled = 1;
 }
 
-my $rule_format = "%-15s %-30s %-30s %-15s %-15s %-15s\n";
-
 sub iptables_restore_cmdlist {
 my ($cmdlist) = @_;
 
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v3 firewall 11/13] cleanup parameters to ruleset_generate_rule

2017-10-09 Thread Tom Weber
remove $actions and $goto - not used anymore
---
 src/PVE/Firewall.pm | 19 +++
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index d9c2347..d249f7a 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -2050,7 +2050,7 @@ sub ruleset_generate_action {
 }
 
 sub ruleset_generate_rule {
-my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
+my ($ruleset, $chain, $ipversion, $rule, $cluster_conf, $fw_conf) = @_;
 
 my $rules;
 
@@ -2294,12 +2294,10 @@ sub ruleset_generate_vm_rules {
eval {
if ($direction eq 'OUT') {
rule_substitude_action($rule, { ACCEPT => 
"PVEFW-SET-ACCEPT-MARK", REJECT => "PVEFW-reject" });
-   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
- undef, $cluster_conf, $vmfw_conf);
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
$cluster_conf, $vmfw_conf);
} else {
rule_substitude_action($rule, { ACCEPT => $in_accept , 
REJECT => "PVEFW-reject" });
-   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
- undef, $cluster_conf, $vmfw_conf);
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
$cluster_conf, $vmfw_conf);
}
};
warn $@ if $@;
@@ -2428,8 +2426,7 @@ sub enable_host_firewall {
ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, 
'IN', $accept_action, $ipversion);
} elsif ($rule->{type} eq 'in') {
rule_substitude_action($rule, { ACCEPT => $accept_action, 
REJECT => "PVEFW-reject" });
-   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
- undef, $cluster_conf, $hostfw_conf);
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
$cluster_conf, $hostfw_conf);
}
};
warn $@ if $@;
@@ -2485,8 +2482,7 @@ sub enable_host_firewall {
ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, 
'OUT', $accept_action, $ipversion);
} elsif ($rule->{type} eq 'out') {
rule_substitude_action($rule, { ACCEPT => $accept_action, 
REJECT => "PVEFW-reject" });
-   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
- undef, $cluster_conf, $hostfw_conf);
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
$cluster_conf, $hostfw_conf);
}
};
warn $@ if $@;
@@ -2532,7 +2528,7 @@ sub generate_group_rules {
next if $rule->{type} ne 'in';
next if $rule->{ipversion} && $rule->{ipversion} ne $ipversion;
rule_substitude_action($rule, { ACCEPT => "PVEFW-SET-ACCEPT-MARK", 
REJECT => "PVEFW-reject" });
-   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, undef, 
undef, $cluster_conf);
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
$cluster_conf);
 }
 
 $chain = "GROUP-${group}-OUT";
@@ -2546,8 +2542,7 @@ sub generate_group_rules {
# we use PVEFW-SET-ACCEPT-MARK (Instead of ACCEPT) because we need to
# check also other tap rules later
rule_substitude_action($rule, { ACCEPT => 'PVEFW-SET-ACCEPT-MARK', 
REJECT => "PVEFW-reject" });
-   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, undef,
- undef, $cluster_conf);
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
$cluster_conf);
 }
 }
 
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v3 firewall 03/13] integrate logging into ruleset_addrule

2017-10-09 Thread Tom Weber
---
 src/PVE/Firewall.pm | 33 ++---
 1 file changed, 10 insertions(+), 23 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index f1aecef..ad59267 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -2002,10 +2002,14 @@ sub ruleset_addrule_old {
 }
 
 sub ruleset_addrule {
-   my ($ruleset, $chain, $match, $action, $log) = @_;
+   my ($ruleset, $chain, $match, $action, $log, $logmsg, $vmid) = @_;
 
die "no such chain '$chain'\n" if !$ruleset->{$chain};
 
+   if (defined($log) && $log) {
+   my $logaction = get_log_rule_base($chain, $vmid, $logmsg, $log);
+   push @{$ruleset->{$chain}}, "-A $chain $match $logaction";
+   }
push @{$ruleset->{$chain}}, "-A $chain $match $action";
 }
 
@@ -2020,27 +2024,15 @@ sub ruleset_insertrule {
 sub get_log_rule_base {
 my ($chain, $vmid, $msg, $loglevel) = @_;
 
-die "internal error - no log level" if !defined($loglevel);
-
 $vmid = 0 if !defined($vmid);
+$msg = "" if !defined($msg);
 
 # Note: we use special format for prefix to pass further
-# info to log daemon (VMID, LOGVELEL and CHAIN)
+# info to log daemon (VMID, LOGLEVEL and CHAIN)
 
 return "-j NFLOG --nflog-prefix \":$vmid:$loglevel:$chain: $msg\"";
 }
 
-sub ruleset_addlog {
-my ($ruleset, $chain, $vmid, $msg, $loglevel, $match) = @_;
-
-return if !defined($loglevel);
-
-my $logaction = get_log_rule_base($chain, $vmid, $msg, $loglevel);
-
-$match = "" if !defined $match;
-ruleset_addrule($ruleset, $chain, $match, $logaction);
-}
-
 sub ruleset_add_chain_policy {
 my ($ruleset, $chain, $ipversion, $vmid, $policy, $loglevel, 
$accept_action) = @_;
 
@@ -2053,15 +2045,11 @@ sub ruleset_add_chain_policy {
 
ruleset_addrule($ruleset, $chain, "", "-j PVEFW-Drop");
 
-   ruleset_addlog($ruleset, $chain, $vmid, "policy $policy: ", $loglevel);
-
-   ruleset_addrule($ruleset, $chain, "", "-j DROP");
+   ruleset_addrule($ruleset, $chain, "", "-j DROP", $loglevel, "policy 
$policy: ", $vmid);
 } elsif ($policy eq 'REJECT') {
ruleset_addrule($ruleset, $chain, "", "-j PVEFW-Reject");
 
-   ruleset_addlog($ruleset, $chain, $vmid, "policy $policy: ", $loglevel);
-
-   ruleset_addrule($ruleset, $chain, "", "-g PVEFW-reject");
+   ruleset_addrule($ruleset, $chain, "", "-g PVEFW-reject", $loglevel, 
"policy $policy:", $vmid);
 } else {
# should not happen
die "internal error: unknown policy '$policy'";
@@ -2093,8 +2081,7 @@ sub ruleset_chain_add_input_filters {
 if ($cluster_conf->{ipset}->{blacklist}){
if (!ruleset_chain_exist($ruleset, "PVEFW-blacklist")) {
ruleset_create_chain($ruleset, "PVEFW-blacklist");
-   ruleset_addlog($ruleset, "PVEFW-blacklist", 0, "DROP: ", $loglevel) 
if $loglevel;
-   ruleset_addrule($ruleset, "PVEFW-blacklist", "", "-j DROP");
+   ruleset_addrule($ruleset, "PVEFW-blacklist", "", "-j DROP", 
$loglevel, "DROP: ");
}
my $ipset_chain = compute_ipset_chain_name(0, 'blacklist', $ipversion);
ruleset_addrule($ruleset, $chain, "-m set --match-set ${ipset_chain} 
src", "-j PVEFW-blacklist");
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v3 firewall 02/13] prepare code for more generic firewall logging

2017-10-09 Thread Tom Weber
making ruleset generation aware of a match and action
part in iptable rules.
code will generate the same iptables as before! (except for
a few additional spaces between match and action).
---
 src/PVE/Firewall.pm  | 166 ++-
 src/PVE/FirewallSimulator.pm |   2 +-
 2 files changed, 100 insertions(+), 68 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 5d78686..f1aecef 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1776,7 +1776,7 @@ sub ipset_get_chains {
 return $res;
 }
 
-sub ruleset_generate_cmdstr {
+sub ruleset_generate_match {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
 
 return if defined($rule->{enable}) && !$rule->{enable};
@@ -1907,6 +1907,14 @@ sub ruleset_generate_cmdstr {
 
 push @cmd, "-m addrtype --dst-type $rule->{dsttype}" if $rule->{dsttype};
 
+return scalar(@cmd) ? join(' ', @cmd) : undef;
+}
+
+sub ruleset_generate_action {
+my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
+
+my @cmd = ();
+
 if (my $action = $rule->{action}) {
$action = $actions->{$action} if defined($actions->{$action});
$goto = 1 if !defined($goto) && $action eq 'PVEFW-SET-ACCEPT-MARK';
@@ -1916,6 +1924,17 @@ sub ruleset_generate_cmdstr {
 return scalar(@cmd) ? join(' ', @cmd) : undef;
 }
 
+sub ruleset_generate_cmdstr {
+my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
+my $match = ruleset_generate_match($ruleset, $chain, $ipversion, $rule, 
$actions, $goto, $cluster_conf, $fw_conf);
+my $action = ruleset_generate_action($ruleset, $chain, $ipversion, $rule, 
$actions, $goto, $cluster_conf, $fw_conf);
+
+return undef if !(defined($match) or defined($action));
+my $ret = defined($match) ? $match : "";
+$ret = "$ret $action" if defined($action);
+return $ret;
+}
+
 sub ruleset_generate_rule {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
 
@@ -1929,15 +1948,19 @@ sub ruleset_generate_rule {
 
 # update all or nothing
 
-my @cmds = ();
+my @mstrs = ();
+my @astrs = ();
 foreach my $tmp (@$rules) {
-   if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain, $ipversion, 
$tmp, $actions, $goto, $cluster_conf, $fw_conf)) {
-   push @cmds, $cmdstr;
+   my $m = ruleset_generate_match($ruleset, $chain, $ipversion, $tmp, 
$actions, $goto, $cluster_conf, $fw_conf);
+   my $a = ruleset_generate_action($ruleset, $chain, $ipversion, $tmp, 
$actions, $goto, $cluster_conf, $fw_conf);
+   if (defined $m or defined $a) {
+   push @mstrs, defined($m) ? $m : "";
+   push @astrs, defined($a) ? $a : "";
}
 }
 
-foreach my $cmdstr (@cmds) {
-   ruleset_addrule($ruleset, $chain, $cmdstr);
+for my $i (0 .. $#mstrs) {
+   ruleset_addrule($ruleset, $chain, $mstrs[$i], $astrs[$i]);
 }
 }
 
@@ -1946,8 +1969,10 @@ sub ruleset_generate_rule_insert {
 
 die "implement me" if $rule->{macro}; # not implemented, because not 
needed so far
 
-if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain, $ipversion, 
$rule, $actions, $goto)) {
-   ruleset_insertrule($ruleset, $chain, $cmdstr);
+my $match = ruleset_generate_match($ruleset, $chain, $ipversion, $rule, 
$actions, $goto);
+my $action = ruleset_generate_action($ruleset, $chain, $ipversion, $rule, 
$actions, $goto);
+if (defined $match && defined $action) {
+   ruleset_insertrule($ruleset, $chain, $match, $action);
 }
 }
 
@@ -1968,7 +1993,7 @@ sub ruleset_chain_exist {
 return $ruleset->{$chain} ? 1 : undef;
 }
 
-sub ruleset_addrule {
+sub ruleset_addrule_old {
my ($ruleset, $chain, $rule) = @_;
 
die "no such chain '$chain'\n" if !$ruleset->{$chain};
@@ -1976,12 +2001,20 @@ sub ruleset_addrule {
push @{$ruleset->{$chain}}, "-A $chain $rule";
 }
 
+sub ruleset_addrule {
+   my ($ruleset, $chain, $match, $action, $log) = @_;
+
+   die "no such chain '$chain'\n" if !$ruleset->{$chain};
+
+   push @{$ruleset->{$chain}}, "-A $chain $match $action";
+}
+
 sub ruleset_insertrule {
-   my ($ruleset, $chain, $rule) = @_;
+   my ($ruleset, $chain, $match, $action, $log) = @_;
 
die "no such chain '$chain'\n" if !$ruleset->{$chain};
 
-   unshift @{$ruleset->{$chain}}, "-A $chain $rule";
+   unshift @{$ruleset->{$chain}}, "-A $chain $match $action";
 }
 
 sub get_log_rule_base {
@@ -1998,15 +2031,14 @@ sub get_log_rule_base {
 }
 
 sub ruleset_addlog {
-my ($ruleset, $chain, $vmid, $msg, $loglevel, $rule) = @_;
+my ($ruleset, $chain, $vmid, $msg, $loglevel, $match) = @_;
 
 return if !defined($loglevel);
 
-my $logrule = get_log_rule_base($chain, $vmid, $msg, $loglevel);
-
-$logrule = "$rule $logrule" if defined($rule);
+my $logaction = get_log_rule_base($chain, $vmid, $msg, $loglevel);
 
-ru

[pve-devel] [PATCH v3 firewall 04/13] convert string based rule definitions to hashes

2017-10-09 Thread Tom Weber
also extending %rule with log,logmsg,match,target
---
 src/PVE/Firewall.pm | 223 
 1 file changed, 120 insertions(+), 103 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index ad59267..634ff90 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -142,6 +142,20 @@ my $log_level_hash = {
 emerg => 0,
 };
 
+# %rule
+#
+# name => optional
+# action =>
+# proto =>
+# sport =>
+# dport =>
+# log => optional, loglevel
+# logmsg => optional, logmsg - overwrites default
+# iface_in
+# iface_out
+# match => optional, overwrites generation of match
+# target => optional, overwrites action
+
 # we need to overwrite some macros for ipv6
 my $pve_ipv6fw_macros = {
 'Ping' => [
@@ -536,7 +550,7 @@ my $FWACCEPTMARK_OFF = "0x/0x8000";
 my $pve_std_chains = {};
 $pve_std_chains->{4} = {
 'PVEFW-SET-ACCEPT-MARK' => [
-   "-j MARK --set-mark $FWACCEPTMARK_ON",
+   { target => "-j MARK --set-mark $FWACCEPTMARK_ON" },
 ],
 'PVEFW-DropBroadcast' => [
# same as shorewall 'Broadcast'
@@ -552,10 +566,10 @@ $pve_std_chains->{4} = {
{ action => 'DROP', dsttype => 'BROADCAST' },
{ action => 'DROP', source => '224.0.0.0/4' },
{ action => 'DROP', proto => 'icmp' },
-   "-p tcp -j REJECT --reject-with tcp-reset",
-   "-p udp -j REJECT --reject-with icmp-port-unreachable",
-   "-p icmp -j REJECT --reject-with icmp-host-unreachable",
-   "-j REJECT --reject-with icmp-host-prohibited",
+   { match => '-p tcp', target => '-j REJECT --reject-with tcp-reset' },
+   { match => '-p udp', target => '-j REJECT --reject-with 
icmp-port-unreachable' },
+   { match => '-p icmp', target => '-j REJECT --reject-with 
icmp-host-unreachable' },
+   { target => '-j REJECT --reject-with icmp-host-prohibited' },
 ],
 'PVEFW-Drop' => [
# same as shorewall 'Drop', which is equal to DROP,
@@ -568,7 +582,7 @@ $pve_std_chains->{4} = {
{ action => 'ACCEPT', proto => 'icmp', dport => 'fragmentation-needed' 
},
{ action => 'ACCEPT', proto => 'icmp', dport => 'time-exceeded' },
# Drop packets with INVALID state
-   "-m conntrack --ctstate INVALID -j DROP",
+   { action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
{ action => 'DROP', proto => 'udp', dport => '135,445', nbdport => 2 },
{ action => 'DROP', proto => 'udp', dport => '137:139'},
@@ -576,7 +590,7 @@ $pve_std_chains->{4} = {
{ action => 'DROP', proto => 'tcp', dport => '135,139,445', nbdport => 
3 },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
-   "-p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -j DROP",
+   { action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
# Drop DNS replies
{ action => 'DROP', proto => 'udp', sport => 53 },
 ],
@@ -591,7 +605,7 @@ $pve_std_chains->{4} = {
{ action => 'ACCEPT', proto => 'icmp', dport => 'fragmentation-needed' 
},
{ action => 'ACCEPT', proto => 'icmp', dport => 'time-exceeded' },
# Drop packets with INVALID state
-   "-m conntrack --ctstate INVALID -j DROP",
+   { action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
{ action => 'PVEFW-reject', proto => 'udp', dport => '135,445', nbdport 
=> 2 },
{ action => 'PVEFW-reject', proto => 'udp', dport => '137:139'},
@@ -599,111 +613,118 @@ $pve_std_chains->{4} = {
{ action => 'PVEFW-reject', proto => 'tcp', dport => '135,139,445', 
nbdport => 3 },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
-   "-p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -j DROP",
+   { action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
# Drop DNS replies
{ action => 'DROP', proto => 'udp', sport => 53 },
 ],
 'PVEFW-tcpflags' => [
# same as shorewall tcpflags action.
# Packets arriving on this interface are checked for som illegal 
combinations of TCP flags
-   "-p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -g 
PVEFW-logflags",
-   "-p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -g 
PVEFW-logflags",
-   "-p tcp -m tcp --tcp-flags SYN,RST SYN,RST -g PVEFW-logflags",
-   "-p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -g PVEFW-logflags",
-   "-p tcp -m tcp --sport 0 --tcp-flags FIN,SYN,RST,ACK SYN -g 
PVEFW-logflags",
+   { match => '-p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG 
FIN,PSH,URG', target => '-g PVEFW-logflags' },
+   { match => '-p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE', 
target => '-g PVEFW-logflags' },
+   { match => '-p tcp -m tcp --tcp-flags SYN,RST SYN,RST', target 

Re: [pve-devel] [PATCH container] Fix restore with multiple mountpoints

2017-10-09 Thread Tom Weber
Anyone care about this?
I have two cases of containers were i have to manually fix after a
restore.

  Tom

Am Dienstag, den 26.09.2017, 15:29 +0200 schrieb Tom Weber:
> If you use mountpoints inside a container, and change ownership of
> these, a restore of the CT will reset them to root:root again.
> 
> That's because the whole CT FS gets prepared and mounted together
> with
> (of course) an owner of root:root for the mp.
> As tar uses the option --skip-old-files it won't touch these dirs
> then.
> 
> I don't see why one would need --skip-old-files for a restore job (or
> did I miss something?)
> 
> 
> Tom Weber (1):
>   remove --skip-old-files from tar restore options
> 
>  src/PVE/LXC/Create.pm | 5 -
>  1 file changed, 5 deletions(-)
> 
___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH v3 firewall 00/13] Firewall code cleanups

2017-10-18 Thread Tom Weber
Am Mittwoch, den 18.10.2017, 12:44 +0200 schrieb Wolfgang Bumiller:
> On Mon, Oct 09, 2017 at 12:16:18PM +0200, Tom Weber wrote:
> > 
> > third version. mostly converting rules into structures.
> > reorganized ruleset_generate_rule and everything around it.
> > please note that some of the stuff implemented in the first patches
> > gets eliminated later. So maybe it's worth reading all patches
> > before
> > flaming me ;-)
> Where would be the fun in that?
> 
> Anyway, the patches seem fine.
> Only thing I'm not too happy about currently is that $pve_std_chains
> is
> still a global. Currently we could clone it in generate_std_chains()
> directly as this is both what modifies and uses it, unless this
> conflicts with later changes of yours - then it would still be a nice
> finish up to this point in the series and change it into a parameter
> passed from the outside later on.

The cloning of the still hardwired _conf is just to make the behavior
of $pve_std_chains similar to what it'd be if we build it from parsing
configuration files.
That means various switches/settings would default and be reset to
whats in the config on every rebuild of the rules and not be carried
around if code changes them in the internal structure - remember what
hit me when I thought I only need to turn on logging?

For now, and the code as it is, it doesn't make a difference but it
makes my thinking and maybe the future a bit easier ;)

Just tell me if I should keep it or drop it for v4

> OTOH the _conf+clone patch could just be skipped for now as well
> until
> we actually need it, as the rest of the series doesn't strictly
> depend
> on that change to be there. Partly due to the length of the series.
> I don't want you to have to drag along the entire patch set with each
> version. Apart from the above I have no objections to applying the
> series as it is.
> (Although we do still miss the Signed-off-by lines which I forgot to
> mention the last couple of times, sorry.)
> So if you can send a v4 with the above changes we could apply it and
> continue from there.

Sounds great. So i'll try to make a v4 this evening.

  Tom
___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v4 firewall 10/13] rule_substitude_action, remove ruleset_generate_rule_old

2017-10-18 Thread Tom Weber
implement rule_substitude_action
eliminate use of ruleset_genereate_rule_old and remove it

Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm | 73 ++---
 1 file changed, 24 insertions(+), 49 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 633aa7a..95e00bd 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1800,6 +1800,15 @@ sub ipset_get_chains {
 return $res;
 }
 
+# substitude action of rule according to action hash
+sub rule_substitude_action {
+my ($rule, $actions) = @_;
+
+if (my $action = $rule->{action}) {
+   $rule->{action} = $actions->{$action} if defined($actions->{$action});
+}
+}
+
 # generate a src or dst match
 # $dir(ection) is either d or s
 sub ipt_gen_src_or_dst_match {
@@ -2061,40 +2070,6 @@ sub ruleset_generate_rule {
 }
 }
 
-sub ruleset_generate_rule_old {
-my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
-
-my $rules;
-
-if ($rule->{macro}) {
-   $rules = &$apply_macro($rule->{macro}, $rule, 0, $ipversion);
-} else {
-   $rules = [ $rule ];
-}
-
-# update all or nothing
-
-# fixme: lots of temporary ugliness
-my @mstrs = ();
-my @astrs = ();
-my @logging = ();
-my @logmsg = ();
-foreach my $tmp (@$rules) {
-   my $m = ruleset_generate_match($ruleset, $chain, $ipversion, $tmp, 
$actions, $goto, $cluster_conf, $fw_conf);
-   my $a = ruleset_generate_action($ruleset, $chain, $ipversion, $tmp, 
$actions, $goto, $cluster_conf, $fw_conf);
-   if (defined $m or defined $a) {
-   push @mstrs, defined($m) ? $m : "";
-   push @astrs, defined($a) ? $a : "";
-   push @logging, $tmp->{log};
-   push @logmsg, $tmp->{logmsg};
-   }
-}
-
-for my $i (0 .. $#mstrs) {
-   ruleset_addrule($ruleset, $chain, $mstrs[$i], $astrs[$i], $logging[$i], 
$logmsg[$i]);
-}
-}
-
 sub ruleset_generate_rule_insert {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto) = @_;
 
@@ -2170,8 +2145,9 @@ sub ruleset_add_chain_policy {
 
 if ($policy eq 'ACCEPT') {
 
-   ruleset_generate_rule_old($ruleset, $chain, $ipversion, { action => 
'ACCEPT' },
- { ACCEPT =>  $accept_action});
+   my $rule = { action => 'ACCEPT' };
+   rule_substitude_action($rule, { ACCEPT =>  $accept_action});
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule);
 
 } elsif ($policy eq 'DROP') {
 
@@ -2317,12 +2293,12 @@ sub ruleset_generate_vm_rules {
next if $rule->{type} ne $lc_direction;
eval {
if ($direction eq 'OUT') {
-   ruleset_generate_rule_old($ruleset, $chain, $ipversion, 
$rule,
- { ACCEPT => "PVEFW-SET-ACCEPT-MARK", 
REJECT => "PVEFW-reject" },
+   rule_substitude_action($rule, { ACCEPT => 
"PVEFW-SET-ACCEPT-MARK", REJECT => "PVEFW-reject" });
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
  undef, $cluster_conf, $vmfw_conf);
} else {
-   ruleset_generate_rule_old($ruleset, $chain, $ipversion, 
$rule,
- { ACCEPT => $in_accept , REJECT => 
"PVEFW-reject" },
+   rule_substitude_action($rule, { ACCEPT => $in_accept , 
REJECT => "PVEFW-reject" });
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
  undef, $cluster_conf, $vmfw_conf);
}
};
@@ -2451,8 +2427,8 @@ sub enable_host_firewall {
if ($rule->{type} eq 'group') {
ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, 
'IN', $accept_action, $ipversion);
} elsif ($rule->{type} eq 'in') {
-   ruleset_generate_rule_old($ruleset, $chain, $ipversion, $rule,
- { ACCEPT => $accept_action, REJECT => 
"PVEFW-reject" },
+   rule_substitude_action($rule, { ACCEPT => $accept_action, 
REJECT => "PVEFW-reject" });
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
  undef, $cluster_conf, $hostfw_conf);
}
};
@@ -2508,8 +2484,8 @@ sub enable_host_firewall {
if ($rule->{type} eq 'group') {
ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, 
'OUT', $accept_action, $ipversion);
} elsif ($rule->{type} eq 'out') {
-   ruleset_generat

[pve-devel] [PATCH v4 firewall 04/13] convert string based rule definitions to hashes

2017-10-18 Thread Tom Weber
also extending %rule with log,logmsg,match,target

Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm | 223 
 1 file changed, 120 insertions(+), 103 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index ad59267..634ff90 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -142,6 +142,20 @@ my $log_level_hash = {
 emerg => 0,
 };
 
+# %rule
+#
+# name => optional
+# action =>
+# proto =>
+# sport =>
+# dport =>
+# log => optional, loglevel
+# logmsg => optional, logmsg - overwrites default
+# iface_in
+# iface_out
+# match => optional, overwrites generation of match
+# target => optional, overwrites action
+
 # we need to overwrite some macros for ipv6
 my $pve_ipv6fw_macros = {
 'Ping' => [
@@ -536,7 +550,7 @@ my $FWACCEPTMARK_OFF = "0x/0x8000";
 my $pve_std_chains = {};
 $pve_std_chains->{4} = {
 'PVEFW-SET-ACCEPT-MARK' => [
-   "-j MARK --set-mark $FWACCEPTMARK_ON",
+   { target => "-j MARK --set-mark $FWACCEPTMARK_ON" },
 ],
 'PVEFW-DropBroadcast' => [
# same as shorewall 'Broadcast'
@@ -552,10 +566,10 @@ $pve_std_chains->{4} = {
{ action => 'DROP', dsttype => 'BROADCAST' },
{ action => 'DROP', source => '224.0.0.0/4' },
{ action => 'DROP', proto => 'icmp' },
-   "-p tcp -j REJECT --reject-with tcp-reset",
-   "-p udp -j REJECT --reject-with icmp-port-unreachable",
-   "-p icmp -j REJECT --reject-with icmp-host-unreachable",
-   "-j REJECT --reject-with icmp-host-prohibited",
+   { match => '-p tcp', target => '-j REJECT --reject-with tcp-reset' },
+   { match => '-p udp', target => '-j REJECT --reject-with 
icmp-port-unreachable' },
+   { match => '-p icmp', target => '-j REJECT --reject-with 
icmp-host-unreachable' },
+   { target => '-j REJECT --reject-with icmp-host-prohibited' },
 ],
 'PVEFW-Drop' => [
# same as shorewall 'Drop', which is equal to DROP,
@@ -568,7 +582,7 @@ $pve_std_chains->{4} = {
{ action => 'ACCEPT', proto => 'icmp', dport => 'fragmentation-needed' 
},
{ action => 'ACCEPT', proto => 'icmp', dport => 'time-exceeded' },
# Drop packets with INVALID state
-   "-m conntrack --ctstate INVALID -j DROP",
+   { action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
{ action => 'DROP', proto => 'udp', dport => '135,445', nbdport => 2 },
{ action => 'DROP', proto => 'udp', dport => '137:139'},
@@ -576,7 +590,7 @@ $pve_std_chains->{4} = {
{ action => 'DROP', proto => 'tcp', dport => '135,139,445', nbdport => 
3 },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
-   "-p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -j DROP",
+   { action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
# Drop DNS replies
{ action => 'DROP', proto => 'udp', sport => 53 },
 ],
@@ -591,7 +605,7 @@ $pve_std_chains->{4} = {
{ action => 'ACCEPT', proto => 'icmp', dport => 'fragmentation-needed' 
},
{ action => 'ACCEPT', proto => 'icmp', dport => 'time-exceeded' },
# Drop packets with INVALID state
-   "-m conntrack --ctstate INVALID -j DROP",
+   { action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
{ action => 'PVEFW-reject', proto => 'udp', dport => '135,445', nbdport 
=> 2 },
{ action => 'PVEFW-reject', proto => 'udp', dport => '137:139'},
@@ -599,111 +613,118 @@ $pve_std_chains->{4} = {
{ action => 'PVEFW-reject', proto => 'tcp', dport => '135,139,445', 
nbdport => 3 },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
-   "-p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -j DROP",
+   { action => 'DROP', match =>

[pve-devel] [PATCH v4 firewall 07/13] iptables address matching in own subroutine

2017-10-18 Thread Tom Weber
put generation of iptables source/destination address matching
in own subroutine and use this in ruleset_generate_match

Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm | 104 
 1 file changed, 47 insertions(+), 57 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index f009e58..89a8ef3 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1799,6 +1799,51 @@ sub ipset_get_chains {
 return $res;
 }
 
+# generate a src or dst match
+# $dir(ection) is either d or s
+sub ipt_gen_src_or_dst_match {
+my ($adr, $dir, $ipversion, $cluster_conf, $fw_conf) = @_;
+
+my $srcdst;
+if ($dir eq 's') {
+   $srcdst = "src";
+} elsif ($dir eq 'd') {
+   $srcdst = "dst";
+} else {
+   die "ipt_gen_src_or_dst_match: invalid direction $dir \n";
+}
+
+my $match;
+if ($adr =~ m/^\+/) {
+   if ($adr =~ m/^\+(${ipset_name_pattern})$/) {
+   my $name = $1;
+   my $ipset_chain;
+   if ($fw_conf && $fw_conf->{ipset}->{$name}) {
+   $ipset_chain = compute_ipset_chain_name($fw_conf->{vmid}, 
$name, $ipversion);
+   } elsif ($cluster_conf && $cluster_conf->{ipset}->{$name}) {
+   $ipset_chain = compute_ipset_chain_name(0, $name, $ipversion);
+   } else {
+   die "no such ipset '$name'\n";
+   }
+   $match = "-m set --match-set ${ipset_chain} ${srcdst}";
+   } else {
+   die "invalid security group name '$adr'\n";
+   }
+} elsif ($adr =~ m/^${ip_alias_pattern}$/){
+   my $alias = lc($adr);
+   my $e = $fw_conf ? $fw_conf->{aliases}->{$alias} : undef;
+   $e = $cluster_conf->{aliases}->{$alias} if !$e && $cluster_conf;
+   die "no such alias '$adr'\n" if !$e;
+   $match = "-${dir} $e->{cidr}";
+} elsif ($adr =~ m/\-/){
+   $match = "-m iprange --${srcdst}-range $adr";
+} else {
+   $match = "-${dir} $adr";
+}
+
+return $match;
+}
+
 sub ruleset_generate_match {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
 
@@ -1820,63 +1865,8 @@ sub ruleset_generate_match {
 my $source = $rule->{source};
 my $dest = $rule->{dest};
 
-if ($source) {
-if ($source =~ m/^\+/) {
-   if ($source =~ m/^\+(${ipset_name_pattern})$/) {
-   my $name = $1;
-   if ($fw_conf && $fw_conf->{ipset}->{$name}) {
-   my $ipset_chain = 
compute_ipset_chain_name($fw_conf->{vmid}, $name, $ipversion);
-   push @cmd, "-m set --match-set ${ipset_chain} src";
-   } elsif ($cluster_conf && $cluster_conf->{ipset}->{$name}) {
-   my $ipset_chain = compute_ipset_chain_name(0, $name, 
$ipversion);
-   push @cmd, "-m set --match-set ${ipset_chain} src";
-   } else {
-   die "no such ipset '$name'\n";
-   }
-   } else {
-   die "invalid security group name '$source'\n";
-   }
-   } elsif ($source =~ m/^${ip_alias_pattern}$/){
-   my $alias = lc($source);
-   my $e = $fw_conf ? $fw_conf->{aliases}->{$alias} : undef;
-   $e = $cluster_conf->{aliases}->{$alias} if !$e && $cluster_conf;
-   die "no such alias '$source'\n" if !$e;
-   push @cmd, "-s $e->{cidr}";
-} elsif ($source =~ m/\-/){
-   push @cmd, "-m iprange --src-range $source";
-   } else {
-   push @cmd, "-s $source";
-}
-}
-
-if ($dest) {
-if ($dest =~ m/^\+/) {
-   if ($dest =~ m/^\+(${ipset_name_pattern})$/) {
-   my $name = $1;
-   if ($fw_conf && $fw_conf->{ipset}->{$name}) {
-   my $ipset_chain = 
compute_ipset_chain_name($fw_conf->{vmid}, $name, $ipversion);
-   push @cmd, "-m set --match-set ${ipset_chain} dst";
-   } elsif ($cluster_conf && $cluster_conf->{ipset}->{$name}) {
-   my $ipset_chain = compute_ipset_chain_name(0, $name, 
$ipversion);
-   push @cmd, "-m set --match-set ${ipset_chain} dst";
-   } else {
-   die "no such ipset '$name'\n";
-   }
-   } else {
-   die "invalid security group name '$dest'\n";
-   }
-   } elsif ($dest =~ m/^${ip_alias_pattern}$/){
-   my $alias = lc($dest);
-   my $e = $fw_conf ? $fw_conf->{aliases}->{$alia

[pve-devel] [PATCH v4 firewall 06/13] eliminate unused nbdport in pve_std_chains_conf

2017-10-18 Thread Tom Weber
Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index c7ddd10..f009e58 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -586,10 +586,10 @@ $pve_std_chains_conf->{4} = {
# Drop packets with INVALID state
{ action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
-   { action => 'DROP', proto => 'udp', dport => '135,445', nbdport => 2 },
-   { action => 'DROP', proto => 'udp', dport => '137:139'},
+   { action => 'DROP', proto => 'udp', dport => '135,445' },
+   { action => 'DROP', proto => 'udp', dport => '137:139' },
{ action => 'DROP', proto => 'udp', dport => '1024:65535', sport => 137 
},
-   { action => 'DROP', proto => 'tcp', dport => '135,139,445', nbdport => 
3 },
+   { action => 'DROP', proto => 'tcp', dport => '135,139,445' },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
{ action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
@@ -609,10 +609,10 @@ $pve_std_chains_conf->{4} = {
# Drop packets with INVALID state
{ action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
-   { action => 'PVEFW-reject', proto => 'udp', dport => '135,445', nbdport 
=> 2 },
+   { action => 'PVEFW-reject', proto => 'udp', dport => '135,445' },
{ action => 'PVEFW-reject', proto => 'udp', dport => '137:139'},
{ action => 'PVEFW-reject', proto => 'udp', dport => '1024:65535', 
sport => 137 },
-   { action => 'PVEFW-reject', proto => 'tcp', dport => '135,139,445', 
nbdport => 3 },
+   { action => 'PVEFW-reject', proto => 'tcp', dport => '135,139,445' },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
{ action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
@@ -682,10 +682,10 @@ $pve_std_chains_conf->{6} = {
# Drop packets with INVALID state
{ action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
-   { action => 'DROP', proto => 'udp', dport => '135,445', nbdport => 2 },
+   { action => 'DROP', proto => 'udp', dport => '135,445' },
{ action => 'DROP', proto => 'udp', dport => '137:139'},
{ action => 'DROP', proto => 'udp', dport => '1024:65535', sport => 137 
},
-   { action => 'DROP', proto => 'tcp', dport => '135,139,445', nbdport => 
3 },
+   { action => 'DROP', proto => 'tcp', dport => '135,139,445' },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
{ action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
@@ -706,10 +706,10 @@ $pve_std_chains_conf->{6} = {
# Drop packets with INVALID state
{ action => 'DROP', match => '-m conntrack --ctstate INVALID', },
# Drop Microsoft SMB noise
-   { action => 'PVEFW-reject', proto => 'udp', dport => '135,445', nbdport 
=> 2 },
-   { action => 'PVEFW-reject', proto => 'udp', dport => '137:139'},
+   { action => 'PVEFW-reject', proto => 'udp', dport => '135,445' },
+   { action => 'PVEFW-reject', proto => 'udp', dport => '137:139' },
{ action => 'PVEFW-reject', proto => 'udp', dport => '1024:65535', 
sport => 137 },
-   { action => 'PVEFW-reject', proto => 'tcp', dport => '135,139,445', 
nbdport => 3 },
+   { action => 'PVEFW-reject', proto => 'tcp', dport => '135,139,445' },
{ action => 'DROP', proto => 'udp', dport => 1900 }, # UPnP
# Drop new/NotSyn traffic so that it doesn't get logged
{ action => 'DROP', match => '-p tcp -m tcp ! --tcp-flags 
FIN,SYN,RST,ACK SYN' },
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v4 firewall 12/13] remove unused ruleset_generate_rule_insert

2017-10-18 Thread Tom Weber
Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm | 12 
 1 file changed, 12 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 4821759..8d36175 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -2070,18 +2070,6 @@ sub ruleset_generate_rule {
 }
 }
 
-sub ruleset_generate_rule_insert {
-my ($ruleset, $chain, $ipversion, $rule, $actions, $goto) = @_;
-
-die "implement me" if $rule->{macro}; # not implemented, because not 
needed so far
-
-my $match = ruleset_generate_match($ruleset, $chain, $ipversion, $rule, 
$actions, $goto);
-my $action = ruleset_generate_action($ruleset, $chain, $ipversion, $rule, 
$actions, $goto);
-if (defined $match && defined $action) {
-   ruleset_insertrule($ruleset, $chain, $match, $action);
-}
-}
-
 sub ruleset_create_chain {
 my ($ruleset, $chain) = @_;
 
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v4 firewall 11/13] cleanup parameters to ruleset_generate_rule

2017-10-18 Thread Tom Weber
remove $actions and $goto - not used anymore

Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm | 19 +++
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 95e00bd..4821759 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -2050,7 +2050,7 @@ sub ruleset_generate_action {
 }
 
 sub ruleset_generate_rule {
-my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
+my ($ruleset, $chain, $ipversion, $rule, $cluster_conf, $fw_conf) = @_;
 
 my $rules;
 
@@ -2294,12 +2294,10 @@ sub ruleset_generate_vm_rules {
eval {
if ($direction eq 'OUT') {
rule_substitude_action($rule, { ACCEPT => 
"PVEFW-SET-ACCEPT-MARK", REJECT => "PVEFW-reject" });
-   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
- undef, $cluster_conf, $vmfw_conf);
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
$cluster_conf, $vmfw_conf);
} else {
rule_substitude_action($rule, { ACCEPT => $in_accept , 
REJECT => "PVEFW-reject" });
-   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
- undef, $cluster_conf, $vmfw_conf);
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
$cluster_conf, $vmfw_conf);
}
};
warn $@ if $@;
@@ -2428,8 +2426,7 @@ sub enable_host_firewall {
ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, 
'IN', $accept_action, $ipversion);
} elsif ($rule->{type} eq 'in') {
rule_substitude_action($rule, { ACCEPT => $accept_action, 
REJECT => "PVEFW-reject" });
-   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
- undef, $cluster_conf, $hostfw_conf);
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
$cluster_conf, $hostfw_conf);
}
};
warn $@ if $@;
@@ -2485,8 +2482,7 @@ sub enable_host_firewall {
ruleset_add_group_rule($ruleset, $cluster_conf, $chain, $rule, 
'OUT', $accept_action, $ipversion);
} elsif ($rule->{type} eq 'out') {
rule_substitude_action($rule, { ACCEPT => $accept_action, 
REJECT => "PVEFW-reject" });
-   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
undef,
- undef, $cluster_conf, $hostfw_conf);
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
$cluster_conf, $hostfw_conf);
}
};
warn $@ if $@;
@@ -2532,7 +2528,7 @@ sub generate_group_rules {
next if $rule->{type} ne 'in';
next if $rule->{ipversion} && $rule->{ipversion} ne $ipversion;
rule_substitude_action($rule, { ACCEPT => "PVEFW-SET-ACCEPT-MARK", 
REJECT => "PVEFW-reject" });
-   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, undef, 
undef, $cluster_conf);
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
$cluster_conf);
 }
 
 $chain = "GROUP-${group}-OUT";
@@ -2546,8 +2542,7 @@ sub generate_group_rules {
# we use PVEFW-SET-ACCEPT-MARK (Instead of ACCEPT) because we need to
# check also other tap rules later
rule_substitude_action($rule, { ACCEPT => 'PVEFW-SET-ACCEPT-MARK', 
REJECT => "PVEFW-reject" });
-   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, undef,
- undef, $cluster_conf);
+   ruleset_generate_rule($ruleset, $chain, $ipversion, $rule, 
$cluster_conf);
 }
 }
 
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v4 firewall 13/13] remove ruleset_generate_match, ruleset_generate_action

2017-10-18 Thread Tom Weber
ruleset_generate_match and ruleset_generate_action not used anymore

Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm | 97 -
 1 file changed, 97 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 8d36175..c858b85 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1952,103 +1952,6 @@ sub ipt_rule_to_cmds {
 return @iptcmds;
 }
 
-sub ruleset_generate_match {
-my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
-
-return if defined($rule->{enable}) && !$rule->{enable};
-return if $rule->{errors};
-
-return $rule->{match} if defined $rule->{match};
-
-die "unable to emit macro - internal error" if $rule->{macro}; # should 
not happen
-
-my $nbdport = defined($rule->{dport}) ? 
parse_port_name_number_or_range($rule->{dport}, 1) : 0;
-my $nbsport = defined($rule->{sport}) ? 
parse_port_name_number_or_range($rule->{sport}, 0) : 0;
-
-my @cmd = ();
-
-push @cmd, "-i $rule->{iface_in}" if $rule->{iface_in};
-push @cmd, "-o $rule->{iface_out}" if $rule->{iface_out};
-
-my $source = $rule->{source};
-my $dest = $rule->{dest};
-
-push @cmd, ipt_gen_src_or_dst_match($source, 's', $ipversion, 
$cluster_conf, $fw_conf) if $source;
-push @cmd, ipt_gen_src_or_dst_match($dest, 'd', $ipversion, $cluster_conf, 
$fw_conf) if $dest;
-
-if (my $proto = $rule->{proto}) {
-   push @cmd, "-p $proto";
-
-   my $multiport = 0;
-   $multiport++ if $nbdport > 1;
-   $multiport++ if $nbsport > 1;
-
-   push @cmd, "--match multiport" if $multiport;
-
-   die "multiport: option '--sports' cannot be used together with 
'--dports'\n"
-   if ($multiport == 2) && ($rule->{dport} ne $rule->{sport});
-
-   if ($rule->{dport}) {
-   if ($proto eq 'icmp') {
-   # Note: we use dport to store --icmp-type
-   die "unknown icmp-type '$rule->{dport}'\n"
-   if $rule->{dport} !~ /^\d+$/ && 
!defined($icmp_type_names->{$rule->{dport}});
-   push @cmd, "-m icmp --icmp-type $rule->{dport}";
-   } elsif ($proto eq 'icmpv6') {
-   # Note: we use dport to store --icmpv6-type
-   die "unknown icmpv6-type '$rule->{dport}'\n"
-   if $rule->{dport} !~ /^\d+$/ && 
!defined($icmpv6_type_names->{$rule->{dport}});
-   push @cmd, "-m icmpv6 --icmpv6-type $rule->{dport}";
-   } elsif (!$PROTOCOLS_WITH_PORTS->{$proto}) {
-   die "protocol $proto does not have ports\n";
-   } else {
-   if ($nbdport > 1) {
-   if ($multiport == 2) {
-   push @cmd,  "--ports $rule->{dport}";
-   } else {
-   push @cmd, "--dports $rule->{dport}";
-   }
-   } else {
-   push @cmd, "--dport $rule->{dport}";
-   }
-   }
-   }
-
-   if ($rule->{sport}) {
-   die "protocol $proto does not have ports\n"
-if !$PROTOCOLS_WITH_PORTS->{$proto};
-   if ($nbsport > 1) {
-   push @cmd, "--sports $rule->{sport}" if $multiport != 2;
-   } else {
-   push @cmd, "--sport $rule->{sport}";
-   }
-   }
-} elsif ($rule->{dport} || $rule->{sport}) {
-   die "destination port '$rule->{dport}', but no protocol specified\n" if 
$rule->{dport};
-   die "source port '$rule->{sport}', but no protocol specified\n" if 
$rule->{sport};
-}
-
-push @cmd, "-m addrtype --dst-type $rule->{dsttype}" if $rule->{dsttype};
-
-return scalar(@cmd) ? join(' ', @cmd) : undef;
-}
-
-sub ruleset_generate_action {
-my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
-
-return $rule->{target} if defined $rule->{target};
-
-my @cmd = ();
-
-if (my $action = $rule->{action}) {
-   $action = $actions->{$action} if defined($actions->{$action});
-   $goto = 1 if !defined($goto) && $action eq 'PVEFW-SET-ACCEPT-MARK';
-   push @cmd, $goto ? "-g $action" : "-j $action";
-}
-
-return scalar(@cmd) ? join(' ', @cmd) : undef;
-}
-
 sub ruleset_generate_rule {
 my ($ruleset, $chain, $ipversion, $rule, $cluster_conf, $fw_conf) = @_;
 
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v4 firewall 00/13] Firewall code cleanups

2017-10-18 Thread Tom Weber
4th version.
third version with signed off lines
make $pve_std_chains a copy of $pve_std_chains_conf is optional

Tom Weber (13):
  remove unused $rule_format
  prepare code for more generic firewall logging
  integrate logging into ruleset_addrule
  convert string based rule definitions to hashes
  make $pve_std_chains a copy of $pve_std_chains_conf
  eliminate unused nbdport in pve_std_chains_conf
  iptables address matching in own subroutine
  implement ipt_rule_to_cmds, ruleset_add_ipt_cmd
  remove unused ruleset_generate_cmdstr
  rule_substitude_action, remove ruleset_generate_rule_old
  cleanup parameters to ruleset_generate_rule
  remove unused ruleset_generate_rule_insert
  remove ruleset_generate_match, ruleset_generate_action

 src/PVE/Firewall.pm  | 674 ++-
 src/PVE/FirewallSimulator.pm |   2 +-
 2 files changed, 342 insertions(+), 334 deletions(-)

-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v4 firewall 09/13] remove unused ruleset_generate_cmdstr

2017-10-18 Thread Tom Weber
Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index b492086..633aa7a 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -2040,17 +2040,6 @@ sub ruleset_generate_action {
 return scalar(@cmd) ? join(' ', @cmd) : undef;
 }
 
-sub ruleset_generate_cmdstr {
-my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
-my $match = ruleset_generate_match($ruleset, $chain, $ipversion, $rule, 
$actions, $goto, $cluster_conf, $fw_conf);
-my $action = ruleset_generate_action($ruleset, $chain, $ipversion, $rule, 
$actions, $goto, $cluster_conf, $fw_conf);
-
-return undef if !(defined($match) or defined($action));
-my $ret = defined($match) ? $match : "";
-$ret = "$ret $action" if defined($action);
-return $ret;
-}
-
 sub ruleset_generate_rule {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
 
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v4 firewall 01/13] remove unused $rule_format

2017-10-18 Thread Tom Weber
Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index cc81325..5d78686 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1648,8 +1648,6 @@ sub enable_bridge_firewall {
 $bridge_firewall_enabled = 1;
 }
 
-my $rule_format = "%-15s %-30s %-30s %-15s %-15s %-15s\n";
-
 sub iptables_restore_cmdlist {
 my ($cmdlist) = @_;
 
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v4 firewall 02/13] prepare code for more generic firewall logging

2017-10-18 Thread Tom Weber
making ruleset generation aware of a match and action
part in iptable rules.
code will generate the same iptables as before! (except for
a few additional spaces between match and action).

Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm  | 166 ++-
 src/PVE/FirewallSimulator.pm |   2 +-
 2 files changed, 100 insertions(+), 68 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 5d78686..f1aecef 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -1776,7 +1776,7 @@ sub ipset_get_chains {
 return $res;
 }
 
-sub ruleset_generate_cmdstr {
+sub ruleset_generate_match {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
 
 return if defined($rule->{enable}) && !$rule->{enable};
@@ -1907,6 +1907,14 @@ sub ruleset_generate_cmdstr {
 
 push @cmd, "-m addrtype --dst-type $rule->{dsttype}" if $rule->{dsttype};
 
+return scalar(@cmd) ? join(' ', @cmd) : undef;
+}
+
+sub ruleset_generate_action {
+my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
+
+my @cmd = ();
+
 if (my $action = $rule->{action}) {
$action = $actions->{$action} if defined($actions->{$action});
$goto = 1 if !defined($goto) && $action eq 'PVEFW-SET-ACCEPT-MARK';
@@ -1916,6 +1924,17 @@ sub ruleset_generate_cmdstr {
 return scalar(@cmd) ? join(' ', @cmd) : undef;
 }
 
+sub ruleset_generate_cmdstr {
+my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
+my $match = ruleset_generate_match($ruleset, $chain, $ipversion, $rule, 
$actions, $goto, $cluster_conf, $fw_conf);
+my $action = ruleset_generate_action($ruleset, $chain, $ipversion, $rule, 
$actions, $goto, $cluster_conf, $fw_conf);
+
+return undef if !(defined($match) or defined($action));
+my $ret = defined($match) ? $match : "";
+$ret = "$ret $action" if defined($action);
+return $ret;
+}
+
 sub ruleset_generate_rule {
 my ($ruleset, $chain, $ipversion, $rule, $actions, $goto, $cluster_conf, 
$fw_conf) = @_;
 
@@ -1929,15 +1948,19 @@ sub ruleset_generate_rule {
 
 # update all or nothing
 
-my @cmds = ();
+my @mstrs = ();
+my @astrs = ();
 foreach my $tmp (@$rules) {
-   if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain, $ipversion, 
$tmp, $actions, $goto, $cluster_conf, $fw_conf)) {
-   push @cmds, $cmdstr;
+   my $m = ruleset_generate_match($ruleset, $chain, $ipversion, $tmp, 
$actions, $goto, $cluster_conf, $fw_conf);
+   my $a = ruleset_generate_action($ruleset, $chain, $ipversion, $tmp, 
$actions, $goto, $cluster_conf, $fw_conf);
+   if (defined $m or defined $a) {
+   push @mstrs, defined($m) ? $m : "";
+   push @astrs, defined($a) ? $a : "";
}
 }
 
-foreach my $cmdstr (@cmds) {
-   ruleset_addrule($ruleset, $chain, $cmdstr);
+for my $i (0 .. $#mstrs) {
+   ruleset_addrule($ruleset, $chain, $mstrs[$i], $astrs[$i]);
 }
 }
 
@@ -1946,8 +1969,10 @@ sub ruleset_generate_rule_insert {
 
 die "implement me" if $rule->{macro}; # not implemented, because not 
needed so far
 
-if (my $cmdstr = ruleset_generate_cmdstr($ruleset, $chain, $ipversion, 
$rule, $actions, $goto)) {
-   ruleset_insertrule($ruleset, $chain, $cmdstr);
+my $match = ruleset_generate_match($ruleset, $chain, $ipversion, $rule, 
$actions, $goto);
+my $action = ruleset_generate_action($ruleset, $chain, $ipversion, $rule, 
$actions, $goto);
+if (defined $match && defined $action) {
+   ruleset_insertrule($ruleset, $chain, $match, $action);
 }
 }
 
@@ -1968,7 +1993,7 @@ sub ruleset_chain_exist {
 return $ruleset->{$chain} ? 1 : undef;
 }
 
-sub ruleset_addrule {
+sub ruleset_addrule_old {
my ($ruleset, $chain, $rule) = @_;
 
die "no such chain '$chain'\n" if !$ruleset->{$chain};
@@ -1976,12 +2001,20 @@ sub ruleset_addrule {
push @{$ruleset->{$chain}}, "-A $chain $rule";
 }
 
+sub ruleset_addrule {
+   my ($ruleset, $chain, $match, $action, $log) = @_;
+
+   die "no such chain '$chain'\n" if !$ruleset->{$chain};
+
+   push @{$ruleset->{$chain}}, "-A $chain $match $action";
+}
+
 sub ruleset_insertrule {
-   my ($ruleset, $chain, $rule) = @_;
+   my ($ruleset, $chain, $match, $action, $log) = @_;
 
die "no such chain '$chain'\n" if !$ruleset->{$chain};
 
-   unshift @{$ruleset->{$chain}}, "-A $chain $rule";
+   unshift @{$ruleset->{$chain}}, "-A $chain $match $action";
 }
 
 sub get_log_rule_base {
@@ -1998,15 +2031,14 @@ sub get_log_rule_base {
 }
 
 sub ruleset_addlog {
-my ($ruleset, $chain, $vmid, $msg, $loglevel, $rule) = @_;
+my ($ruleset, 

[pve-devel] [PATCH v4 firewall 03/13] integrate logging into ruleset_addrule

2017-10-18 Thread Tom Weber
Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm | 33 ++---
 1 file changed, 10 insertions(+), 23 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index f1aecef..ad59267 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -2002,10 +2002,14 @@ sub ruleset_addrule_old {
 }
 
 sub ruleset_addrule {
-   my ($ruleset, $chain, $match, $action, $log) = @_;
+   my ($ruleset, $chain, $match, $action, $log, $logmsg, $vmid) = @_;
 
die "no such chain '$chain'\n" if !$ruleset->{$chain};
 
+   if (defined($log) && $log) {
+   my $logaction = get_log_rule_base($chain, $vmid, $logmsg, $log);
+   push @{$ruleset->{$chain}}, "-A $chain $match $logaction";
+   }
push @{$ruleset->{$chain}}, "-A $chain $match $action";
 }
 
@@ -2020,27 +2024,15 @@ sub ruleset_insertrule {
 sub get_log_rule_base {
 my ($chain, $vmid, $msg, $loglevel) = @_;
 
-die "internal error - no log level" if !defined($loglevel);
-
 $vmid = 0 if !defined($vmid);
+$msg = "" if !defined($msg);
 
 # Note: we use special format for prefix to pass further
-# info to log daemon (VMID, LOGVELEL and CHAIN)
+# info to log daemon (VMID, LOGLEVEL and CHAIN)
 
 return "-j NFLOG --nflog-prefix \":$vmid:$loglevel:$chain: $msg\"";
 }
 
-sub ruleset_addlog {
-my ($ruleset, $chain, $vmid, $msg, $loglevel, $match) = @_;
-
-return if !defined($loglevel);
-
-my $logaction = get_log_rule_base($chain, $vmid, $msg, $loglevel);
-
-$match = "" if !defined $match;
-ruleset_addrule($ruleset, $chain, $match, $logaction);
-}
-
 sub ruleset_add_chain_policy {
 my ($ruleset, $chain, $ipversion, $vmid, $policy, $loglevel, 
$accept_action) = @_;
 
@@ -2053,15 +2045,11 @@ sub ruleset_add_chain_policy {
 
ruleset_addrule($ruleset, $chain, "", "-j PVEFW-Drop");
 
-   ruleset_addlog($ruleset, $chain, $vmid, "policy $policy: ", $loglevel);
-
-   ruleset_addrule($ruleset, $chain, "", "-j DROP");
+   ruleset_addrule($ruleset, $chain, "", "-j DROP", $loglevel, "policy 
$policy: ", $vmid);
 } elsif ($policy eq 'REJECT') {
ruleset_addrule($ruleset, $chain, "", "-j PVEFW-Reject");
 
-   ruleset_addlog($ruleset, $chain, $vmid, "policy $policy: ", $loglevel);
-
-   ruleset_addrule($ruleset, $chain, "", "-g PVEFW-reject");
+   ruleset_addrule($ruleset, $chain, "", "-g PVEFW-reject", $loglevel, 
"policy $policy:", $vmid);
 } else {
# should not happen
die "internal error: unknown policy '$policy'";
@@ -2093,8 +2081,7 @@ sub ruleset_chain_add_input_filters {
 if ($cluster_conf->{ipset}->{blacklist}){
if (!ruleset_chain_exist($ruleset, "PVEFW-blacklist")) {
ruleset_create_chain($ruleset, "PVEFW-blacklist");
-   ruleset_addlog($ruleset, "PVEFW-blacklist", 0, "DROP: ", $loglevel) 
if $loglevel;
-   ruleset_addrule($ruleset, "PVEFW-blacklist", "", "-j DROP");
+   ruleset_addrule($ruleset, "PVEFW-blacklist", "", "-j DROP", 
$loglevel, "DROP: ");
}
my $ipset_chain = compute_ipset_chain_name(0, 'blacklist', $ipversion);
ruleset_addrule($ruleset, $chain, "-m set --match-set ${ipset_chain} 
src", "-j PVEFW-blacklist");
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v4 firewall 05/13] make $pve_std_chains a copy of $pve_std_chains_conf

2017-10-18 Thread Tom Weber
create a new $pve_std_chains with $pve_std_chains_conf as template on
every compilation of the rules. This avoids persitant changes to the
$pve_std_chains and makes it easier to read the std_chains configuration
from external config files (later to implement).

Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 634ff90..c7ddd10 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -20,6 +20,7 @@ use IO::File;
 use Net::IP;
 use PVE::Tools qw(run_command lock_file dir_glob_foreach);
 use Encode;
+use Storable qw(dclone);
 
 my $hostfw_conf_filename = "/etc/pve/local/host.fw";
 my $pvefw_conf_dir = "/etc/pve/firewall";
@@ -548,7 +549,8 @@ my $FWACCEPTMARK_ON  = "0x8000/0x8000";
 my $FWACCEPTMARK_OFF = "0x/0x8000";
 
 my $pve_std_chains = {};
-$pve_std_chains->{4} = {
+my $pve_std_chains_conf = {};
+$pve_std_chains_conf->{4} = {
 'PVEFW-SET-ACCEPT-MARK' => [
{ target => "-j MARK --set-mark $FWACCEPTMARK_ON" },
 ],
@@ -641,7 +643,7 @@ $pve_std_chains->{4} = {
 ],
 };
 
-$pve_std_chains->{6} = {
+$pve_std_chains_conf->{6} = {
 'PVEFW-SET-ACCEPT-MARK' => [
{ target => "-j MARK --set-mark $FWACCEPTMARK_ON" },
 ],
@@ -3354,6 +3356,9 @@ sub compile {
 
 my $vmfw_configs;
 
+# fixme: once we read standard chains from config this needs to be put in 
test/standard cases below
+$pve_std_chains = dclone($pve_std_chains_conf);
+
 if ($vmdata) { # test mode
my $testdir = $vmdata->{testdir} || die "no test directory specified";
my $filename = "$testdir/cluster.fw";
-- 
2.7.4

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v4 firewall 08/13] implement ipt_rule_to_cmds, ruleset_add_ipt_cmd

2017-10-18 Thread Tom Weber
ipt_rule_to_cmds converts a %rule to an array of iptables commands
ruleset_add_ipt_cmd adds such an iptables command to a chain
ruleset_generate_rule uses these now
ruleset_generate_rule_old is an interim workaround

Signed-off-by: Tom Weber 
---
 src/PVE/Firewall.pm | 151 
 1 file changed, 140 insertions(+), 11 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index 89a8ef3..b492086 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -146,14 +146,15 @@ my $log_level_hash = {
 # %rule
 #
 # name => optional
+# enable => [0|1]
 # action =>
 # proto =>
-# sport =>
-# dport =>
+# sport => port[,port[,port]].. or port:port
+# dport => port[,port[,port]].. or port:port
 # log => optional, loglevel
 # logmsg => optional, logmsg - overwrites default
-# iface_in
-# iface_out
+# iface_in => incomin interface
+# iface_out => outgoing interface
 # match => optional, overwrites generation of match
 # target => optional, overwrites action
 
@@ -1844,6 +1845,104 @@ sub ipt_gen_src_or_dst_match {
 return $match;
 }
 
+# convert a %rule to an array of iptables commands
+sub ipt_rule_to_cmds {
+my ($rule, $chain, $ipversion, $cluster_conf, $fw_conf, $vmid) = @_;
+
+die "ipt_rule_to_cmds unable to handle macro" if $rule->{macro}; #should 
not happen
+
+my @match = ();
+
+if (defined $rule->{match}) {
+   push @match, $rule->{match};
+} else {
+   push @match, "-i $rule->{iface_in}" if $rule->{iface_in};
+   push @match, "-o $rule->{iface_out}" if $rule->{iface_out};
+
+   if ($rule->{source}) {
+   push @match, ipt_gen_src_or_dst_match($rule->{source}, 's', 
$ipversion, $cluster_conf, $fw_conf);
+   }
+   if ($rule->{dest}) {
+   push @match, ipt_gen_src_or_dst_match($rule->{dest}, 'd', 
$ipversion, $cluster_conf, $fw_conf);
+   }
+
+   if (my $proto = $rule->{proto}) {
+   push @match, "-p $proto";
+
+   my $nbdport = defined($rule->{dport}) ? 
parse_port_name_number_or_range($rule->{dport}, 1) : 0;
+   my $nbsport = defined($rule->{sport}) ? 
parse_port_name_number_or_range($rule->{sport}, 0) : 0;
+
+   my $multiport = 0;
+   $multiport++ if $nbdport > 1;
+   $multiport++ if $nbsport > 1;
+
+   push @match, "--match multiport" if $multiport;
+
+   die "multiport: option '--sports' cannot be used together with 
'--dports'\n"
+   if ($multiport == 2) && ($rule->{dport} ne $rule->{sport});
+
+   if ($rule->{dport}) {
+   if ($proto eq 'icmp') {
+   # Note: we use dport to store --icmp-type
+   die "unknown icmp-type '$rule->{dport}'\n"
+   if $rule->{dport} !~ /^\d+$/ && 
!defined($icmp_type_names->{$rule->{dport}});
+   push @match, "-m icmp --icmp-type $rule->{dport}";
+   } elsif ($proto eq 'icmpv6') {
+   # Note: we use dport to store --icmpv6-type
+   die "unknown icmpv6-type '$rule->{dport}'\n"
+   if $rule->{dport} !~ /^\d+$/ && 
!defined($icmpv6_type_names->{$rule->{dport}});
+   push @match, "-m icmpv6 --icmpv6-type $rule->{dport}";
+   } elsif (!$PROTOCOLS_WITH_PORTS->{$proto}) {
+   die "protocol $proto does not have ports\n";
+   } else {
+   if ($nbdport > 1) {
+   if ($multiport == 2) {
+   push @match,  "--ports $rule->{dport}";
+   } else {
+   push @match, "--dports $rule->{dport}";
+   }
+   } else {
+   push @match, "--dport $rule->{dport}";
+   }
+   }
+   }
+
+   if ($rule->{sport}) {
+   die "protocol $proto does not have ports\n"
+   if !$PROTOCOLS_WITH_PORTS->{$proto};
+   if ($nbsport > 1) {
+   push @match, "--sports $rule->{sport}" if $multiport != 2;
+   } else {
+   push @match, "--sport $rule->{sport}";
+   }
+   }
+   } elsif ($rule->{dport} || $rule->{sport}) {
+   die "destination port '$rule->{dport}', but no protocol 
specified\n" if $rule->{dport};
+   die "source port '$rule->{sport}', but no protocol specified\n" if 
$rule->{sport};
+   }
+

Re: [pve-devel] pve-firewall : nftables ?

2018-11-28 Thread Tom Weber
Am Dienstag, den 27.11.2018, 14:55 +0100 schrieb Wolfgang Bumiller:
> The pve-firewall code is very iptables-oriented though, and I'm not
> sure
> if maybe we're not better off splitting the rule-generating part out
> and write the nftables variant from scratch... The iptables part
> would
> be considered feature-frozen from that point on I'd say/hope/think...

Yes, I think in the long term rule generation really needs to be
separated completely from rule definition. Right now there's a lot of
implicit iptable rule generation inside pve-firewall, which makes it a
real pain.

Just to throw in another idea:
How about using something like shorewall (shorewall.net) to handle the
whole firewall generation code from a higher level. I'm using it for in
really complex setups for years and i am very happy with it. (I know
this won't solve the nftables problem right now).

  Tom


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] firewall: Razor Macro broken and opens Firewall

2019-03-30 Thread Tom Weber
Hi, in the middle of a weekend migration i realized that the 'Razor'
Macro is broken and basically disables ALL firewalling for a Container,
at least when used in a Security Group.

Looking at Firewall.pm
..
'RNDC' => [
"BIND remote management protocol",
{ action => 'PARAM', proto => 'tcp', dport => '953' },
],
'Razor' => [
"Razor Antispam System",
{ action => 'ACCEPT', proto => 'tcp', dport => '2703' },
],
'Rdate' => [
"Remote time retrieval (rdate)",
{ action => 'PARAM', proto => 'tcp', dport => '37' },
],
..

The Problem seems obvious (might have even missed that one myself when
I was working on this some time ago).

As mentioned, I'm in the middle of a bigger migration so just a short
notice and no patch (fix seems obvious)... 

I consider this serious because it silently disables ALL firewalling
(at least for me). Even though Razor Macro probably isn't used often.

Regards,
  Tom




___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] rfc : pve-network : idea to generate and reload config accross the nodes

2019-04-04 Thread Tom Weber
Am Mittwoch, den 03.04.2019, 07:03 +0200 schrieb Dietmar Maurer:
> > I think, something easy, is that we could have a copy of each
> > /etc/network/interfaces of each node in
> > /etc/pve/nodes//interfaces.
> > (could be done we a change is done in gui local netowrk, or local
> > network daemon copy it at regular interval in case of manual change
> > for example).
> > 
> > 
> > Like this, it's very easy, when a network change is one at
> > datacenter level, we can directly test it on all network interfaces
> > of all nodes ( /etc/pve/nodes/*/interfaces). (in the api endpoint),

/etc/network/interfaces is only a small part of actual network
configuration.

> I is still unclear to me how you do those tests? AFAIK, ifreload does
> not have a --dry-run option. Even when it has such option, it would
> need access to the local node? (to see what interfaces exists, ...).
> 
> So if you really need/want to test before apply, we could add and API
> call for that:
> 
> POST /api2/json/nodes//test_network_changes
> 
> We can then add a TEST button to the GUI, or call those this test API
> on all nodes before we apply changes.
> 
> > and then write directly the conf. (no need vnet.new tmp file).
> 
> I think network configuration is really complex, and we should avoid
> to do anything automatically.
> I would prefer and "APPLY" button, so that I have full control over
> when network changes happen.
> Maybe an extra "TEST" button would be also helpful.

Probably helpful but as you said, network configuration can be really
complex (good luck finding my tinc bridges in the interfaces file - let
alone developing a test).

Why not have a static (host specific) part that never ever gets touched
by pve. Usually all thats needed to get the node into the cluster.
Additional parts can be managed via the cluster - selectable on which
nodes (including all) to apply.
If you select/mark a node, try to apply, if that fails, fall back to
your static basic configuration above and show errors so the admin can
fix, ideally with the node still in the cluster.

So you can test on single test-nodes if you need or apply on all if
you're sure about your changes.

We don't try to prevent shooting our feet at other places either (like
firewalling).

Best,
  Tom










___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [RFC container] mountpoints: create parent dirs with correct owner

2019-07-24 Thread Tom Weber
it seems like you're working in an area of code that could also be
relevant for my (small) problem from:
https://pve.proxmox.com/pipermail/pve-devel/2017-September/028814.html
https://pve.proxmox.com/pipermail/pve-devel/2017-October/029004.html

or maybe this could also be a problem if your mps are owned by user not
root in an unprivileged container.

i didn't really dig into your patch, just a hint.

Regards,
  Tom


Am Mittwoch, den 24.07.2019, 13:37 +0200 schrieb Fabian Grünbichler:
> otherwise unprivileged containers might end up with directories that
> they cannot modify since they are owned by the user root in the host
> namespace, instead of root inside the container.
> 
> note: the problematic behaviour is only exhibited when an
> intermediate
> directory needs to be created, e.g. a mountpoint /test/mp gets
> mounted,
> and /test does not yet exist.
> 
> Signed-off-by: Fabian Grünbichler 
> ---
> Notes:
> requires fchownat support in PVE::Tools - see other patch and
> bump
> build-depends + depends accordingly after applying!
> 
> I am not sure whether this is 100% correct w.r.t. error edge
> cases, since we
> potentially die after mkdirat without calling fchownat. it is for
> sure better
> than the status quo though ;)
> 
> thank you Dietmar for noticing the buggy behaviour!
> 
>  src/PVE/LXC.pm| 27 ---
>  src/PVE/VZDump/LXC.pm |  7 +--
>  src/lxc-pve-prestart-hook |  4 +++-
>  3 files changed, 24 insertions(+), 14 deletions(-)
> 
> diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
> index 2252685..0a1d95a 100644
> --- a/src/PVE/LXC.pm
> +++ b/src/PVE/LXC.pm
> @@ -1177,13 +1177,15 @@ sub mount_all {
>  my $volid_list = PVE::LXC::Config->get_vm_volumes($conf);
>  PVE::Storage::activate_volumes($storage_cfg, $volid_list);
>  
> +my (undef, $rootuid, $rootgid) = parse_id_maps($conf);
> +
>  eval {
>   PVE::LXC::Config->foreach_mountpoint($conf, sub {
>   my ($ms, $mountpoint) = @_;
>  
>   $mountpoint->{ro} = 0 if $ignore_ro;
>  
> - mountpoint_mount($mountpoint, $rootdir, $storage_cfg);
> + mountpoint_mount($mountpoint, $rootdir, $storage_cfg,
> undef, $rootuid, $rootgid);
>  });
>  };
>  if (my $err = $@) {
> @@ -1258,8 +1260,8 @@ sub run_with_loopdev {
>  #   * the 2nd deepest directory (parent of the above)
>  #   * directory name of the last directory
>  # So that the path $2/$3 should lead to $1 afterwards.
> -sub walk_tree_nofollow($$$) {
> -my ($start, $subdir, $mkdir) = @_;
> +sub walk_tree_nofollow($$$;$$) {
> +my ($start, $subdir, $mkdir, $rootuid, $rootgid) = @_;
>  
>  # splitdir() returns '' for empty components including the
> leading /
>  my @comps = grep { length($_)>0 } File::Spec->splitdir($subdir);
> @@ -1288,6 +1290,9 @@ sub walk_tree_nofollow($$$) {
>  
>   $next = PVE::Tools::openat(fileno($fd), $component,
> O_NOFOLLOW | O_DIRECTORY);
>   die "failed to create path: $dir: $!\n" if !$next;
> +
> + PVE::Tools::fchownat(fileno($next), '', $rootuid, $rootgid,
> PVE::Tools::AT_EMPTY_PATH)
> + if defined($rootuid) && defined($rootgid);
>   }
>  
>   close $second if defined($last_component);
> @@ -1381,17 +1386,17 @@ sub bindmount {
>  # from $rootdir and $mount and walk the path from $rootdir to the
> final
>  # directory to check for symlinks.
>  sub __mount_prepare_rootdir {
> -my ($rootdir, $mount) = @_;
> +my ($rootdir, $mount, $rootuid, $rootgid) = @_;
>  $rootdir =~ s!/+!/!g;
>  $rootdir =~ s!/+$!!;
>  my $mount_path = "$rootdir/$mount";
> -my ($mpfd, $parentfd, $last_dir) = walk_tree_nofollow($rootdir,
> $mount, 1);
> +my ($mpfd, $parentfd, $last_dir) = walk_tree_nofollow($rootdir,
> $mount, 1, $rootuid, $rootgid);
>  return ($rootdir, $mount_path, $mpfd, $parentfd, $last_dir);
>  }
>  
>  # use $rootdir = undef to just return the corresponding mount path
>  sub mountpoint_mount {
> -my ($mountpoint, $rootdir, $storage_cfg, $snapname) = @_;
> +my ($mountpoint, $rootdir, $storage_cfg, $snapname, $rootuid,
> $rootgid) = @_;
>  
>  my $volid = $mountpoint->{volume};
>  my $mount = $mountpoint->{mp};
> @@ -1408,7 +1413,7 @@ sub mountpoint_mount {
>  
>  if (defined($rootdir)) {
>   ($rootdir, $mount_path, $mpfd, $parentfd, $last_dir) =
> - __mount_prepare_rootdir($rootdir, $mount);
> + __mount_prepare_rootdir($rootdir, $mount, $rootuid,
> $rootgid);
>  }
>  
>  my ($storage, $volname) = PVE::Storage::parse_volume_id($volid,
> 1);
> @@ -2007,7 +2012,7 @@ sub run_unshared {
>  }
>  
>  my $copy_volume = sub {
> -my ($src_volid, $src, $dst_volid, $dest, $storage_cfg,
> $snapname, $bwlimit) = @_;
> +my ($src_volid, $src, $dst_volid, $dest, $storage_cfg,
> $snapname, $bwlimit, $rootuid,  $rootgid) = @_;
>  
>  my $src_mp = { volume => $src_volid, mp => '/', ro => 1 };
>  $src_mp->{type}