fonoster / routr

⚡ The future of programmable SIP servers.
https://routr.io
MIT License
1.39k stars 146 forks source link

[FEATURE]: TLSv1.3 support #289

Open flash7777 opened 2 weeks ago

flash7777 commented 2 weeks ago

Is your feature request related to a problem?

TLSv1.2 is very vulnerable, especially this implementation because CBC RSA and SHA were statically programmed in. Java supports TLS 1.3 even in backported way till Java 8.

Describe the solution you'd like

routr should support TLSv1.3 for sip. when set up in the list of protocols, it should accept incoming tls 1.3 connections. the sip component (jain) could be upgraded or overriden with setup of TLSv1.3 context.

if the source is beeing touched, any static cipher config should be removed from the code. If its needed for proper initializing of the ssl context, it should be placed in the config files.

Describe alternatives you've considered

encryption is missing on application level.

Additional context

image

weak https://ciphersuite.info/cs/TLS_RSA_WITH_AES_128_CBC_SHA/ https://ciphersuite.info/cs/TLS_RSA_WITH_3DES_EDE_CBC_SHA/

insecure https://ciphersuite.info/cs/TLS_DH_anon_WITH_AES_128_CBC_SHA/ https://ciphersuite.info/cs/TLS_DH_anon_WITH_3DES_EDE_CBC_SHA/ https://ciphersuite.info/cs/SSL_DH_anon_WITH_3DES_EDE_CBC_SHA/

flash7777 commented 2 weeks ago

its possible to force "TLSv1.3" via securityContext:

        securityContext: {
            debugging: false,
            trustStore: 'etc/certs/domains-cert.jks',
            trustStorePassword: 'changeit',
            keyStore: 'etc/certs/domains-cert.jks',
            keyStorePassword: 'changeit',
            keyStoreType: 'jks',
            client: {
                authType: 'Want',
                protocols: ['TLSv1.2','TLSv1.3']
            }
        },

via libs/server.bundle.js authType: 'Want',\n protocols: ['TLSv1.2'] => TLS12 authType: 'Want',\n protocols: ['TLSv1.2', 'TLSv1.3'] => TLS12 authType: 'Want',\n protocols: ['TLSv1.3', 'TLSv1.2'] => TLS12 authType: 'Want',\n protocols: ['TLSv1.3'] => TLS13

=> so it has to be set to TLSv1.3 ONLY

this is not clean, but acceptable.

then it is loading TLS1.3 CIPHERs ...

[INFO ] Starting Routr [INFO ] using Want tls auth policy javax.net.ssl|DEBUG|01|main|2024-08-31 07:34:35.118 UTC|null:-1|jdk.tls.keyLimits: entry = AES/GCM/NoPadding KeyUpdate 2^37. AES/GCM/NOPADDING:KEYUPDATE = 137438953472 javax.net.ssl|DEBUG|01|main|2024-08-31 07:34:35.159 UTC|null:-1|jdk.tls.keyLimits: entry = ChaCha20-Poly1305 KeyUpdate 2^37. CHACHA20-POLY1305:KEYUPDATE = 137438953472 [WARN ] using default tls security policy

but finally on connect:

javax.net.ssl|DEBUG|22|NioSelector-TLS-10.12.20.100/5061|2024-08-31 07:49:45.290 UTC|null:-1|No available cipher suite for TLSv1.3 javax.net.ssl|ERROR|22|NioSelector-TLS-10.12.20.100/5061|2024-08-31 07:49:45.299 UTC|null:-1|Fatal (INTERNAL_ERROR): problem unwrapping net record

=> so it would be good to have the ciphers either defaulted

jain sip allows overriding by "setEnabledCipherSuites" or set by config: TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256 TLS_AES_128_GCM_SHA256 TLS_AES_128_CCM_8_SHA256 TLS_AES_128_CCM_SHA256

jain-interface:

 * <b>NOTE: This function must be called before adding a TLS listener</b>
 * 
 * @param String
 *            [] The new set of ciphers to support.
 * @return
 * 
 */
public void setEnabledCipherSuites(String[] newCipherSuites) {
    cipherSuites = newCipherSuites;
}
flash7777 commented 2 weeks ago

I found a way to hotfix this cipher part by adding some lines to libs/server.bundle.js:

Server.prototype.setup = function () {
    showExternInfo(config);
    try {
        var os = new LogOutputStream();
        var ps = new PrintStream(os);
        System.setOut(ps);
        if (config.spec.securityContext.debugging) {
            Java.type('java.lang.System').setProperty('javax.net.debug', 'ssl');
        }
        var sipFactory = SipFactory.getInstance();
        sipFactory.setPathName('gov.nist');

        // fix begin
        this.sipStack = sipFactory.createSipStack(properties);
        var enabledCiphers  = [  'TLS_CHACHA20_POLY1305_SHA256', 'TLS_AES_128_GCM_SHA256', 'TLS_AES_256_GCM_SHA384' ];
        var disabledCiphers = [  'TLS_AES_128_CCM_8_SHA256',  'TLS_AES_128_CCM_SHA256' ];
        LOG.info("override ciphers, TLSv1.3 mandatory");
        this.sipStack.setEnabledCipherSuites(enabledCiphers);
        this.sipStack.setEnabledProtocols(["TLSv1.3"]);  // FIXME: works only if forced to TLSv1.3
        LOG.info(enabledCiphers);
        // fix end

        var sipProvider = this.buildSipProvider(this.sipStack, config.spec.transport);
        var ctxStorage = new ContextStorage(sipProvider);
        var processor = new Processor(sipProvider, this.dataAPIs, ctxStorage);
        sipProvider.addSipListener(processor.listener);
        this.ctxStorage = ctxStorage;
    }
    catch (e) {
        LOG.error(ExceptionUtils.getRootCause(e));
    }
};

It's important to mention that the CCM ciphers were causing some problems on my system, which is why I disabled them. Perhaps the following approach would be a good idea:

enabledCiphers = config.spec.securityContext.client.chipers.join()

psanders commented 5 days ago

First, a huge thanks for the level of detail and effort.

Based on your comments, I propose the following changes:

For the environment variables, I propose using:

How does this sound? Let me know if you have additional feedback before I start working this.

flash7777 commented 5 days ago

perfect.

further thoughts: for migration and older ecosystems it should be possible to switch to older tls and ciphers, so "removing older versions" is ok in terms of configuration only.

and please consider if also other parts are affected, f.i. outbound connect? its not the only part where jain is used.