all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Gabriel Goller <g.goller@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH ve-rs v2 2/2] fix: firewall: introduce iptables to nftables mapping for icmpv6-types
Date: Mon,  6 Oct 2025 12:19:30 +0200	[thread overview]
Message-ID: <20251006101933.90655-3-g.goller@proxmox.com> (raw)
In-Reply-To: <20251006101933.90655-1-g.goller@proxmox.com>

Some of the iptables icmpv6-type options we expose in the UI don't exist
in nftables, so we need to make a mapping with a custom type and code to
support them. There are also some options that have been renamed in
nftables, which can be mapped to the new name:
https://wiki.nftables.org/wiki-nftables/index.php/Supported_features_compared_to_xtables#icmp6

Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
---
 proxmox-ve-config/src/firewall/cluster.rs     |  9 +--
 .../src/firewall/types/rule_match.rs          | 72 ++++++++++++++++---
 2 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/proxmox-ve-config/src/firewall/cluster.rs b/proxmox-ve-config/src/firewall/cluster.rs
index d588302b0783..5e1143fb2617 100644
--- a/proxmox-ve-config/src/firewall/cluster.rs
+++ b/proxmox-ve-config/src/firewall/cluster.rs
@@ -143,7 +143,7 @@ mod tests {
         log::{LogLevel, LogRateLimitTimescale},
         rule::{Kind, RuleGroup},
         rule_match::{
-            Icmpv6, Icmpv6Code, IpAddrMatch, IpMatch, Ports, Protocol, RuleMatch, Tcp, Udp,
+            Icmpv6, Icmpv6Code, Icmpv6Type, IpAddrMatch, IpMatch, Ports, Protocol, RuleMatch, Tcp, Udp
         },
     };
 
@@ -331,9 +331,10 @@ IN BGP(REJECT) -log crit -source 1.2.3.4
                             .unwrap()
                         ))),
                     }),
-                    proto: Some(Protocol::Icmpv6(Icmpv6::new_code(Icmpv6Code::Named(
-                        "port-unreachable"
-                    )))),
+                    proto: Some(Protocol::Icmpv6(Icmpv6::new_ty_and_code(
+                        Icmpv6Type::Numeric(1),
+                        Icmpv6Code::Numeric(4)
+                    ))),
                     log: Some(LogLevel::Nolog),
                     ..Default::default()
                 }),
diff --git a/proxmox-ve-config/src/firewall/types/rule_match.rs b/proxmox-ve-config/src/firewall/types/rule_match.rs
index f99a936b454a..99625d0e31a5 100644
--- a/proxmox-ve-config/src/firewall/types/rule_match.rs
+++ b/proxmox-ve-config/src/firewall/types/rule_match.rs
@@ -664,10 +664,10 @@ impl Icmpv6 {
         }
     }
 
