Skip to content

Commit

Permalink
conntrack: fix expectations for ftp+DNAT.
Browse files Browse the repository at this point in the history
When configuring the nat part of an expectation, care must be taken to
look at the master nat action and direction to properly reproduce it.

DNAT tests have been added to both active and passive modes, all
ftp/tftp tests titles have been updated to reflect they are dealing with
SNAT.

Fixes: bd5e81a ("Userspace Datapath: Add ALG infra and FTP.")
Co-authored-by: Darrell Ball <[email protected]>
Signed-off-by: Darrell Ball <[email protected]>
Signed-off-by: David Marchand <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
2 people authored and blp committed Jan 19, 2019
1 parent 253e4dc commit efa29a8
Show file tree
Hide file tree
Showing 2 changed files with 211 additions and 23 deletions.
12 changes: 10 additions & 2 deletions lib/conntrack.c
Original file line number Diff line number Diff line change
Expand Up @@ -2713,21 +2713,29 @@ expectation_create(struct conntrack *ct, ovs_be16 dst_port,
if (reply) {
src_addr = master_conn->key.src.addr;
dst_addr = master_conn->key.dst.addr;
alg_exp_node->nat_rpl_dst = true;
if (skip_nat) {
alg_nat_repl_addr = dst_addr;
} else if (master_conn->nat_info &&
master_conn->nat_info->nat_action & NAT_ACTION_DST) {
alg_nat_repl_addr = master_conn->rev_key.src.addr;
alg_exp_node->nat_rpl_dst = false;
} else {
alg_nat_repl_addr = master_conn->rev_key.dst.addr;
}
alg_exp_node->nat_rpl_dst = true;
} else {
src_addr = master_conn->rev_key.src.addr;
dst_addr = master_conn->rev_key.dst.addr;
alg_exp_node->nat_rpl_dst = false;
if (skip_nat) {
alg_nat_repl_addr = src_addr;
} else if (master_conn->nat_info &&
master_conn->nat_info->nat_action & NAT_ACTION_DST) {
alg_nat_repl_addr = master_conn->key.dst.addr;
alg_exp_node->nat_rpl_dst = true;
} else {
alg_nat_repl_addr = master_conn->key.src.addr;
}
alg_exp_node->nat_rpl_dst = false;
}
if (src_ip_wc) {
memset(&src_addr, 0, sizeof src_addr);
Expand Down
222 changes: 201 additions & 21 deletions tests/system-traffic.at
Original file line number Diff line number Diff line change
Expand Up @@ -4224,7 +4224,7 @@ dnl
dnl Checks the implementation of conntrack with FTP ALGs in combination with
dnl NAT, using the provided flow table.
m4_define([CHECK_FTP_NAT],
[AT_SETUP([conntrack - FTP NAT $1])
[AT_SETUP([conntrack - FTP $1])
AT_SKIP_IF([test $HAVE_FTP = no])
AT_SKIP_IF([test $HAVE_LFTP = no])
CHECK_CONNTRACK()
Expand Down Expand Up @@ -4266,16 +4266,16 @@ ls
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP])

dnl CHECK_FTP_NAT_PRE_RECIRC(TITLE, IP_ADDR, IP_ADDR_AS_HEX)
dnl CHECK_FTP_SNAT_PRE_RECIRC(TITLE, IP_ADDR, IP_ADDR_AS_HEX)
dnl
dnl Checks the implementation of conntrack with FTP ALGs in combination with
dnl NAT, with flow tables that implement the NATing as part of handling of
dnl initial incoming packets - ie, the first flow is ct(nat,table=foo).
dnl
dnl IP_ADDR must specify the NAT address in standard "10.1.1.x" format,
dnl and IP_ADDR_AS_HEX must specify the same address as hex, eg 0x0a0101xx.
m4_define([CHECK_FTP_NAT_PRE_RECIRC], [dnl
CHECK_FTP_NAT([prerecirc $1], [$2], [dnl
m4_define([CHECK_FTP_SNAT_PRE_RECIRC], [dnl
CHECK_FTP_NAT([SNAT prerecirc $1], [$2], [dnl
dnl track all IP traffic, de-mangle non-NEW connections
table=0 in_port=1, ip, action=ct(table=1,nat)
table=0 in_port=2, ip, action=ct(table=2,nat)
Expand Down Expand Up @@ -4329,7 +4329,7 @@ tcp,orig=(src=10.1.1.2,dst=$2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1
])

dnl Check that ct(nat,table=foo) works without TCP sequence adjustment.
CHECK_FTP_NAT_PRE_RECIRC([], [10.1.1.9], [0x0a010109])
CHECK_FTP_SNAT_PRE_RECIRC([], [10.1.1.9], [0x0a010109])

dnl Check that ct(nat,table=foo) works with TCP sequence adjustment.
dnl
Expand All @@ -4340,9 +4340,9 @@ dnl of 10.1.1.1 used in the test and 10.1.1.240 here), the FTP NAT ALG must
dnl resize the packet and adjust TCP sequence numbers. This test is kept
dnl separate from the above to easier identify issues in this code on different
dnl kernels.
CHECK_FTP_NAT_PRE_RECIRC([seqadj], [10.1.1.240], [0x0a0101f0])
CHECK_FTP_SNAT_PRE_RECIRC([seqadj], [10.1.1.240], [0x0a0101f0])

dnl CHECK_FTP_NAT_POST_RECIRC(TITLE, IP_ADDR, IP_ADDR_AS_HEX)
dnl CHECK_FTP_SNAT_POST_RECIRC(TITLE, IP_ADDR, IP_ADDR_AS_HEX)
dnl
dnl Checks the implementation of conntrack with FTP ALGs in combination with
dnl NAT, with flow tables that implement the NATing after the first round
Expand All @@ -4351,8 +4351,8 @@ dnl flow will implement the NATing with ct(nat..),output:foo.
dnl
dnl IP_ADDR must specify the NAT address in standard "10.1.1.x" format,
dnl and IP_ADDR_AS_HEX must specify the same address as hex, eg 0x0a0101xx.
m4_define([CHECK_FTP_NAT_POST_RECIRC], [dnl
CHECK_FTP_NAT([postrecirc $1], [$2], [dnl
m4_define([CHECK_FTP_SNAT_POST_RECIRC], [dnl
CHECK_FTP_NAT([SNAT postrecirc $1], [$2], [dnl
dnl track all IP traffic (this includes a helper call to non-NEW packets.)
table=0 ip, action=ct(table=1)
dnl
Expand Down Expand Up @@ -4395,7 +4395,7 @@ tcp,orig=(src=10.1.1.2,dst=$2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1
])

dnl Check that ct(nat,table=foo) works without TCP sequence adjustment.
CHECK_FTP_NAT_POST_RECIRC([], [10.1.1.9], [0x0a010109])
CHECK_FTP_SNAT_POST_RECIRC([], [10.1.1.9], [0x0a010109])

dnl Check that ct(nat,table=foo) works with TCP sequence adjustment.
dnl
Expand All @@ -4406,10 +4406,10 @@ dnl of 10.1.1.1 used in the test and 10.1.1.240 here), the FTP NAT ALG must
dnl resize the packet and adjust TCP sequence numbers. This test is kept
dnl separate from the above to easier identify issues in this code on different
dnl kernels.
CHECK_FTP_NAT_POST_RECIRC([seqadj], [10.1.1.240], [0x0a0101f0])
CHECK_FTP_SNAT_POST_RECIRC([seqadj], [10.1.1.240], [0x0a0101f0])


dnl CHECK_FTP_NAT_ORIG_TUPLE(TITLE, IP_ADDR, IP_ADDR_AS_HEX)
dnl CHECK_FTP_SNAT_ORIG_TUPLE(TITLE, IP_ADDR, IP_ADDR_AS_HEX)
dnl
dnl Checks the implementation of conntrack original direction tuple matching
dnl with FTP ALGs in combination with NAT, with flow tables that implement
Expand All @@ -4419,8 +4419,8 @@ dnl commiting of NATed and other connections with ct(nat..),output:foo.
dnl
dnl IP_ADDR must specify the NAT address in standard "10.1.1.x" format,
dnl and IP_ADDR_AS_HEX must specify the same address as hex, eg 0x0a0101xx.
m4_define([CHECK_FTP_NAT_ORIG_TUPLE], [dnl
CHECK_FTP_NAT([orig tuple $1], [$2], [dnl
m4_define([CHECK_FTP_SNAT_ORIG_TUPLE], [dnl
CHECK_FTP_NAT([SNAT orig tuple $1], [$2], [dnl
dnl Store zone in reg4 and packet direction in reg3 (IN=1, OUT=2).
dnl NAT is only applied to OUT-direction packets, so that ACL
dnl processing can be done with non-NATted headers.
Expand Down Expand Up @@ -4526,13 +4526,13 @@ tcp,orig=(src=10.1.1.2,dst=$2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1

dnl Check that ct(nat,table=foo) works without TCP sequence adjustment with
dnl an ACL table based on matching on conntrack original direction tuple only.
CHECK_FTP_NAT_ORIG_TUPLE([], [10.1.1.9], [0x0a010109])
CHECK_FTP_SNAT_ORIG_TUPLE([], [10.1.1.9], [0x0a010109])

dnl Check that ct(nat,table=foo) works with TCP sequence adjustment with
dnl an ACL table based on matching on conntrack original direction tuple only.
CHECK_FTP_NAT_ORIG_TUPLE([seqadj], [10.1.1.240], [0x0a0101f0])
CHECK_FTP_SNAT_ORIG_TUPLE([seqadj], [10.1.1.240], [0x0a0101f0])

AT_SETUP([conntrack - IPv4 FTP Passive with NAT])
AT_SETUP([conntrack - IPv4 FTP Passive with SNAT])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
Expand Down Expand Up @@ -4592,6 +4592,186 @@ tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([conntrack - IPv4 FTP Passive with DNAT])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
CHECK_CONNTRACK_ALG()

OVS_TRAFFIC_VSWITCHD_START()

ADD_NAMESPACES(at_ns0, at_ns1)

ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
NS_CHECK_EXEC([at_ns0], [ip link set dev p0 address e6:66:c1:11:11:11])
NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.2 e6:66:c1:22:22:22])
NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.240 e6:66:c1:22:22:22])

ADD_VETH(p1, at_ns1, br0, "10.1.1.240/24")
NS_CHECK_EXEC([at_ns1], [ip link set dev p1 address e6:66:c1:22:22:22])
NS_CHECK_EXEC([at_ns1], [arp -s 10.1.1.1 e6:66:c1:11:11:11])

dnl Allow any traffic from ns0->ns1.
AT_DATA([flows.txt], [dnl
dnl track all IPv4 traffic and NAT any established traffic.
table=0 priority=10 ip, action=ct(nat,table=1)
table=0 priority=0 action=drop
dnl
dnl Table 1
dnl
dnl Allow new FTP control connections.
table=1 in_port=1 ct_state=+new tcp nw_src=10.1.1.1 tp_dst=21 action=ct(alg=ftp,commit,nat(dst=10.1.1.240)),2
dnl Allow related TCP connections from port 1.
table=1 in_port=1 ct_state=+new+rel tcp nw_src=10.1.1.1 action=ct(commit,nat),2
dnl Allow established TCP connections both ways, post-NAT match.
table=1 in_port=1 ct_state=+est tcp nw_dst=10.1.1.240 action=2
table=1 in_port=2 ct_state=+est tcp nw_dst=10.1.1.1 action=1

dnl Allow ICMP both ways.
table=1 priority=100 in_port=1 icmp, action=2
table=1 priority=100 in_port=2 icmp, action=1
table=1 priority=0, action=drop
])

AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])

dnl Check that the stacks working to avoid races.
OVS_WAIT_UNTIL([ip netns exec at_ns0 ping -c 1 10.1.1.240 >/dev/null])

OVS_START_L7([at_ns1], [ftp])

dnl FTP requests from p0->p1 should work fine.
NS_CHECK_EXEC([at_ns0], [wget ftp://10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0.log])

dnl Discards CLOSE_WAIT and CLOSING
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.240,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),protoinfo=(state=<cleared>)
tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.240,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),protoinfo=(state=<cleared>),helper=ftp
])

OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([conntrack - IPv4 FTP Active with DNAT])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
CHECK_CONNTRACK_ALG()

OVS_TRAFFIC_VSWITCHD_START()

ADD_NAMESPACES(at_ns0, at_ns1)

ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
NS_CHECK_EXEC([at_ns0], [ip link set dev p0 address e6:66:c1:11:11:11])
NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.2 e6:66:c1:22:22:22])
NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.240 e6:66:c1:22:22:22])

ADD_VETH(p1, at_ns1, br0, "10.1.1.240/24")
NS_CHECK_EXEC([at_ns1], [ip link set dev p1 address e6:66:c1:22:22:22])
NS_CHECK_EXEC([at_ns1], [arp -s 10.1.1.1 e6:66:c1:11:11:11])

dnl Allow any traffic from ns0->ns1.
AT_DATA([flows.txt], [dnl
dnl track all IPv4 traffic and NAT any established traffic.
table=0 priority=10 ip, action=ct(nat,table=1)
table=0 priority=0 action=drop
dnl
dnl Table 1
dnl
dnl Allow new FTP control connections.
table=1 in_port=1 ct_state=+new tcp nw_src=10.1.1.1 tp_dst=21 action=ct(alg=ftp,commit,nat(dst=10.1.1.240)),2
dnl Allow related TCP connections from port 1.
table=1 in_port=2 ct_state=+new+rel tcp nw_src=10.1.1.240 action=ct(commit,nat),1
dnl Allow established TCP connections both ways, post-NAT match.
table=1 in_port=1 ct_state=+est tcp nw_dst=10.1.1.240 action=2
table=1 in_port=2 ct_state=+est tcp nw_dst=10.1.1.1 action=1

dnl Allow ICMP both ways.
table=1 priority=100 in_port=1 icmp, action=2
table=1 priority=100 in_port=2 icmp, action=1
table=1 priority=0, action=drop
])

AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])

dnl Check that the stacks working to avoid races.
OVS_WAIT_UNTIL([ip netns exec at_ns0 ping -c 1 10.1.1.240 >/dev/null])

OVS_START_L7([at_ns1], [ftp])

dnl FTP requests from p0->p1 should work fine.
NS_CHECK_EXEC([at_ns0], [wget ftp://10.1.1.2 --no-passive-ftp -t 3 -T 1 --retry-connrefused -v -o wget0.log])

dnl Discards CLOSE_WAIT and CLOSING
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.240,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),protoinfo=(state=<cleared>),helper=ftp
tcp,orig=(src=10.1.1.240,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=<cleared>)
])

OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([conntrack - IPv4 FTP Active with DNAT with reverse skew])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
CHECK_CONNTRACK_ALG()

OVS_TRAFFIC_VSWITCHD_START()

ADD_NAMESPACES(at_ns0, at_ns1)

ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
NS_CHECK_EXEC([at_ns0], [ip link set dev p0 address e6:66:c1:11:11:11])
NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.2 e6:66:c1:22:22:22])
NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.240 e6:66:c1:22:22:22])

ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
NS_CHECK_EXEC([at_ns1], [ip link set dev p1 address e6:66:c1:22:22:22])
NS_CHECK_EXEC([at_ns1], [arp -s 10.1.1.1 e6:66:c1:11:11:11])

dnl Allow any traffic from ns0->ns1.
AT_DATA([flows.txt], [dnl
dnl track all IPv4 traffic and NAT any established traffic.
table=0 priority=10 ip, action=ct(nat,table=1)
table=0 priority=0 action=drop
dnl
dnl Table 1
dnl
dnl Allow new FTP control connections.
table=1 in_port=1 ct_state=+new tcp nw_src=10.1.1.1 tp_dst=21 action=ct(alg=ftp,commit,nat(dst=10.1.1.2)),2
dnl Allow related TCP connections from port 1.
table=1 in_port=2 ct_state=+new+rel tcp nw_src=10.1.1.2 action=ct(commit,nat),1
dnl Allow established TCP connections both ways, post-NAT match.
table=1 in_port=1 ct_state=+est tcp nw_dst=10.1.1.2 action=2
table=1 in_port=2 ct_state=+est tcp nw_dst=10.1.1.1 action=1

dnl Allow ICMP both ways.
table=1 priority=100 in_port=1 icmp, action=2
table=1 priority=100 in_port=2 icmp, action=1
table=1 priority=0, action=drop
])

AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])

dnl Check that the stacks working to avoid races.
OVS_WAIT_UNTIL([ip netns exec at_ns0 ping -c 1 10.1.1.2 >/dev/null])

OVS_START_L7([at_ns1], [ftp])

dnl FTP requests from p0->p1 should work fine.
NS_CHECK_EXEC([at_ns0], [wget ftp://10.1.1.240 --no-passive-ftp -t 3 -T 1 --retry-connrefused -v -o wget0.log])

dnl Discards CLOSE_WAIT and CLOSING
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
tcp,orig=(src=10.1.1.1,dst=10.1.1.240,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),protoinfo=(state=<cleared>),helper=ftp
tcp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.1.1.240,sport=<cleared>,dport=<cleared>),protoinfo=(state=<cleared>)
])

OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([conntrack - IPv6 HTTP with SNAT])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
Expand Down Expand Up @@ -4733,7 +4913,7 @@ udp,orig=(src=fc00::1,dst=fc00::2,sport=<cleared>,dport=<cleared>),reply=(src=fc
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([conntrack - IPv6 FTP with NAT])
AT_SETUP([conntrack - IPv6 FTP with SNAT])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
Expand Down Expand Up @@ -4793,7 +4973,7 @@ tcp,orig=(src=fc00::2,dst=fc00::240,sport=<cleared>,dport=<cleared>),reply=(src=
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([conntrack - IPv6 FTP Passive with NAT])
AT_SETUP([conntrack - IPv6 FTP Passive with SNAT])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
Expand Down Expand Up @@ -4854,7 +5034,7 @@ tcp,orig=(src=fc00::1,dst=fc00::2,sport=<cleared>,dport=<cleared>),reply=(src=fc
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([conntrack - IPv6 FTP with NAT - orig tuple])
AT_SETUP([conntrack - IPv6 FTP with SNAT - orig tuple])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
Expand Down Expand Up @@ -4914,7 +5094,7 @@ tcp,orig=(src=fc00::2,dst=fc00::240,sport=<cleared>,dport=<cleared>),reply=(src=
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([conntrack - IPv4 TFTP with NAT])
AT_SETUP([conntrack - IPv4 TFTP with SNAT])
AT_SKIP_IF([test $HAVE_TFTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
Expand Down

0 comments on commit efa29a8

Please sign in to comment.