netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] tests: shell: nat_ftp SNAT/DNAT only testcases
@ 2025-10-28 16:56 Andrii Melnychenko
  2025-10-28 16:56 ` [PATCH v2 1/2] tests: shell: Refactored nat_ftp, added rulesets and testcase functions Andrii Melnychenko
  2025-10-28 16:56 ` [PATCH v2 2/2] tests: shell: Added SNAT/DNAT only cases for nat_ftp Andrii Melnychenko
  0 siblings, 2 replies; 4+ messages in thread
From: Andrii Melnychenko @ 2025-10-28 16:56 UTC (permalink / raw)
  To: netfilter-devel, fw

Added new testcases to test SNAT or DNAT only for passive and active modes.
There was an issue that DNAT doesn't set up sequence adjustment for NAT conntrack.
The last patch with a fix to the kernel was present here:
https://lkml.org/lkml/2025/10/24/1254

This series of patches adds tests that should cover an issue with seqadj for SNAT/DNAT.

Changes since v1:
 * refactored/split patches

Andrii Melnychenko (2):
  tests: shell: Refactored nat_ftp, added rulesets and testcase
    functions
  tests: shell: Added SNAT/DNAT only cases for nat_ftp

 tests/shell/testcases/packetpath/nat_ftp | 108 +++++++++++++++++------
 1 file changed, 80 insertions(+), 28 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 1/2] tests: shell: Refactored nat_ftp, added rulesets and testcase functions
  2025-10-28 16:56 [PATCH v2 0/2] tests: shell: nat_ftp SNAT/DNAT only testcases Andrii Melnychenko
