diff --git a/ChangeLog b/ChangeLog index e6b0ed9..7309db5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,7 +22,11 @@ Version 4.5.3 'dan Eider': - merge PR #739 (by hills) * SSL reload has hidden bugs which cause crashes - Fix regression in PR #739 - - Add option to disable RFC8750 + - Try to mitigate amplification attatck + * Add option --no-rfc5780 + to force disable RFC8750 + * Add new option --no-stun-backward-compatibility + Disable handling old STUN Binding requests and disable MAPPED-ADDRESS attribute in binding response (use only the XOR-MAPPED-ADDRESS). 10/01/2021 Oleg Moskalenko Mihály Mészáros Version 4.5.2 'dan Eider': diff --git a/README.turnserver b/README.turnserver index 9972264..457b3d0 100644 --- a/README.turnserver +++ b/README.turnserver @@ -615,6 +615,7 @@ Options with values: This option disables this original behavior, because the NAT behavior discovery adds attributes to response, and this increase the possibility of an amplification attack. Strongly encouraged to use this option to decrease gain factor in STUN binding responses. +--no-stun-backward-compatibility Disable handling old STUN Binding requests and disable MAPPED-ADDRESS attribute in binding response (use only the XOR-MAPPED-ADDRESS). ================================== diff --git a/examples/etc/turnserver.conf b/examples/etc/turnserver.conf index 68f27b7..7a1b708 100644 --- a/examples/etc/turnserver.conf +++ b/examples/etc/turnserver.conf @@ -773,3 +773,11 @@ # no-rfc5780 +# Disable handling old STUN Binding requests and disable MAPPED-ADDRESS +# attribute in binding response (use only the XOR-MAPPED-ADDRESS). +# +# Strongly encouraged to use this option to decrease gain factor in STUN +# binding responses. +# +no-stun-backward-compatibility + diff --git a/src/apps/common/stun_buffer.c b/src/apps/common/stun_buffer.c index e3f3b9a..7eea8d7 100644 --- a/src/apps/common/stun_buffer.c +++ b/src/apps/common/stun_buffer.c @@ -239,7 +239,7 @@ int stun_set_binding_response(stun_buffer* buf, stun_tid* tid, const ioa_addr *reflexive_addr, int error_code, const uint8_t *reason) { return stun_set_binding_response_str(buf->buf, (size_t*)(&(buf->len)), tid, reflexive_addr, error_code, reason, - 0,0); + 0,0,1); } void stun_prepare_binding_request(stun_buffer* buf) { diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index d5e04e9..2cce4c2 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -186,7 +186,8 @@ ALLOCATION_DEFAULT_ADDRESS_FAMILY_IPV4, /* allocation_default_address_family */ 0, /* no_dynamic_ip_list */ 0, /* no_dynamic_realms */ -0 /* log_binding */ +0, /* log_binding */ +0, /* no_stun_backward_compatibility */ }; //////////////// OpenSSL Init ////////////////////// @@ -696,6 +697,8 @@ static char Usage[] = "Usage: turnserver [options]\n" " This option disables this original behavior, because the NAT behavior discovery\n" " adds attributes to response, and this increase the possibility of an amplification attack.\n" " Strongly encouraged to use this option to decrease gain factor in STUN binding responses.\n" +" --no-stun-backward-compatibility Disable handling old STUN Binding requests and disable MAPPED-ADDRESS attribute\n" +" in binding response (use only the XOR-MAPPED-ADDRESS).\n" " -h Help\n" "\n"; @@ -842,7 +845,8 @@ enum EXTRA_OPTS { SECRET_KEY_OPT, ACME_REDIRECT_OPT, LOG_BINDING_OPT, - NO_RFC5780 + NO_RFC5780, + NO_STUN_BACKWARD_COMPATIBILITY_OPT }; struct myoption { @@ -980,6 +984,7 @@ static const struct myoption long_options[] = { { "acme-redirect", required_argument, NULL, ACME_REDIRECT_OPT }, { "log-binding", optional_argument, NULL, LOG_BINDING_OPT }, { "no-rfc5780", optional_argument, NULL, NO_RFC5780 }, + { "no-stun-backward-compatibility", optional_argument, NULL, NO_STUN_BACKWARD_COMPATIBILITY_OPT }, { NULL, no_argument, NULL, 0 } }; @@ -1656,6 +1661,9 @@ static void set_option(int c, char *value) case NO_RFC5780: turn_params.rfc5780 = 0; break; + case NO_STUN_BACKWARD_COMPATIBILITY_OPT: + turn_params.no_stun_backward_compatibility = get_bool_value(value); + break; /* these options have been already taken care of before: */ case 'l': diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index 778dad0..9f791ec 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -339,6 +339,7 @@ typedef struct _turn_params_ { int no_dynamic_realms; vint log_binding; + vint no_stun_backward_compatibility; } turn_params_t; extern turn_params_t turn_params; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index 86d79e3..0d835db 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -1660,41 +1660,43 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int bufferevent_enable(rs->auth_in_buf, EV_READ); init_turn_server(&(rs->server), - rs->id, turn_params.verbose, - rs->ioa_eng, turn_params.ct, 0, - turn_params.fingerprint, DONT_FRAGMENT_SUPPORTED, - start_user_check, - check_new_allocation_quota, - release_allocation_quota, - turn_params.external_ip, - &turn_params.check_origin, - &turn_params.no_tcp_relay, - &turn_params.no_udp_relay, - &turn_params.stale_nonce, - &turn_params.max_allocate_lifetime, - &turn_params.channel_lifetime, - &turn_params.permission_lifetime, - &turn_params.stun_only, - &turn_params.no_stun, - &turn_params.no_software_attribute, - &turn_params.web_admin_listen_on_workers, - &turn_params.alternate_servers_list, - &turn_params.tls_alternate_servers_list, - &turn_params.aux_servers_list, - turn_params.udp_self_balance, - &turn_params.no_multicast_peers, &turn_params.allow_loopback_peers, - &turn_params.ip_whitelist, &turn_params.ip_blacklist, - send_socket_to_relay, - &turn_params.secure_stun, &turn_params.mobility, - turn_params.server_relay, - send_turn_session_info, - send_https_socket, - allocate_bps, - turn_params.oauth, - turn_params.oauth_server_name, - turn_params.acme_redirect, - turn_params.allocation_default_address_family, - &turn_params.log_binding); + rs->id, turn_params.verbose, + rs->ioa_eng, turn_params.ct, 0, + turn_params.fingerprint, DONT_FRAGMENT_SUPPORTED, + start_user_check, + check_new_allocation_quota, + release_allocation_quota, + turn_params.external_ip, + &turn_params.check_origin, + &turn_params.no_tcp_relay, + &turn_params.no_udp_relay, + &turn_params.stale_nonce, + &turn_params.max_allocate_lifetime, + &turn_params.channel_lifetime, + &turn_params.permission_lifetime, + &turn_params.stun_only, + &turn_params.no_stun, + &turn_params.no_software_attribute, + &turn_params.web_admin_listen_on_workers, + &turn_params.alternate_servers_list, + &turn_params.tls_alternate_servers_list, + &turn_params.aux_servers_list, + turn_params.udp_self_balance, + &turn_params.no_multicast_peers, &turn_params.allow_loopback_peers, + &turn_params.ip_whitelist, &turn_params.ip_blacklist, + send_socket_to_relay, + &turn_params.secure_stun, &turn_params.mobility, + turn_params.server_relay, + send_turn_session_info, + send_https_socket, + allocate_bps, + turn_params.oauth, + turn_params.oauth_server_name, + turn_params.acme_redirect, + turn_params.allocation_default_address_family, + &turn_params.log_binding, + &turn_params.no_stun_backward_compatibility + ); if(to_set_rfc5780) { set_rfc5780(&(rs->server), get_alt_addr, send_message_from_listener_to_client); diff --git a/src/client++/TurnMsgLib.h b/src/client++/TurnMsgLib.h index 288aa2d..c8cb0d3 100644 --- a/src/client++/TurnMsgLib.h +++ b/src/client++/TurnMsgLib.h @@ -989,7 +989,7 @@ public: stun_set_binding_response_str(_buffer, &_sz, &tid, &reflexive_addr, error_code, - reason, 0 , 0); + reason, 0 , 0 , 1); } bool isBindingResponse() const { diff --git a/src/client/ns_turn_msg.c b/src/client/ns_turn_msg.c index d0c8d88..549f379 100644 --- a/src/client/ns_turn_msg.c +++ b/src/client/ns_turn_msg.c @@ -1140,7 +1140,7 @@ void stun_set_binding_request_str(uint8_t* buf, size_t *len) { int stun_set_binding_response_str(uint8_t* buf, size_t *len, stun_tid* tid, const ioa_addr *reflexive_addr, int error_code, const uint8_t *reason, - uint32_t cookie, int old_stun) + uint32_t cookie, int old_stun, int no_stun_backward_compatibility) { if (!error_code) { @@ -1154,7 +1154,7 @@ int stun_set_binding_response_str(uint8_t* buf, size_t *len, stun_tid* tid, return -1; } if(reflexive_addr) { - if (stun_attr_add_addr_str(buf, len, STUN_ATTRIBUTE_MAPPED_ADDRESS, reflexive_addr) < 0) + if (!no_stun_backward_compatibility && stun_attr_add_addr_str(buf, len, STUN_ATTRIBUTE_MAPPED_ADDRESS, reflexive_addr) < 0) return -1; } } else if (!old_stun) { diff --git a/src/client/ns_turn_msg.h b/src/client/ns_turn_msg.h index 5588569..759c091 100644 --- a/src/client/ns_turn_msg.h +++ b/src/client/ns_turn_msg.h @@ -124,7 +124,7 @@ void stun_set_binding_request_str(uint8_t* buf, size_t *len); int stun_set_binding_response_str(uint8_t* buf, size_t *len, stun_tid* tid, const ioa_addr *reflexive_addr, int error_code, const uint8_t *reason, - uint32_t cookie, int old_stun); + uint32_t cookie, int old_stun, int no_stun_backward_compatibility); int stun_is_binding_request_str(const uint8_t* buf, size_t len, size_t offset); int stun_is_binding_response_str(const uint8_t* buf, size_t len); diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index e5a6609..3143a6c 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -2867,7 +2867,7 @@ static int handle_turn_binding(turn_turnserver *server, size_t len = ioa_network_buffer_get_size(nbh); if (stun_set_binding_response_str(ioa_network_buffer_data(nbh), &len, tid, - get_remote_addr_from_ioa_socket(ss->client_socket), 0, NULL, cookie, old_stun) >= 0) { + get_remote_addr_from_ioa_socket(ss->client_socket), 0, NULL, cookie, old_stun, *server->no_stun_backward_compatibility) >= 0) { addr_cpy(response_origin, get_local_addr_from_ioa_socket(ss->client_socket)); @@ -4606,7 +4606,11 @@ static int read_client_connection(turn_turnserver *server, return 0; } - } else if (old_stun_is_command_message_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh), &old_stun_cookie) && !(*(server->no_stun))) { + } else if ( + old_stun_is_command_message_str(ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh), &old_stun_cookie) && + !(*(server->no_stun)) && + !(*(server->no_stun_backward_compatibility)) + ) { ioa_network_buffer_handle nbh = ioa_network_buffer_allocate(server->e); int resp_constructed = 0; @@ -4932,7 +4936,8 @@ void init_turn_server(turn_turnserver* server, const char* oauth_server_name, const char* acme_redirect, ALLOCATION_DEFAULT_ADDRESS_FAMILY allocation_default_address_family, - vintp log_binding) { + vintp log_binding, + vintp no_stun_backward_compatibility) { if (!server) return; @@ -5006,6 +5011,8 @@ void init_turn_server(turn_turnserver* server, set_ioa_timer(server->e, 1, 0, timer_timeout_handler, server, 1, "timer_timeout_handler"); server->log_binding = log_binding; + + server->no_stun_backward_compatibility = no_stun_backward_compatibility; } ioa_engine_handle turn_server_get_engine(turn_turnserver *s) { diff --git a/src/server/ns_turn_server.h b/src/server/ns_turn_server.h index 6f989bf..2160388 100644 --- a/src/server/ns_turn_server.h +++ b/src/server/ns_turn_server.h @@ -187,6 +187,9 @@ struct _turn_turnserver { /* Log Binding Requrest */ vintp log_binding; + + /* Disable handling old STUN Binding Requests and disable MAPPED-ADDRESS attribute in response */ + vintp no_stun_backward_compatibility; }; const char * get_version(turn_turnserver *server); @@ -234,7 +237,9 @@ void init_turn_server(turn_turnserver* server, const char* oauth_server_name, const char* acme_redirect, ALLOCATION_DEFAULT_ADDRESS_FAMILY allocation_default_address_family, - vintp log_binding); + vintp log_binding, + vintp no_stun_backward_compatibility + ); ioa_engine_handle turn_server_get_engine(turn_turnserver *s);