Re: scrubbing support in Netfilter

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tuesday 2008-05-27 17:12, Nicolas Bareil wrote:
>
>
>I developped a Netfilter module which performs packet normalization, the
>"scrubbing" feature of OpenBSD[1]. Normalized trafic offers the
>following possibilities :

I seem to remember that Linux's TCP or nf_conntrack already does
some scrubbing.

>The current patch achieves the following transformations :
>
>* IPv4
>  - Random IP ID
>  - Zeroify ToS

Zeroify? Clearing the TOS is probably not a good idea because
it defeats packet scheduling (if it uses TOS).

>  - TTL normalization
>
>* TCP
> - Random TCP Sequence

I wonder if Linux already has this.

> - TCP Options
>   - Random Timestamp

Is this even RFC compatible?

>   - Sanity checks on MSS

>The following patch is "self-contained" : only nf_conntrack_proto_tcp.c is
>modified, the other files are new. The iptables patch is following this
>email. 

I suggest you have a look at "Writing your own Netfilter modules"
(abbreviated NFM in this reply) document from
http://jengelh.medozas.de/ , since I have seen a few outdated
constructs in your code.

>+	ct = nf_ct_get(skb, &ctinfo);
>+	if (!ct) {
>+		DEBUGP("ipt_SCRUB: No conntrack matching this packet.\n");
>+		return XT_CONTINUE;
>+	}
>+	nfscrub = nfct_scrub(ct);
>+	if (!nfscrub)
>+		nf_scrub_setup(skb, ct, ctinfo, info);
>+
>+	return XT_CONTINUE; /* XXX final decision: NF_ACCEPT ou XT_CONTINUE ? */
>+}

XT_CONTINUE is correct here, since you are in the mangle table,
so it is not an XXX case anymore :-)

>+static bool ipt_scrub_checkentry(const char *tablename,
>+				 const void *e,
>+				 const struct xt_target *target,
>+				 void *targinfo,
>+				 unsigned int hook_mask)
>+{
>+	return 1; /* There should be no invalid configuration possible */
>+}

Remove this function.

>+/*
>+ * nf_scrub_ip_tos_adjust()
>+ *
>+ * Overwrite the IP ToS with 0. Things like SSH, telnet use
>+ * this field (in vain on Internet ?).
>+ *
>+ */
>+void nf_scrub_ip_tos_adjust(struct iphdr *iph
>+			    , struct nf_conn *ct)
>+{
>+	NF_CT_ASSERT(iph);
>+	csum_replace2(&iph->check, ntohs(iph->tos), 0);
>+	iph->tos = 0;
>+}

Yes they do, don't just nuke it!

>+bool nf_scrub_ipv4_adjust(struct sk_buff *skb
>+			  , struct nf_conn *ct
>+			  , enum ip_conntrack_info ctinfo)
>+{
>+	struct iphdr *iph = ip_hdr(skb);
>+	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
>+	struct tcphdr *th;
>+	NF_CT_ASSERT(iph && ct);
>+
>+	if (ct->scrub & SCRUB_TCP_OPTIONS) {
>+		th = (struct tcphdr *) (((caddr_t)iph)+iph->ihl*4);
>+		if (!nf_scrub_tcp_parse_options(th, ct, ctinfo))
>+			return NF_DROP;
>+	}

Use tcp_hdr(). caddr_t? No, this is not BSD. [Also elsewhere.]
Try the book :)

>+obj-$(CONFIG_NF_SCRUB) += ip6t_SCRUB.o

Write a single module, as described in NFM.

>+	if (nexthdr == IPPROTO_TCP) {
>+		tcp = (struct tcphdr *)(skb_network_header(skb)+tcpoff);
>+		nf_scrub_tcp_setup(skb, tcp, ct, ctinfo);
>+	}
>+	return true;
>+}
>+EXPORT_SYMBOL(nf_scrub_ipv6_setup);

tcp_hdr?

