This patch removes the fallback to ephemeral ports when a SNAT port range is specified; DNAT already does not fallback to ephemeral ports, in general. This is not restrictive to the user and makes it easier to limit NAT L4 port selection.
The documentation is updated and a new test is added to enforce the behavior. Reported-at: https://mail.openvswitch.org/pipermail/ovs-dev/2019-February/356607.html Fixes: 286de2729955 ("dpdk: Userspace Datapath: Introduce NAT Support.") Signed-off-by: Darrell Ball <dlu...@gmail.com> --- lib/conntrack.c | 8 +++++--- lib/ovs-actions.xml | 11 ++++++----- tests/system-traffic.at | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/lib/conntrack.c b/lib/conntrack.c index ecac584..7ead3ad 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c @@ -2175,9 +2175,11 @@ nat_select_range_tuple(struct conntrack *ct, const struct conn *conn, uint16_t port = first_port; bool all_ports_tried = false; - /* For DNAT, we don't use ephemeral ports. */ - bool ephemeral_ports_tried = conn->nat_info->nat_action & NAT_ACTION_DST - ? true : false; + /* For DNAT or for specified port ranges, we don't use ephemeral ports. */ + bool ephemeral_ports_tried + = conn->nat_info->nat_action & NAT_ACTION_DST || + conn->nat_info->nat_action & NAT_ACTION_SRC_PORT + ? true : false; union ct_addr first_addr = ct_addr; bool pat_enabled = conn->key.nw_proto != IPPROTO_ICMP && conn->key.nw_proto != IPPROTO_ICMPV6; diff --git a/lib/ovs-actions.xml b/lib/ovs-actions.xml index fec0b95..84df842 100644 --- a/lib/ovs-actions.xml +++ b/lib/ovs-actions.xml @@ -1664,11 +1664,12 @@ $ ovs-ofctl -O OpenFlow10 add-flow br0 actions=mod_nw_src:1.2.3.4 <dd> The L4 <var>port</var> or range <code><var>port1</var>-<var>port2</var></code> from which the - translated port should be selected. In case of a mapping conflict - the datapath may choose any other non-conflicting port number - instead, even when no port range is specified. The port number - selection can be informed by the optional <code>random</code> and - <code>hash</code> flags described below. + translated port should be selected. When a port range is + specified, fallback to ephemeral ports does not happen, else, + it will. The port number selection can be informed by the + optional <code>random</code> and <code>hash</code> flags + described below. The userspace datapath only supports the + <code>hash</code> behavior. </dd> </dl> diff --git a/tests/system-traffic.at b/tests/system-traffic.at index d1f8c10..b124181 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -3994,6 +3994,56 @@ 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 - SNAT with port range with exhaustion]) +CHECK_CONNTRACK() +CHECK_CONNTRACK_NAT() +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 80:88:88:88:88:88]) +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24") + +dnl Allow any traffic from ns0->ns1. Only allow nd, return traffic from ns1->ns0. +AT_DATA([flows.txt], [dnl +in_port=1,tcp,action=ct(commit,zone=1,nat(src=10.1.1.240:34568,random)),2 +in_port=2,ct_state=-trk,tcp,tp_dst=34567,action=ct(table=0,zone=1,nat) +in_port=2,ct_state=-trk,tcp,tp_dst=34568,action=ct(table=0,zone=1,nat) +in_port=2,ct_state=+trk,ct_zone=1,tcp,action=1 +dnl +dnl ARP +priority=100 arp arp_op=1 action=move:OXM_OF_ARP_TPA[[]]->NXM_NX_REG2[[]],resubmit(,8),goto_table:10 +priority=10 arp action=normal +priority=0,action=drop +dnl +dnl MAC resolution table for IP in reg2, stores mac in OXM_OF_PKT_REG0 +table=8,reg2=0x0a0101f0/0xfffffff0,action=load:0x808888888888->OXM_OF_PKT_REG0[[]] +table=8,priority=0,action=load:0->OXM_OF_PKT_REG0[[]] +dnl ARP responder mac filled in at OXM_OF_PKT_REG0, or 0 for normal action. +dnl TPA IP in reg2. +dnl Swaps the fields of the ARP message to turn a query to a response. +table=10 priority=100 arp xreg0=0 action=normal +table=10 priority=10,arp,arp_op=1,action=load:2->OXM_OF_ARP_OP[[]],move:OXM_OF_ARP_SHA[[]]->OXM_OF_ARP_THA[[]],move:OXM_OF_PKT_REG0[[0..47]]->OXM_OF_ARP_SHA[[]],move:OXM_OF_ARP_SPA[[]]->OXM_OF_ARP_TPA[[]],move:NXM_NX_REG2[[]]->OXM_OF_ARP_SPA[[]],move:NXM_OF_ETH_SRC[[]]->NXM_OF_ETH_DST[[]],move:OXM_OF_PKT_REG0[[0..47]]->NXM_OF_ETH_SRC[[]],move:NXM_OF_IN_PORT[[]]->NXM_NX_REG3[[0..15]],load:0->NXM_OF_IN_PORT[[]],output:NXM_NX_REG3[[0..15]] +table=10 priority=0 action=drop +]) + +AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt]) + +dnl HTTP requests from p0->p1 should work fine. +OVS_START_L7([at_ns1], [http]) +NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 1 -T 1 --retry-connrefused -v -o wget0.log]) + +NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 1 -T 1 --retry-connrefused -v -o wget0.log], [4]) + +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2) | sed -e 's/dst=10.1.1.2[[45]][[0-9]]/dst=10.1.1.2XX/' | uniq], [0], [dnl +tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.2XX,sport=<cleared>,dport=<cleared>),zone=1,protoinfo=(state=<cleared>) +]) + +OVS_TRAFFIC_VSWITCHD_STOP(["dnl +/Unable to NAT due to tuple space exhaustion - if DoS attack, use firewalling and\/or zone partitioning./d +/Dropped .* log messages in last .* seconds \(most recently, .* seconds ago\) due to excessive rate/d"]) +AT_CLEANUP AT_SETUP([conntrack - more complex SNAT]) CHECK_CONNTRACK() -- 1.9.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev