Просмотр исходного кода

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.
Dave Lambley 2 лет назад
Родитель
Сommit
20c8d86a34

+ 6 - 0
examples/etc/turnserver.conf

@@ -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

+ 11 - 1
src/apps/relay/mainrelay.c

@@ -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':

+ 1 - 0
src/apps/relay/mainrelay.h

@@ -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;

+ 14 - 14
src/apps/relay/netengine.c

@@ -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);

+ 36 - 4
src/server/ns_turn_server.c

@@ -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) {

+ 18 - 16
src/server/ns_turn_server.h

@@ -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);