public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Hannes Laimer <h.laimer@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH access-control/cluster/docs/manager/network/proxmox{-ve-rs,-firewall,-perl-rs} v3 00/38] sdn: add microsegmentation support
Date: Tue, 22 Sep 2026 12:09:04 +0200	[thread overview]
Message-ID: <20260922100943.1151484-1-h.laimer@proxmox.com> (raw)

Guests on a vnet are separated only by IP addressing and the guest
firewall. Its address rules have to follow every move and renumbering.
No identity crosses nodes with a frame, and tags and names carry no
policy.

This series adds a group-based policy with a datacenter panel over
/etc/pve/sdn/microseg.cfg and /cluster/sdn/microseg. A rule has a
priority and a verdict and matches a source and a destination predicate
over groups, any, all or exact. It can be narrowed to a protocol and
ports, an ICMP type or a firewall macro. Assignments bind guest
interfaces to groups by guest, tag or name regex, and a subgroup member
is in every group above it. VXLAN and EVPN zones gain a vxlan-gbp option
that carries the identity across nodes. The host stamps it where a frame
enters the bridge, so a guest cannot forge its own.

Default is deny. Rules are stateless and directional, so a reply needs
its own allow, or the rule is marked both ways, which is exactly that
pair with the ports swapped. The highest priority wins, at a tie the
more specific all and exact predicates decide, and deny wins among
equals. Identities stay stable across config changes, and a retired one
is reused only after a quarantine. A full apply swaps a node's policy in
one transaction, and a guest interface is enforced before it is bridged.
A running config a node cannot read fails every guest start there, one
it cannot parse or build fails the start of guests with assigned
interfaces, as does an interface headed for an Open vSwitch port without
a firewall bridge. One already on such a port is named in the node's
network reload task and stays unenforced until the firewall option is
set. A guest matched after the last apply stays unmanaged until the next
one.

proxmox-ve-config carries the types, the identity engine and the desired
state, the policy in a form no enforcing mechanism depends on.
pve-cluster adds the observed file, pve-access-control the ACL path.
pve-network holds the config, the API, the zone option and the plug
trigger. proxmox-microseg, a library crate in the proxmox-firewall
workspace, renders the desired state into a bridge family nftables
table, and pve-rs binds it next to the config, so Perl applies it on an
SDN apply and on a NIC plug. pve-manager adds the panel and applies on
network reload. pve-docs adds the section. Connection tracking, rule
logging, the SRv6 carrier and an eBPF plane are left out on purpose.

libpve-network-perl loads only with the pve-cluster of this series and
needs its libpve-rs-perl, or every guest start on the node fails at the
plug. It gains dependencies on nftables and libpve-guest-common-perl.
The API package needs the libpve-access-control of this series, or no
ACL can be granted on /sdn/microseg and its endpoints only see what /sdn
passes down. pve-manager builds only with the pve-docs of this series,
whose anchors its help buttons name, and at runtime needs the new
libpve-network-perl, since its network reload applies the microseg
policy through it. pve-rs builds against the proxmox-microseg crate,
which pulls in proxmox-nftables. pve-rs and the crate both need a
proxmox-ve-config with the new module, and so does the proxmox-firewall
source package that carries the crate. None of these floors is bumped
here. The ifupdown2 vxlan-gbp attribute and four proxmox-nftables
patches (building without the config extension, mark-keyed verdict
maps, shared protocol rendering, crate packaging) are sent separately.

# changelog
v3:
 - data plane moved from eBPF programs to an nftables bridge-family
   table, proxmox-ebpf is gone and the data plane is a library crate in
   the proxmox-firewall workspace that pve-rs binds, without an agent
   binary or a boot-time unit since the first plug builds the table, the
   desired state it renders lives in proxmox-ve-config, and
   libpve-network-perl depends on nftables
 - rules can be narrowed to a protocol, ports, an ICMP type or a
   firewall macro, the protocol and port rendering is shared with the
   firewall
 - a rule can be marked both ways, which applies it with the predicates
   and the ports swapped as well, under one id, so the reply rule of a
   stateless pair no longer has to be written by hand
 - groups can form a hierarchy, membership in a subgroup implies the
   groups above it, and for all and exact predicates specificity breaks
   priority ties so a subgroup rule outranks its parent's
 - a plug fails when the running config cannot be read, or cannot be
   parsed or built and the NIC is assigned, or an assigned NIC would
   become an Open vSwitch port with no firewall bridge, an unreachable
   pmxcfs fails the plug instead of reading as an empty config, and a
   realized set without an identity fails the apply instead of passing
   as untagged
 - the microseg endpoints check their privileges on a new /sdn/microseg
   ACL path, added by a pve-access-control patch in the series
 - the overview endpoint reports identity id space usage, shown in the
   tree header
 - the pve-cluster patch also registers the file with the version array
   pmxcfs keeps for observed files
 - validation rejects mark 0 for a group, `untagged` in an all or exact
   destination, and `untagged` next to real groups in an all or exact
   source
 - an assignment naming an interface index is realized whether or not
   the guest has that interface yet, and tag matcher tags are
   normalized like guest tags
 - the running config stores the realized assignments per group set
   with per-guest interface lists, so the file stays small at scale
 - the network reload warns about an assigned interface that is already
   up on an Open vSwitch port without a firewall bridge, since only a
   plug can refuse one
 - two-column rule editor reusing the firewall's selectors, the tree
   shows subgroups
 - the SRv6 carrier is out of the series, it belongs with an SRv6 zone
 - the ifupdown2 `vxlan-gbp` attribute and the proxmox-nftables
   additions with the crate packaging are sent as standalone patches,
   the zone option stays in the series and the evpn vxlan-learning fix
   is folded into it
 - docs updated, cover letter rewritten
