From 85d8f98dd787c66858182da762967356d1f3e4b8 Mon Sep 17 00:00:00 2001 From: Martin Barrowcliff Date: Sat, 4 Jun 2011 08:11:38 -0400 Subject: [PATCH] xt_TARPIT: fix a kernel oops in --reset mode 1. Moved misplaced code that was causing kernel oops in reset mode. 2. Added payload size calc to honeypot mode, so ack sequence may ACK the length of client's sent payload packets correctly. 3. Modified TTL for honeypot mode so we look more like a Windows machine. --- doc/changelog.txt | 2 ++ extensions/xt_TARPIT.c | 71 +++++++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/doc/changelog.txt b/doc/changelog.txt index 9d9996b..491f479 100644 --- a/doc/changelog.txt +++ b/doc/changelog.txt @@ -1,6 +1,8 @@ HEAD ==== +Fixes: +- xt_TARPIT: fix a kernel oops in --reset mode v1.36 (2011-06-03) diff --git a/extensions/xt_TARPIT.c b/extensions/xt_TARPIT.c index fd1a031..880e5aa 100644 --- a/extensions/xt_TARPIT.c +++ b/extensions/xt_TARPIT.c @@ -58,7 +58,7 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook, struct sk_buff *nskb; const struct iphdr *oldhdr; struct iphdr *niph; - u_int16_t tmp; + uint16_t tmp, payload; /* A truncated TCP header is not going to be useful */ if (oldskb->len < ip_hdrlen(oldskb) + sizeof(struct tcphdr)) @@ -69,29 +69,6 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook, if (oth == NULL) return; - if (mode == XTTARPIT_TARPIT) { - /* No replies for RST, FIN or !SYN,!ACK */ - if (oth->rst || oth->fin || (!oth->syn && !oth->ack)) - return; -#if 0 - /* Rate-limit replies to !SYN,ACKs */ - if (!oth->syn && oth->ack) - if (!xrlim_allow(rt_dst(ort), HZ)) - return; -#endif - } else if (mode == XTTARPIT_HONEYPOT) { - /* Do not answer any resets regardless of combination */ - if (oth->rst || oth->seq == 0xDEADBEEF) - return; - } else if (mode == XTTARPIT_RESET) { - tcph->window = 0; - tcph->ack = false; - tcph->syn = false; - tcph->rst = true; - tcph->seq = oth->ack_seq; - tcph->ack_seq = oth->seq; - } - /* Check checksum. */ if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) return; @@ -127,6 +104,9 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook, tcph->source = tcph->dest; tcph->dest = tmp; + /* Calculate payload size?? */ + payload = nskb->len - ip_hdrlen(nskb) - sizeof(struct tcphdr); + /* Truncate to length (no data) */ tcph->doff = sizeof(struct tcphdr) / 4; skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr)); @@ -136,7 +116,9 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook, ((u_int8_t *)tcph)[13] = 0; if (mode == XTTARPIT_TARPIT) { - /* Use supplied sequence number or make a new one */ + /* No replies for RST, FIN or !SYN,!ACK */ + if (oth->rst || oth->fin || (!oth->syn && !oth->ack)) + return; tcph->seq = oth->ack ? oth->ack_seq : 0; /* Our SYN-ACKs must have a >0 window */ @@ -149,7 +131,16 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook, tcph->ack = true; tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn); } +#if 0 + /* Rate-limit replies to !SYN,ACKs */ + if (!oth->syn && oth->ack) + if (!xrlim_allow(rt_dst(ort), HZ)) + return; +#endif } else if (mode == XTTARPIT_HONEYPOT) { + /* Do not answer any resets regardless of combination */ + if (oth->rst || oth->seq == 0xDEADBEEF) + return; /* Send a reset to scanners. They like that. */ if (oth->syn && oth->ack) { tcph->window = 0; @@ -159,23 +150,29 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook, tcph->seq = oth->ack_seq; tcph->rst = true; } + /* SYN > SYN-ACK */ if (oth->syn && !oth->ack) { tcph->syn = true; tcph->ack = true; - tcph->window = oth->window; - tcph->ack_seq = oth->seq; - tcph->seq = htonl(net_random() | ~oth->seq); + tcph->window = oth->window & + ((net_random() & 0x1f) - 0xf); + tcph->seq = htonl(net_random() & ~oth->seq); + tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn); } + /* ACK > ACK */ - if (oth->ack && !oth->fin && !oth->syn) { + if (oth->ack && (!(oth->fin || oth->syn))) { tcph->syn = false; tcph->ack = true; tcph->window = oth->window & ((net_random() & 0x1f) - 0xf); - tcph->ack_seq = htonl(ntohl(oth->seq) + 1); + tcph->ack_seq = payload > 100 ? + htonl(ntohl(oth->seq) + payload) : + oth->seq; tcph->seq = oth->ack_seq; } + /* * FIN > RST. * We cannot terminate gracefully so just be abrupt. @@ -188,6 +185,13 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook, tcph->ack = false; tcph->rst = true; } + } else if (mode == XTTARPIT_RESET) { + tcph->window = 0; + tcph->ack = false; + tcph->syn = false; + tcph->rst = true; + tcph->seq = oth->ack_seq; + tcph->ack_seq = oth->seq; } /* Adjust TCP checksum */ @@ -204,7 +208,7 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook, /* Set DF, id = 0 */ niph->frag_off = htons(IP_DF); - if (mode == XTTARPIT_TARPIT) + if (mode == XTTARPIT_TARPIT || mode == XTTARPIT_RESET) niph->id = 0; else if (mode == XTTARPIT_HONEYPOT) niph->id = ~oldhdr->id + 1; @@ -225,7 +229,10 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook, nskb->ip_summed = CHECKSUM_NONE; /* Adjust IP TTL */ - niph->ttl = dst_metric(skb_dst(nskb), RTAX_HOPLIMIT); + if (mode == XTTARPIT_HONEYPOT) + niph->ttl = 128; + else + niph->ttl = dst_metric(skb_dst(nskb), RTAX_HOPLIMIT); /* Adjust IP checksum */ niph->check = 0;