Skip to content

Commit

Permalink
[NETFILTER]: tcp conntrack: do liberal tracking for picked up connect…
Browse files Browse the repository at this point in the history
…ions

Do liberal tracking (only RSTs need to be in-window) for connections picked
up without seeing a SYN to deal with window scaling. Also change logging
of invalid packets not to log packets accepted by liberal tracking to avoid
spamming the logs.

Based on suggestion from James Ralston <ralston@pobox.com>

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Feb 8, 2007
1 parent 6fecd19 commit a09113c
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 51 deletions.
4 changes: 3 additions & 1 deletion include/linux/netfilter/nf_conntrack_tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ enum tcp_conntrack {
/* This sender sent FIN first */
#define IP_CT_TCP_FLAG_CLOSE_INIT 0x04

/* Be liberal in window checking */
#define IP_CT_TCP_FLAG_BE_LIBERAL 0x08

#ifdef __KERNEL__

struct ip_ct_tcp_state {
u_int32_t td_end; /* max of seq + len */
u_int32_t td_maxend; /* max of ack + max(win, 1) */
u_int32_t td_maxwin; /* max(win) */
u_int8_t td_scale; /* window scale factor */
u_int8_t loose; /* used when connection picked up from the middle */
u_int8_t flags; /* per direction options */
};

Expand Down
40 changes: 15 additions & 25 deletions net/ipv4/netfilter/ip_conntrack_proto_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,9 @@ static DEFINE_RWLOCK(tcp_lock);
If it's non-zero, we mark only out of window RST segments as INVALID. */
int ip_ct_tcp_be_liberal __read_mostly = 0;

/* When connection is picked up from the middle, how many packets are required
to pass in each direction when we assume we are in sync - if any side uses
window scaling, we lost the game.
If it is set to zero, we disable picking up already established
/* If it is set to zero, we disable picking up already established
connections. */
int ip_ct_tcp_loose __read_mostly = 3;
int ip_ct_tcp_loose __read_mostly = 1;

/* Max number of the retransmitted packets without receiving an (acceptable)
ACK from the destination. If this number is reached, a shorter timer
Expand Down Expand Up @@ -694,11 +691,10 @@ static int tcp_in_window(struct ip_ct_tcp *state,
before(sack, receiver->td_end + 1),
after(ack, receiver->td_end - MAXACKWINDOW(sender)));

if (sender->loose || receiver->loose ||
(before(seq, sender->td_maxend + 1) &&
after(end, sender->td_end - receiver->td_maxwin - 1) &&
before(sack, receiver->td_end + 1) &&
after(ack, receiver->td_end - MAXACKWINDOW(sender)))) {
if (before(seq, sender->td_maxend + 1) &&
after(end, sender->td_end - receiver->td_maxwin - 1) &&
before(sack, receiver->td_end + 1) &&
after(ack, receiver->td_end - MAXACKWINDOW(sender))) {
/*
* Take into account window scaling (RFC 1323).
*/
Expand Down Expand Up @@ -743,15 +739,13 @@ static int tcp_in_window(struct ip_ct_tcp *state,
state->retrans = 0;
}
}
/*
* Close the window of disabled window tracking :-)
*/
if (sender->loose)
sender->loose--;

res = 1;
} else {
if (LOG_INVALID(IPPROTO_TCP))
res = 0;
if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
ip_ct_tcp_be_liberal)
res = 1;
if (!res && LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: %s ",
before(seq, sender->td_maxend + 1) ?
Expand All @@ -762,8 +756,6 @@ static int tcp_in_window(struct ip_ct_tcp *state,
: "ACK is over the upper bound (ACKed data not seen yet)"
: "SEQ is under the lower bound (already ACKed data retransmitted)"
: "SEQ is over the upper bound (over the window of the receiver)");

res = ip_ct_tcp_be_liberal;
}

DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
Expand Down Expand Up @@ -1105,8 +1097,6 @@ static int tcp_new(struct ip_conntrack *conntrack,

tcp_options(skb, iph, th, &conntrack->proto.tcp.seen[0]);
conntrack->proto.tcp.seen[1].flags = 0;
conntrack->proto.tcp.seen[0].loose =
conntrack->proto.tcp.seen[1].loose = 0;
} else if (ip_ct_tcp_loose == 0) {
/* Don't try to pick up connections. */
return 0;
Expand All @@ -1127,11 +1117,11 @@ static int tcp_new(struct ip_conntrack *conntrack,
conntrack->proto.tcp.seen[0].td_maxwin;
conntrack->proto.tcp.seen[0].td_scale = 0;

/* We assume SACK. Should we assume window scaling too? */
/* We assume SACK and liberal window checking to handle
* window scaling */
conntrack->proto.tcp.seen[0].flags =
conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM;
conntrack->proto.tcp.seen[0].loose =
conntrack->proto.tcp.seen[1].loose = ip_ct_tcp_loose;
conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM |
IP_CT_TCP_FLAG_BE_LIBERAL;
}

conntrack->proto.tcp.seen[1].td_end = 0;
Expand Down
40 changes: 15 additions & 25 deletions net/netfilter/nf_conntrack_proto_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,9 @@ static DEFINE_RWLOCK(tcp_lock);
If it's non-zero, we mark only out of window RST segments as INVALID. */
int nf_ct_tcp_be_liberal __read_mostly = 0;

/* When connection is picked up from the middle, how many packets are required
to pass in each direction when we assume we are in sync - if any side uses
window scaling, we lost the game.
If it is set to zero, we disable picking up already established
/* If it is set to zero, we disable picking up already established
connections. */
int nf_ct_tcp_loose __read_mostly = 3;
int nf_ct_tcp_loose __read_mostly = 1;

/* Max number of the retransmitted packets without receiving an (acceptable)
ACK from the destination. If this number is reached, a shorter timer
Expand Down Expand Up @@ -650,11 +647,10 @@ static int tcp_in_window(struct ip_ct_tcp *state,
before(sack, receiver->td_end + 1),
after(ack, receiver->td_end - MAXACKWINDOW(sender)));

if (sender->loose || receiver->loose ||
(before(seq, sender->td_maxend + 1) &&
after(end, sender->td_end - receiver->td_maxwin - 1) &&
before(sack, receiver->td_end + 1) &&
after(ack, receiver->td_end - MAXACKWINDOW(sender)))) {
if (before(seq, sender->td_maxend + 1) &&
after(end, sender->td_end - receiver->td_maxwin - 1) &&
before(sack, receiver->td_end + 1) &&
after(ack, receiver->td_end - MAXACKWINDOW(sender))) {
/*
* Take into account window scaling (RFC 1323).
*/
Expand Down Expand Up @@ -699,15 +695,13 @@ static int tcp_in_window(struct ip_ct_tcp *state,
state->retrans = 0;
}
}
/*
* Close the window of disabled window tracking :-)
*/
if (sender->loose)
sender->loose--;

res = 1;
} else {
if (LOG_INVALID(IPPROTO_TCP))
res = 0;
if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
nf_ct_tcp_be_liberal)
res = 1;
if (!res && LOG_INVALID(IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: %s ",
before(seq, sender->td_maxend + 1) ?
Expand All @@ -718,8 +712,6 @@ static int tcp_in_window(struct ip_ct_tcp *state,
: "ACK is over the upper bound (ACKed data not seen yet)"
: "SEQ is under the lower bound (already ACKed data retransmitted)"
: "SEQ is over the upper bound (over the window of the receiver)");

res = nf_ct_tcp_be_liberal;
}

DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
Expand Down Expand Up @@ -1063,8 +1055,6 @@ static int tcp_new(struct nf_conn *conntrack,

tcp_options(skb, dataoff, th, &conntrack->proto.tcp.seen[0]);
conntrack->proto.tcp.seen[1].flags = 0;
conntrack->proto.tcp.seen[0].loose =
conntrack->proto.tcp.seen[1].loose = 0;
} else if (nf_ct_tcp_loose == 0) {
/* Don't try to pick up connections. */
return 0;
Expand All @@ -1085,11 +1075,11 @@ static int tcp_new(struct nf_conn *conntrack,
conntrack->proto.tcp.seen[0].td_maxwin;
conntrack->proto.tcp.seen[0].td_scale = 0;

/* We assume SACK. Should we assume window scaling too? */
/* We assume SACK and liberal window checking to handle
* window scaling */
conntrack->proto.tcp.seen[0].flags =
conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM;
conntrack->proto.tcp.seen[0].loose =
conntrack->proto.tcp.seen[1].loose = nf_ct_tcp_loose;
conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM |
IP_CT_TCP_FLAG_BE_LIBERAL;
}

conntrack->proto.tcp.seen[1].td_end = 0;
Expand Down

0 comments on commit a09113c

Please sign in to comment.