Securing Kurento Applications
Table of Contents
Securing Application Servers
Configure a Java server to use HTTPS
Obtain a certificate. For this, either request one from a trusted Certification Authority (CA), or generate your own one as explained here: Self-Signed Certificates.
Convert your PEM certificate to either Java KeyStore (JKS) or PKCS#12. The former is a proprietary format limited to the Java ecosystem, while the latter is an industry-wide used format. To make a PKCS#12 file from an already existing PEM certificate, run these commands:
openssl pkcs12 \ -export \ -in cert.pem -inkey key.pem \ -out cert.p12 -passout pass:123456 chmod 440 *.p12
Use the certificate in your application.
Place your PKCS#12 file cert.p12 in
src/main/resources/
, and add this to the application.properties file:server.ssl.key-store=classpath:cert.p12 server.ssl.key-store-password=123456 server.ssl.key-store-type=PKCS12
Start the Spring Boot application:
mvn spring-boot:run \ -Dspring-boot.run.jvmArguments="-Dkms.url=ws://{KMS_HOST}:8888/kurento"
Note
If you plan on using a webserver as proxy, like Nginx or Apache, you’ll need to setAllowedOrigins when registering the handler. Please read the official Spring documentation entry for more info.
Configure a Node.js server to use HTTPS
Obtain a certificate. For this, either request one from a trusted Certification Authority (CA), or generate your own one as explained here: Self-Signed Certificates.
Add the following changes to your server.js, in order to enable HTTPS:
... var express = require('express'); var ws = require('ws'); var fs = require('fs'); var https = require('https'); ... var options = { cert: fs.readFileSync('cert.pem'), key: fs.readFileSync('key.pem'), }; var app = express(); var server = https.createServer(options, app).listen(port, function() { ... }); ... var wss = new ws.Server({ server : server, path : '/' }); wss.on('connection', function(ws) { ....
Start application
npm start
Configure JavaScript applications to use HTTPS
WebRTC requires HTTPS, so your JavaScript application must be served by a secure web server. You can use whichever one you prefer, such as Nginx or Apache. For quick tests, a very straightforward option is to use the simple, zero-configuration http-server based on Node.js:
curl -sSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install nodejs
sudo npm install -g http-server
Obtain a certificate. For this, either request one from a trusted Certification Authority (CA), or generate your own one as explained here: Self-Signed Certificates.
Start the HTTPS web server, using the SSL certificate:
http-server -p 8443 --ssl --cert cert.pem --key key.pem
Securing Kurento Media Server
Signaling Plane security (WebSocket)
With the default configuration, Kurento Media Server will use the ws://
URI scheme for non-secure WebSocket connections, listening on the port TCP 8888. Application Servers (Kurento clients) will establish a WebSocket connection with KMS, in order to control the media server and send messages conforming to the Kurento Protocol.
This is fine for initial stages of application development, but before deploying on production environments you’ll probably want to move to wss://
connections, i.e. using Secure WebSocket, which by default uses the port TCP 8433.
To enable Secure WebSocket, edit the main KMS configuration file (/etc/kurento/kurento.conf.json
), and un-comment the following lines:
"secure": {
"port": 8433,
"certificate": "cert+key.pem",
"password": "KEY_PASSWORD"
}
If you use a signed certificate issued by a trusted Certification Authority (CA) such as Verisign or Let’s Encrypt, then you are done. Just skip to the next section: Connecting to Secure WebSocket.
However, if you are going to use an untrusted self-signed certificate (typically during development), there is still more work to do.
Generate your own certificate as explained here: Self-Signed Certificates. Now, because self-signed certificates are untrusted by nature, client browsers and server applications will reject it by default. You’ll need to force all consumers of the certificate to accept it:
Java applications. Follow the instructions of this link: SunCertPathBuilderException: unable to find valid certification path to requested target (archive).
Get InstallCert.java from here: https://github.com/escline/InstallCert.
You’ll need to instruct the KurentoClient to allow using certificates. For this purpose, create an JsonRpcClient:
SslContextFactory sec = new SslContextFactory(true); sec.setValidateCerts(false); JsonRpcClientWebSocket rpcClient = new JsonRpcClientWebSocket(uri, sec); KurentoClient kurentoClient = KurentoClient.createFromJsonRpcClient(rpcClient);
Node.js applications. Take a look at this page: Painless Self Signed Certificates in node.js (archive).
For a faster but INSECURE alternative, configure Node.js to accept (instead of reject) invalid TLS certificates by default, setting the environment variable flag NODE_TLS_REJECT_UNAUTHORIZED to 0; this will disable the TLS validation for your whole Node.js app. You can set this environment variable before executing your app, or directly in your app code by adding the following line before performing the connection:
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
Browser JavaScript. Similar to what happens with self-signed certificates used for HTTPS, browsers also require the user to accept a security warning before Secure WebSocket connections can be established. This is done by directly opening the KMS WebSocket URL:
https://{KMS_HOST}:8433/kurento
.
Connecting to Secure WebSocket
Now that KMS is listening for Secure WebSocket connections, and (if using a self-signed certificate) your Application Server is configured to accept the certificate used in KMS, you have to change the WebSocket URL used in your application logic.
Make sure your application uses a WebSocket URL that starts with wss://
instead of ws://
. Depending on the platform, this is done in different ways:
Java: Launch with a kms.url property. For example:
mvn spring-boot:run \ -Dspring-boot.run.jvmArguments="-Dkms.url=wss://{KMS_HOST}:8433/kurento"
Node.js: Launch with the ws_uri command-line argument. For example:
npm start -- --ws_uri="wss://{KMS_HOST}:8433/kurento"
Browser JavaScript: Application-specific method. For example, using hardcoded values:
const ws_uri: "wss://" + location.hostname + ":8433/kurento";
Media Plane security (DTLS)
WebRTC uses DTLS for media data authentication. By default, if no certificate is provided for this, Kurento Media Server will auto-generate a new self-signed certificate for every WebRtcEndpoint instance.
Alternatively, an already existing certificate can be provided to be used for all endpoints. For this, edit the file /etc/kurento/modules/kurento/WebRtcEndpoint.conf.ini
and set either pemCertificateRSA or pemCertificateECDSA with a file containing both your certificate (chain) file(s) and the private key. You can generate such file with the cat
command:
# Make a single file to be used with Kurento Media Server.
cat cert.pem key.pem >cert+key.pem
Then, configure the path to cert+key.pem
.
Setting a custom certificate for DTLS is needed, for example, for situations where you have to manage multiple media servers and want to make sure that all of them use the same certificate for their connections. Some browsers, such as Firefox, require this in order to allow multiple WebRTC connections from the same tab to different KMS instances.