summaryrefslogtreecommitdiffstats
path: root/src/plugins/nat/nat44_cli.c
diff options
context:
space:
mode:
authorFilip Varga <fivarga@cisco.com>2020-02-25 14:31:33 +0100
committerOle Trøan <otroan@employees.org>2020-03-13 11:17:13 +0000
commita73f2d6f53c224668bd6bbea1a980ee4313c794f (patch)
treec40965985639940beb294e8688aedbe30e47a548 /src/plugins/nat/nat44_cli.c
parentc27b43673237c3971c1c170646b531728e0d8eb1 (diff)
nat: timed out session scavenging upgrade
Patch changes the behavior of session scavenging and fixes multiple nat issues. Allows proper session clearing and removes issue with lingering sessions in session db. Patch also updates and fixes CLI/API calls for better readability of session state metrics. Fixes security issue that would allow attacker to reuse timed out session in both directions (in2out/out2in). Type: improvement Signed-off-by: Filip Varga <fivarga@cisco.com> Change-Id: I78897585a2a57291fad5db6d457941aa0a0457bd
Diffstat (limited to 'src/plugins/nat/nat44_cli.c')
-rw-r--r--src/plugins/nat/nat44_cli.c195
1 files changed, 128 insertions, 67 deletions
diff --git a/src/plugins/nat/nat44_cli.c b/src/plugins/nat/nat44_cli.c
index 11e87092ae7..45e00693676 100644
--- a/src/plugins/nat/nat44_cli.c
+++ b/src/plugins/nat/nat44_cli.c
@@ -122,9 +122,7 @@ nat44_session_cleanup_command_fn (vlib_main_t * vm,
vlib_cli_command_t * cmd)
{
clib_error_t *error = 0;
-
- nat44_force_session_cleanup ();
-
+ nat44_force_users_cleanup ();
return error;
}
@@ -645,56 +643,26 @@ nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input,
{
snat_main_per_thread_data_t *tsm;
snat_main_t *sm = &snat_main;
- snat_address_t *a;
snat_session_t *s;
- u32 free_ports, free_ports_addr;
- if (sm->deterministic)
+ if (sm->deterministic || !sm->endpoint_dependent)
return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
- if (sm->endpoint_dependent)
- vlib_cli_output (vm, "mode: endpoint-depenent");
-
- // print timeouts
- vlib_cli_output (vm, "icmp timeout: %u", sm->icmp_timeout);
- vlib_cli_output (vm, "udp timeout: %u", sm->udp_timeout);
-
- vlib_cli_output (vm, "tcp established timeout: %u",
- sm->tcp_established_timeout);
- vlib_cli_output (vm, "tcp transitory timeout: %u",
- sm->tcp_transitory_timeout);
-
// print session configuration values
vlib_cli_output (vm, "max translations: %u", sm->max_translations);
vlib_cli_output (vm, "max translations per user: %u",
sm->max_translations_per_user);
- // do we need also twice-nat addresses ??
- if (vec_len (sm->addresses))
- {
- free_ports = 0;
- /* *INDENT-OFF* */
- vec_foreach (a, sm->addresses)
- {
- free_ports_addr = sm->port_per_thread;
-
- #define _(N, i, n, s) \
- free_ports_addr -= a->busy_##n##_ports;
- foreach_snat_protocol
- #undef _
+ u32 count = 0;
- vlib_cli_output (vm, "addr: %U free ports: %u out of: %u",
- format_ip4_address, &a->addr, free_ports_addr, sm->port_per_thread);
+ u64 now = vlib_time_now (sm->vlib_main);
+ u64 sess_timeout_time;
- free_ports += free_ports_addr;
- }
- /* *INDENT-ON* */
- vlib_cli_output (vm, "free ports overall: %u out of: %u",
- free_ports,
- vec_len (sm->addresses) * sm->port_per_thread);
- }
+ u32 udp_sessions = 0;
+ u32 tcp_sessions = 0;
+ u32 icmp_sessions = 0;
- u32 count = 0;
+ u32 timed_out = 0;
u32 transitory = 0;
u32 established = 0;
@@ -703,14 +671,44 @@ nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input,
/* *INDENT-OFF* */
vec_foreach (tsm, sm->per_thread_data)
{
- count += vec_len (tsm->sessions);
pool_foreach (s, tsm->sessions,
({
- if (s->state)
- transitory++;
- else
- established++;
+ sess_timeout_time = s->last_heard +
+ (f64) nat44_session_get_timeout (sm, s);
+ if (now >= sess_timeout_time)
+ timed_out++;
+
+ switch (s->in2out.protocol)
+ {
+ case SNAT_PROTOCOL_ICMP:
+ icmp_sessions++;
+ break;
+ case SNAT_PROTOCOL_TCP:
+ tcp_sessions++;
+ if (s->state)
+ transitory++;
+ else
+ established++;
+ break;
+ case SNAT_PROTOCOL_UDP:
+ default:
+ udp_sessions++;
+ break;
+ }
}));
+ count += pool_elts (tsm->sessions);
+
+ vlib_cli_output (vm, "tid[%u] session scavenging cleared: %u",
+ tsm->thread_index, tsm->cleared);
+ vlib_cli_output (vm, "tid[%u] session scavenging cleanup runs: %u",
+ tsm->thread_index, tsm->cleanup_runs);
+
+ if (now < tsm->cleanup_timeout)
+ vlib_cli_output (vm, "tid[%u] session scavenging next run in: %f",
+ tsm->thread_index, tsm->cleanup_timeout - now);
+ else
+ vlib_cli_output (vm, "tid[%u] session scavenging next run in: 0",
+ tsm->thread_index);
}
/* *INDENT-ON* */
}
@@ -720,17 +718,51 @@ nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input,
/* *INDENT-OFF* */
pool_foreach (s, tsm->sessions,
({
- if (s->state)
- transitory++;
- else
- established++;
+ sess_timeout_time = s->last_heard +
+ (f64) nat44_session_get_timeout (sm, s);
+ if (now >= sess_timeout_time)
+ timed_out++;
+
+ switch (s->in2out.protocol)
+ {
+ case SNAT_PROTOCOL_ICMP:
+ icmp_sessions++;
+ break;
+ case SNAT_PROTOCOL_TCP:
+ tcp_sessions++;
+ if (s->state)
+ transitory++;
+ else
+ established++;
+ break;
+ case SNAT_PROTOCOL_UDP:
+ default:
+ udp_sessions++;
+ break;
+ }
}));
/* *INDENT-ON* */
- count = vec_len (tsm->sessions);
+ count = pool_elts (tsm->sessions);
+
+ vlib_cli_output (vm, "tid[0] session scavenging cleared: %u",
+ tsm->cleared);
+ vlib_cli_output (vm, "tid[0] session scavenging cleanup runs: %u",
+ tsm->cleanup_runs);
+
+ if (now < tsm->cleanup_timeout)
+ vlib_cli_output (vm, "tid[0] session scavenging next run in: %f",
+ tsm->cleanup_timeout - now);
+ else
+ vlib_cli_output (vm, "tid[0] session scavenging next run in: 0");
}
- vlib_cli_output (vm, "established sessions: %u", established);
- vlib_cli_output (vm, "transitory sessions: %u", transitory);
- vlib_cli_output (vm, "sessions: %u", count);
+
+ vlib_cli_output (vm, "total timed out sessions: %u", timed_out);
+ vlib_cli_output (vm, "total sessions: %u", count);
+ vlib_cli_output (vm, "total tcp sessions: %u", tcp_sessions);
+ vlib_cli_output (vm, "total tcp established sessions: %u", established);
+ vlib_cli_output (vm, "total tcp transitory sessions: %u", transitory);
+ vlib_cli_output (vm, "total udp sessions: %u", udp_sessions);
+ vlib_cli_output (vm, "total icmp sessions: %u", icmp_sessions);
return 0;
}
@@ -1439,20 +1471,38 @@ static clib_error_t *
nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_command_t * cmd)
{
- int verbose = 0;
+ unformat_input_t _line_input, *line_input = &_line_input;
+ clib_error_t *error = 0;
snat_main_t *sm = &snat_main;
snat_main_per_thread_data_t *tsm;
+
+ int detail = 0, metrics = 0;
snat_user_t *u;
int i = 0;
if (sm->deterministic)
return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
- if (unformat (input, "detail"))
- verbose = 1;
+ if (!unformat_user (input, unformat_line_input, line_input))
+ goto print;
- vlib_cli_output (vm, "NAT44 sessions:");
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "detail"))
+ detail = 1;
+ else if (unformat (line_input, "metrics"))
+ metrics = 1;
+ else
+ {
+ error = clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, line_input);
+ break;
+ }
+ }
+ unformat_free (line_input);
+print:
+ vlib_cli_output (vm, "NAT44 sessions:");
/* *INDENT-OFF* */
vec_foreach_index (i, sm->per_thread_data)
{
@@ -1461,14 +1511,24 @@ nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_output (vm, "-------- thread %d %s: %d sessions --------\n",
i, vlib_worker_threads[i].name,
pool_elts (tsm->sessions));
- pool_foreach (u, tsm->users,
- ({
- vlib_cli_output (vm, " %U", format_snat_user, tsm, u, verbose);
- }));
+ if (metrics)
+ {
+ u64 now = vlib_time_now (sm->vlib_main);
+ pool_foreach (u, tsm->users,
+ ({
+ vlib_cli_output (vm, " %U", format_snat_user_v2, tsm, u, now);
+ }));
+ }
+ else
+ {
+ pool_foreach (u, tsm->users,
+ ({
+ vlib_cli_output (vm, " %U", format_snat_user, tsm, u, detail);
+ }));
+ }
}
/* *INDENT-ON* */
-
- return 0;
+ return error;
}
static clib_error_t *
@@ -1896,10 +1956,9 @@ set_timeout_command_fn (vlib_main_t * vm,
goto done;
}
}
-
done:
unformat_free (line_input);
-
+ sm->min_timeout = nat44_minimal_timeout (sm);
return error;
}
@@ -1910,6 +1969,8 @@ nat_show_timeouts_command_fn (vlib_main_t * vm,
{
snat_main_t *sm = &snat_main;
+ // fix text
+ vlib_cli_output (vm, "min session cleanup timeout: %dsec", sm->min_timeout);
vlib_cli_output (vm, "udp timeout: %dsec", sm->udp_timeout);
vlib_cli_output (vm, "tcp-established timeout: %dsec",
sm->tcp_established_timeout);
@@ -2535,7 +2596,7 @@ VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
?*/
VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
.path = "show nat44 sessions",
- .short_help = "show nat44 sessions [detail]",
+ .short_help = "show nat44 sessions [detail|metrics]",
.function = nat44_show_sessions_command_fn,
};