Discover the new easier way to develop Kurento video applications

Securing Kurento Applications

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: Generating a self-signed certificate.

  • 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.port=8443
    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 -U clean 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 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: Generating a self-signed certificate.

  • 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 -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install --yes 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: Generating a self-signed certificate.

  • Start the HTTPS web server, using the SSL certificate:

    http-server -p 8443 --ssl --cert cert.pem --key key.pem
    

Securing Kurento Media Server

Securing the Signaling Plane (WebSocket)

With the default configuration, Kurento Media Server will use the ws:// URI scheme for non-secure WebSocket connections, listening on the port 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 API.

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 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 a secured KMS.

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: Generating a self-signed certificate. 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 applications. Take a look at this page: Painless Self Signed Certificates in node.js (archive).

    For a faster but INSECURE alternative, configure Node 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 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 a secured KMS

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 -U clean spring-boot:run \
        -Dspring-boot.run.jvmArguments="-Dkms.url=wss://{KMS_HOST}:8433/kurento"
    
  • Node: 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";
    

Securing the Media Plane (WebRTC DTLS)

WebRTC uses DTLS for media data authentication. By default, if no certificate is provided for this, Kurento Media Server will auto-generate its own self-signed certificate for every WebRtcEndpoint instance, but it is also possible to provide an already existing certificate to be used for all endpoints.

To do so, edit the file /etc/kurento/modules/kurento/WebRtcEndpoint.conf.ini and set either pemCertificateRSA or pemCertificateECDSA with a file containing the concatenation of your certificate (chain) file(s) and the private key.

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.

Generating a self-signed certificate

You need to provide a valid SSL certificate in order to enable all sorts of security features, ranging from HTTPS to Secure WebSocket (wss://). For this, there are two alternatives:

  • Obtain a certificate from a trusted Certification Authority (CA). This should be your primary choice, and will be necessary for production-grade deployments.

  • Create your own untrusted self-signed certificate. This can ease operations during the phase of software development. You can search articles online that explain how to do this, for example this one.

    Alternatively, it is much easier and convenient to use a self-signed certificate generation tool, such as mkcert. This kind of tools already take into account the requisites and limitations of most popular applications and browsers, so that you don’t need to.

    Note that while a self-signed certificate can be used for web development, browsers will show a big security warning. Users will see this warning, and must click to accept the unsafe certificate before proceeding to the page.

    To generate certificates with mkcert, run these commands:

    CAROOT="$PWD" mkcert -cert-file ./cert.pem -key-file ./key.pem \
        "127.0.0.1" \
        "::1"       \
        "localhost" \
        "a.test"    \
        "b.test"    \
        "c.test"
    
    chmod 440 *.pem