Skip to content

Commit

Permalink
Add max_window options
Browse files Browse the repository at this point in the history
When enabled, TCP packets are forced to use maximum window size for debugging purposes or to avoid conntrack breaks (possibly due to dropped window change ACKs)
  • Loading branch information
hack3ric committed Dec 1, 2024
1 parent 3e6e3ff commit 21df02d
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 11 deletions.
3 changes: 2 additions & 1 deletion bpf/egress.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ int egress_handler(struct __sk_buff* skb) {
__be32 csum_diff = 0;
try_tc(mangle_data(skb, ip_end + sizeof(*udp), &csum_diff, padding));
decl_shot(struct tcphdr, tcp, ip_end, skb);
update_tcp_header(tcp, payload_len, seq, ack_seq, conn_cwnd);
update_tcp_header(tcp, payload_len, seq, ack_seq,
settings->max_window ? 0xffff << CWND_SCALE : conn_cwnd);

__u32 csum_off = ip_end + offsetof(struct tcphdr, check);
redecl_shot(struct tcphdr, tcp, ip_end, skb);
Expand Down
6 changes: 4 additions & 2 deletions bpf/ingress.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,10 @@ int ingress_handler(struct xdp_md* xdp) {
bpf_spin_unlock(&conn->lock);

if (flags & TCP_FLAG_SYN && flags & TCP_FLAG_ACK) log_conn(LOG_CONN_ACCEPT, &conn_key);
if (will_send_ctrl_packet)
send_ctrl_packet(&conn_key, flags, seq, ack_seq, flags & TCP_FLAG_RST ? 0 : cwnd);
if (will_send_ctrl_packet) {
__u32 out_cwnd = flags & TCP_FLAG_RST ? 0 : settings->max_window ? 0xffff << CWND_SCALE : cwnd;
send_ctrl_packet(&conn_key, flags, seq, ack_seq, out_cwnd);
}
if (unlikely(flags & TCP_FLAG_RST)) {
log_destroy(&conn_key, DESTROY_INVALID, cooldown);
use_pktbuf(RB_ITEM_FREE_PKTBUF, pktbuf);
Expand Down
6 changes: 4 additions & 2 deletions common/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,9 @@ struct filter_settings {
};
} keepalive, k; };
__s16 padding;
__s16 max_window;
};
__s16 array[7];
__s16 array[8];
};
};
// clang-format on
Expand All @@ -238,10 +239,11 @@ static const struct filter_settings DEFAULT_SETTINGS = {
.handshake.array = {2, 3},
.keepalive.array = {180, 10, 3, 600},
.padding = 0,
.max_window = true,
};

static const struct filter_settings FALLBACK_SETTINGS = {
.array = {-1, -1, -1, -1, -1, -1, -1},
.array = {-1, -1, -1, -1, -1, -1, -1, -1},
};