-    pub fn new_code(code: Icmpv6Code) -> Self {
+    pub fn new_ty_and_code(ty: Icmpv6Type, code: Icmpv6Code) -> Self {
         Self {
+            ty: Some(ty),
             code: Some(code),
-            ..Default::default()
         }
     }
 
@@ -695,23 +695,73 @@ enum IcmpTypeMap {
     Custom((u8, u8)),
 }
 
+/// Some icmp_types are not supported by nftables. See:
+/// https://wiki.nftables.org/wiki-nftables/index.php/Supported_features_compared_to_xtables#icmp6
+/// Some have an exact equivalent in nftables and for some others we need to set a custom type and
+/// code combination.
+#[sortable]
+const IPTABLES_ICMPV6_TYPES_MAPPING: [(&str, IcmpTypeMap); 19] = sorted!([
+    ("no-route", IcmpTypeMap::Custom((1, 0))),
+    ("communication-prohibited", IcmpTypeMap::Custom((1, 1))),
+    ("beyond-scope", IcmpTypeMap::Custom((1, 2))),
+    ("address-unreachable", IcmpTypeMap::Custom((1, 3))),
+    ("port-unreachable", IcmpTypeMap::Custom((1, 4))),
+    ("failed-policy", IcmpTypeMap::Custom((1, 5))),
+    ("reject-route'", IcmpTypeMap::Custom((1, 6))),
+    ("ttl-zero-during-transit", IcmpTypeMap::Custom((3, 0))),
+    ("ttl-zero-during-reassembly", IcmpTypeMap::Custom((3, 1))),
+    ("bad-header", IcmpTypeMap::Custom((4, 0))),
+    ("unknown-header-type", IcmpTypeMap::Custom((4, 1))),
+    ("unknown-option", IcmpTypeMap::Custom((4, 2))),
+    ("router-solicitation", IcmpTypeMap::Map("nd-router-solicit")),
+    ("router-advertisement", IcmpTypeMap::Map("nd-router-advert")),
+    (
+        "neighbor-solicitation",
+        IcmpTypeMap::Map("nd-neighbor-solicit")
+    ),
+    (
+        "neighbour-solicitation",
+        IcmpTypeMap::Map("nd-neighbor-solicit")
+    ),
+    (
+        "neighbor-advertisement",
+        IcmpTypeMap::Map("nd-neighbor-advert")
+    ),
+    (
+        "neighbour-advertisement",
+        IcmpTypeMap::Map("nd-neighbor-advert")
+    ),
+    ("redirect", IcmpTypeMap::Map("nd-redirect")),
+]);
+
 impl FromStr for Icmpv6 {
     type Err = Error;
 
     fn from_str(s: &str) -> Result<Self, Self::Err> {
         let mut this = Self::default();
 
-        if let Ok(ty) = s.parse() {
-            this.ty = Some(ty);
-            return Ok(this);
+        // Some icmpv6 types exist in iptables, but do not in nftables. Some of these map exactly
+        // onto other types, for others we need to use a custom type/code combination.
+        if let Ok(index) = IPTABLES_ICMPV6_TYPES_MAPPING.binary_search_by(|v| v.0.cmp(s)) {
+            match IPTABLES_ICMPV6_TYPES_MAPPING[index].1 {
+                IcmpTypeMap::Map(mapped_nftables_type) => {
+                    this.ty = Some(Icmpv6Type::Named(mapped_nftables_type));
+                    return Ok(this);
+                }
+                IcmpTypeMap::Custom((ty, code)) => {
+                    this.ty = Some(Icmpv6Type::Numeric(ty));
+                    this.code = Some(Icmpv6Code::Numeric(code));
+                    return Ok(this);
+                }
+            }
         }
 
-        if let Ok(code) = s.parse() {
-            this.code = Some(code);
+        if let Ok(ty) = s.parse() {
+            this.ty = Some(ty);
             return Ok(this);
         }
 
-        bail!("supplied string is neither a valid icmpv6 type nor code");
+        bail!("supplied string is not a valid icmpv6 type");
     }
 }
 
@@ -1015,13 +1065,13 @@ mod tests {
             }
         );
 
-        icmp = "admin-prohibited".parse().expect("valid icmpv6 code");
+        icmp = "unknown-header-type".parse().expect("valid icmpv6 type");
 
         assert_eq!(
             icmp,
             Icmpv6 {
-                ty: None,
-                code: Some(Icmpv6Code::Named("admin-prohibited"))
+                ty: Some(Icmpv6Type::Numeric(4)),
+                code: Some(Icmpv6Code::Numeric(1))
             }
         );
     }
-- 
2.47.3



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


  parent reply	other threads:[~2025-10-06 10:20 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-06 10:19 [pve-devel] [PATCH proxmox-firewall/ve-rs v2 0/3] Fix ICMP types in nftables Gabriel Goller
2025-10-06 10:19 ` [pve-devel] [PATCH ve-rs v2 1/2] fix: firewall: introduce iptables to nftables mapping for icmp-types Gabriel Goller
2025-10-07 11:43   ` Gabriel Goller
2025-10-06 10:19 ` Gabriel Goller [this message]
2025-10-06 10:19 ` [pve-devel] [PATCH proxmox-firewall v2 1/1] tests: add icmpv6 type mapping test Gabriel Goller
2025-10-08 13:17 ` [pve-devel] [PATCH proxmox-firewall/ve-rs v2 0/3] Fix ICMP types in nftables Stefan Hanreich

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=20251006101933.90655-3-g.goller@proxmox.com \
    --to=g.goller@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal