Skip to content

Commit 5bdac41

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: nat: fix icmp id randomization
Sven Auhagen reported that a 2nd ping request will fail if 'fully-random' mode is used. Reason is that if no proto information is given, min/max are both 0, so we set the icmp id to 0 instead of chosing a random value between 0 and 65535. Update test case as well to catch this, without fix this yields: [..] ERROR: cannot ping ns1 from ns2 with ip masquerade fully-random (attempt 2) ERROR: cannot ping ns1 from ns2 with ipv6 masquerade fully-random (attempt 2) ... becaus 2nd ping clashes with existing 'id 0' icmp conntrack and gets dropped. Fixes: 203f2e7 ("netfilter: nat: remove l4proto->unique_tuple") Reported-by: Sven Auhagen <[email protected]> Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 33d1c01 commit 5bdac41

File tree

2 files changed

+35
-12
lines changed

2 files changed

+35
-12
lines changed

net/netfilter/nf_nat_core.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,14 @@ static void nf_nat_l4proto_unique_tuple(struct nf_conntrack_tuple *tuple,
415415
case IPPROTO_ICMPV6:
416416
/* id is same for either direction... */
417417
keyptr = &tuple->src.u.icmp.id;
418-
min = range->min_proto.icmp.id;
419-
range_size = ntohs(range->max_proto.icmp.id) -
420-
ntohs(range->min_proto.icmp.id) + 1;
418+
if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)) {
419+
min = 0;
420+
range_size = 65536;
421+
} else {
422+
min = ntohs(range->min_proto.icmp.id);
423+
range_size = ntohs(range->max_proto.icmp.id) -
424+
ntohs(range->min_proto.icmp.id) + 1;
425+
}
421426
goto find_free_id;
422427
#if IS_ENABLED(CONFIG_NF_CT_PROTO_GRE)
423428
case IPPROTO_GRE:

tools/testing/selftests/netfilter/nft_nat.sh

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ EOF
321321

322322
test_masquerade6()
323323
{
324+
local natflags=$1
324325
local lret=0
325326

326327
ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
@@ -354,13 +355,13 @@ ip netns exec ns0 nft -f - <<EOF
354355
table ip6 nat {
355356
chain postrouting {
356357
type nat hook postrouting priority 0; policy accept;
357-
meta oif veth0 masquerade
358+
meta oif veth0 masquerade $natflags
358359
}
359360
}
360361
EOF
361362
ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
362363
if [ $? -ne 0 ] ; then
363-
echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerading"
364+
echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerade $natflags"
364365
lret=1
365366
fi
366367

@@ -397,27 +398,34 @@ EOF
397398
fi
398399
done
399400

401+
ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
402+
if [ $? -ne 0 ] ; then
403+
echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerade $natflags (attempt 2)"
404+
lret=1
405+
fi
406+
400407
ip netns exec ns0 nft flush chain ip6 nat postrouting
401408
if [ $? -ne 0 ]; then
402409
echo "ERROR: Could not flush ip6 nat postrouting" 1>&2
403410
lret=1
404411
fi
405412

406-
test $lret -eq 0 && echo "PASS: IPv6 masquerade for ns2"
413+
test $lret -eq 0 && echo "PASS: IPv6 masquerade $natflags for ns2"
407414

408415
return $lret
409416
}
410417

411418
test_masquerade()
412419
{
420+
local natflags=$1
413421
local lret=0
414422

415423
ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
416424
ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
417425

418426
ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
419427
if [ $? -ne 0 ] ; then
420-
echo "ERROR: canot ping ns1 from ns2"
428+
echo "ERROR: cannot ping ns1 from ns2 $natflags"
421429
lret=1
422430
fi
423431

@@ -443,13 +451,13 @@ ip netns exec ns0 nft -f - <<EOF
443451
table ip nat {
444452
chain postrouting {
445453
type nat hook postrouting priority 0; policy accept;
446-
meta oif veth0 masquerade
454+
meta oif veth0 masquerade $natflags
447455
}
448456
}
449457
EOF
450458
ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
451459
if [ $? -ne 0 ] ; then
452-
echo "ERROR: cannot ping ns1 from ns2 with active ip masquerading"
460+
echo "ERROR: cannot ping ns1 from ns2 with active ip masquere $natflags"
453461
lret=1
454462
fi
455463

@@ -485,13 +493,19 @@ EOF
485493
fi
486494
done
487495

496+
ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
497+
if [ $? -ne 0 ] ; then
498+
echo "ERROR: cannot ping ns1 from ns2 with active ip masquerade $natflags (attempt 2)"
499+
lret=1
500+
fi
501+
488502
ip netns exec ns0 nft flush chain ip nat postrouting
489503
if [ $? -ne 0 ]; then
490504
echo "ERROR: Could not flush nat postrouting" 1>&2
491505
lret=1
492506
fi
493507

494-
test $lret -eq 0 && echo "PASS: IP masquerade for ns2"
508+
test $lret -eq 0 && echo "PASS: IP masquerade $natflags for ns2"
495509

496510
return $lret
497511
}
@@ -750,8 +764,12 @@ test_local_dnat
750764
test_local_dnat6
751765

752766
reset_counters
753-
test_masquerade
754-
test_masquerade6
767+
test_masquerade ""
768+
test_masquerade6 ""
769+
770+
reset_counters
771+
test_masquerade "fully-random"
772+
test_masquerade6 "fully-random"
755773

756774
reset_counters
757775
test_redirect

0 commit comments

Comments
 (0)