diff --git a/extensions/libxt_SCRUB.c b/extensions/libxt_SCRUB.c
new file mode 100644
index 0000000..a8aecc9
--- /dev/null
+++ b/extensions/libxt_SCRUB.c
@@ -0,0 +1,307 @@
+/* Shared library add-on to iptables for the SCRUB target
+ * (C) 2008 by Nicolas Bareil <nico@chdir.org>
+ *
+ * This program is distributed under the terms of GNU GPL
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+#include <linux/netfilter/xt_SCRUB.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+
+#define SCRUB_ALL (SCRUB_IP_TOS_ADJUST|SCRUB_IP_RAND_ID_ADJUST|SCRUB_IP_TTL_ADJUST|SCRUB_TCP_SEQ_ADJUST|SCRUB_TCP_OPT_TIMESTAMP_ADJUST|SCRUB_TCP_OPT_MSS_ADJUST)
+
+bool ipv6 = false;
+
+static void scrub_tg_init(struct xt_entry_target *t)
+{
+	struct xt_scrub_info *info = (struct xt_scrub_info *) t->data;
+
+	info->flags = 0;
+	info->ttl.scrubbing_default = SCRUB_NORMALIZE_TTL;
+	info->ttl.modifying_threshold = SCRUB_TTL_LOW_THRESHOLD;
+	info->ttl.dropping_threshold = SCRUB_TTL_DROP_IF_LOWER;
+}
+
+static void scrub_tg6_init(struct xt_entry_target *t)
+{
+	struct xt_scrub_info *info = (struct xt_scrub_info *) t->data;
+
+	info->flags = 0;
+}
+
+static void scrub_tg_help(void) 
+{
+	printf(
+"SCRUB target options\n"
+"       --scrub-everything          : Enable all features\n"
+"   [!] --ip-zero-tos               : Zeroify the IP ToS (be careful)\n"
+"   [!] --ip-rand-id                : Randomize IP ID\n\n"
+"   [!] --ip-scrub-ttl              : Enable the TTL tranformations\n"
+"       --ip-ttl-default 12         : Set the default TTL when normalizing\n"
+"       --ip-ttl-low-threshold      : Set the lowest TTL that we can put\n"
+"       --ip-ttl-dropping-threshold : Set the minimum TTL possible, drop if lower\n"
+"   [!] --ip-ttl-sealed             : Do not allow the TTL to be changed in a connection\n\n"
+"   [!] --tcp-rand-seq              : Randomize TCP Initial Sequence Number\n"
+"   [!] --tcp-opt-rand-timestamp    : Randomize TCP Timestamp\n"
+"   [!] --tcp-opt-check-mss         : Enable sanity checks on TCP MSS option\n\n"
+"\n");
+}
+
+static void scrub_tg6_help(void) 
+{
+	printf(
+"SCRUB target options\n"
+"       --scrub-everything          : Enable all features\n"
+"   [!] --tcp-rand-seq              : Randomize TCP Initial Sequence Number\n"
+"   [!] --tcp-opt-rand-timestamp    : Randomize TCP Timestamp\n"
+"   [!] --tcp-opt-check-mss         : Enable sanity checks on TCP MSS option\n\n"
+"\n");
+}
+
+static int scrub_tg_parse(int c, char **argv, int invert, unsigned int *flags,
+		const void *entry,
+		struct xt_entry_target **target)
+{
+	struct xt_scrub_info *info = (struct xt_scrub_info *) (*target)->data;
+	int adjust_bit = 0;
+	unsigned int tmp;
+        *flags=1;
+
+	if (c == '*') {
+		/* do not overwrite "--no-something" */
+		info->flags= (SCRUB_ALL & ~info->flags) ;
+		return true;
+
+	} else {
+		switch (c) {
+		case '0':
+			adjust_bit = SCRUB_IP_TOS_ADJUST;
+			break;
+
+		case '1':
+			adjust_bit = SCRUB_IP_RAND_ID_ADJUST;
+			break;
+
+		case '9':
+			adjust_bit = SCRUB_IP_TTL_ADJUST;
+			break;
+
+		case '2':
+			if (string_to_number(optarg, 0, 255, &tmp) == -1)
+				exit_error(PARAMETER_PROBLEM, "Invalid threshold");
+			else
+				info->ttl.scrubbing_default = tmp;
+			break;
+
+		case '3':
+			if (string_to_number(optarg, 0, 255, &tmp) == -1)
+				exit_error(PARAMETER_PROBLEM, "Invalid threshold");
+			else
+				info->ttl.modifying_threshold = tmp;
+			break;
+
+		case '4':
+			if (string_to_number(optarg, 0, 255, &tmp) == -1)
+				exit_error(PARAMETER_PROBLEM, "Invalid threshold");
+			else
+				info->ttl.dropping_threshold = tmp;
+			break;
+
+		case '5':
+			adjust_bit = SCRUB_IP_TTL_ADJUST;
+			break;
+
+		case '6':
+			adjust_bit = SCRUB_TCP_SEQ_ADJUST;
+			break;
+
+		case '7':
+			adjust_bit = SCRUB_TCP_OPT_TIMESTAMP_ADJUST;
+			break;
+
+		case '8':
+			adjust_bit = SCRUB_TCP_OPT_MSS_ADJUST;
+			break;
+
+		default:
+			printf("===> %c, WTF\n", c);
+			return false;
+		}
+
+		if (adjust_bit) {
+			if (invert)
+				info->flags |= (info->flags & ~adjust_bit);
+			else
+				info->flags |= adjust_bit;
+		}
+	}
+
+	return true;
+}
+
+static int scrub_tg6_parse(int c, char **argv, int invert, unsigned int *flags,
+		const void *entry,
+		struct xt_entry_target **target)
+{
+	struct xt_scrub_info *info = (struct xt_scrub_info *) (*target)->data;
+	int adjust_bit = 0;
+        *flags=1;
+
+	if (c == '*') {
+		/* do not overwrite "--no-something" */
+		info->flags= (SCRUB_ALL & ~info->flags) ;
+		return true;
+	} else {
+		switch (c) {
+		case '6':
+			adjust_bit = SCRUB_TCP_SEQ_ADJUST;
+			break;
+
+		case '7':
+			adjust_bit = SCRUB_TCP_OPT_TIMESTAMP_ADJUST;
+			break;
+
+		case '8':
+			adjust_bit = SCRUB_TCP_OPT_MSS_ADJUST;
+			break;
+
+		default:
+			return 0;
+		}
+
+		if (adjust_bit) {
+			if (invert)
+				info->flags |= (info->flags & ~adjust_bit);
+			else
+				info->flags |= adjust_bit;
+		}
+	}
+
+	return 1;
+}
+
+static void scrub_tg_save(const void *ip, const struct xt_entry_target *target)
+{
+	struct xt_scrub_info *info = (struct xt_scrub_info *) target->data;
+
+	if (info->flags == SCRUB_ALL) {
+		printf("--scrub-everything ");
+		return;
+	}
+
+	if (info->flags & SCRUB_TCP_SEQ_ADJUST)
+		printf("--tcp-rand-seq ");
+
+	if (info->flags & SCRUB_IP_RAND_ID_ADJUST)
+		printf("--ip-rand-id ");
+
+	if (info->flags & SCRUB_IP_TOS_ADJUST)
+		printf("--ip-zero-tos ");
+
+	if (info->flags & SCRUB_IP_TTL_ADJUST)
+		printf("--ip-scrub-ttl --ip-ttl-default %u --ip-ttl-low-threshold %u --ip-ttl-dropping-threschold %u "
+		       , info->ttl.scrubbing_default
+		       , info->ttl.modifying_threshold
+		       , info->ttl.dropping_threshold);
+
+	if (info->flags & SCRUB_TCP_OPT_MSS_ADJUST)
+		printf("--tcp-opt-check-mss ");
+
+	if (info->flags & SCRUB_TCP_OPT_TIMESTAMP_ADJUST)
+		printf("--tcp-opt-rand-timestamp ");
+
+	if (info->flags & SCRUB_IP_SEALED_TTL_ADJUST)
+		printf("--ip-ttl-sealed ");
+}
+
+static void scrub_tg_print(const void *ip,
+		const struct xt_entry_target *target, int numeric)
+{
+	const struct xt_scrub_info *info =
+		(struct xt_scrub_info *) target->data;
+
+	printf("SCRUB ");
+
+	if (info->flags & SCRUB_IP_TTL_ADJUST)
+		printf("ttl-adjust [default-ttl=%u low-threshold=%u dropping-threschold=%u] "
+		       , info->ttl.scrubbing_default
+		       , info->ttl.modifying_threshold
+		       , info->ttl.dropping_threshold);
+
+	if (info->flags & SCRUB_TCP_SEQ_ADJUST)
+		printf("random-tcp-isn ");
+
+	if (info->flags & SCRUB_IP_RAND_ID_ADJUST)
+		printf("random-ip-id ");
+
+	if (info->flags & SCRUB_IP_TOS_ADJUST)
+		printf("zeroify-ip-tos ");
+
+	if (info->flags & SCRUB_TCP_OPT_MSS_ADJUST)
+		printf("check-tcp-mss ");
+
+	if (info->flags & SCRUB_TCP_OPT_TIMESTAMP_ADJUST)
+		printf("random-tcp-timestamp ");
+
+	if (info->flags & SCRUB_IP_SEALED_TTL_ADJUST)
+		printf("ip-ttl-sealed ");
+}
+
+static const struct option scrub_tg_opts[] = {
+	{.name = "scrub-everything", .has_arg = false, .val = '*'},
+	{.name = "ip-zero-tos",      .has_arg = false, .val = '0'},
+	{.name = "ip-rand-id",       .has_arg = false, .val  = '1' },
+
+	{.name = "ip-scrub-ttl",              .has_arg = false, .val = '9'},
+	{.name = "ip-ttl-default",            .has_arg = true, .val = '2'},
+	{.name = "ip-ttl-low-threshold",      .has_arg = true, .val = '3'},
+	{.name = "ip-ttl-dropping-threshold", .has_arg = true, .val = '4'},
+	{.name = "ip-ttl-sealed",             .has_arg = false, .val = '5'},
+
+	{.name = "tcp-rand-seq",            .has_arg = false, .val = '6'},
+	{.name = "tcp-opt-rand-timestamp",  .has_arg = false, .val = '7'},
+	{.name = "tcp-opt-check-mss",       .has_arg = false, .val = '8'},
+
+	{ NULL }
+};
+
+static struct xtables_target scrub_tg_reg = {
+	.name		= "SCRUB",
+	.version	= XTABLES_VERSION,
+	.family         = AF_INET,
+	.size		= XT_ALIGN(sizeof(struct xt_scrub_info)),
+	.userspacesize	= XT_ALIGN(sizeof(struct xt_scrub_info)),
+	.help		= scrub_tg_help,
+	.init		= scrub_tg_init,
+	.parse		= scrub_tg_parse,
+	.print		= scrub_tg_print,
+	.save		= scrub_tg_save,
+	.extra_opts	= scrub_tg_opts 
+};
+
+static struct xtables_target scrub_tg6_reg = {
+	.name		= "SCRUB",
+	.version	= XTABLES_VERSION,
+	.family         = AF_INET6,
+	.size		= XT_ALIGN(sizeof(struct xt_scrub_info)),
+	.userspacesize	= XT_ALIGN(sizeof(struct xt_scrub_info)),
+	.help		= scrub_tg6_help,
+	.init		= scrub_tg6_init,
+	.parse		= scrub_tg6_parse,
+	.print		= scrub_tg_print,
+	.save		= scrub_tg_save,
+	.extra_opts	= scrub_tg_opts 
+};
+
+void _init(void)
+{
+	xtables_register_target(&scrub_tg_reg);
+	xtables_register_target(&scrub_tg6_reg);
+}
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index 3b452a6..720fabb 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -132,4 +132,29 @@ enum ip_conntrack_expect_events {
 	IPEXP_NEW = (1 << IPEXP_NEW_BIT),
 };
 