static inline void filter_settings_apply(struct filter_settings* local,
Expand Down
5 changes: 4 additions & 1 deletion docs/mimic.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
`-p, --padding`
: Padding size appended to each packet. Pass 'random' to use random padding.

`-W, --max-window`
: Always use maximum window size in TCP packets.

`-F, --file=PATH`
: Load configuration from file

Expand Down Expand Up @@ -108,7 +111,7 @@ See **/usr/share/doc/mimic/eth0.conf.example** for detailed examples.
`log.verbosity`
: Controls how much information should be printed. Log level equal to or higher (in number) than log verbosity will be discarded. Both number and string matching log levels are accepted. Number must be greater than or equal to 0. Defaults to info (2). Available levels are: 0 - error (cannot be discarded), 1 - warn, 2 - info, 3 - debug, 4 - trace.

`handshake`, `keepalive`, `padding`
`handshake`, `keepalive`, `padding`, `max_window`
: See [**OPTIONS**](#options).

`filter`
Expand Down
8 changes: 5 additions & 3 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,11 @@ static int parse_int_seq(char* str, int* nums, size_t len) {
return nums_idx;
}

__attribute__((unused)) static int parse_bool(const char* str, bool* result) {
static int parse_bool(const char* str, __s16* result) {
if (strcmp("true", str) == 0 || strcmp("1", str) == 0)
*result = true;
*result = 1;
else if (strcmp("false", str) == 0 || strcmp("0", str) == 0)
*result = false;
*result = 0;
else
ret(-EINVAL, _("invalid boolean value: '%s'"), str);
return 0;
Expand Down Expand Up @@ -159,6 +159,8 @@ static int parse_setting(const char* k, char* v, struct filter_settings* setting
try(parse_keepalive(v, &settings->keepalive));
else if (strcmp("padding", k) == 0)
try(parse_padding(v, &settings->padding));
else if (strcmp("max_window", k) == 0)
try(parse_bool(v, &settings->max_window));
else
return 0;
return 1;
Expand Down
9 changes: 7 additions & 2 deletions src/run.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ static const struct argp_option options[] = {
{"keepalive", 'k', N_("t:i:r:s"), 0, N_("Controls keepalive mechanism"), 2},
{"padding", 'p', N_("bytes"), 0,
N_("Padding size appended to each packet. Pass 'random' to use random padding."), 2},
{"max-window", 'W', NULL, 0, N_("Always use maximum window size in TCP packets"), 2},
{"file", 'F', N_("PATH"), 0, N_("Load configuration from file"), 3},
{},
};
Expand Down Expand Up @@ -77,6 +78,9 @@ static inline error_t args_parse_opt(int key, char* arg, struct argp_state* stat
case 'p':
try(parse_padding(arg, &args->gsettings.padding));
break;
case 'W':
args->gsettings.max_window = true;
break;
case 'F':
args->file = arg;
break;
Expand Down Expand Up @@ -356,21 +360,22 @@ static int do_routine(int conns_fd, const char* ifname) {
time_diff_sec(tstamp, conn.stale_tstamp) >= conn.settings.keepalive.stale) {
reset = remove = true;
} else if (conn.settings.keepalive.time > 0 && retry_secs >= conn.settings.keepalive.time) {
__u32 cwnd = conn.settings.max_window ? 0xffff << CWND_SCALE : conn.cwnd;
if (conn.settings.keepalive.interval <= 0) {
reset = true;
} else if (conn.retry_tstamp >= conn.reset_tstamp) {
log_conn(LOG_DEBUG, &key, _("sending keepalive"));
conn.reset_tstamp = tstamp;
conn.keepalive_sent = true;
send_ctrl_packet(&key, TCP_FLAG_ACK, conn.seq - 1, conn.ack_seq, conn.cwnd, ifname);
send_ctrl_packet(&key, TCP_FLAG_ACK, conn.seq - 1, conn.ack_seq, cwnd, ifname);
bpf_map_update_elem(conns_fd, &key, &conn, BPF_EXIST | BPF_F_LOCK);
} else {
int reset_secs = time_diff_sec(tstamp, conn.reset_tstamp);
if (reset_secs >= conn.settings.keepalive.retry * conn.settings.keepalive.interval) {
reset = true;
} else if (reset_secs % conn.settings.keepalive.interval == 0) {
log_conn(LOG_DEBUG, &key, _("sending keepalive"));
send_ctrl_packet(&key, TCP_FLAG_ACK, conn.seq - 1, conn.ack_seq, conn.cwnd, ifname);
send_ctrl_packet(&key, TCP_FLAG_ACK, conn.seq - 1, conn.ack_seq, cwnd, ifname);
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/show.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ int show_overview(int whitelist_fd, struct filter_settings* gs, int log_verbosit
fprintf(out, _(", padding random"));
else if (gs->padding)
fprintf(out, _(", padding %d"), gs->padding);
if (gs->max_window) fprintf(out, _(", max window"));
fprintf(out, "\n");

char buf[FILTER_FMT_MAX_LEN];
Expand Down Expand Up @@ -97,6 +98,9 @@ int show_overview(int whitelist_fd, struct filter_settings* gs, int log_verbosit
else
fprintf(out, ",padding=%d", info.settings.padding);
}
if (a->max_window != b->max_window) {
fprintf(out, _(",max_window=%s"), info.settings.max_window ? "true" : "false");
}
if (strlen(info.host) != 0) fprintf(out, _(" %s(resolved from %s)"), RESET GRAY, info.host);
fprintf(out, RESET "\n");
}
Expand Down

0 comments on commit 21df02d

Please sign in to comment.