v2:
 - core model reworked: each interface now holds a *set* of groups
   compiled into a per-NIC wire identity, replacing the single-group
   parent/child tree
 - rules gained explicit `src`/`dst` predicates (any/all/exact) and a
   `prio`, replacing the implicit tree-distance ordering
 - `untagged` is now a nameable built-in group (mark 0)
 - assignments are additive: a NIC's set is the union of all that
   resolve to it
 - added tag-matcher and name-regex assignments
 - rule and dynamic-assignment ids are now generated
 - identity allocation is fresh-first with quarantined reclamation, so
   churn cannot exhaust the id space
 - split the SRv6 carrier support into droppable tail patches
 - updated docs
 - updated cover-letter


proxmox-ve-rs:

Hannes Laimer (8):
  ve-config: firewall: add a constructor for sctp matches
  ve-config: sdn: add microseg signature-identity engine
  ve-config: sdn: add microseg config types
  ve-config: sdn: microseg: add tag matcher
  ve-config: sdn: microseg: add name regex matcher
  ve-config: sdn: microseg: narrow rules by protocol and ports
  ve-config: sdn: microseg: add group hierarchy
  ve-config: sdn: microseg: add the desired state

 .../src/firewall/types/rule_match.rs          |    4 +
 .../src/sdn/microseg/identity.rs              |  625 +++
 proxmox-ve-config/src/sdn/microseg/mod.rs     | 3819 +++++++++++++++++
 proxmox-ve-config/src/sdn/microseg/state.rs   |  316 ++
 proxmox-ve-config/src/sdn/mod.rs              |    1 +
 5 files changed, 4765 insertions(+)
 create mode 100644 proxmox-ve-config/src/sdn/microseg/identity.rs
 create mode 100644 proxmox-ve-config/src/sdn/microseg/mod.rs
 create mode 100644 proxmox-ve-config/src/sdn/microseg/state.rs


proxmox-firewall:

Hannes Laimer (5):
  nftables: build without the config extension
  nftables: add support for mark-keyed verdict maps
  nftables: move protocol match rendering into the lib
  nftables: package the crate for debcargo
  microseg: add the SDN microsegmentation data plane

 .gitignore                                    |   4 +
 Cargo.toml                                    |   4 +
 Makefile                                      |  12 +-
 build.sh                                      |  46 ++
 proxmox-firewall/src/rule.rs                  | 166 +---
 proxmox-microseg/Cargo.toml                   |  22 +
 proxmox-microseg/debian/changelog             |   6 +
 proxmox-microseg/debian/control               |  46 ++
 proxmox-microseg/debian/copyright             |  18 +
 proxmox-microseg/debian/debcargo.toml         |   7 +
 proxmox-microseg/debian/source/format         |   1 +
 proxmox-microseg/src/dataplane.rs             |  12 +
 proxmox-microseg/src/lib.rs                   |  41 +
 proxmox-microseg/src/nft.rs                   | 458 +++++++++++
 proxmox-microseg/src/nic.rs                   |  54 ++
 proxmox-microseg/src/running_config.rs        |  28 +
 ..._tests__empty_state_removes_the_table.snap |  24 +
 ..._tests__full_apply_replaces_the_table.snap | 726 ++++++++++++++++++
 ...t__tests__nic_apply_adds_its_elements.snap |  46 ++
 proxmox-nftables/Cargo.toml                   |   7 +-
 proxmox-nftables/debian/changelog             |   6 +
 proxmox-nftables/debian/control               |  60 ++
 proxmox-nftables/debian/copyright             |  18 +
 proxmox-nftables/debian/debcargo.toml         |   7 +
 proxmox-nftables/debian/source/format         |   1 +
 proxmox-nftables/src/expression.rs            |   3 +-
 proxmox-nftables/src/lib.rs                   |   2 +
 proxmox-nftables/src/protocol.rs              |  70 ++
 proxmox-nftables/src/statement.rs             |  10 +
 proxmox-nftables/src/types.rs                 |   1 +
 30 files changed, 1748 insertions(+), 158 deletions(-)
 create mode 100755 build.sh
 create mode 100644 proxmox-microseg/Cargo.toml
 create mode 100644 proxmox-microseg/debian/changelog
 create mode 100644 proxmox-microseg/debian/control
 create mode 100644 proxmox-microseg/debian/copyright
 create mode 100644 proxmox-microseg/debian/debcargo.toml
 create mode 100644 proxmox-microseg/debian/source/format
 create mode 100644 proxmox-microseg/src/dataplane.rs
 create mode 100644 proxmox-microseg/src/lib.rs
 create mode 100644 proxmox-microseg/src/nft.rs
 create mode 100644 proxmox-microseg/src/nic.rs
 create mode 100644 proxmox-microseg/src/running_config.rs
 create mode 100644 proxmox-microseg/src/snapshots/proxmox_microseg__nft__tests__empty_state_removes_the_table.snap
 create mode 100644 proxmox-microseg/src/snapshots/proxmox_microseg__nft__tests__full_apply_replaces_the_table.snap
 create mode 100644 proxmox-microseg/src/snapshots/proxmox_microseg__nft__tests__nic_apply_adds_its_elements.snap
 create mode 100644 proxmox-nftables/debian/changelog
 create mode 100644 proxmox-nftables/debian/control
 create mode 100644 proxmox-nftables/debian/copyright
 create mode 100644 proxmox-nftables/debian/debcargo.toml
 create mode 100644 proxmox-nftables/debian/source/format
 create mode 100644 proxmox-nftables/src/protocol.rs


