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
====
Fixes:
- xt_TARPIT: fix a kernel oops in --reset mode
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;
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;