+enum nf_scrub_transformations {
+    /* scrub tcp sequence adjusting */
+    SCRUB_TCP_SEQ_ADJUST_BIT = 1,
+    SCRUB_TCP_SEQ_ADJUST = (1 << SCRUB_TCP_SEQ_ADJUST_BIT),
+
+    SCRUB_IP_RAND_ID_ADJUST_BIT = 2,
+    SCRUB_IP_RAND_ID_ADJUST = (1 << SCRUB_IP_RAND_ID_ADJUST_BIT),
+
+    SCRUB_IP_TTL_ADJUST_BIT = 3,
+    SCRUB_IP_TTL_ADJUST = (1 << SCRUB_IP_TTL_ADJUST_BIT),
+
+    SCRUB_IP_TOS_ADJUST_BIT = 4,
+    SCRUB_IP_TOS_ADJUST = (1 << SCRUB_IP_TOS_ADJUST_BIT),
+
+    SCRUB_TCP_OPT_MSS_ADJUST_BIT = 5,
+    SCRUB_TCP_OPT_MSS_ADJUST = (1 << SCRUB_TCP_OPT_MSS_ADJUST_BIT),
+
+    SCRUB_TCP_OPT_TIMESTAMP_ADJUST_BIT = 6,
+    SCRUB_TCP_OPT_TIMESTAMP_ADJUST = (1 << SCRUB_TCP_OPT_TIMESTAMP_ADJUST_BIT),
+
+    SCRUB_IP_SEALED_TTL_ADJUST_BIT = 7,
+    SCRUB_IP_SEALED_TTL_ADJUST = (1 << SCRUB_IP_SEALED_TTL_ADJUST_BIT),
+};
+
+
 #endif /* _NF_CONNTRACK_COMMON_H */