@ 2025-10-28 16:56 ` Andrii Melnychenko
  2025-10-29 17:43   ` Phil Sutter
  2025-10-28 16:56 ` [PATCH v2 2/2] tests: shell: Added SNAT/DNAT only cases for nat_ftp Andrii Melnychenko
  1 sibling, 1 reply; 4+ messages in thread
From: Andrii Melnychenko @ 2025-10-28 16:56 UTC (permalink / raw)
  To: netfilter-devel, fw

Refactored the setup of nft rulesets, now it is possible to set up an
SNAT or DNAT-only ruleset for future tests.
Presented the testcase function to test passive or active modes.

Signed-off-by: Andrii Melnychenko <a.melnychenko@vyos.io>
---
 tests/shell/testcases/packetpath/nat_ftp | 86 +++++++++++++++---------
 1 file changed, 53 insertions(+), 33 deletions(-)

diff --git a/tests/shell/testcases/packetpath/nat_ftp b/tests/shell/testcases/packetpath/nat_ftp
index d0faf2ef..bc116f6e 100755
--- a/tests/shell/testcases/packetpath/nat_ftp
+++ b/tests/shell/testcases/packetpath/nat_ftp
@@ -77,7 +77,7 @@ ip -net $S route add ${ip_rc}/64 via ${ip_rs} dev s_r
 ip netns exec $C ping -q -6 ${ip_sr} -c1 > /dev/null
 assert_pass "topo initialization"
 
-reload_ruleset()
+reload_ruleset_base()
 {
 	ip netns exec $R conntrack -F 2> /dev/null
 	ip netns exec $R $NFT -f - <<-EOF
@@ -87,12 +87,6 @@ reload_ruleset()
 			type "ftp" protocol tcp;
 		}
 
-		chain PRE-dnat {
-			type nat hook prerouting priority dstnat; policy accept;
-			# Dnat the control connection, data connection will be automaticly NATed.
-			ip6 daddr ${ip_rc} counter ip6 nexthdr tcp tcp dport 2121 counter dnat ip6 to [${ip_sr}]:21
-		}
-
 		chain PRE-aftnat {
 			type filter hook prerouting priority 350; policy drop;
 			iifname r_c tcp dport 21 ct state new ct helper set "ftp-standard" counter accept
@@ -111,14 +105,43 @@ reload_ruleset()
 			ip6 nexthdr tcp ct state established counter accept
 			ip6 nexthdr tcp ct state related     counter log accept
 		}
+	}
+	EOF
+	assert_pass "apply ftp helper base ruleset"
+}
+
+load_dnat()
+{
+	ip netns exec $R $NFT -f - <<-EOF
+	table ip6 ftp_helper_nat_test {
+		chain PRE-dnat {
+			type nat hook prerouting priority dstnat; policy accept;
+			# Dnat the control connection, data connection will be automaticly NATed.
+			ip6 daddr ${ip_rc} counter ip6 nexthdr tcp tcp dport 2121 counter dnat ip6 to [${ip_sr}]:21
+		}
+	}
+	EOF
+	assert_pass "apply ftp helper DNAT ruleset"
+}
 
+load_snat()
+{
+	ip netns exec $R $NFT -f - <<-EOF
+	table ip6 ftp_helper_nat_test {
 		chain POST-srcnat {
 			type nat hook postrouting priority srcnat; policy accept;
 			ip6 daddr ${ip_sr} ip6 nexthdr tcp tcp dport 21 counter snat ip6 to [${ip_rs}]:16500
 		}
 	}
 	EOF
-	assert_pass "apply ftp helper ruleset"
+	assert_pass "apply ftp helper SNAT ruleset"
+}
+
+reload_ruleset()
+{
+	reload_ruleset_base
+	load_dnat
+	load_snat
 }
 
 dd if=/dev/urandom of="$INFILE" bs=4096 count=1 2>/dev/null
@@ -141,38 +164,35 @@ wait_local_port_listen $S 21 tcp
 ip netns exec $S ss -6ltnp | grep -q '*:21'
 assert_pass "start vsftpd server"
 
+test_case()
+{
+	tag=$1
+	ftp_ip_and_port=$2
+	client_ip_to_check=$3
+	additional_curl_options=$4
+
+	ip netns exec $S tcpdump -q --immediate-mode -Ui s_r -w ${PCAP} 2> /dev/null &
+	pid=$!
+	sleep 0.5
+	ip netns exec $C curl ${additional_curl_options} --no-progress-meter --connect-timeout 5 ftp://${ftp_ip_and_port}/$(basename $INFILE) -o $OUTFILE
+	assert_pass "curl ftp "${tag}
+
+	cmp "$INFILE" "$OUTFILE"
+	assert_pass "FTP "${tag}": The input and output files remain the same when traffic passes through NAT."
+
+	kill $pid; sync
+	tcpdump -nnr ${PCAP} src ${client_ip_to_check} and dst ${ip_sr} 2>&1 |grep -q FTP
+	assert_pass "assert FTP traffic NATed"
+}
 
 # test passive mode
 reload_ruleset
-ip netns exec $S tcpdump -q --immediate-mode -Ui s_r -w ${PCAP} 2> /dev/null &
-pid=$!
-sleep 0.5
-ip netns exec $C curl --no-progress-meter --connect-timeout 5 ftp://[${ip_rc}]:2121/$(basename $INFILE) -o $OUTFILE
-assert_pass "curl ftp passive mode "
-
-cmp "$INFILE" "$OUTFILE"
-assert_pass "FTP Passive mode: The input and output files remain the same when traffic passes through NAT."
-
-kill $pid; sync
-tcpdump -nnr ${PCAP} src ${ip_rs} and dst ${ip_sr} 2>&1 |grep -q FTP
-assert_pass "assert FTP traffic NATed"
+test_case "Passive mode" [${ip_rc}]:2121 ${ip_rs}
 
 
 # test active mode
 reload_ruleset
-
-ip netns exec $S tcpdump -q --immediate-mode -Ui s_r -w ${PCAP} 2> /dev/null &
-pid=$!
-sleep 0.5
-ip netns exec $C curl --no-progress-meter -P - --connect-timeout 5 ftp://[${ip_rc}]:2121/$(basename $INFILE) -o $OUTFILE
-assert_pass "curl ftp active mode "
-
-cmp "$INFILE" "$OUTFILE"
-assert_pass "FTP Active mode: in and output files remain the same when FTP traffic passes through NAT."
-
-kill $pid; sync
-tcpdump -nnr ${PCAP} src ${ip_rs} and dst ${ip_sr} 2>&1 |grep -q FTP
-assert_pass "assert FTP traffic NATed"
+test_case "Active mode" [${ip_rc}]:2121 ${ip_rs} "-P -"
 
 # trap calls cleanup
 exit 0
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 2/2] tests: shell: Added SNAT/DNAT only cases for nat_ftp
  2025-10-28 16:56 [PATCH v2 0/2] tests: shell: nat_ftp SNAT/DNAT only testcases Andrii Melnychenko
  2025-10-28 16:56 ` [PATCH v2 1/2] tests: shell: Refactored nat_ftp, added rulesets and testcase functions Andrii Melnychenko
@ 2025-10-28 16:56 ` Andrii Melnychenko
  1 sibling, 0 replies; 4+ messages in thread
From: Andrii Melnychenko @ 2025-10-28 16:56 UTC (permalink / raw)
  To: netfilter-devel, fw

Added cases for SNAT or DNAT only for active and passive modes.

Signed-off-by: Andrii Melnychenko <a.melnychenko@vyos.io>
---
 tests/shell/testcases/packetpath/nat_ftp | 32 ++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/tests/shell/testcases/packetpath/nat_ftp b/tests/shell/testcases/packetpath/nat_ftp
index bc116f6e..97161025 100755
--- a/tests/shell/testcases/packetpath/nat_ftp
+++ b/tests/shell/testcases/packetpath/nat_ftp
@@ -144,6 +144,18 @@ reload_ruleset()
 	load_snat
 }
 
+reload_ruleset_dnat_only()
+{
+	reload_ruleset_base
+	load_dnat
+}
+
+reload_ruleset_snat_only()
+{
+	reload_ruleset_base
+	load_snat
+}
+
 dd if=/dev/urandom of="$INFILE" bs=4096 count=1 2>/dev/null
 chmod 755 $INFILE
 assert_pass "Prepare the file for FTP transmission"
@@ -190,9 +202,29 @@ reload_ruleset
 test_case "Passive mode" [${ip_rc}]:2121 ${ip_rs}
 
 
+# test passive mode DNAT only
+reload_ruleset_dnat_only
+test_case "Passive mode DNAT only" [${ip_rc}]:2121 ${ip_cr}
+
+
+# test passive mode SNAT only
+reload_ruleset_snat_only
+test_case "Passive mode SNAT only" [${ip_sr}]:21 ${ip_rs}
+
+
 # test active mode
 reload_ruleset
 test_case "Active mode" [${ip_rc}]:2121 ${ip_rs} "-P -"
 
+
+# test active mode DNAT only
+reload_ruleset_dnat_only
+test_case "Active mode DNAT only" [${ip_rc}]:2121 ${ip_cr} "-P -"
+
+
+# test active mode SNAT only
+reload_ruleset_snat_only
+test_case "Active mode SNAT only" [${ip_sr}]:21 ${ip_rs} "-P -"
+
 # trap calls cleanup
 exit 0
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 1/2] tests: shell: Refactored nat_ftp, added rulesets and testcase functions
  2025-10-28 16:56 ` [PATCH v2 1/2] tests: shell: Refactored nat_ftp, added rulesets and testcase functions Andrii Melnychenko