pve-cluster:

Hannes Laimer (1):
  cfs: add 'sdn/microseg.cfg' to observed files

 src/PVE/Cluster.pm  | 1 +
 src/pmxcfs/status.c | 1 +
 2 files changed, 2 insertions(+)


pve-access-control:

Hannes Laimer (1):
  permissions: add ACL path for SDN microsegmentation

 src/PVE/AccessControl.pm | 1 +
 1 file changed, 1 insertion(+)


proxmox-perl-rs:

Hannes Laimer (2):
  pve-rs: sdn: add microseg config binding
  pve-rs: sdn: microseg: bind the data plane

 pve-rs/Cargo.toml                   |   2 +
 pve-rs/Makefile                     |   1 +
 pve-rs/debian/control               |   1 +
 pve-rs/src/bindings/sdn/microseg.rs | 278 ++++++++++++++++++++++++++++
 pve-rs/src/bindings/sdn/mod.rs      |   1 +
 5 files changed, 283 insertions(+)
 create mode 100644 pve-rs/src/bindings/sdn/microseg.rs


pve-network:

Hannes Laimer (8):
  sdn: zones: add vxlan-gbp option to vxlan and evpn zones
  sdn: microseg: add config, API and guest inventory
  sdn: dry-run: show pending microseg changes
  sdn: zones: trigger microseg apply on tap_plug
  sdn: microseg: add tag matcher
  sdn: microseg: add name regex matcher
  sdn: microseg: expose protocol, port and macro rule options
  sdn: microseg: expose the group parent

 debian/control                                |   2 +
 src/PVE/API2/Network/SDN.pm                   |  38 +-
 src/PVE/API2/Network/SDN/Makefile             |   2 +
 src/PVE/API2/Network/SDN/Microseg.pm          | 277 +++++++
 .../API2/Network/SDN/Microseg/Assignment.pm   | 192 +++++
 src/PVE/API2/Network/SDN/Microseg/Group.pm    | 191 +++++
 src/PVE/API2/Network/SDN/Microseg/Makefile    |  10 +
 src/PVE/API2/Network/SDN/Microseg/Rule.pm     | 194 +++++
 src/PVE/API2/Network/SDN/Zones.pm             |   8 +
 src/PVE/Network/SDN.pm                        |  36 +
 src/PVE/Network/SDN/Makefile                  |   1 +
 src/PVE/Network/SDN/Microseg.pm               | 774 ++++++++++++++++++
 src/PVE/Network/SDN/Zones.pm                  |   5 +
 src/PVE/Network/SDN/Zones/EvpnPlugin.pm       |   5 +
 src/PVE/Network/SDN/Zones/VxlanPlugin.pm      |  10 +
 .../zones/evpn/gbp/expected_controller_config |  77 ++
 .../zones/evpn/gbp/expected_sdn_interfaces    |  45 +
 src/test/zones/evpn/gbp/interfaces            |   7 +
 src/test/zones/evpn/gbp/sdn_config            |  26 +
 .../zones/vxlan/gbp/expected_sdn_interfaces   |  16 +
 src/test/zones/vxlan/gbp/interfaces           |   7 +
 src/test/zones/vxlan/gbp/sdn_config           |  11 +
 22 files changed, 1932 insertions(+), 2 deletions(-)
 create mode 100644 src/PVE/API2/Network/SDN/Microseg.pm
 create mode 100644 src/PVE/API2/Network/SDN/Microseg/Assignment.pm
 create mode 100644 src/PVE/API2/Network/SDN/Microseg/Group.pm
 create mode 100644 src/PVE/API2/Network/SDN/Microseg/Makefile
 create mode 100644 src/PVE/API2/Network/SDN/Microseg/Rule.pm
 create mode 100644 src/PVE/Network/SDN/Microseg.pm
 create mode 100644 src/test/zones/evpn/gbp/expected_controller_config
 create mode 100644 src/test/zones/evpn/gbp/expected_sdn_interfaces
 create mode 100644 src/test/zones/evpn/gbp/interfaces
 create mode 100644 src/test/zones/evpn/gbp/sdn_config
 create mode 100644 src/test/zones/vxlan/gbp/expected_sdn_interfaces
 create mode 100644 src/test/zones/vxlan/gbp/interfaces
 create mode 100644 src/test/zones/vxlan/gbp/sdn_config


