Asterisk, WebRTC and DTLS

Just sharing this info here because I'm too lazy to file a bug report, yet spent some time investigating the issue. Talking OpenWrt 23.05.3 w/ Asterisk 20.8.1-1 (had the same problem w/ earlier versions though, it never worked).

The reason why WebRTC doesn't work is bc no media transmission path is established, and the reason behind that is that Asterisk is using the wrong DTLS version, namely v1, which is long outdated. See tcpdump here.

On Alpine 3.20.1, on the other hand, with exactly the same Asterisk version and exactly the same Asterisk configuration, things go smoothly, because DTLS v1.2 is being used, as required by browsers for quite some time now. See here.

Now, what may the reason be? Asterisk itself appears to realize that the version context libssl provides it with is all wrong, that's probably why it's sending an alert right away instead of attempting a misguided DTLS handshake. So my guess is that it's an OpenSSL build misconfiguration rather than an Asterisk issue. Just a guess though.

Either way, if you ran into similar problems in the past, as I did a couple of times trying to get the thing working, that's likely the reason. Just for the (public) record.

Edit: Note that in both cases Asterisk is the DTLS handshake initiating party. It's Asterisk that's sending the Alert in the first, DTLSv1 case, and it's Asterisk that's sending a Client Hello in the DTLSv1.2 case.

Helps to show tcpudp ports, make a dump of million packets to draw conclusions, mid-tls connections looksl ike random Xrap

There's nothing random about it, which you can easily see when you have a little experience looking at network traffic dumps.

I can also show you the browser's WebRTC diagnostics page. First the good case, with the Alpine installation. See, there are two certificate fingerprints, and the connection succeeds.

Now the OpenWrt Asterisk installation (as said, same Asterisk version, same configuration, also of the client). Now there's only one certificate fingerprint, that of the browser, and Asterisk's is missing. Also, the connection shows a failed status.

So once you see that you wonder why. And the reason is what you can see when looking at the traffic. DTLSv1 has been obsolete for a decade or so. Yet, for some mysterious reason, that's all OpenWrt's OpenSSL build is offering Asterisk. Asterisk itself seems to know that that's not enough, and sends an Alert instead of a handshake-initiating Client Hello. And that's where the whole thing fails.

Edit: Also note the "dtlsState=failed" report in the OpenWrt case. That's how I knew what I should be looking for.

expand certificate and check expiry dates?

Did I say "same configuration"? Everything the same, the configuration files of Asterisk, the certs used by it, the IP address, hostname. All replicated to the T on both installations. Identical, with a capital I, except the host system is different.

Look, it's a take it or leave it thing. If you ran into the issue and didn't have the time to figure out what went wrong exactly, this might be a hint that could save a little trouble.

Yes, certificate expires year after issuance.... Same configuration, did not touch it...Wait for some asterix expert to come by and help with application trace record.

More findings.

I decrypted the entire traffic between Asterisk (20.8.1 on both platforms, OpenWrt and Alpine) and Browser-Phone and examined it w/ tshark to see what the difference is. It starts with a HTTP TLS handshake, no problems there, they set up a secure connection in both cases, switch to WebSocket comms, perform their SIP dialog over TLS, the exchanges are, particulars not withstanding, like on-the-fly generated session ids, perfectly identical, really until they trey to set up the media path and negotiate the DTLS. Then, coming from the server in both cases, this happens:


Datagram Transport Layer Security
    DTLS Record Layer: Handshake Protocol: Client Hello
        Content Type: Handshake (22)
        Version: DTLS 1.0 (0xfeff)
        Epoch: 0
        Sequence Number: 0
        Length: 207
        Handshake Protocol: Client Hello
            Handshake Type: Client Hello (1)
            Length: 195
            Message Sequence: 0
            Fragment Offset: 0
            Fragment Length: 195
            Version: DTLS 1.2 (0xfefd)
            Random: 74e02d6977089b4df200a7bba4c2e9474af1f3ea9000a68915688cad0554f16c
                GMT Unix Time: Feb 20, 2032 01:12:25.000000000 CET
                Random Bytes: 77089b4df200a7bba4c2e9474af1f3ea9000a68915688cad0554f16c
            Session ID Length: 0


Datagram Transport Layer Security
    DTLSv1.0 Record Layer: Alert (Level: Fatal, Description: Protocol Version)
        Content Type: Alert (21)
        Version: DTLS 1.0 (0xfeff)
        Epoch: 0
        Sequence Number: 0
        Length: 2
        Alert Message
            Level: Fatal (2)
            Description: Protocol Version (70)

and that's the whole difference. Mind the "Record Layer" version.

Also of interest, potentially, on Alpine 3.20.1:

# openssl s_server -help 2>&1 | grep dtls
 -dtls                      Use any DTLS version
 -dtls1                     Just talk DTLSv1
 -dtls1_2                   Just talk DTLSv1.2

whereas on OpenWrt 20.05.3

# openssl s_server -help 2>&1 | grep dtls

Okay, seems like DTSL support isn't built in. A look into the build log of an openwrt-23.05_x86/64 image builder reveals

./Configure linux-x86_64-openwrt
[ ... snip ... ]
[ ... snip ... ]

So there you can see which features are deliberately disabled by the build configuration of the OpenSSL library, among them DTLS. In particular, no WebRTC for OpenWrt users.

Check what is missing in default config, it kind of depends on openssl....

OpenSSL ist built alright, but DTLS is disabled in the build config. See the switch.

To conclude, I now built the thing myself, it's one box in 'make menuconfig' that needs to be checked, and DTLS works. I've tested it already.

It's enough to just build the libopenssl and, optional, openssl-util packages, no further dependencies are involved. Be careful what build platform you choose though, I did it in an Alpine LXC container and ran into one or two issues bc of libmusl headers slightly differing from the GNU ones. But otherwise it's no problem.

To install the created ipk files temporarily move /etc/opkg/distfeeds.conf out of the way (followed by an "opkg update" of course), because else opkg will always pull the packages from the repositories even if you specify the ipk file on the command line.

As said, one checkbox. That's all it needs, and WebRTC works w/ Asterisk. The output of the second command was empty before, see one of my previous posts:

# grep 'PRETTY\|BOARD' /etc/os-release
PRETTY_NAME="OpenWrt 23.05.3"
# openssl s_server -h 2>&1 | grep dtls
 -dtls                      Use any DTLS version
 -dtls1                     Just talk DTLSv1
 -dtls1_2                   Just talk DTLSv1.2