1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# Check that UNREPLIED tcp conntrack will eventually timeout. 5# 6 7source lib.sh 8 9if ! nft --version > /dev/null 2>&1;then 10 echo "SKIP: Could not run test without nft tool" 11 exit $ksft_skip 12fi 13 14if ! conntrack --version > /dev/null 2>&1;then 15 echo "SKIP: Could not run test without conntrack tool" 16 exit $ksft_skip 17fi 18 19ret=0 20 21cleanup() { 22 ip netns pids "$ns1" | xargs kill 2>/dev/null 23 ip netns pids "$ns2" | xargs kill 2>/dev/null 24 25 cleanup_all_ns 26} 27 28ipv4() { 29 echo -n 192.168."$1".2 30} 31 32check_counter() 33{ 34 ns=$1 35 name=$2 36 expect=$3 37 local lret=0 38 39 if ! ip netns exec "$ns2" nft list counter inet filter "$name" | grep -q "$expect"; then 40 echo "ERROR: counter $name in $ns2 has unexpected value (expected $expect)" 1>&2 41 ip netns exec "$ns2" nft list counter inet filter "$name" 1>&2 42 lret=1 43 fi 44 45 return $lret 46} 47 48trap cleanup EXIT 49 50# Create test namespaces 51setup_ns ns1 ns2 52 53# Connect the namespace to the host using a veth pair 54ip -net "$ns1" link add name veth1 type veth peer name veth2 55ip -net "$ns1" link set netns "$ns2" dev veth2 56 57ip -net "$ns1" link set up dev lo 58ip -net "$ns2" link set up dev lo 59ip -net "$ns1" link set up dev veth1 60ip -net "$ns2" link set up dev veth2 61 62ip -net "$ns2" addr add 10.11.11.2/24 dev veth2 63ip -net "$ns2" route add default via 10.11.11.1 64 65ip netns exec "$ns2" sysctl -q net.ipv4.conf.veth2.forwarding=1 66 67# add a rule inside NS so we enable conntrack 68ip netns exec "$ns1" nft -f - <<EOF 69table inet filter { 70 chain input { 71 type filter hook input priority 0; policy accept; 72 ct state established accept 73 } 74} 75EOF 76 77ip -net "$ns1" addr add 10.11.11.1/24 dev veth1 78ip -net "$ns1" route add 10.99.99.99 via 10.11.11.2 79 80# Check connectivity works 81ip netns exec "$ns1" ping -q -c 2 10.11.11.2 >/dev/null || exit 1 82 83ip netns exec "$ns2" socat -u -4 TCP-LISTEN:8080,reuseaddr STDOUT & 84 85ip netns exec "$ns2" nft -f - <<EOF 86table inet filter { 87 counter connreq { } 88 counter redir { } 89 chain input { 90 type filter hook input priority 0; policy accept; 91 ct state new tcp flags syn ip daddr 10.99.99.99 tcp dport 80 counter name "connreq" accept 92 ct state new ct status dnat tcp dport 8080 counter name "redir" accept 93 } 94} 95EOF 96if [ $? -ne 0 ]; then 97 echo "ERROR: Could not load nft rules" 98 exit 1 99fi 100 101ip netns exec "$ns2" sysctl -q net.netfilter.nf_conntrack_tcp_timeout_syn_sent=10 102 103echo "INFO: connect $ns1 -> $ns2 to the virtual ip" 104ip netns exec "$ns1" bash -c 'for i in $(seq 1 $BUSYWAIT_TIMEOUT) ; do 105 socat -u STDIN TCP:10.99.99.99:80 < /dev/null 106 sleep 0.1 107 done' & 108 109wait_for_attempt() 110{ 111 count=$(ip netns exec "$ns2" conntrack -L -p tcp --dport 80 2>/dev/null | wc -l) 112 if [ "$count" -gt 0 ]; then 113 return 0 114 fi 115 116 return 1 117} 118 119# wait for conntrack to pick the new connection request up before loading 120# the nat redirect rule. 121if ! busywait "$BUSYWAIT_TIMEOUT" wait_for_attempt; then 122 echo "ERROR: $ns2 did not pick up tcp connection from peer" 123 exit 1 124fi 125 126ip netns exec "$ns2" nft -f - <<EOF 127table inet nat { 128 chain prerouting { 129 type nat hook prerouting priority 0; policy accept; 130 ip daddr 10.99.99.99 tcp dport 80 redirect to :8080 131 } 132} 133EOF 134if [ $? -ne 0 ]; then 135 echo "ERROR: Could not load nat redirect" 136 exit 1 137fi 138 139wait_for_redirect() 140{ 141 count=$(ip netns exec "$ns2" conntrack -L -p tcp --reply-port-src 8080 2>/dev/null | wc -l) 142 if [ "$count" -gt 0 ]; then 143 return 0 144 fi 145 146 return 1 147} 148echo "INFO: NAT redirect added in ns $ns2, waiting for $BUSYWAIT_TIMEOUT ms for nat to take effect" 149 150busywait "$BUSYWAIT_TIMEOUT" wait_for_redirect 151ret=$? 152 153expect="packets 1 bytes 60" 154if ! check_counter "$ns2" "redir" "$expect"; then 155 ret=1 156fi 157 158if [ $ret -eq 0 ];then 159 echo "PASS: redirection counter has expected values" 160else 161 echo "ERROR: no tcp connection was redirected" 162fi 163 164exit $ret 165