diff options
-rw-r--r-- | lib/conntrack.c | 8 | ||||
-rw-r--r-- | lib/ovs-actions.xml | 11 | ||||
-rw-r--r-- | tests/system-traffic.at | 50 |
3 files changed, 61 insertions, 8 deletions
diff --git a/lib/conntrack.c b/lib/conntrack.c index ecac584d7..7ead3ad83 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 fec0b95fe..84df842a1 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 d1f8c1021..b1241812e 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() |