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.
This commit is contained in:
Martin Barrowcliff
2011-06-04 08:11:38 -04:00
committed by Jan Engelhardt
parent e84391ce66
commit 85d8f98dd7
2 changed files with 41 additions and 32 deletions

View File

@@ -1,6 +1,8 @@
HEAD HEAD
==== ====
Fixes:
- xt_TARPIT: fix a kernel oops in --reset mode
v1.36 (2011-06-03) v1.36 (2011-06-03)

View File

@@ -58,7 +58,7 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook,
struct sk_buff *nskb; struct sk_buff *nskb;
const struct iphdr *oldhdr; const struct iphdr *oldhdr;
struct iphdr *niph; struct iphdr *niph;
u_int16_t tmp; uint16_t tmp, payload;
/* A truncated TCP header is not going to be useful */ /* A truncated TCP header is not going to be useful */
if (oldskb->len < ip_hdrlen(oldskb) + sizeof(struct tcphdr)) 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) if (oth == NULL)
return; 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. */ /* Check checksum. */
if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
return; return;
@@ -127,6 +104,9 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook,
tcph->source = tcph->dest; tcph->source = tcph->dest;
tcph->dest = tmp; tcph->dest = tmp;
/* Calculate payload size?? */
payload = nskb->len - ip_hdrlen(nskb) - sizeof(struct tcphdr);
/* Truncate to length (no data) */ /* Truncate to length (no data) */
tcph->doff = sizeof(struct tcphdr) / 4; tcph->doff = sizeof(struct tcphdr) / 4;
skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr)); 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; ((u_int8_t *)tcph)[13] = 0;
if (mode == XTTARPIT_TARPIT) { 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; tcph->seq = oth->ack ? oth->ack_seq : 0;
/* Our SYN-ACKs must have a >0 window */ /* 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 = true;
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn); 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) { } 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. */ /* Send a reset to scanners. They like that. */
if (oth->syn && oth->ack) { if (oth->syn && oth->ack) {
tcph->window = 0; tcph->window = 0;
@@ -159,23 +150,29 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook,
tcph->seq = oth->ack_seq; tcph->seq = oth->ack_seq;
tcph->rst = true; tcph->rst = true;
} }
/* SYN > SYN-ACK */ /* SYN > SYN-ACK */
if (oth->syn && !oth->ack) { if (oth->syn && !oth->ack) {
tcph->syn = true; tcph->syn = true;
tcph->ack = true; tcph->ack = true;
tcph->window = oth->window; tcph->window = oth->window &
tcph->ack_seq = oth->seq; ((net_random() & 0x1f) - 0xf);
tcph->seq = htonl(net_random() | ~oth->seq); tcph->seq = htonl(net_random() & ~oth->seq);
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn);
} }
/* ACK > ACK */ /* ACK > ACK */
if (oth->ack && !oth->fin && !oth->syn) { if (oth->ack && (!(oth->fin || oth->syn))) {
tcph->syn = false; tcph->syn = false;
tcph->ack = true; tcph->ack = true;
tcph->window = oth->window & tcph->window = oth->window &
((net_random() & 0x1f) - 0xf); ((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; tcph->seq = oth->ack_seq;
} }
/* /*
* FIN > RST. * FIN > RST.
* We cannot terminate gracefully so just be abrupt. * 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->ack = false;
tcph->rst = true; 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 */ /* Adjust TCP checksum */
@@ -204,7 +208,7 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook,
/* Set DF, id = 0 */ /* Set DF, id = 0 */
niph->frag_off = htons(IP_DF); niph->frag_off = htons(IP_DF);
if (mode == XTTARPIT_TARPIT) if (mode == XTTARPIT_TARPIT || mode == XTTARPIT_RESET)
niph->id = 0; niph->id = 0;
else if (mode == XTTARPIT_HONEYPOT) else if (mode == XTTARPIT_HONEYPOT)
niph->id = ~oldhdr->id + 1; 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; nskb->ip_summed = CHECKSUM_NONE;
/* Adjust IP TTL */ /* 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 */ /* Adjust IP checksum */
niph->check = 0; niph->check = 0;