@ 2025-10-29 17:43   ` Phil Sutter
  0 siblings, 0 replies; 4+ messages in thread
From: Phil Sutter @ 2025-10-29 17:43 UTC (permalink / raw)
  To: Andrii Melnychenko; +Cc: netfilter-devel, fw

Hi,

On Tue, Oct 28, 2025 at 05:56:06PM +0100, Andrii Melnychenko wrote:
> Refactored the setup of nft rulesets, now it is possible to set up an
> SNAT or DNAT-only ruleset for future tests.
> Presented the testcase function to test passive or active modes.
> 
> Signed-off-by: Andrii Melnychenko <a.melnychenko@vyos.io>
> ---
>  tests/shell/testcases/packetpath/nat_ftp | 86 +++++++++++++++---------
>  1 file changed, 53 insertions(+), 33 deletions(-)
> 
> diff --git a/tests/shell/testcases/packetpath/nat_ftp b/tests/shell/testcases/packetpath/nat_ftp
> index d0faf2ef..bc116f6e 100755
> --- a/tests/shell/testcases/packetpath/nat_ftp
> +++ b/tests/shell/testcases/packetpath/nat_ftp
> @@ -77,7 +77,7 @@ ip -net $S route add ${ip_rc}/64 via ${ip_rs} dev s_r
>  ip netns exec $C ping -q -6 ${ip_sr} -c1 > /dev/null
>  assert_pass "topo initialization"
>  
> -reload_ruleset()
> +reload_ruleset_base()
>  {
>  	ip netns exec $R conntrack -F 2> /dev/null
>  	ip netns exec $R $NFT -f - <<-EOF
> @@ -87,12 +87,6 @@ reload_ruleset()
>  			type "ftp" protocol tcp;
>  		}
>  
> -		chain PRE-dnat {
> -			type nat hook prerouting priority dstnat; policy accept;
> -			# Dnat the control connection, data connection will be automaticly NATed.
> -			ip6 daddr ${ip_rc} counter ip6 nexthdr tcp tcp dport 2121 counter dnat ip6 to [${ip_sr}]:21
> -		}
> -
>  		chain PRE-aftnat {
>  			type filter hook prerouting priority 350; policy drop;
>  			iifname r_c tcp dport 21 ct state new ct helper set "ftp-standard" counter accept
> @@ -111,14 +105,43 @@ reload_ruleset()
>  			ip6 nexthdr tcp ct state established counter accept
>  			ip6 nexthdr tcp ct state related     counter log accept
>  		}
> +	}
> +	EOF
> +	assert_pass "apply ftp helper base ruleset"
> +}
> +
> +load_dnat()
> +{
> +	ip netns exec $R $NFT -f - <<-EOF
> +	table ip6 ftp_helper_nat_test {
> +		chain PRE-dnat {
> +			type nat hook prerouting priority dstnat; policy accept;
> +			# Dnat the control connection, data connection will be automaticly NATed.
> +			ip6 daddr ${ip_rc} counter ip6 nexthdr tcp tcp dport 2121 counter dnat ip6 to [${ip_sr}]:21
> +		}
> +	}
> +	EOF
> +	assert_pass "apply ftp helper DNAT ruleset"
> +}
>  
> +load_snat()
> +{
> +	ip netns exec $R $NFT -f - <<-EOF
> +	table ip6 ftp_helper_nat_test {
>  		chain POST-srcnat {
>  			type nat hook postrouting priority srcnat; policy accept;
>  			ip6 daddr ${ip_sr} ip6 nexthdr tcp tcp dport 21 counter snat ip6 to [${ip_rs}]:16500
>  		}
>  	}
>  	EOF
> -	assert_pass "apply ftp helper ruleset"
> +	assert_pass "apply ftp helper SNAT ruleset"
> +}
> +
> +reload_ruleset()
> +{
> +	reload_ruleset_base
> +	load_dnat
> +	load_snat
>  }
>  
>  dd if=/dev/urandom of="$INFILE" bs=4096 count=1 2>/dev/null
> @@ -141,38 +164,35 @@ wait_local_port_listen $S 21 tcp
>  ip netns exec $S ss -6ltnp | grep -q '*:21'
>  assert_pass "start vsftpd server"
>  
> +test_case()
> +{
> +	tag=$1
> +	ftp_ip_and_port=$2
> +	client_ip_to_check=$3
> +	additional_curl_options=$4
> +
> +	ip netns exec $S tcpdump -q --immediate-mode -Ui s_r -w ${PCAP} 2> /dev/null &
> +	pid=$!
> +	sleep 0.5
> +	ip netns exec $C curl ${additional_curl_options} --no-progress-meter --connect-timeout 5 ftp://${ftp_ip_and_port}/$(basename $INFILE) -o $OUTFILE
> +	assert_pass "curl ftp "${tag}
> +
> +	cmp "$INFILE" "$OUTFILE"
> +	assert_pass "FTP "${tag}": The input and output files remain the same when traffic passes through NAT."
> +
> +	kill $pid; sync
> +	tcpdump -nnr ${PCAP} src ${client_ip_to_check} and dst ${ip_sr} 2>&1 |grep -q FTP
> +	assert_pass "assert FTP traffic NATed"
> +}
>  
>  # test passive mode
>  reload_ruleset
> -ip netns exec $S tcpdump -q --immediate-mode -Ui s_r -w ${PCAP} 2> /dev/null &
> -pid=$!
> -sleep 0.5
> -ip netns exec $C curl --no-progress-meter --connect-timeout 5 ftp://[${ip_rc}]:2121/$(basename $INFILE) -o $OUTFILE
> -assert_pass "curl ftp passive mode "
> -
> -cmp "$INFILE" "$OUTFILE"
> -assert_pass "FTP Passive mode: The input and output files remain the same when traffic passes through NAT."
> -
> -kill $pid; sync
> -tcpdump -nnr ${PCAP} src ${ip_rs} and dst ${ip_sr} 2>&1 |grep -q FTP
> -assert_pass "assert FTP traffic NATed"
> +test_case "Passive mode" [${ip_rc}]:2121 ${ip_rs}
                            ~~~~~~~~~~~~~~~
I think you should add double-quotes around this parameter to avoid
inadvertent shell globbing from taking place. Yes, it is a bug in the
old code already (if at all) but it's a good chance to fix it now.

Consequently the curl parameter dereferencing the variable should be
quoted as well.

>  # test active mode
>  reload_ruleset
> -
> -ip netns exec $S tcpdump -q --immediate-mode -Ui s_r -w ${PCAP} 2> /dev/null &
> -pid=$!
> -sleep 0.5
> -ip netns exec $C curl --no-progress-meter -P - --connect-timeout 5 ftp://[${ip_rc}]:2121/$(basename $INFILE) -o $OUTFILE
> -assert_pass "curl ftp active mode "
> -
> -cmp "$INFILE" "$OUTFILE"
> -assert_pass "FTP Active mode: in and output files remain the same when FTP traffic passes through NAT."
> -
> -kill $pid; sync
> -tcpdump -nnr ${PCAP} src ${ip_rs} and dst ${ip_sr} 2>&1 |grep -q FTP
> -assert_pass "assert FTP traffic NATed"
> +test_case "Active mode" [${ip_rc}]:2121 ${ip_rs} "-P -"
                           ~~~~~~~~~~~~~~~
Same here.

Cheers, Phil

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-10-29 17:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-28 16:56 [PATCH v2 0/2] tests: shell: nat_ftp SNAT/DNAT only testcases Andrii Melnychenko
2025-10-28 16:56 ` [PATCH v2 1/2] tests: shell: Refactored nat_ftp, added rulesets and testcase functions Andrii Melnychenko
2025-10-29 17:43   ` Phil Sutter
2025-10-28 16:56 ` [PATCH v2 2/2] tests: shell: Added SNAT/DNAT only cases for nat_ftp Andrii Melnychenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).