VoIP语音通话研究【进阶篇(四):freeswitch+webrtc+sip.js的通话】
Posted on 2020-10-04 23:54 shihuc 阅读(6812) 评论(0) 编辑 收藏 举报今天这个博文,可以说涉及到的应用场景还是非常有价值的,因为基于WebRTC的应用,让音视频通话,基于浏览器就可以完成,客户端变得简洁,方便。 后台交换系统,我们选择freeswitch,虽然freeswitch相对比较复杂,配置也好,还是相关的概念理解也好,都需要较长时间的摸索,借用一个网友的说法,就是熬。但是,freeswitch的性能和二次开发的便捷性,是很多人看好的。
freeswitch的安装,相对来说,算是比较复杂的,有很多坑,但是网上有不少的帖子介绍freeswitch的安装, 我这里就不做过多的介绍。只想强调一下,或者做个备注,以后自己可以查阅(我的linux系统是CentOS7, freeswitch版本是1.8.6 64bit的),安装过程中,网上很多地方说yasm和nasm,汇编处理,提升编解码速度,很多说yasm和nasm一样,装那个都可以,但是我装nasm总是遇到:
vpx_dsp/x86/intrapred_sse2.asm:64: error: invalid combination of opcode and operands
后来,我卸载nasm,然后安装yasm,并将freeswitch整个安装文件重新来一遍,恢复初始状态(将之前编译用的freeswitch目录删除,重新解压freeswitch 1.8.6 的tar.gz包),上述错误便不再出现。
还有很多坑,这里就不再多说,网上百度很多相关帖子,每扫除一个坑,最好将编译环境重置一下,这样会减少不必要的说不清楚的麻烦,我在这个上面吃了大亏。
回归今天的重点话题,基于浏览器的音视频通话。因为chrome,Firefox以及其他一些主流浏览器现在基本都支持WebRTC,这个实现基于IP的音视频通话,提供了很多便利。但是呢,WebRTC要求安全通信,要求基于SSL, 否则会出现下面的提示:
--unsafely-treat-insecure-origin-as-secure
虽然说,不用https打开Web应用,在chrome下,用http打开,出现上述这个警告,在浏览器地址栏输入下面内容:
chrome://flags/#unsafely-treat-insecure-origin-as-secure
这样,结合下面的配图,先在1对应的区域输入你要访问的URL地址,然后再在2对应的按钮处选择enabled,重启浏览器后,再访问地址,浏览器是允许访问的。这是权宜之计的解决方案,在生产中,或者用户测试阶段,手机浏览器上操作,这个显然是不行的,让用户去做这个配置,然后访问,你觉得可行么?
于是乎,为了搞清楚,基于https的访问web应用,就有了本博文。
为了实现Freeswitch+WebRTC+sip.js的基本通话功能的验证,这里采用自签名的证书进行验证。 我们先看看,freeswitch默认的wss.pem证书是多少位的,我们好参照着创建一个一样长度的证书。

