From d2bbeb7d42b45e4d97411e5c124845905975fd46 Mon Sep 17 00:00:00 2001 From: Alin Nastac Date: Thu, 12 Jul 2018 10:36:02 +0200 Subject: [PATCH] firewall3: make reject types selectable by user RFC 6092 recommends in section 3.3.1 that an IPv6 CPE must respond to unsolicited inbound SYNs with an ICMPv6 Destination Unreachable error code 1 (Communication with destination administratively prohibited). Signed-off-by: Alin Nastac Acked-by: Jo-Philipp Wich --- defaults.c | 34 ++++++++++++++++++++++++++++++++-- options.c | 13 +++++++++++++ options.h | 12 ++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/defaults.c b/defaults.c index 11fbf0d..f42eed6 100644 --- a/defaults.c +++ b/defaults.c @@ -41,6 +41,8 @@ const struct fw3_option fw3_flag_opts[] = { FW3_OPT("output", target, defaults, policy_output), FW3_OPT("drop_invalid", bool, defaults, drop_invalid), + FW3_OPT("tcp_reject_code", reject_code, defaults, tcp_reject_code), + FW3_OPT("any_reject_code", reject_code, defaults, any_reject_code), FW3_OPT("syn_flood", bool, defaults, syn_flood), FW3_OPT("synflood_protect", bool, defaults, syn_flood), @@ -102,6 +104,30 @@ check_offloading(struct uci_element *e, bool *offloading) *offloading = false; } +static void +check_any_reject_code(struct uci_element *e, enum fw3_reject_code *any_reject_code) +{ + if (*any_reject_code == FW3_REJECT_CODE_TCP_RESET) { + warn_elem(e, "tcp-reset not valid for any_reject_code, defaulting to port-unreach"); + *any_reject_code = FW3_REJECT_CODE_PORT_UNREACH; + } +} + +static const char* +get_reject_code(enum fw3_family family, enum fw3_reject_code reject_code) +{ + switch (reject_code) { + case FW3_REJECT_CODE_TCP_RESET: + return "tcp-reset"; + case FW3_REJECT_CODE_PORT_UNREACH: + return "port-unreach"; + case FW3_REJECT_CODE_ADM_PROHIBITED: + return family == FW3_FAMILY_V6 ? "adm-prohibited": "admin-prohib"; + default: + return "unknown"; + } +} + void fw3_load_defaults(struct fw3_state *state, struct uci_package *p) { @@ -111,6 +137,8 @@ fw3_load_defaults(struct fw3_state *state, struct uci_package *p) bool seen = false; + defs->tcp_reject_code = FW3_REJECT_CODE_TCP_RESET; + defs->any_reject_code = FW3_REJECT_CODE_PORT_UNREACH; defs->syn_flood_rate.rate = 25; defs->syn_flood_rate.burst = 50; defs->tcp_syncookies = true; @@ -138,6 +166,8 @@ fw3_load_defaults(struct fw3_state *state, struct uci_package *p) check_policy(e, &defs->policy_output, "output"); check_policy(e, &defs->policy_forward, "forward"); + check_any_reject_code(e, &defs->any_reject_code); + check_offloading(e, &defs->flow_offloading); } } @@ -278,12 +308,12 @@ fw3_print_default_head_rules(struct fw3_ipt_handle *handle, r = fw3_ipt_rule_create(handle, &tcp, NULL, NULL, NULL, NULL); fw3_ipt_rule_target(r, "REJECT"); - fw3_ipt_rule_addarg(r, false, "--reject-with", "tcp-reset"); + fw3_ipt_rule_addarg(r, false, "--reject-with", get_reject_code(handle->family, defs->tcp_reject_code)); fw3_ipt_rule_append(r, "reject"); r = fw3_ipt_rule_new(handle); fw3_ipt_rule_target(r, "REJECT"); - fw3_ipt_rule_addarg(r, false, "--reject-with", "port-unreach"); + fw3_ipt_rule_addarg(r, false, "--reject-with", get_reject_code(handle->family, defs->any_reject_code)); fw3_ipt_rule_append(r, "reject"); break; diff --git a/options.c b/options.c index 087aa63..c85bafd 100644 --- a/options.c +++ b/options.c @@ -86,6 +86,12 @@ const char *fw3_flag_names[__FW3_FLAG_MAX] = { "DROP", }; +const char *fw3_reject_code_names[__FW3_REJECT_CODE_MAX] = { + "tcp-reset", + "port-unreach", + "adm-prohibited", +}; + const char *fw3_limit_units[__FW3_LIMIT_UNIT_MAX] = { "second", "minute", @@ -169,6 +175,13 @@ fw3_parse_target(void *ptr, const char *val, bool is_list) FW3_FLAG_ACCEPT, FW3_FLAG_MASQUERADE); } +bool +fw3_parse_reject_code(void *ptr, const char *val, bool is_list) +{ + return parse_enum(ptr, val, &fw3_reject_code_names[FW3_REJECT_CODE_TCP_RESET], + FW3_REJECT_CODE_TCP_RESET, FW3_REJECT_CODE_ADM_PROHIBITED); +} + bool fw3_parse_limit(void *ptr, const char *val, bool is_list) { diff --git a/options.h b/options.h index 08fecf6..0b73a84 100644 --- a/options.h +++ b/options.h @@ -88,6 +88,15 @@ enum fw3_flag __FW3_FLAG_MAX }; +enum fw3_reject_code +{ + FW3_REJECT_CODE_TCP_RESET = 0, + FW3_REJECT_CODE_PORT_UNREACH = 1, + FW3_REJECT_CODE_ADM_PROHIBITED = 2, + + __FW3_REJECT_CODE_MAX +}; + extern const char *fw3_flag_names[__FW3_FLAG_MAX]; @@ -276,6 +285,8 @@ struct fw3_defaults enum fw3_flag policy_forward; bool drop_invalid; + enum fw3_reject_code tcp_reject_code; + enum fw3_reject_code any_reject_code; bool syn_flood; struct fw3_limit syn_flood_rate; @@ -580,6 +591,7 @@ bool fw3_parse_bool(void *ptr, const char *val, bool is_list); bool fw3_parse_int(void *ptr, const char *val, bool is_list); bool fw3_parse_string(void *ptr, const char *val, bool is_list); bool fw3_parse_target(void *ptr, const char *val, bool is_list); +bool fw3_parse_reject_code(void *ptr, const char *val, bool is_list); bool fw3_parse_limit(void *ptr, const char *val, bool is_list); bool fw3_parse_device(void *ptr, const char *val, bool is_list); bool fw3_parse_address(void *ptr, const char *val, bool is_list); -- 2.25.1