>+++ b/net/netfilter/nf_conntrack_proto_tcp.c
>@@ -26,6 +26,10 @@
>...
>+	if (test_bit(SCRUB_TCP_SEQ_ADJUST_BIT, &ct->scrub)
>+	    && dir == IP_CT_DIR_ORIGINAL) {
>+		if (!nf_scrub_tcp_seq_adjust((struct tcphdr *)th, ct, ctinfo))
>+			return -NF_ACCEPT;
>+	}
>+#endif
>...
>+#ifdef CONFIG_NF_SCRUB_NEEDED
>+	if (test_bit(SCRUB_TCP_SEQ_ADJUST_BIT, &ct->scrub)
>+	    && dir == IP_CT_DIR_REPLY) {
>+		if (!nf_scrub_tcp_ack_adjust((struct tcphdr *)th, ct, ctinfo))
>+			return -NF_ACCEPT;
>+
>+		if (!nf_scrub_tcp_sack_adjust((struct tcphdr *)th, ct, ctinfo))
>+			return -NF_ACCEPT;
>+	}
>+#endif

Instead of adding casts to th, just remove the const from th, no?


>Here is the iptables patch.
>
>+static void help(void) 
>+{
>+	printf(
>+"SCRUB target v%s options\n"
>+"  --rand-ipid value		Set a random IP ID\n"
>+, XTABLES_VERSION);
>+}

XTABLES_VERSION does not really reflect the SCRUB version.
Just write "SCRUB target options:\n"

>+static int parse(int c, char **argv, int invert, unsigned int *flags,
>+		const void *entry,
>+		struct xt_entry_target **target)
>+{
>+	struct ipt_scrub_info *info = (struct ipt_scrub_info *) (*target)->data;
>+
>+        *flags=1;
>+
>+	switch (c) {
>+	case '!':
>+		/* do not overwrite "--no-something" */
>+		info->flags= (SCRUB_ALL & ~info->flags) ;
>+

Possibly unwanted fallthrough?

>+	case '2':
>+		if (string_to_number(optarg, 0, 255, (unsigned int *) &(info->ttl.scrubbing_default)) == -1)

Stack corruption. Don't just mindlessy use casts...

>+			exit_error(PARAMETER_PROBLEM, "Invalid threshold");
>+		break;
>+
>+	case '3':
>+		if (string_to_number(optarg, 0, 255, (unsigned int *) &(info->ttl.modifying_threshold)) == -1)
>+			exit_error(PARAMETER_PROBLEM, "Invalid threshold");
>+		break;
>+
>+	case '4':
>+		if (string_to_number(optarg, 0, 255, (unsigned int *) &(info->ttl.dropping_threshold)) == -1)
>+			exit_error(PARAMETER_PROBLEM, "Invalid threshold");
>+		break;

Same..

>+static void save(const void *ip, const struct xt_entry_target *target)
>+{
>+}
>+

Something *is* *missing*. :)

>+static struct option opts[] = {
>+	{ "scrub-everything", 0, 0, '!'},
>+	{ "ip-zero-tos", 0, 0, '0'},
>+	{ "ip-rand-id", 0, 0, '1' },
>+
>+	{ "ip-ttl-scrub", 0, 0, '9'},
>+	{ "ip-ttl-default", 1, 0, '2'},
>+	{ "ip-ttl-low-threshold", 1, 0, '3'},
>+	{ "ip-ttl-dropping-threshold", 1, 0, '4'},
>+	{ "ip-ttl-sealed", 0, 0, '5'},
>+
>+	{ "tcp-rand-seq", 0, 0, '6'},
>+	{ "tcp-opt-rand-timestamp", 0, 0, '7'},
>+	{ "tcp-opt-check-mss", 0, 0, '8'},
>+
>+	/* inverse parameter, is there another way */

Well you could make use of `iptables -j SCRUB ! --tcp-rand-seq`.
(See NFM book on how to scan for '!'.)

>+static struct xtables_target SCRUB = {
>+	.next		= NULL, 

Unspecified fields are always initialized to NULL, so..

>+	.name		= "SCRUB",
>+	.version	= XTABLES_VERSION,
>+	.size		= XT_ALIGN(sizeof(struct ipt_scrub_info)),
>+	.userspacesize	= XT_ALIGN(sizeof(struct ipt_scrub_info)),
>+	.help		= help,
>+	.init		= init,
>+	.parse		= parse,
>+	.final_check	= final_check,
>+	.print		= print,
>+	.save		= save,
>+	.extra_opts	= opts 
>+};
>+


>index 0000000..7d21083
>--- /dev/null
>+++ b/extensions/libipt_SCRUB.c

And _everything_ again. Suggest to combine all the code.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux