Ver código fonte

ALPN support added

mom040267 11 anos atrás
pai
commit
06389df97c

+ 2 - 1
ChangeLog

@@ -1,6 +1,7 @@
 12/09/2014 Oleg Moskalenko <[email protected]>
 Version 4.3.2.1 'Tolomei':
-	- DTLS v1.2 supported (for OpenSSL 1.0.2+);
+	- DTLS v1.2 supported (when compiled with OpenSSL 1.0.2+ );
+	- STUN/TURN ALPN supported (when compiled with OpenSSL 1.0.2+ );
 
 11/29/2014 Oleg Moskalenko <[email protected]>
 Version 4.3.1.3 'Tolomei':

+ 15 - 4
README.turnserver

@@ -195,11 +195,11 @@ Flags:
 
 --no-sslv3		Do not allow SSLv3 protocol.
 
---no-tlsv1		Do not allow TLSv1 protocol.
+--no-tlsv1		Do not allow TLSv1/DTLSv1 protocol.
 
 --no-tlsv1_1		Do not allow TLSv1.1 protocol.
 
---no-tlsv1_2		Do not allow TLSv1.2 protocol.
+--no-tlsv1_2		Do not allow TLSv1.2/DTLSv1.2 protocol.
 
 --no-udp		Do not start UDP client listeners.
 
@@ -775,7 +775,18 @@ it will set the users for you (see the turnadmin manuals). If you are using SQLi
 turnserver or turnadmin will initialize the empty database, for you, when started. The 
 TURN server installation process creates an empty initialized SQLite database in the default 
 location (/var/db/turndb or /usr/local/var/db/turndb or /var/lib/turn/turndb, depending on the system).
-    
+
+=================================
+
+ALPN
+
+The server supports ALPNs "stun.turn" and "stun.nat-discovery", when
+compiled with OpenSSL 1.0.2 or newer. If the server receives a TLS/DTLS
+ClientHello message that contains one or both of those ALPNs, then the
+server chooses the first stun.* label and sends it back (in the ServerHello)
+in the ALPN extention field. If no stun.* label is found, then the server
+does not include the ALPN information into the ServerHello.
+
 =================================
 
 LIBRARIES
@@ -786,7 +797,7 @@ The C++ wrapper for the messaging functionality is located in TurnMsgLib.h heade
 An example of C++ code can be found in stunclient.c file. 
 
 =================================
- 
+
 DOCS
 
 After installation, run the command:

+ 1 - 3
TODO

@@ -57,9 +57,7 @@
 
 1) For extra difficult NAT/FWs, consider implementing Websockets.
 
-2) ALPN with TLS and DTLS (when OpenSSL 1.0.2 is available).
-
-3) Redirect draft.
+2) Redirect draft.
 
 ==================================================================
 

+ 1 - 1
examples/etc/turnserver.conf

@@ -620,7 +620,7 @@
 #
 #ne=[1|2|3]
 
-# Do not allow an SSL/TLS version of protocol
+# Do not allow an SSL/TLS/DTLS version of protocol
 #
 #no-sslv2
 #no-sslv3

+ 1 - 1
man/man1/turnadmin.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "06 December 2014" "" ""
+.TH TURN 1 "10 December 2014" "" ""
 .SH GENERAL INFORMATION
 
 \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage 

+ 13 - 3
man/man1/turnserver.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "06 December 2014" "" ""
+.TH TURN 1 "10 December 2014" "" ""
 .SH GENERAL INFORMATION
 
 The \fBTURN Server\fP project contains the source code of a TURN server and TURN client 
@@ -291,7 +291,7 @@ Do not allow SSLv3 protocol.
 .TP
 .B
 \fB\-\-no\-tlsv1\fP
-Do not allow TLSv1 protocol.
+Do not allow TLSv1/DTLSv1 protocol.
 .TP
 .B
 \fB\-\-no\-tlsv1_1\fP
@@ -299,7 +299,7 @@ Do not allow TLSv1.1 protocol.
 .TP
 .B
 \fB\-\-no\-tlsv1_2\fP
-Do not allow TLSv1.2 protocol.
+Do not allow TLSv1.2/DTLSv1.2 protocol.
 .TP
 .B
 \fB\-\-no\-udp\fP
@@ -1032,6 +1032,16 @@ TURN server installation process creates an empty initialized SQLite database in
 location (/var/db/turndb or /usr/local/var/db/turndb or /var/lib/turn/turndb, depending on the system).
 .PP
 =================================
+.SH ALPN
+
+The server supports ALPNs "stun.turn" and "stun.nat\-discovery", when
+compiled with OpenSSL 1.0.2 or newer. If the server receives a TLS/DTLS
+ClientHello message that contains one or both of those ALPNs, then the
+server chooses the first stun.* label and sends it back (in the ServerHello)
+in the ALPN extention field. If no stun.* label is found, then the server
+does not include the ALPN information into the ServerHello.
+.PP
+=================================
 .SH LIBRARIES
 
 In the lib/ sub\-directory the build process will create TURN client messaging library.

+ 1 - 1
man/man1/turnutils.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "06 December 2014" "" ""
+.TH TURN 1 "10 December 2014" "" ""
 .SH GENERAL INFORMATION
 
 A set of turnutils_* programs provides some utility functionality to be used

+ 71 - 2
src/apps/relay/mainrelay.c

@@ -515,9 +515,9 @@ static char Usage[] = "Usage: turnserver [options]\n"
 "						Flags --dh566 and --dh2066 are ignored when the DH key is taken from a file.\n"
 " --no-sslv2					Do not allow SSLv2 protocol.\n"
 " --no-sslv3					Do not allow SSLv3 protocol.\n"
-" --no-tlsv1					Do not allow TLSv1 protocol.\n"
+" --no-tlsv1					Do not allow TLSv1/DTLSv1 protocol.\n"
 " --no-tlsv1_1					Do not allow TLSv1.1 protocol.\n"
-" --no-tlsv1_2					Do not allow TLSv1.2 protocol.\n"
+" --no-tlsv1_2					Do not allow TLSv1.2/DTLSv1.2 protocol.\n"
 " --no-udp					Do not start UDP client listeners.\n"
 " --no-tcp					Do not start TCP client listeners.\n"
 " --no-tls					Do not start TLS client listeners.\n"
@@ -2339,8 +2339,59 @@ static int pem_password_func(char *buf, int size, int rwflag, void *password)
 	return (strlen(buf));
 }
 
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION
+
+static int ServerALPNCallback(SSL *s,
+				const unsigned char **out,
+				unsigned char *outlen,
+				const unsigned char *in,
+				unsigned int inlen,
+				void *arg) {
+
+	UNUSED_ARG(s);
+	UNUSED_ARG(arg);
+
+	unsigned char sa_len = (unsigned char)strlen(STUN_ALPN);
+	unsigned char ta_len = (unsigned char)strlen(TURN_ALPN);
+	unsigned char ha_len = (unsigned char)strlen(HTTP_ALPN);
+
+	int found_http = 0;
+
+	const unsigned char *ptr = in;
+	while(ptr < (in+inlen)) {
+		unsigned char current_len = *ptr;
+		if(ptr+1+current_len > in+inlen)
+			break;
+		if((current_len == sa_len) && (memcmp(ptr+1,STUN_ALPN,sa_len)==0)) {
+			*out = ptr+1;
+			*outlen = sa_len;
+			return SSL_TLSEXT_ERR_OK;
+		}
+		if((current_len == ta_len) && (memcmp(ptr+1,TURN_ALPN,ta_len)==0)) {
+			*out = ptr+1;
+			*outlen = ta_len;
+			return SSL_TLSEXT_ERR_OK;
+		}
+		if((current_len == ha_len) && (memcmp(ptr+1,HTTP_ALPN,ha_len)==0)) {
+			found_http = 1;
+		}
+		ptr += 1 + current_len;
+	}
+
+	if(found_http)
+		return SSL_TLSEXT_ERR_NOACK;
+
+	return SSL_TLSEXT_ERR_NOACK; //???
+}
+
+#endif
+
 static void set_ctx(SSL_CTX* ctx, const char *protocol)
 {
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION
+	SSL_CTX_set_alpn_select_cb(ctx, ServerALPNCallback, NULL);
+#endif
+
 	SSL_CTX_set_default_passwd_cb_userdata(ctx, turn_params.tls_password);
 
 	SSL_CTX_set_default_passwd_cb(ctx, pem_password_func);
@@ -2437,6 +2488,14 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol)
 				dh = get_dh1066();
 		}
 
+		/*
+		if(!dh) {
+			dh = DH_new();
+			DH_generate_parameters_ex(dh, 32, DH_GENERATOR_2, 0);
+			DH_generate_key(dh);
+		}
+		*/
+
 		if(!dh) {
 		  TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot allocate DH suite\n",__FUNCTION__);
 		} else {
@@ -2469,6 +2528,16 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol)
 			op |= SSL_OP_NO_TLSv1_2;
 #endif
 
+#if defined(SSL_OP_NO_DTLSv1)
+		if(turn_params.no_tlsv1)
+			op |= SSL_OP_NO_DTLSv1;
+#endif
+
+#if defined(SSL_OP_NO_DTLSv1_2)
+		if(turn_params.no_tlsv1_2)
+			op |= SSL_OP_NO_DTLSv1_2;
+#endif
+
 #if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
 		op |= SSL_OP_CIPHER_SERVER_PREFERENCE;
 #endif

+ 9 - 0
src/apps/uclient/startuclient.c

@@ -50,6 +50,11 @@ static uint64_t current_reservation_token = 0;
 static int allocate_rtcp = 0;
 static const int never_allocate_rtcp = 0;
 
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION
+static const unsigned char kALPNProtos[] = "\x09stun.turn\x12stun.nat-discovery";
+static const size_t kALPNProtosLen = sizeof(kALPNProtos) - 1;
+#endif
+
 /////////////////////////////////////////
 
 int rare_event(void)
@@ -86,6 +91,10 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again
 
 	ssl = SSL_NEW(root_tls_ctx[ctxtype]);
 
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_FIRST_ALPN_VERSION
+	SSL_set_alpn_protos(ssl, kALPNProtos, kALPNProtosLen);
+#endif
+
 	if(use_tcp) {
 		SSL_set_fd(ssl, fd);
 	} else {

+ 8 - 2
src/ns_turn_defs.h

@@ -60,8 +60,6 @@
 extern "C" {
 #endif
 
-///////////////////////////////////////////
-
 /* NS types: */
 
 #define	s08bits	char
@@ -218,6 +216,14 @@ typedef u32bits turn_time_t;
 #define DELETE_TURN_CHANNEL_KERNEL(handler)
 #endif
 
+/* ALPN */
+
+#define OPENSSL_FIRST_ALPN_VERSION (0x10002003L)
+
+#define STUN_ALPN "stun.nat-discovery"
+#define TURN_ALPN "stun.turn"
+#define HTTP_ALPN "http/1.1"
+
 ////////////////////////////////////////////////////////
 
 #ifdef __cplusplus