1
0
mirror of https://github.com/coturn/coturn.git synced 2025-10-26 12:31:00 +01:00

Return a 400 response to HTTP requests (#1231)

For our deployment, it is useful if coturn returns a valid HTTP response to an HTTP request. To do this on the same port as STUN/TURN and without enabling the admin site, I have extended `read_client_connection()` to return a canned HTTP response, in response to an HTTP request, rather than immediately closing the connection.
This commit is contained in:
Dave Lambley 2023-11-06 01:25:12 +00:00 committed by GitHub
parent 0fb6addecb
commit 20c8d86a34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 86 additions and 35 deletions

View File

@ -797,3 +797,9 @@ no-stun-backward-compatibility
# binding responses.
#
response-origin-only-with-rfc5780
# Return an HTTP/S response when an HTTP/S connection is made to a TCP port
# otherwise only supporting STUN/TURN. This may be useful for debugging and
# diagnosing connection problems. A "400 Not supported" response is currently
# returned.
#respond-http-unsupported

View File

@ -231,7 +231,8 @@ turn_params_t turn_params = {
0, /* log_binding */
0, /* no_stun_backward_compatibility */
0 /* response_origin_only_with_rfc5780 */
0, /* response_origin_only_with_rfc5780 */
0 /* respond_http_unsupported */
};
//////////////// OpenSSL Init //////////////////////
@ -1271,6 +1272,10 @@ static char Usage[] =
" in binding response (use only the XOR-MAPPED-ADDRESS).\n"
" --response-origin-only-with-rfc5780 Only send RESPONSE-ORIGIN attribute in binding response if "
"RFC5780 is enabled.\n"
" --respond-http-unsupported Return an HTTP reponse with a 400 status code to HTTP "
"connections made to ports not\n"
" supporting HTTP. The default behaviour is to immediately "
"close the connection.\n"
" --version Print version (and exit).\n"
" -h Help\n"
"\n";
@ -1426,6 +1431,7 @@ enum EXTRA_OPTS {
NO_RFC5780,
NO_STUN_BACKWARD_COMPATIBILITY_OPT,
RESPONSE_ORIGIN_ONLY_WITH_RFC5780_OPT,
RESPOND_HTTP_UNSUPPORTED_OPT,
VERSION_OPT
};
@ -1568,6 +1574,7 @@ static const struct myoption long_options[] = {
{"no-rfc5780", optional_argument, NULL, NO_RFC5780},
{"no-stun-backward-compatibility", optional_argument, NULL, NO_STUN_BACKWARD_COMPATIBILITY_OPT},
{"response-origin-only-with-rfc5780", optional_argument, NULL, RESPONSE_ORIGIN_ONLY_WITH_RFC5780_OPT},
{"respond-http-unsupported", optional_argument, NULL, RESPOND_HTTP_UNSUPPORTED_OPT},
{"version", optional_argument, NULL, VERSION_OPT},
{"syslog-facility", required_argument, NULL, SYSLOG_FACILITY_OPT},
{NULL, no_argument, NULL, 0}};
@ -2263,6 +2270,9 @@ static void set_option(int c, char *value) {
case RESPONSE_ORIGIN_ONLY_WITH_RFC5780_OPT:
turn_params.response_origin_only_with_rfc5780 = get_bool_value(value);
break;
case RESPOND_HTTP_UNSUPPORTED_OPT:
turn_params.respond_http_unsupported = get_bool_value(value);
break;
/* these options have been already taken care of before: */
case 'l':

View File

@ -330,6 +330,7 @@ typedef struct _turn_params_ {
vint log_binding;
vint no_stun_backward_compatibility;
vint response_origin_only_with_rfc5780;
vint respond_http_unsupported;
} turn_params_t;
extern turn_params_t turn_params;

View File

@ -1621,20 +1621,20 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int
bufferevent_setcb(rs->auth_in_buf, relay_receive_auth_message, NULL, NULL, rs);
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,
&turn_params.no_stun_backward_compatibility, &turn_params.response_origin_only_with_rfc5780);
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, &turn_params.no_stun_backward_compatibility,
&turn_params.response_origin_only_with_rfc5780, &turn_params.respond_http_unsupported);
if (to_set_rfc5780) {
set_rfc5780(&(rs->server), get_alt_addr, send_message_from_listener_to_client);

View File

@ -4497,7 +4497,8 @@ static int read_client_connection(turn_turnserver *server, ts_ur_super_session *
if (is_stream_socket(st)) {
if (is_http((char *)ioa_network_buffer_data(in_buffer->nbh), ioa_network_buffer_get_size(in_buffer->nbh))) {
const char *proto = "HTTP";
const char *proto = st == TLS_SOCKET ? "HTTPS" : "HTTP";
if ((st == TCP_SOCKET) && (try_acme_redirect((char *)ioa_network_buffer_data(in_buffer->nbh),
ioa_network_buffer_get_size(in_buffer->nbh), server->acme_redirect,
ss->client_socket) == 0)) {
@ -4505,7 +4506,6 @@ static int read_client_connection(turn_turnserver *server, ts_ur_super_session *
return 0;
} else if (*server->web_admin_listen_on_workers) {
if (st == TLS_SOCKET) {
proto = "HTTPS";
set_ioa_socket_app_type(ss->client_socket, HTTPS_CLIENT_SOCKET);
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s (%s %s) request: %zu\n", __FUNCTION__, proto,
get_ioa_socket_cipher(ss->client_socket), get_ioa_socket_ssl_method(ss->client_socket),
@ -4531,6 +4531,36 @@ static int read_client_connection(turn_turnserver *server, ts_ur_super_session *
handle_http_echo(ss->client_socket);
}
return 0;
} else if (*server->respond_http_unsupported) {
/* Our incoming connection is HTTP, but we are not serving the
* admin site. Return a 400 response. */
if (st == TLS_SOCKET) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s (%s %s) returning 400 response: %zu\n", __FUNCTION__, proto,
get_ioa_socket_cipher(ss->client_socket), get_ioa_socket_ssl_method(ss->client_socket),
ioa_network_buffer_get_size(in_buffer->nbh));
set_ioa_socket_app_type(ss->client_socket, HTTPS_CLIENT_SOCKET);
} else {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: %s returning 400 response", __FUNCTION__, proto);
}
ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(ss->client_socket->e);
/* HTTP content */
char *content = "HTTP not supported.\n";
/* Measure length of content */
int content_length = strlen(content);
/* Construct full response */
char buffer[1024];
snprintf(buffer, sizeof(buffer),
"HTTP/1.1 400 %s Not supported\r\nConnection: close\r\nContent-Type: "
"text/plain\r\nContent-Length: %d\r\n\r\n%s",
proto, content_length, content);
ioa_network_buffer_set_size(nbh_http, strlen(buffer));
memcpy(ioa_network_buffer_data(nbh_http), buffer, strlen(buffer));
send_data_from_ioa_socket_nbh(ss->client_socket, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE, NULL);
} else {
ss->to_be_closed = 1;
return 0;
@ -4774,8 +4804,8 @@ void init_turn_server(turn_turnserver *server, turnserver_id id, int verbose, io
send_turn_session_info_cb send_turn_session_info, send_https_socket_cb send_https_socket,
allocate_bps_cb allocate_bps_func, int oauth, const char *oauth_server_name,
const char *acme_redirect, ALLOCATION_DEFAULT_ADDRESS_FAMILY allocation_default_address_family,
vintp log_binding, vintp no_stun_backward_compatibility,
vintp response_origin_only_with_rfc5780) {
vintp log_binding, vintp no_stun_backward_compatibility, vintp response_origin_only_with_rfc5780,
vintp respond_http_unsupported) {
if (!server)
return;
@ -4853,6 +4883,8 @@ void init_turn_server(turn_turnserver *server, turnserver_id id, int verbose, io
server->no_stun_backward_compatibility = no_stun_backward_compatibility;
server->response_origin_only_with_rfc5780 = response_origin_only_with_rfc5780;
server->respond_http_unsupported = respond_http_unsupported;
}
ioa_engine_handle turn_server_get_engine(turn_turnserver *s) {

View File

@ -194,28 +194,30 @@ struct _turn_turnserver {
/* Only send RESPONSE-ORIGIN attribute in response if RFC5780 is enabled */
vintp response_origin_only_with_rfc5780;
/* Return an HTTP 400 response to HTTP connections made to ports not
otherwise handling HTTP. */
vintp respond_http_unsupported;
};
const char *get_version(turn_turnserver *server);
///////////////////////////////////////////
void init_turn_server(turn_turnserver *server, turnserver_id id, int verbose, ioa_engine_handle e,
turn_credential_type ct, int stun_port, int fingerprint, dont_fragment_option_t dont_fragment,
get_user_key_cb userkeycb, check_new_allocation_quota_cb chquotacb,
release_allocation_quota_cb raqcb, ioa_addr *external_addr, vintp check_origin,
vintp no_tcp_relay, vintp no_udp_relay, vintp stale_nonce, vintp max_allocate_lifetime,
vintp channel_lifetime, vintp permission_lifetime, vintp stun_only, vintp no_stun,
vintp no_software_attribute, vintp web_admin_listen_on_workers,
turn_server_addrs_list_t *alternate_servers_list,
turn_server_addrs_list_t *tls_alternate_servers_list, turn_server_addrs_list_t *aux_servers_list,
int self_udp_balance, vintp no_multicast_peers, vintp allow_loopback_peers,
ip_range_list_t *ip_whitelist, ip_range_list_t *ip_blacklist,
send_socket_to_relay_cb send_socket_to_relay, vintp secure_stun, vintp mobility, int server_relay,
send_turn_session_info_cb send_turn_session_info, send_https_socket_cb send_https_socket,
allocate_bps_cb allocate_bps_func, int oauth, const char *oauth_server_name,
const char *acme_redirect, ALLOCATION_DEFAULT_ADDRESS_FAMILY allocation_default_address_family,
vintp log_binding, vintp no_stun_backward_compatibility, vintp response_origin_only_with_rfc5780);
void init_turn_server(
turn_turnserver *server, turnserver_id id, int verbose, ioa_engine_handle e, turn_credential_type ct, int stun_port,
int fingerprint, dont_fragment_option_t dont_fragment, get_user_key_cb userkeycb,
check_new_allocation_quota_cb chquotacb, release_allocation_quota_cb raqcb, ioa_addr *external_addr,
vintp check_origin, vintp no_tcp_relay, vintp no_udp_relay, vintp stale_nonce, vintp max_allocate_lifetime,
vintp channel_lifetime, vintp permission_lifetime, vintp stun_only, vintp no_stun, vintp no_software_attribute,
vintp web_admin_listen_on_workers, turn_server_addrs_list_t *alternate_servers_list,
turn_server_addrs_list_t *tls_alternate_servers_list, turn_server_addrs_list_t *aux_servers_list,
int self_udp_balance, vintp no_multicast_peers, vintp allow_loopback_peers, ip_range_list_t *ip_whitelist,
ip_range_list_t *ip_blacklist, send_socket_to_relay_cb send_socket_to_relay, vintp secure_stun, vintp mobility,
int server_relay, send_turn_session_info_cb send_turn_session_info, send_https_socket_cb send_https_socket,
allocate_bps_cb allocate_bps_func, int oauth, const char *oauth_server_name, const char *acme_redirect,
ALLOCATION_DEFAULT_ADDRESS_FAMILY allocation_default_address_family, vintp log_binding,
vintp no_stun_backward_compatibility, vintp response_origin_only_with_rfc5780, vintp respond_http_unsupported);
ioa_engine_handle turn_server_get_engine(turn_turnserver *s);