blob: c2fb3a1c8ebcd00ba76b87b223b264d01bf2500a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
#!/bin/bash
# NFT_TEST_REQUIRES(NFT_TEST_HAVE_tcpdump)
# NFT_TEST_REQUIRES(NFT_TEST_HAVE_curl)
# NFT_TEST_REQUIRES(NFT_TEST_HAVE_vsftpd)
. $NFT_TEST_LIBRARY_FILE
cleanup()
{
for i in $R $C $S;do
kill $(ip netns pid $i) 2>/dev/null
ip netns del $i
done
rm -rf $WORKDIR
}
trap cleanup EXIT
assert_failout()
{
ip netns exec $R $NFT list ruleset
tcpdump -nnr ${PCAP}
test -r /proc/net/nf_conntrack && ip netns exec $R cat /proc/net/nf_conntrack
ip netns exec $R conntrack -S
ip netns exec $R conntrack -L
ip netns exec $S ss -nitepal
}
rnd=$(mktemp -u XXXXXXXX)
R="natftp-router-$rnd"
C="natftp-client-$rnd"
S="natftp-server-$rnd"
WORKDIR="/tmp/nat_ftp_test-$rnd"
FTPCONF="$WORKDIR/ftp-conf"
INFILE="$WORKDIR/infile"
OUTFILE="$WORKDIR/outfile"
PCAP="$WORKDIR/tcpdump.pcap"
umask 022
mkdir -p $WORKDIR
assert_pass "mkdir $WORKDIR"
modprobe nf_nat_ftp
assert_pass "modprobe nf_nat_ftp. Needed for DNAT of data connection and active mode PORT change with SNAT"
ip_sr=2001:db8:ffff:22::1
ip_cr=2001:db8:ffff:21::2
ip_rs=2001:db8:ffff:22::fffe
ip_rc=2001:db8:ffff:21::fffe
ip netns add $R
ip netns add $S
ip netns add $C
ip -net $S link set lo up
ip -net $R link set lo up
ip -net $C link set lo up
ip netns exec $R sysctl -wq net.ipv6.conf.all.forwarding=1
ip link add s_r netns $S type veth peer name r_s netns $R
ip link add c_r netns $C type veth peer name r_c netns $R
ip -net $S link set s_r up
ip -net $R link set r_s up
ip -net $R link set r_c up
ip -net $C link set c_r up
ip -net $S addr add ${ip_sr}/64 dev s_r nodad
ip -net $C addr add ${ip_cr}/64 dev c_r nodad
ip -net $R addr add ${ip_rs}/64 dev r_s nodad
ip -net $R addr add ${ip_rc}/64 dev r_c nodad
ip -net $C route add ${ip_rs}/64 via ${ip_rc} dev c_r
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()
{
ip netns exec $R conntrack -F 2> /dev/null
ip netns exec $R $NFT -f - <<-EOF
flush ruleset
table ip6 ftp_helper_nat_test {
ct helper ftp-standard {
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
ip6 nexthdr tcp ct state related counter accept
ip6 nexthdr tcp ct state established counter accept
ip6 nexthdr icmpv6 counter accept
counter log
}
chain forward {
type filter hook forward priority filter; policy drop;
ip6 daddr ${ip_sr} counter tcp dport 21 ct state new counter accept
ip6 nexthdr tcp ct state established counter accept
ip6 nexthdr tcp ct state related counter log accept
}
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"
}
dd if=/dev/urandom of="$INFILE" bs=4096 count=1 2>/dev/null
chmod 755 $INFILE
assert_pass "Prepare the file for FTP transmission"
cat > ${FTPCONF} <<-EOF
anonymous_enable=YES
anon_root=${WORKDIR}
local_enable=YES
connect_from_port_20=YES
listen=NO
listen_ipv6=YES
pam_service_name=vsftpd
background=YES
EOF
ip netns exec $S vsftpd ${FTPCONF}
wait_local_port_listen $S 21 tcp
ip netns exec $S ss -6ltnp | grep -q '*:21'
assert_pass "start vsftpd server"
# 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 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"
# trap calls cleanup
exit 0
|