Linux Netfilter development
 help / color / mirror / Atom feed
* [PATCH nft] tests: shell: add packetpath test for nat on loopback
@ 2026-09-16  7:18 Florian Westphal
  0 siblings, 0 replies; only message in thread
From: Florian Westphal @ 2026-09-16  7:18 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Esoteric use case, but legal: NAT port rewrite over loopback.
Also add drop rule to ensure that the packet is still tracked
in input.

Assisted-by: LLM
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 .../packetpath/dumps/nat_lo.json-nft          | 152 ++++++++++++++++++
 .../testcases/packetpath/dumps/nat_lo.nft     |  14 ++
 tests/shell/testcases/packetpath/nat_lo       |  42 +++++
 3 files changed, 208 insertions(+)
 create mode 100644 tests/shell/testcases/packetpath/dumps/nat_lo.json-nft
 create mode 100644 tests/shell/testcases/packetpath/dumps/nat_lo.nft
 create mode 100755 tests/shell/testcases/packetpath/nat_lo

diff --git a/tests/shell/testcases/packetpath/dumps/nat_lo.json-nft b/tests/shell/testcases/packetpath/dumps/nat_lo.json-nft
new file mode 100644
index 000000000000..1b8dca338ee0
--- /dev/null
+++ b/tests/shell/testcases/packetpath/dumps/nat_lo.json-nft
@@ -0,0 +1,152 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "nat",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "nat",
+        "name": "output",
+        "handle": 0,
+        "type": "nat",
+        "hook": "output",
+        "prio": -100,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "nat",
+        "chain": "output",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 1234
+            }
+          },
+          {
+            "redirect": {
+              "port": 12345
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "drop"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "established",
+                "related",
+                "new"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": {
+                "set": [
+                  1,
+                  58
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/packetpath/dumps/nat_lo.nft b/tests/shell/testcases/packetpath/dumps/nat_lo.nft
new file mode 100644
index 000000000000..65259ec80242
--- /dev/null
+++ b/tests/shell/testcases/packetpath/dumps/nat_lo.nft
@@ -0,0 +1,14 @@
+table inet nat {
+	chain output {
+		type nat hook output priority dstnat; policy accept;
+		tcp dport 1234 redirect to :12345
+	}
+}
+table inet filter {
+	chain input {
+		type filter hook input priority filter; policy drop;
+		ct state established,related,new accept
+		meta l4proto { 1, 58 } accept
+		counter packets 0 bytes 0 drop
+	}
+}
diff --git a/tests/shell/testcases/packetpath/nat_lo b/tests/shell/testcases/packetpath/nat_lo
new file mode 100755
index 000000000000..862aadc82ef1
--- /dev/null
+++ b/tests/shell/testcases/packetpath/nat_lo
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+set -e
+
+$NFT -f - <<EOF
+table inet nat {
+	chain output {
+		type nat hook output priority dstnat; policy accept;
+		tcp dport 1234 redirect to :12345
+	}
+}
+
+table inet filter {
+	chain input {
+		type filter hook input priority filter; policy drop;
+		ct state new,established,related accept
+		meta l4proto { icmp, icmpv6 } accept
+		counter drop
+	}
+}
+EOF
+
+ip link set lo up
+
+# Start listener on the target port
+timeout 5 socat TCP6-LISTEN:12345,ipv6only=1,fork STDOUT &
+PID1=$!
+timeout 5 socat TCP4-LISTEN:12345,fork STDOUT &
+PID2=$!
+
+# Give socat a moment to bind
+sleep 1
+
+# Test IPv4 translation
+echo "Testing IPv4..."
+echo "hello ipv4" | socat -u STDIN TCP:127.0.0.1:1234
+
+# Test IPv6 translation
+echo "Testing IPv6..."
+echo "hello ipv6" | socat -u STDIN TCP:[::1]:1234
+
+kill $PID1 $PID2
-- 
2.55.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-16  7:19 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-16  7:18 [PATCH nft] tests: shell: add packetpath test for nat on loopback Florian Westphal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox