From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Bill Fink <billfink@mindspring.com>
Cc: netfilter@vger.kernel.org, netfilter-devel@vger.kernel.org, fw@strlen.de
Subject: Re: conntrackd segfault on EPSV IPv6 ftp command when using ftp ExpectationSync
Date: Thu, 11 Jul 2013 00:08:20 +0200 [thread overview]
Message-ID: <20130710220820.GA20666@localhost> (raw)
In-Reply-To: <20130710055815.a1bd2c1d.billfink@mindspring.com>
[-- Attachment #1: Type: text/plain, Size: 1502 bytes --]
On Wed, Jul 10, 2013 at 05:58:15AM -0400, Bill Fink wrote:
> Almost there. With the above patch, I now successfully get
> IPv6 expectations on the backup firewall. Unfortunately they're
> not quite right. On the backup firewall, the expectation src-IP
> is the same as the dst-IP (either IPv4 or IPv6).
>
> Primary firewall:
>
> [root@sen-fw1 linux-3.7.3-101.fc17.x86_64]# conntrack -L expect
> 251 proto=6 src=192.168.218.199 dst=192.168.28.198 sport=0 dport=54705 mask-src=255.255.255.255 mask-dst=255.255.255.255 sport=0 dport=65535 master-src=192.168.218.199 master-dst=192.168.28.198 sport=56877 dport=21 class=0 helper=ftp
> conntrack v1.4.0 (conntrack-tools): 1 expectations have been shown.
>
> Backup firewall:
>
> [root@sen-fw2 linux-3.7.3-101.fc17.x86_64]# conntrack -L expect
> 245 proto=6 src=192.168.28.198 dst=192.168.28.198 sport=0 dport=54705 mask-src=255.255.255.255 mask-dst=255.255.255.255 sport=0 dport=65535 master-src=192.168.218.199 master-dst=192.168.28.198 sport=56877 dport=21 class=0 helper=ftp
> conntrack v1.4.0 (conntrack-tools): 1 expectations have been shown.
>
> This was an unfortunate side affect of the patch to fix the
> conntrackd segfault problem. If I use Florian's version
> of the fix segfault patch rather than Pablo's then all is
> good.
Thanks for the information, however, we still need to get working back
the filtering support.
Could you give a try to the following patch, please?
It applies on top of conntrack-tools master branch, thanks.
[-- Attachment #2: 0001-conntrackd-add-specific-filtering-for-expectations.patch --]
[-- Type: text/x-diff, Size: 8971 bytes --]
>From 964b9a11a15f27dc4393d07dd9971f65c9fe998c Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Wed, 10 Jul 2013 23:35:22 +0200
Subject: [PATCH] conntrackd: add specific filtering for expectations
This patch adds exp_filter_conntrack, that allows us to filter expectations
based on its master conntrack. Previously, the daemon was relying on the
existing ct_filter_conntrack, however, we cannot use it since the master
tuple of the expectation has neither reply tuple nor state.
This partially reverts (479a37a conntrackd: fix crash with IPv6 expectation
in the filtering code) as it was incorrectly setting the reply tuple of the
master conntrack.
Reported-by: Bill Fink <billfink@mindspring.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/filter.h | 1 +
src/ctnl.c | 37 ++++---------
src/filter.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 158 insertions(+), 34 deletions(-)
diff --git a/include/filter.h b/include/filter.h
index 3c7c8cc..e1cf671 100644
--- a/include/filter.h
+++ b/include/filter.h
@@ -51,6 +51,7 @@ void ct_filter_set_logic(struct ct_filter *f,
enum ct_filter_type type,
enum ct_filter_logic logic);
int ct_filter_conntrack(const struct nf_conntrack *ct, int userspace);
+int exp_filter_conntrack(const struct nf_conntrack *master);
struct exp_filter;
struct nf_expect;
diff --git a/src/ctnl.c b/src/ctnl.c
index 9e1cfa1..c37c38a 100644
--- a/src/ctnl.c
+++ b/src/ctnl.c
@@ -211,35 +211,14 @@ out:
return NFCT_CB_CONTINUE;
}
-static const struct nf_conntrack *exp_get_master_ct(struct nf_expect *exp)
-{
- struct nf_conntrack *master =
- (struct nf_conntrack *)nfexp_get_attr(exp, ATTR_EXP_MASTER);
-
- /* The function ct_filter_conntrack needs the source address of the
- * reply tuple, emulate it.
- */
- switch (nfct_get_attr_u8(master, ATTR_L3PROTO)) {
- case AF_INET:
- nfct_set_attr_u32(master, ATTR_REPL_IPV4_SRC,
- nfct_get_attr_u32(master, ATTR_IPV4_DST));
- break;
- case AF_INET6:
- nfct_set_attr(master, ATTR_REPL_IPV6_SRC,
- nfct_get_attr(master, ATTR_IPV6_DST));
- break;
- }
-
- return master;
-}
-
static int exp_event_handler(const struct nlmsghdr *nlh,
enum nf_conntrack_msg_type type,
struct nf_expect *exp,
void *data)
{
int origin_type;
- const struct nf_conntrack *master = exp_get_master_ct(exp);
+ const struct nf_conntrack *master =
+ nfexp_get_attr(exp, ATTR_EXP_MASTER);
STATE(stats).nl_events_received++;
@@ -247,7 +226,7 @@ static int exp_event_handler(const struct nlmsghdr *nlh,
STATE(stats).nl_events_filtered++;
goto out;
}
- if (ct_filter_conntrack(master, 1))
+ if (exp_filter_conntrack(master))
return NFCT_CB_CONTINUE;
origin_type = origin_find(nlh);
@@ -296,12 +275,13 @@ static int dump_handler(enum nf_conntrack_msg_type type,
static int exp_dump_handler(enum nf_conntrack_msg_type type,
struct nf_expect *exp, void *data)
{
- const struct nf_conntrack *master = exp_get_master_ct(exp);
+ const struct nf_conntrack *master =
+ nfexp_get_attr(exp, ATTR_EXP_MASTER);
if (!exp_filter_find(STATE(exp_filter), exp))
return NFCT_CB_CONTINUE;
- if (ct_filter_conntrack(master, 1))
+ if (exp_filter_conntrack(master))
return NFCT_CB_CONTINUE;
switch(type) {
@@ -329,12 +309,13 @@ static int get_handler(enum nf_conntrack_msg_type type,
static int exp_get_handler(enum nf_conntrack_msg_type type,
struct nf_expect *exp, void *data)
{
- const struct nf_conntrack *master = exp_get_master_ct(exp);
+ const struct nf_conntrack *master =
+ nfexp_get_attr(exp, ATTR_EXP_MASTER);
if (!exp_filter_find(STATE(exp_filter), exp))
return NFCT_CB_CONTINUE;
- if (ct_filter_conntrack(master, 1))
+ if (exp_filter_conntrack(master))
return NFCT_CB_CONTINUE;
STATE(get_retval) = 1;
diff --git a/src/filter.c b/src/filter.c
index e21cfde..c160c1a 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -279,13 +279,10 @@ __ct_filter_test_mask4(const void *ptr, const void *ct)
(elem->ip & elem->mask) == (dst & elem->mask));
}
-static int
-__ct_filter_test_mask6(const void *ptr, const void *ct)
+static inline int
+vector_elem_cmp_ipv6(const struct ct_filter_netmask_ipv6 *elem,
+ const uint32_t *src, const uint32_t *dst)
{
- const struct ct_filter_netmask_ipv6 *elem = ptr;
- const uint32_t *src = nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC);
- const uint32_t *dst = nfct_get_attr(ct, ATTR_REPL_IPV6_SRC);
-
return (((elem->ip[0] & elem->mask[0]) == (src[0] & elem->mask[0]) &&
(elem->ip[1] & elem->mask[1]) == (src[1] & elem->mask[1]) &&
(elem->ip[2] & elem->mask[2]) == (src[2] & elem->mask[2]) &&
@@ -297,6 +294,16 @@ __ct_filter_test_mask6(const void *ptr, const void *ct)
}
static int
+__ct_filter_test_mask6(const void *ptr, const void *ct)
+{
+ const struct ct_filter_netmask_ipv6 *elem = ptr;
+ const uint32_t *src = nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC);
+ const uint32_t *dst = nfct_get_attr(ct, ATTR_REPL_IPV6_SRC);
+
+ return vector_elem_cmp_ipv6(elem, src, dst);
+}
+
+static int
__ct_filter_test_state(struct ct_filter *f, const struct nf_conntrack *ct)
{
uint16_t val = 0;
@@ -407,6 +414,141 @@ int ct_filter_conntrack(const struct nf_conntrack *ct, int userspace)
return 0;
}
+static int exp_filter_ipv4(const void *ptr, const void *master)
+{
+ const struct ct_filter_netmask_ipv4 *elem = ptr;
+ const uint32_t src = nfct_get_attr_u32(master, ATTR_IPV4_SRC);
+ const uint32_t dst = nfct_get_attr_u32(master, ATTR_IPV4_DST);
+
+ return ((elem->ip & elem->mask) == (src & elem->mask) ||
+ (elem->ip & elem->mask) == (dst & elem->mask));
+}
+
+static int exp_filter_ipv6(const void *ptr, const void *master)
+{
+ const struct ct_filter_netmask_ipv6 *elem = ptr;
+ const uint32_t *src = nfct_get_attr(master, ATTR_IPV6_SRC);
+ const uint32_t *dst = nfct_get_attr(master, ATTR_IPV6_DST);
+
+ return vector_elem_cmp_ipv6(elem, src, dst);
+}
+
+static inline int
+exp_filter_test_ipv4(struct ct_filter *f, const struct nf_conntrack *ct)
+{
+ int id_src, id_dst;
+ uint32_t src, dst;
+
+ src = nfct_get_attr_u32(ct, ATTR_IPV4_SRC);
+ dst = nfct_get_attr_u32(ct, ATTR_IPV4_DST);
+
+ id_src = hashtable_hash(f->h, &src);
+ id_dst = hashtable_hash(f->h, &dst);
+
+ return hashtable_find(f->h, &src, id_src) ||
+ hashtable_find(f->h, &dst, id_dst);
+}
+
+static inline int
+exp_filter_test_ipv6(struct ct_filter *f, const struct nf_conntrack *ct)
+{
+ int id_src, id_dst;
+ const uint32_t *src, *dst;
+
+ src = nfct_get_attr(ct, ATTR_IPV6_SRC);
+ dst = nfct_get_attr(ct, ATTR_IPV6_DST);
+
+ id_src = hashtable_hash(f->h6, src);
+ id_dst = hashtable_hash(f->h6, dst);
+
+ return hashtable_find(f->h6, src, id_src) ||
+ hashtable_find(f->h6, dst, id_dst);
+}
+
+static int exp_filter_check(struct ct_filter *f, const struct nf_conntrack *ct)
+{
+ int ret, protonum = nfct_get_attr_u8(ct, ATTR_L4PROTO);
+
+ /* no event filtering at all */
+ if (f == NULL)
+ return 1;
+
+ if (f->logic[CT_FILTER_L4PROTO] != -1) {
+ ret = test_bit_u32(protonum, f->l4protomap);
+ if (ret ^ f->logic[CT_FILTER_L4PROTO])
+ return 0;
+ }
+
+ if (f->logic[CT_FILTER_ADDRESS] != -1) {
+ switch (nfct_get_attr_u8(ct, ATTR_L3PROTO)) {
+ case AF_INET:
+ ret = vector_iterate(f->v, ct, exp_filter_ipv4);
+ if (ret ^ f->logic[CT_FILTER_ADDRESS])
+ return 0;
+ ret = exp_filter_test_ipv4(f, ct);
+ if (ret ^ f->logic[CT_FILTER_ADDRESS])
+ return 0;
+ break;
+ case AF_INET6:
+ ret = vector_iterate(f->v6, ct, exp_filter_ipv6);
+ if (ret ^ f->logic[CT_FILTER_ADDRESS])
+ return 0;
+ ret = exp_filter_test_ipv6(f, ct);
+ if (ret ^ f->logic[CT_FILTER_ADDRESS])
+ return 0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 1;
+}
+
+static inline int exp_filter_sanity_check(const struct nf_conntrack *master)
+{
+ if (!nfct_attr_is_set(master, ATTR_L3PROTO)) {
+ dlog(LOG_ERR, "missing layer 3 protocol");
+ return 0;
+ }
+
+ switch (nfct_get_attr_u8(master, ATTR_L3PROTO)) {
+ case AF_INET:
+ if (!nfct_attr_is_set(master, ATTR_IPV4_SRC) ||
+ !nfct_attr_is_set(master, ATTR_IPV4_DST)) {
+ dlog(LOG_ERR, "missing IPv4 address. "
+ "You forgot to load "
+ "nf_conntrack_ipv4?");
+ return 0;
+ }
+ break;
+ case AF_INET6:
+ if (!nfct_attr_is_set(master, ATTR_IPV6_SRC) ||
+ !nfct_attr_is_set(master, ATTR_IPV6_DST)) {
+ dlog(LOG_ERR, "missing IPv6 address. "
+ "You forgot to load "
+ "nf_conntrack_ipv6?");
+ return 0;
+ }
+ break;
+ }
+ return 1;
+}
+
+int exp_filter_conntrack(const struct nf_conntrack *master)
+{
+ if (!exp_filter_sanity_check(master))
+ return 1;
+
+ /* The master tuple of the expectation has neither reply tuple nor
+ * state, use specific filtering function for this case.
+ */
+ if (!exp_filter_check(STATE(us_filter), master))
+ return 1;
+
+ return 0;
+}
+
struct exp_filter {
struct list_head list;
};
--
1.7.10.4
next prev parent reply other threads:[~2013-07-10 22:09 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-05 6:03 conntrackd segfault on EPSV IPv6 ftp command when using ftp ExpectationSync Bill Fink
2013-07-05 8:19 ` Florian Westphal
2013-07-05 19:45 ` Bill Fink
2013-07-05 23:52 ` Bill Fink
2013-07-06 13:23 ` Pablo Neira Ayuso
2013-07-07 7:04 ` Bill Fink
2013-07-09 5:30 ` Bill Fink
2013-07-09 18:22 ` Pablo Neira Ayuso
2013-07-10 9:58 ` Bill Fink
2013-07-10 22:08 ` Pablo Neira Ayuso [this message]
2013-07-11 0:48 ` Pablo Neira Ayuso
2013-07-11 15:19 ` Bill Fink
2013-07-12 7:01 ` Bill Fink
2013-07-15 12:49 ` Pablo Neira Ayuso
2013-07-16 5:55 ` Bill Fink
2013-07-16 21:33 ` Pablo Neira Ayuso
2013-07-16 21:37 ` Pablo Neira Ayuso
2013-07-22 7:00 ` Bill Fink
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130710220820.GA20666@localhost \
--to=pablo@netfilter.org \
--cc=billfink@mindspring.com \
--cc=fw@strlen.de \
--cc=netfilter-devel@vger.kernel.org \
--cc=netfilter@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).