[root@fs3 certs]# vi wss.pem -----BEGIN PRIVATE KEY----- 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 qwKKHXhZ0lsdvF3PCfSJ3t2wlVQS4IU= -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIEujCCAqICAQAwDQYJKoZIhvcNAQEFBQAwIjELMAkGA1UEBhMCVVMxEzARBgNV BAMMCkZyZWVTV0lUQ0gwIBcNMjAwOTE2MDY1NDI2WhgPMjEyMDA4MzAwNjU0MjZa MCIxCzAJBgNVBAYTAlVTMRMwEQYDVQQDDApGcmVlU1dJVENIMIICIjANBgkqhkiG 9w0BAQEFAAOCAg8AMIICCgKCAgEAxo+WPK/TdhqD39Qciwft8R3Y/c3gfJ0JZEdR Ogv4YaBxF1397YnUPFU+tjD8CKWPj5PeW9c4QNYGI3bloXYbjhWXWoR8LL3VmLM0 Ym7pdoEUd9I9IZGkfFCndg/0RA+rqaAdhRg2+X5/i0QqkEhV0geuy4kFtyWyrjPn ipxYKrQMQ380N/dxMZFLTYnVXOTr96Y1yxdq2pS3Cpxlzxi1Qy2kr/bUcj+KE21o KnZY7J5xG9241sGo3qoc4ZVIxGefC/es8ioVsd36FJ+GR1I4t6kc3Kx7VraN9cuY HGx7ix/fAcbC+ri5og9iQU5/BMolufJqIPq+yetNwiQY851dWPsDqcRDl3758U3t 4KJ9+deCiRrdm/fOjMpuPSC5G4T66vjngZGWv4JmTwF/Qlm7Ww4BeJPY7mwUsIN5 4AzGZbPxRfDtE/BbWQhxr0PFLwYRvLsTB+RYdGAgAZk+m5Yacn+yuPoSIo4bJqzk 9pj76Tf6r1/ELNrVJSKipi9JfobLm0KzBqejAL1nEF2Um6MleIrnP5KjY49ktdmI 4CgMMK05XS723JYx3NrUeLwuRXdxBi6HDAybkAopSaxu+DA24HUsMloYY0sZj0Db L+U73SCZgagrGtgm6s1XhSAJRxzTYMfKhqdY6yZIn4vLGQHU7QGBmn7zFqW39s2I +mVV0lUCAwEAATANBgkqhkiG9w0BAQUFAAOCAgEATQMU5A6qlX6N7rCge7kdUSFk 90GwEah0ipW7TzR0i73GY8Bi14KS8Ler2NsKIby/k9RGaZFJljWml8nYgQNGvCVb vNerp/0IKQmv+J2G3Qp5fCJZnU8+eAn4QDUd2cbKJfcKWqYJ40ax4na68SzCUXJL uO6xSP/bCSi+b6jsUDdcSYe2kNRhx3PMF6CJ75hKpDWygdQrNmEqeRiwSTKdvzC6 oo3yzKQlovtPSXcj+XArWZenIbBju4uclaa2A8gxOvZcf91pyZcxq38MBWxhf1Gr gTDA45FCSYw/vKM+Z4X04/bUq/H1RZxOxsp9+TdrWvb9iRjb5zScizv0P7PkWJws 6ILnnbFo+cSjmH313WbJz2grGf0Y2V0We7wctGk09eStIpXFb1ardxrAqIvS2SrU Z6pi1A0xX3xtffO07uOVDwhF4th3SjJOd1GWJVw7YhYtNA8Y8ciTvGqBRLKchgGo Fv8tw/p0s+LCksw6Z46pHRxJwEr8EJXL0lx+z78vPlVi7rkm1HKaWJ89Jgm3zlfW Nus7waZk5UDPvcLZQJdhPQf6qQkhnmQOmBcxbI2JGILq2+URFq2NXX0BdfA/iOHM zFKjAxn2A0xG6fRiLYpApFG4zMv5UyxzgOd0vrzfvteHXJ2vKIu1/dELAwqlVRW+ pa/40prAPOZpXbZ5bWk= -----END CERTIFICATE-----
从私钥的注释头可知,他是PKCS#8格式的密钥。这个格式需要从openssl genrsa生成的私钥,经过格式转换得到,这里先了解一下这个基本信息即可。freeswitch这么强大,常见的私钥格式应该都可以支持吧,再说了pkcs#8是比较常见的私钥格式,就连流行的一逼的JAVA创建的证书对应的私钥默认都是pkcs#8的呢。
接下来看看wss.pem内容有什么特点,下面用openssl x509指令看看。

[root@fs3 certs]# openssl x509 -in wss.pem -noout -text Certificate: Data: Version: 1 (0x0) Serial Number: 0 (0x0) Signature Algorithm: sha1WithRSAEncryption Issuer: C = US, CN = FreeSWITCH Validity Not Before: Sep 16 06:54:26 2020 GMT Not After : Aug 30 06:54:26 2120 GMT Subject: C = US, CN = FreeSWITCH Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (4096 bit) Modulus: 00:c6:8f:96:3c:af:d3:76:1a:83:df:d4:1c:8b:07: ed:f1:1d:d8:fd:cd:e0:7c:9d:09:64:47:51:3a:0b: f8:61:a0:71:17:5d:fd:ed:89:d4:3c:55:3e:b6:30: fc:08:a5:8f:8f:93:de:5b:d7:38:40:d6:06:23:76: e5:a1:76:1b:8e:15:97:5a:84:7c:2c:bd:d5:98:b3: 34:62:6e:e9:76:81:14:77:d2:3d:21:91:a4:7c:50: a7:76:0f:f4:44:0f:ab:a9:a0:1d:85:18:36:f9:7e: 7f:8b:44:2a:90:48:55:d2:07:ae:cb:89:05:b7:25: b2:ae:33:e7:8a:9c:58:2a:b4:0c:43:7f:34:37:f7: 71:31:91:4b:4d:89:d5:5c:e4:eb:f7:a6:35:cb:17: 6a:da:94:b7:0a:9c:65:cf:18:b5:43:2d:a4:af:f6: d4:72:3f:8a:13:6d:68:2a:76:58:ec:9e:71:1b:dd: b8:d6:c1:a8:de:aa:1c:e1:95:48:c4:67:9f:0b:f7: ac:f2:2a:15:b1:dd:fa:14:9f:86:47:52:38:b7:a9: 1c:dc:ac:7b:56:b6:8d:f5:cb:98:1c:6c:7b:8b:1f: df:01:c6:c2:fa:b8:b9:a2:0f:62:41:4e:7f:04:ca: 25:b9:f2:6a:20:fa:be:c9:eb:4d:c2:24:18:f3:9d: 5d:58:fb:03:a9:c4:43:97:7e:f9:f1:4d:ed:e0:a2: 7d:f9:d7:82:89:1a:dd:9b:f7:ce:8c:ca:6e:3d:20: b9:1b:84:fa:ea:f8:e7:81:91:96:bf:82:66:4f:01: 7f:42:59:bb:5b:0e:01:78:93:d8:ee:6c:14:b0:83: 79:e0:0c:c6:65:b3:f1:45:f0:ed:13:f0:5b:59:08: 71:af:43:c5:2f:06:11:bc:bb:13:07:e4:58:74:60: 20:01:99:3e:9b:96:1a:72:7f:b2:b8:fa:12:22:8e: 1b:26:ac:e4:f6:98:fb:e9:37:fa:af:5f:c4:2c:da: d5:25:22:a2:a6:2f:49:7e:86:cb:9b:42:b3:06:a7: a3:00:bd:67:10:5d:94:9b:a3:25:78:8a:e7:3f:92: a3:63:8f:64:b5:d9:88:e0:28:0c:30:ad:39:5d:2e: f6:dc:96:31:dc:da:d4:78:bc:2e:45:77:71:06:2e: 87:0c:0c:9b:90:0a:29:49:ac:6e:f8:30:36:e0:75: 2c:32:5a:18:63:4b:19:8f:40:db:2f:e5:3b:dd:20: 99:81:a8:2b:1a:d8:26:ea:cd:57:85:20:09:47:1c: d3:60:c7:ca:86:a7:58:eb:26:48:9f:8b:cb:19:01: d4:ed:01:81:9a:7e:f3:16:a5:b7:f6:cd:88:fa:65: 55:d2:55 Exponent: 65537 (0x10001) Signature Algorithm: sha1WithRSAEncryption 4d:03:14:e4:0e:aa:95:7e:8d:ee:b0:a0:7b:b9:1d:51:21:64: f7:41:b0:11:a8:74:8a:95:bb:4f:34:74:8b:bd:c6:63:c0:62: d7:82:92:f0:b7:ab:d8:db:0a:21:bc:bf:93:d4:46:69:91:49: 96:35:a6:97:c9:d8:81:03:46:bc:25:5b:bc:d7:ab:a7:fd:08: 29:09:af:f8:9d:86:dd:0a:79:7c:22:59:9d:4f:3e:78:09:f8: 40:35:1d:d9:c6:ca:25:f7:0a:5a:a6:09:e3:46:b1:e2:76:ba: f1:2c:c2:51:72:4b:b8:ee:b1:48:ff:db:09:28:be:6f:a8:ec: 50:37:5c:49:87:b6:90:d4:61:c7:73:cc:17:a0:89:ef:98:4a: a4:35:b2:81:d4:2b:36:61:2a:79:18:b0:49:32:9d:bf:30:ba: a2:8d:f2:cc:a4:25:a2:fb:4f:49:77:23:f9:70:2b:59:97:a7: 21:b0:63:bb:8b:9c:95:a6:b6:03:c8:31:3a:f6:5c:7f:dd:69: c9:97:31:ab:7f:0c:05:6c:61:7f:51:ab:81:30:c0:e3:91:42: 49:8c:3f:bc:a3:3e:67:85:f4:e3:f6:d4:ab:f1:f5:45:9c:4e: c6:ca:7d:f9:37:6b:5a:f6:fd:89:18:db:e7:34:9c:8b:3b:f4: 3f:b3:e4:58:9c:2c:e8:82:e7:9d:b1:68:f9:c4:a3:98:7d:f5: dd:66:c9:cf:68:2b:19:fd:18:d9:5d:16:7b:bc:1c:b4:69:34: f5:e4:ad:22:95:c5:6f:56:ab:77:1a:c0:a8:8b:d2:d9:2a:d4: 67:aa:62:d4:0d:31:5f:7c:6d:7d:f3:b4:ee:e3:95:0f:08:45: e2:d8:77:4a:32:4e:77:51:96:25:5c:3b:62:16:2d:34:0f:18: f1:c8:93:bc:6a:81:44:b2:9c:86:01:a8:16:ff:2d:c3:fa:74: b3:e2:c2:92:cc:3a:67:8e:a9:1d:1c:49:c0:4a:fc:10:95:cb: d2:5c:7e:cf:bf:2f:3e:55:62:ee:b9:26:d4:72:9a:58:9f:3d: 26:09:b7:ce:57:d6:36:eb:3b:c1:a6:64:e5:40:cf:bd:c2:d9: 40:97:61:3d:07:fa:a9:09:21:9e:64:0e:98:17:31:6c:8d:89: 18:82:ea:db:e5:11:16:ad:8d:5d:7d:01:75:f0:3f:88:e1:cc: cc:52:a3:03:19:f6:03:4c:46:e9:f4:62:2d:8a:40:a4:51:b8: cc:cb:f9:53:2c:73:80:e7:74:be:bc:df:be:d7:87:5c:9d:af: 28:8b:b5:fd:d1:0b:03:0a:a5:55:15:be:a5:af:f8:d2:9a:c0: 3c:e6:69:5d:b6:79:6d:69
从这个默认的wss.pem证书的内容看,是4096位的RSA加密算法的证书。
1. 创建基于自签名证书的的应用证书(4096位)
1.1 创建根证书的私钥
[root@fs3 certs]# openssl genrsa -out ca4k.key 4096 Generating RSA private key, 4096 bit long modulus (2 primes) .............................................++++ .............................................................++++ e is 65537 (0x010001)
1.2 签发自签名证书
[root@fs3 certs]# openssl req -new -x509 -key ca4k.key -out ca4k.crt -subj "/C=CN/ST=Hubei/L=Wuhan/O=Shihuc/OU=IOV/CN=IOVGFS"
1.3 创建服务端私钥文件
[root@fs3 certs]# openssl genrsa -out svr4k.key 4096 Generating RSA private key, 4096 bit long modulus (2 primes) ............................................................................................................++++ ..........................................................................++++ e is 65537 (0x010001)
1.4 生成证书签发请求文件
[root@fs3 certs]# openssl req -new -key svr4k.key -out svr4k.csr -subj "/C=CN/ST=Hubei/L=Wuhan/O=Shihuc/OU=IOV/CN=192.168.219.138"
1.5 签发服务端证书
[root@fs3 certs]# openssl ca -in svr4k.csr -out svr4k.crt -cert ca4k.crt -keyfile ca4k.key -days 3650 Using configuration from /usr/ssl/openssl.cnf Check that the request matches the signature Signature ok Certificate Details: Serial Number: 1 (0x1) Validity Not Before: Oct 4 17:14:55 2020 GMT Not After : Oct 2 17:14:55 2030 GMT Subject: countryName = CN stateOrProvinceName = Hubei organizationName = Shihuc organizationalUnitName = IOV commonName = 192.168.219.138 X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 02:CB:5B:94:EA:D1:E4:2F:64:81:CE:F4:F0:24:E5:27:25:D1:C5:88 X509v3 Authority Key Identifier: keyid:F1:23:37:F5:02:E3:06:22:8D:8D:E6:5E:ED:5C:85:E4:F2:BB:CA:88 Certificate is to be certified until Oct 2 17:14:55 2030 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
到此,自签名的根证书ca4k.crt、ca4k.key有了,nginx/freeswitch共用的服务端证书文件svr4k.crt、svr4k.key都创建了。这里重点需要注意的是,CN参数的填写,根证书,CN(Common Name)可以随便写,只要自己知道其含义即可,但是服务端证书,其CN的值就不能随便填写了,必须和对应服务器的域名或者IP绑定对应关系,即,要么用服务端的域名,要么是服务的IP地址。
2. 创建FS的WSS.pem证书文件
将svr4k.crt及svr4k.key合并成一个文件,写入到wss.pem文件中,这时,freeswitch的证书路径(/usr/local/freeswitch/certs/)下,需要将原本的dtls-srtp.pem,wss.pem文件备份,或者干脆直接删除,影响不大(删除了,fs会自动创建,但是,最好还是备份比较安全)
[root@fs3 certs]# cat svr4k.crt svr4k.key >wss.pem
这里,指令中,将svr4k.crt写在wss.pem的文件头还是svr4k.key写在文件头,都无所谓的。
接下来,看看,wss.pem的内容:
[root@fs3 certs]# vi wss.pem Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=Hubei, L=Wuhan, O=Shihuc, OU=IOV, CN=IOVGFS Validity Not Before: Oct 4 17:45:42 2020 GMT Not After : Oct 2 17:45:42 2030 GMT Subject: C=CN, ST=Hubei, O=Shihuc, OU=IOV, CN=192.168.219.138 Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (4096 bit) Modulus: 00:cd:b6:89:99:37:80:04:f4:c3:fc:72:33:94:55: 59:3c:c1:8d:f9:ed:57:7c:16:05:09:8c:ed:b3:54: 8e:d8:c9:2f:7a:6e:88:42:44:52:d1:a0:bc:88:35: 03:d9:7b:b6:06:dc:86:14:60:f2:ca:7d:da:d2:05: 86:09:46:94:9b:0c:e7:7b:ac:85:a0:7d:73:6c:f5: 37:89:17:e2:d5:57:0f:d7:48:df:10:80:18:ef:16: 1e:08:b8:c8:45:3d:11:13:a5:7f:a6:3e:d1:ac:da: 42:a8:55:bb:b9:d0:62:f8:5b:fd:82:2c:92:48:47: 4c:16:e6:84:36:e1:de:cb:dd:3a:1f:c9:cf:7c:f4: 2d:43:c5:6d:15:06:d5:f4:60:af:c6:bf:8c:91:4e: ac:90:a8:32:97:1c:ac:a3:ea:a0:9b:66:06:14:a5: 28:c9:14:3a:e7:a8:d0:43:28:59:27:e5:d5:e5:a0: f9:9c:91:bb:6b:be:ff:38:00:db:1e:2b:21:ce:21: 50:56:17:ee:50:9f:fd:02:2c:e7:3e:4c:f8:b8:b3: e0:cf:39:87:cb:bc:a7:71:51:67:e3:96:d4:3d:42: d5:4c:db:95:53:36:48:c1:2b:ab:90:63:c6:e0:86: 7e:a4:64:b8:80:2a:92:23:22:fa:b7:4b:8a:a6:31: 16:ba:25:8f:db:86:f6:e0:7a:b9:7c:68:1b:82:d5: cc:94:35:14:31:32:40:bb:36:c9:55:15:57:d6:39: 18:16:7b:44:f4:be:0b:1d:36:99:a9:09:6e:13:3e: e5:3e:3b:ca:5b:aa:8d:66:0c:e5:f3:6e:2f:cc:85: b0:02:d6:6a:b1:77:73:24:ea:4f:69:cf:6f:6e:92: ad:4d:89:bf:32:2d:04:77:f2:e2:be:62:d9:96:56: b0:85:8b:31:42:d1:44:45:e5:1b:3a:26:34:46:38: 74:4d:6a:b7:ff:38:7a:32:07:31:41:da:c9:bd:1d: ac:f1:a4:19:83:a3:7a:91:0a:8e:b9:1d:50:57:f7: 24:5c:01:78:5a:63:2b:ff:f1:5d:f0:47:0e:46:af: db:0b:b1:fa:fd:f4:ae:01:40:9d:af:a4:77:92:f4: a6:94:81:45:cc:0a:b2:b1:8b:3f:38:51:71:d8:0d: 1f:98:cf:43:8c:0a:2a:51:43:a8:5c:96:cd:2b:7e: 12:3c:bd:0d:8a:67:4b:09:57:cf:ba:3d:b1:56:63: 3b:fb:15:2e:9b:aa:c0:78:b8:03:30:fc:78:4b:7f: cf:62:47:5a:d1:93:3b:db:a8:fb:cd:0a:09:6d:57: ea:af:2e:df:c1:2e:ac:84:87:57:ce:fe:85:23:bb: b1:ea:8b Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 06:91:5E:32:0E:CA:5A:EE:16:85:3A:4C:F0:EA:03:FE:4B:8C:7F:78 X509v3 Authority Key Identifier: keyid:0C:13:6E:0D:C5:CC:3D:56:B5:A6:4B:31:1F:A6:D9:8D:C9:EA:3B:86 Signature Algorithm: sha256WithRSAEncryption 8b:4b:ea:1a:64:b3:69:14:05:8c:fd:c6:33:31:01:19:da:92: 10:15:55:c7:66:92:fd:53:91:e1:7e:5c:34:e3:15:52:b1:0d: d7:de:d1:a0:a3:46:4c:ba:fb:8b:e7:bf:2f:0e:13:75:dc:0f: 95:a3:0f:4f:03:2f:65:fa:2f:9f:e9:33:fc:3e:51:c8:a0:6c: 56:9e:c3:f1:ed:c8:a1:88:b8:14:b9:8d:16:1d:7a:2d:f4:0f: 7d:5d:06:2d:77:2b:ec:f3:e1:39:25:f9:ee:6e:fa:e0:28:4c: 9e:7a:fb:9f:3b:b8:c0:5c:45:23:6c:af:8f:28:61:e2:b8:4e: c9:e1:fd:59:42:dc:bd:2e:83:74:ca:19:56:c5:0a:e4:08:ea: 09:0d:43:73:8a:11:81:fc:30:80:73:e1:31:f6:8e:ed:a4:58: 1b:03:25:2e:04:0f:d5:8f:93:8e:f8:82:56:8b:4c:df:86:54: 65:74:84:0d:e7:c3:5e:0a:e9:53:ec:ad:f6:6b:8e:0b:4a:62: bc:89:75:fd:31:a4:76:e0:48:d1:48:ea:d4:05:26:25:c1:ee: 65:71:06:12:a4:58:1b:bf:52:a4:14:b0:1d:6e:21:28:1e:47: bb:9b:e6:01:50:33:4e:ed:a2:dd:65:68:00:66:be:48:c7:25: e0:31:ed:1a:7b:72:90:b1:42:ca:b5:4c:70:cd:0d:82:07:26: a9:22:70:22:65:57:11:fd:cc:02:48:ce:2d:30:72:33:9e:2d: 14:af:c5:72:01:7e:84:f4:08:fe:84:e5:de:84:82:41:ca:e7: 99:8a:d5:5e:cb:95:42:2a:7a:5c:20:bb:f4:f8:78:7c:cd:f0: 4e:10:3a:0d:8b:0c:f3:23:82:d7:ad:d1:5c:76:85:15:1a:f5: bc:8c:9c:5c:53:f8:c7:2e:c8:8b:90:17:a6:7a:d5:93:5b:42: ec:5a:5d:f5:72:2e:82:63:19:3d:36:8c:58:64:0b:1d:84:b8: 25:6d:f1:fc:e6:d0:4a:32:fb:54:50:83:77:a6:70:07:22:4b: 59:0c:9b:a4:c4:42:81:1e:43:79:12:11:46:bf:00:dc:99:d7: 7a:53:a2:26:3b:58:0f:d9:5f:da:f4:11:23:2d:e1:9b:11:d0: 8a:94:68:42:ba:69:3a:0d:f7:8a:92:a1:3f:35:6d:a3:5a:6e: 5b:29:94:4b:d7:d5:45:37:91:29:16:85:94:9f:9a:88:2b:f6: d4:14:76:15:3e:80:0f:3f:ee:ac:27:7d:7f:61:3d:20:77:8b: 95:93:5d:02:c4:a8:94:2c:5e:64:b6:34:cd:1a:14:80:c0:27: 93:5b:df:44:71:08:92:a6 -----BEGIN CERTIFICATE----- MIIFqzCCA5OgAwIBAgIBATANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJDTjEO MAwGA1UECAwFSHViZWkxDjAMBgNVBAcMBVd1aGFuMRAwDgYDVQQKDAdUYWlrYW5n MQwwCgYDVQQLDANJT1YxDzANBgNVBAMMBklPVkdGUzAeFw0yMDEwMDQxNzQ1NDJa Fw0zMDEwMDIxNzQ1NDJaMFcxCzAJBgNVBAYTAkNOMQ4wDAYDVQQIDAVIdWJlaTEQ MA4GA1UECgwHVGFpa2FuZzEMMAoGA1UECwwDSU9WMRgwFgYDVQQDDA8xOTIuMTY4 LjIxOS4xMzgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNtomZN4AE 9MP8cjOUVVk8wY357Vd8FgUJjO2zVI7YyS96bohCRFLRoLyINQPZe7YG3IYUYPLK fdrSBYYJRpSbDOd7rIWgfXNs9TeJF+LVVw/XSN8QgBjvFh4IuMhFPRETpX+mPtGs 2kKoVbu50GL4W/2CLJJIR0wW5oQ24d7L3Tofyc989C1DxW0VBtX0YK/Gv4yRTqyQ qDKXHKyj6qCbZgYUpSjJFDrnqNBDKFkn5dXloPmckbtrvv84ANseKyHOIVBWF+5Q n/0CLOc+TPi4s+DPOYfLvKdxUWfjltQ9QtVM25VTNkjBK6uQY8bghn6kZLiAKpIj Ivq3S4qmMRa6JY/bhvbgerl8aBuC1cyUNRQxMkC7NslVFVfWORgWe0T0vgsdNpmp CW4TPuU+O8pbqo1mDOXzbi/MhbAC1mqxd3Mk6k9pz29ukq1Nib8yLQR38uK+YtmW VrCFizFC0URF5Rs6JjRGOHRNarf/OHoyBzFB2sm9HazxpBmDo3qRCo65HVBX9yRc AXhaYyv/8V3wRw5Gr9sLsfr99K4BQJ2vpHeS9KaUgUXMCrKxiz84UXHYDR+Yz0OM CipRQ6hcls0rfhI8vQ2KZ0sJV8+6PbFWYzv7FS6bqsB4uAMw/HhLf89iR1rRkzvb qPvNCgltV+qvLt/BLqyEh1fO/oUju7HqiwIDAQABo3sweTAJBgNVHRMEAjAAMCwG CWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV HQ4EFgQUBpFeMg7KWu4WhTpM8OoD/kuMf3gwHwYDVR0jBBgwFoAUDBNuDcXMPVa1 pksxH6bZjcnqO4YwDQYJKoZIhvcNAQELBQADggIBAItL6hpks2kUBYz9xjMxARna khAVVcdmkv1TkeF+XDTjFVKxDdfe0aCjRky6+4vnvy8OE3XcD5WjD08DL2X6L5/p M/w+UcigbFaew/HtyKGIuBS5jRYdei30D31dBi13K+zz4Tkl+e5u+uAoTJ56+587 uMBcRSNsr48oYeK4Tsnh/VlC3L0ug3TKGVbFCuQI6gkNQ3OKEYH8MIBz4TH2ju2k WBsDJS4ED9WPk474glaLTN+GVGV0hA3nw14K6VPsrfZrjgtKYryJdf0xpHbgSNFI 6tQFJiXB7mVxBhKkWBu/UqQUsB1uISgeR7ub5gFQM07tot1laABmvkjHJeAx7Rp7 cpCxQsq1THDNDYIHJqkicCJlVxH9zAJIzi0wcjOeLRSvxXIBfoT0CP6E5d6EgkHK 55mK1V7LlUIqelwgu/T4eHzN8E4QOg2LDPMjgtet0Vx2hRUa9byMnFxT+McuyIuQ F6Z61ZNbQuxaXfVyLoJjGT02jFhkCx2EuCVt8fzm0Eoy+1RQg3emcAciS1kMm6TE QoEeQ3kSEUa/ANyZ13pToiY7WA/ZX9r0ESMt4ZsR0IqUaEK6aToN94qSoT81baNa blsplEvX1UU3kSkWhZSfmogr9tQUdhU+gA8/7qwnfX9hPSB3i5WTXQLEqJQsXmS2 NM0aFIDAJ5Nb30RxCJKm -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- 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 -----END RSA PRIVATE KEY-----
从wss.pem证书内容中可以看出下面几条和默认freeswitch的wss.pem不同点:
1. 自签名生成的wss.pem私钥是pkcs#1格式,而freeswitch默认的wss.pem私钥格式为pkcs#8
2. 自签名生成的wss.pem证书内容含有extension部分,典型的,X509v3 Subject Key Identifier, X509v3 Authority Key Identifier等信息,在freeswitch默认的wss.pem里面是没有的。
3. 配置nginx的SSL
因为我这里nginx和freeswitch在一台机器上,所以,将svr4k.crt以及svr4k.key还有根证书ca4k.crt拷贝到nginx的根证书所在的路径(我这里,/usr/local/openresty/nginx/certs/).
[root@fs3 certs]# pwd /usr/local/openresty/nginx/certs [root@fs3 certs]# ll total 48 -rw-r--r--. 1 root root 2009 Oct 5 01:47 ca4k.crt -rw-------. 1 root root 3243 Oct 5 01:47 ca4k.key -rw-r--r--. 1 root root 1188 Oct 1 15:27 ca.crt -rw-------. 1 root root 1675 Oct 5 01:02 root.key -rw-r--r--. 1 root root 1216 Oct 1 15:27 server.crt -rw-------. 1 root root 1675 Oct 1 15:27 server.key -rw-r--r--. 1 root root 7168 Oct 5 01:48 svr4k.crt -rw-------. 1 root root 3243 Oct 5 01:48 svr4k.key -rw-r--r--. 1 root root 4657 Oct 5 01:01 svr.crt -rw-------. 1 root root 1675 Oct 5 01:01 svr.key 下面看看nginx.conf的SSL的重点部分配置信息: server { listen 443 ssl; server_name localhost; ssl_certificate /usr/local/openresty/nginx/certs/svr4k.crt; ssl_certificate_key /usr/local/openresty/nginx/certs/svr4k.key; ssl_client_certificate /usr/local/openresty/nginx/certs/ca4k.crt; #为了双向验证用,需要ca信息。 location /sip { try_files $uri $uri/ html/sipjss/index.html; alias html/sipjss/; index index.html index.htm; } location /jssip { try_files $uri $uri/ html/ml5/call.htm; alias html/ml5/; index call.htm call.html; } }
这里配置了SSL的证书及相关文件,以及基于sip.js+webrtc的html相关的静态文件所在路径。
这里,需要注意的是,freeswitch的wss.pem的内容,和nginx的证书内容,是一样的,这个非常重要(至少要保证:两个地方证书的根证书是一样的),wss.pem的内容由svr4k.crt和svr4k.key构成,由ca4k.crt签署。这里,只要有一个地方没有匹配上,wss就不会连接成功,例如,nginx的证书文件是用另外一个根证书签发的,或者freeswitch的wss.pem的内容,不是由和nginx的同一个根证书签发的,也不会实现wss连接的成功。
4. freeswitch的wss.pem证书的相关问题
4.1 经过研究,wss.pem的证书位数,不一定必须要是4096位。我经过研究,采用2048位的rsa加密算法生成的证书,按照上面说到的操作步骤,一样能够实现freeswitch在webrtc的sip通话。
4.2 上面的说明过程,证书私钥是openssl生成的默认格式pkcs#1,而freeswitch默认的证书私钥格式是pkcs#8,经过测试验证,pkcs#1的私钥,及对应的证书文件,在freeswitch下,同样是支持的。
4.3 这里前面说到的操作,都是针对nginx和freeswitch在一台机器上的配置和验证,若nginx和freeswitch不在同一台机器上,会怎么样呢?其实也是一样简单的,只要保证nginx的SSL证书和freeswitch的wss.pem对应的证书是由同一个根证书签发得到,即可实现正常通信。我在本地虚拟机192.168.219.135上安装nginx,用ca4k.crt和ca4k.key签发了svr135.crt/svr135.key,经过验证,freeswitch支持WebRTC+sip.js的通话是没有问题的。看下面的附图。
从这个图可以看出, wss连接对应的地址是192.168.219.138:7443,但是web页面对应的地址是https://192.168.219.135/sip.
后面将继续研究WebRTC应用,感兴趣的博友,可以加关注,一起探讨。比如,freeswitch的集群环境建设,这个就是一个比较有挑战的课题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架