Received: by 10.192.165.148 with SMTP id m20csp1896488imm; Thu, 3 May 2018 07:10:02 -0700 (PDT) X-Google-Smtp-Source: AB8JxZrn1jB9z7gQKCTPtFltWqAbrJM5aGIBIDG6IK+znWT0roDgL0J9tKNpmWXh3PnO4FKebcGx X-Received: by 2002:a17:902:7596:: with SMTP id j22-v6mr24413266pll.334.1525356602604; Thu, 03 May 2018 07:10:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525356602; cv=none; d=google.com; s=arc-20160816; b=yNwo4Nmoky3qX1uO5v7q380PcY5N8BxzKBDD0taR3uOytwEAd65+Mg9OBuYxEyFSlW OjVo+Ve3C+zx6CIMM4fWx9l8lcvbaS9+Kt/7+AtL5Lla8vMxljmJh74+hNVxJg4ghqlH 8dOf7DFxLBvLlkQBdoqEpCYu0brFWh0R8k3Om4oZw/OkxqVp4odt18Jw7dJKgi511IS0 xQt66kxI/jWRGq/a1uejVRd7LnRcJVm2RWT7NasqtbWQAVBCmEzPzbny5rFR2V3JL/Zk bmCW6xre3Uj8RRwasSfsb12vzIaBKsdOB/jwtOTmefALIh/OkCNK1isTZtkoj+Dc6jl4 tVaw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=zK7m4Ij61hhAY8qFYEWu/t6mwRoWLLHAeS606BBKIM8=; b=NBK1l44lUnZGGIo1zhRVV+xSacj94j6ZAEbyYHAuOjzEASKGl4Njn+kWiJuFOLTR+Z fQWDzN2Dw7Ng0cinJtTy9RWJCPuZqdY4QS+qaCUpNA0n/H29MuVrMN3vPIi2bQpRPuRa Lg0geWVe4Q8GLJU+vzjrZqiq5yUz7aZweh9LbkaTAej1Pwnkb6wQmEuGODWLYrNlXeeh D64Pdg9hZiC2OdaftsNhCb4BFs/xII4E/rhAOm+TU0RuyoTx+rzoYddjSFdiYqPqugxu ucEmG1WBIK9auCPReo/v1+Pw/sHPl22LvE2NRp1OHBsNcnxNBWZxifnFk5Y4kJA4hL4M 82FQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=W7A5Cl4L; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o14-v6si11813112pgf.174.2018.05.03.07.09.48; Thu, 03 May 2018 07:10:02 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=W7A5Cl4L; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751261AbeECOIX (ORCPT + 99 others); Thu, 3 May 2018 10:08:23 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:51756 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750954AbeECOIU (ORCPT ); Thu, 3 May 2018 10:08:20 -0400 Received: by mail-wm0-f66.google.com with SMTP id j4so28630164wme.1; Thu, 03 May 2018 07:08:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=zK7m4Ij61hhAY8qFYEWu/t6mwRoWLLHAeS606BBKIM8=; b=W7A5Cl4L26GhtXHSTz9djfq5C6TYOrG5SpqYS8sBU26ij/gzEAiZoBpUoalFtvNK3O iSuuGAstbJ6hfI8RlIl4I9nnw0Qjbmq5pPcXQRfTllRvGtOuGxZ1gj09CbpFcZsE/PdS HnbHumG7cHafON+WjrhBvTgeR75sZ+6JHkWPC4/zUQu+3wJij3REsTfrNi3TYGEi611Y 1Ur2tyUlTMybNYFbWWaZ65kce//2/0Ck5LYDkuLVFjFFlgWBzownxrYltI8KJkT4MYHh f3Vgvh9KglpMXrqiPkcAOJR6MRAYPHBhr82VxHVAzasW4c2PjF93VwbqpQJgX4JVjxjN LVIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=zK7m4Ij61hhAY8qFYEWu/t6mwRoWLLHAeS606BBKIM8=; b=avD/tEnKJuXLE7UbB9vMSCLVAhbhw/7WoAPz9Ir4qGaM6ph+TLd3fWprPi0EJWKp4E qr+/cbocJhkYQwFv9EQMpbgnf/HyWwllywjk7aJ/hdkNYTVZIDcEjEEZ+TeHHKO6LJDl le7S7puzxJjiwZMp6PCpR/1bHxXhqF0tFC7fXp92FY2BCer5bPQH//z8dutasftGKMD5 M3S//yjYd7q9Cu/g77WCVppSh53dMM7QmKdsAWQZG49PTphK+8ihcyJ8EGaGKyJlKyPI fFymk+t1944HWNUELuGuGgmlb5lcNkFtMpkYAL4FAtb6uJtGJ64jcD2/SIC3V4kBgNBc 8Jiw== X-Gm-Message-State: ALQs6tB2I71+/2UKrv7yT1UcThcYpuRQVIwto4ZaAUofKVvcYA9kOrhB i1S2L26jNee7JZSX5DKosZML688P0o0= X-Received: by 2002:aa7:d41a:: with SMTP id z26-v6mr31161396edq.242.1525356498988; Thu, 03 May 2018 07:08:18 -0700 (PDT) Received: from kristrev-ThinkPad-X1-Carbon-2nd.lan ([193.213.155.210]) by smtp.gmail.com with ESMTPSA id n8-v6sm8171193edb.5.2018.05.03.07.08.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 03 May 2018 07:08:17 -0700 (PDT) From: Kristian Evensen To: netfilter-devel@vger.kernel.org Cc: Kristian Evensen , Pablo Neira Ayuso , Jozsef Kadlecsik , Florian Westphal , "David S. Miller" , coreteam@netfilter.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] netfilter: nf_queue: Replace conntrack entry Date: Thu, 3 May 2018 16:07:45 +0200 Message-Id: <20180503140745.26588-1-kristian.evensen@gmail.com> X-Mailer: git-send-email 2.14.1 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org SKBs are assigned a conntrack entry before being passed to any NFQUEUEs, and if no entry is found then a new one is created. This behavior causes problems for some traffic patterns. For example, if two UDP packets to/from the same host (using the same ports) arrive at the "same" time, both are assigned a new conntrack entry. After the first packet have traversed all chains, the conntrack entry will be inserted into the global table. The second packet will then be dropped during the insertion step, as an entry for the same flow already exists. One type of application that frequently generates this traffic pattern, is DNS resolvers. This commit introduces a new function that checks, and potentially replaces, the conntrack entry for any additional "new" SKBs mapping to an existing flow. While not a perfect solution, there are still situations where to-be-dropped SKBs can slip through, the situations is improved considerably. On the routers I have used for testing, packets belonging to the same UDP flow are let through (when generating the traffic pattern described above). Without the change in this commit, all packets except the first one was dropped. With the change in this commit, a user can implement "perfect" solutions in user-space. An application can for example keep track of seen UDP flows, and then only release packets belonging to one flow when the entry has been created. Without the change, and SKB is stuck with the original conntrack entry. Signed-off-by: Kristian Evensen --- net/netfilter/nfnetlink_queue.c | 68 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index c97966298..150c11ff4 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -43,6 +43,9 @@ #if IS_ENABLED(CONFIG_NF_CONNTRACK) #include +#include +#include +#include #endif #define NFQNL_QMAX_DEFAULT 1024 @@ -1046,6 +1049,53 @@ static int nfq_id_after(unsigned int id, unsigned int max) return (int)(id - max) > 0; } +#if IS_ENABLED(CONFIG_NF_CONNTRACK) +static void nfqnl_update_ct(struct net *net, struct sk_buff *skb) +{ + const struct nf_conntrack_l3proto *l3proto; + const struct nf_conntrack_l4proto *l4proto; + struct nf_conntrack_tuple_hash *h; + struct nf_conntrack_tuple tuple; + enum ip_conntrack_info ctinfo; + struct nf_conn *ct = NULL; + unsigned int dataoff; + u16 l3num; + u8 l4num; + + ct = nf_ct_get(skb, &ctinfo); + l3num = nf_ct_l3num(ct); + l3proto = nf_ct_l3proto_find_get(l3num); + + if (l3proto->get_l4proto(skb, skb_network_offset(skb), &dataoff, + &l4num) <= 0) { + return; + } + + l4proto = nf_ct_l4proto_find_get(l3num, l4num); + + if (!nf_ct_get_tuple(skb, skb_network_offset(skb), dataoff, l3num, + l4num, net, &tuple, l3proto, l4proto)) { + return; + } + +#if IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) + h = nf_conntrack_find_get(net, &ct->zone, &tuple); +#else + h = nf_conntrack_find_get(net, NULL, &tuple); +#endif + + if (h) { + pr_debug("%s: tuple %u %pI4:%hu -> %pI4:%hu\n", __func__, + tuple.dst.protonum, &tuple.src.u3.ip, + ntohs(tuple.src.u.all), &tuple.dst.u3.ip, + ntohs(tuple.dst.u.all)); + nf_ct_put(ct); + ct = nf_ct_tuplehash_to_ctrack(h); + nf_ct_set(skb, ct, IP_CT_NEW); + } +} +#endif + static int nfqnl_recv_verdict_batch(struct net *net, struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, @@ -1060,6 +1110,7 @@ static int nfqnl_recv_verdict_batch(struct net *net, struct sock *ctnl, LIST_HEAD(batch_list); u16 queue_num = ntohs(nfmsg->res_id); struct nfnl_queue_net *q = nfnl_queue_pernet(net); + enum ip_conntrack_info ctinfo; queue = verdict_instance_lookup(q, queue_num, NETLINK_CB(skb).portid); @@ -1090,6 +1141,16 @@ static int nfqnl_recv_verdict_batch(struct net *net, struct sock *ctnl, list_for_each_entry_safe(entry, tmp, &batch_list, list) { if (nfqa[NFQA_MARK]) entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK])); + +#if IS_ENABLED(CONFIG_NF_CONNTRACK) + nf_ct_get(entry->skb, &ctinfo); + + if (ctinfo == IP_CT_NEW && verdict != NF_STOLEN && + verdict != NF_DROP) { + nfqnl_update_ct(net, entry->skb); + } +#endif + nf_reinject(entry, verdict); } return 0; @@ -1213,6 +1274,13 @@ static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl, if (nfqa[NFQA_MARK]) entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK])); +#if IS_ENABLED(CONFIG_NF_CONNTRACK) + nf_ct_get(entry->skb, &ctinfo); + + if (ctinfo == IP_CT_NEW && verdict != NF_STOLEN && verdict != NF_DROP) + nfqnl_update_ct(net, entry->skb); +#endif + nf_reinject(entry, verdict); return 0; } -- 2.14.1