pve-manager:

Hannes Laimer (9):
  network: apply microseg state on reload
  ui: firewall: register the ICMP type stores by id
  ui: sdn: zones: add vxlan-gbp checkbox to vxlan and evpn
  ui: sdn: add microsegmentation panel
  ui: sdn: dry-run: show pending microseg diff
  ui: sdn: microseg: add tag matcher
  ui: sdn: microseg: add name regex matcher
  ui: sdn: microseg: add narrowing to the rule form
  ui: sdn: microseg: show and edit the group hierarchy

 PVE/API2/Network.pm                         |   4 +
 www/css/ext6-pve.css                        |   8 +
 www/manager6/Makefile                       |   8 +
 www/manager6/Utils.js                       |  34 ++
 www/manager6/data/PermPathStore.js          |   1 +
 www/manager6/dc/Config.js                   |   8 +
 www/manager6/form/MicrosegGroupSelector.js  |  95 ++++
 www/manager6/grid/FirewallRules.js          |   2 +
 www/manager6/sdn/MicrosegView.js            |  43 ++
 www/manager6/sdn/SdnDiffView.js             |  24 +
 www/manager6/sdn/microseg/AssignmentEdit.js | 238 ++++++++++
 www/manager6/sdn/microseg/Base.js           | 123 ++++++
 www/manager6/sdn/microseg/GroupEdit.js      |  47 ++
 www/manager6/sdn/microseg/PolicyView.js     | 401 +++++++++++++++++
 www/manager6/sdn/microseg/RuleEdit.js       | 285 ++++++++++++
 www/manager6/sdn/microseg/Tree.js           | 460 ++++++++++++++++++++
 www/manager6/sdn/zones/EvpnEdit.js          |   8 +
 www/manager6/sdn/zones/VxlanEdit.js         |  11 +
 18 files changed, 1800 insertions(+)
 create mode 100644 www/manager6/form/MicrosegGroupSelector.js
 create mode 100644 www/manager6/sdn/MicrosegView.js
 create mode 100644 www/manager6/sdn/microseg/AssignmentEdit.js
 create mode 100644 www/manager6/sdn/microseg/Base.js
 create mode 100644 www/manager6/sdn/microseg/GroupEdit.js
 create mode 100644 www/manager6/sdn/microseg/PolicyView.js
 create mode 100644 www/manager6/sdn/microseg/RuleEdit.js
 create mode 100644 www/manager6/sdn/microseg/Tree.js


pve-docs:

Hannes Laimer (4):
  sdn: add VXLAN-GBP flag to evpn/vxlan zone sections
  sdn: add microsegmentation section
  sdn: microseg: document narrowed rules
  sdn: microseg: document group hierarchy and the specificity tie-break

 pvesdn.adoc | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 264 insertions(+)


Summary over all repositories:
  84 files changed, 10795 insertions(+), 160 deletions(-)

-- 
Generated by murpp 0.12.0




             reply	other threads:[~2026-09-22 10:10 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-22 10:09 Hannes Laimer [this message]
2026-09-22 10:09 ` [PATCH proxmox-ve-rs v3 01/38] ve-config: firewall: add a constructor for sctp matches Hannes Laimer
2026-09-22 10:09 ` [PATCH proxmox-ve-rs v3 02/38] ve-config: sdn: add microseg signature-identity engine Hannes Laimer
2026-09-22 10:13 ` [PATCH access-control/cluster/docs/manager/network/proxmox{-ve-rs,-firewall,-perl-rs} v3 00/38] sdn: add microsegmentation support Hannes Laimer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260922100943.1151484-1-h.laimer@proxmox.com \
    --to=h.laimer@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal