赞
踩
由于https://appr.tc已经不维护了,导致研究webrtc源代码变得不太方便。同时webrtc编译出来的AppRTCMobile也无法正常和浏览器进行一对一的实时通信,本人花了好长一些时间来解决这些问题,通过解决这些问题特写下这个文章,一方面起到记录使用,另一方面也可以作为他人参考使用,本文在Ubuntu 20.04.6 LTS上部署apprtc,使得两个chrome浏览器可以进行通信,也可以在webrtc for android的AppRTCMobile.apk和chrome浏览器进行通信。
本文只考虑在一台机器中本地部署AppRTC服务器及turn服务的情况,如果需要在公网或者正式商用场景部署,需要考虑https和wss安全链接及其证书的申请和配置等。
图1: 本文搭建后的整体架构
本文假定同学已经具备了以下条件,如果不具备科学上网的条件,可以下载本人上传到网盘的所有资料,完成本文目标(两个chrome浏览器可以进行通信,也可以在webrtc for android的AppRTCMobile.apk和chrome浏览器进行通信)
- mkdir ~/Desktop/webrtc
- # 也可以采用其他版本的nodejs,本文使用v10.16.0
- wget https://nodejs.org/dist/v10.16.0/node-v10.16.0-linux-x64.tar.xz
- # 解压
- tar -xvf node-v10.16.0-linux-x64.tar.xz
- # 进入目录
- cd node-v10.16.0-linux-x64/
- # 查看当前的目录
- pwd
-
- # 确认一下nodejs下bin目录是否有node 和npm文件,如果有就可以执行软连接,比如
- sudo ln -sf /home/louis/Desktop/webrtc/node-v10.16.0-linux-x64/bin/npm /usr/local/bin/
- sudo ln -sf /home/louis/Desktop/webrtc/node-v10.16.0-linux-x64/bin/node /usr/local/bin/
-
- # /home/louis/Desktop/webrtc这个路径你自己创建的路径
-
- # 查看是否安装,安装正常则打印版本号
- node -v
- npm -v
-
- # 有版本信息后安装 grunt-cli,先进到nodejs的bin目录, 要和自己的目录匹配
- cd /home/louis/Desktop/webrtc/node-v10.16.0-linux-x64/bin
- sudo npm install grunt-cli
- sudo ln -sf /home/louis/Desktop/webrtc/node-v10.16.0-linux-x64/bin/grunt /usr/local/bin/
-
- grunt --version
- # 显示grunt-cli v1.4.3

- cd ~/Desktop/webrtc/ # 进到webrtc目录
- wget https://storage.googleapis.com/appengine-sdks/featured/google_appengine_1.9.40.zip # 下载google_appengine
- unzip google_appengine_1.9.40.zip #解压
- export PATH=$PATH:/home/Desktop/webrtc/google_appengine #配置环境变量:在/etc/profile文件最后增加一行,和自己路径保持一致
- source /etc/profile
- cd ~/Desktop/webrtc/ # 进到webrtc目录
- wget http://www.golangtc.com/static/go/1.7/go1.7.linux-amd64.tar.gz
- #创建go工作目录
- mkdir -p ~/Desktop/webrtc/goworkspace/src
- #配置环境变量:在/etc/profile文件最后增加一行:
- sudo vim /etc/profile
-
- export GOPATH=/home/louis/Desktop/webrtc/goworkspace
- source /etc/profile
- cd ~/Desktop/webrtc/
- git clone https://github.com/webrtc/apprtc.git
- # 如果github的连接下不了就用gitee的链接
- # git clone https://gitee.com/sabergithub/apprtc.git
- #将collider的源码软连接到go的工作目录下
- ln -sf /home/louis/Desktop/webrtc/apprtc/src/collider/collider $GOPATH/src
- ln -sf /home/louis/Desktop/webrtc/apprtc/src/collider/collidermain $GOPATH/src
- ln -sf /home/louis/Desktop/webrtc/apprtc/src/collider/collidertest $GOPATH/src
-
- #下一步在编译 go get collidermain
- #报错: package golang.org/x/net/websocket: unrecognized import path "golang.org/x/net/websocket"
- #所以先执行:
- mkdir -p $GOPATH/src/golang.org/x/
- cd $GOPATH/src/golang.org/x/
- git clone https://github.com/golang/net.git net
- cd $GOPATH/src/golang.org/x/net
- git checkout v0.16.0 # 切换到老一点的tag v0.16.0,不然编译不过
- go install net
-
- #编译collidermain
- cd ~/Desktop/webrtc/goworkspace/src
- go get collidermain
- go install collidermain

- cd ~/Desktop/webrtc/
-
- sudo apt-get install libssl-dev
- sudo apt-get install libevent-dev
-
- wget http://coturn.net/turnserver/v4.5.0.7/turnserver-4.5.0.7.tar.gz #可以使用其他版本
- tar xfz turnserver-4.5.0.7.tar.gz
- cd turnserver-4.5.0.7
-
- ./configure
- make
- sudo make install
- sudo apt-get install build-essential zlib1g-dev libpcre3 libpcre3-dev openssl
-
- cd ~/Desktop/webrtc/
- #下载nginx 本文以1.15.8版本为例
- wget http://nginx.org/download/nginx-1.15.8.tar.gz
- tar xvzf nginx-1.15.8.tar.gz
- cd nginx-1.15.8/
-
- # 要支持https请添加--with-http_ssl_module参数
- ./configure --with-http_ssl_module
- # 编译
- make
- #安装
- sudo make install
- sudo ufw allow 3478/tcp
- sudo ufw allow 3478/udp
- sudo ufw allow 8080/tcp
- sudo ufw allow 8080/udp
- sudo ufw allow 8089/tcp
- sudo ufw allow 8089/udp
- sudo ufw allow 3033/tcp
- sudo ufw allow 3033/udp
以下通过git diff的方式说明本人修改了那些部分以便支持本文目标。
- diff --git a/src/app_engine/apprtc.py b/src/app_engine/apprtc.py
- index 933bd7c..54126e3 100755
- --- a/src/app_engine/apprtc.py
- +++ b/src/app_engine/apprtc.py
- @@ -149,8 +149,8 @@ def get_wss_parameters(request):
- wss_url = 'ws://' + wss_host_port_pair + '/ws'
- wss_post_url = 'http://' + wss_host_port_pair
- else:
- - wss_url = 'wss://' + wss_host_port_pair + '/ws'
- - wss_post_url = 'https://' + wss_host_port_pair
- + wss_url = 'ws://' + wss_host_port_pair + '/ws'
- + wss_post_url = 'http://' + wss_host_port_pair
- return (wss_url, wss_post_url)
-
- def get_version_info():
- diff --git a/src/app_engine/constants.py b/src/app_engine/constants.py
- index 682331b..9e44c4b 100644
- --- a/src/app_engine/constants.py
- +++ b/src/app_engine/constants.py
- @@ -37,23 +37,42 @@ ICE_SERVER_OVERRIDE = None
- # ]
- # }
- # ]
- -ICE_SERVER_BASE_URL = 'https://appr.tc'
- +#ICE_SERVER_BASE_URL = 'https://appr.tc'
- +ICE_SERVER_BASE_URL = 'http://192.168.0.104:3033'
- ICE_SERVER_URL_TEMPLATE = '%s/v1alpha/iceconfig?key=%s'
- ICE_SERVER_API_KEY = os.environ.get('ICE_SERVER_API_KEY')
- HEADER_MESSAGE = os.environ.get('HEADER_MESSAGE')
- ICE_SERVER_URLS = [url for url in os.environ.get('ICE_SERVER_URLS', '').split(',') if url]
-
- # Dictionary keys in the collider instance info constant.
- -WSS_INSTANCE_HOST_KEY = 'host_port_pair'
- +#WSS_INSTANCE_HOST_KEY = 'host_port_pair'
- +WSS_INSTANCE_HOST_KEY = '192.168.0.104:8089'#根据自身的ip和端口来决定
- WSS_INSTANCE_NAME_KEY = 'vm_name'
- WSS_INSTANCE_ZONE_KEY = 'zone'
- WSS_INSTANCES = [{
- - WSS_INSTANCE_HOST_KEY: 'apprtc-ws.webrtc.org:443',
- + WSS_INSTANCE_HOST_KEY: '192.168.0.104:8089',
- WSS_INSTANCE_NAME_KEY: 'wsserver-std',
- WSS_INSTANCE_ZONE_KEY: 'us-central1-a'
- }, {
- - WSS_INSTANCE_HOST_KEY: 'apprtc-ws-2.webrtc.org:443',
- + WSS_INSTANCE_HOST_KEY: '192.168.0.104:8089',
- WSS_INSTANCE_NAME_KEY: 'wsserver-std-2',
- WSS_INSTANCE_ZONE_KEY: 'us-central1-f'
- }]
- diff --git a/src/web_app/html/index_template.html b/src/web_app/html/index_template.html
- index ade4c22..d032f20 100644
- --- a/src/web_app/html/index_template.html
- +++ b/src/web_app/html/index_template.html
- @@ -137,6 +137,15 @@
- <script src="/js/storage.js"></script>
-
- <script type="text/javascript">
- + var servers=[{
- + credential:"louis",
- + username:"louis",
- + urls:[
- + "turn:192.168.0.104:3478?transport=udp",
- + "turn:192.168.0.104:3478?transport=tcp"
- + ]
- + }];
- +
- var loadingParams = {
- errorMessages: {{ error_messages }},
- isLoopback: {{ is_loopback }},
- @@ -147,7 +156,8 @@
- {% endif %}
- mediaConstraints: {{ media_constraints | safe }},
- offerOptions: {{ offer_options | safe }},
- - peerConnectionConfig: {{ pc_config | safe }},
- + //peerConnectionConfig: {{ pc_config | safe }},
- + peerConnectionConfig: { "rtcpMuxPolicy":"require","iceServers":servers,"bundlePolicy":"max-bundle"},
- peerConnectionConstraints: {{ pc_constraints | safe }},
- iceServerRequestUrl: '{{ ice_server_url }}',
- iceServerTransports: '{{ ice_server_transports }}',
- diff --git a/src/web_app/js/appcontroller.js b/src/web_app/js/appcontroller.js
- index 16a75d5..b01321e 100644
- --- a/src/web_app/js/appcontroller.js
- +++ b/src/web_app/js/appcontroller.js
- @@ -429,11 +429,12 @@ AppController.prototype.onKeyPress_ = function(event) {
- };
-
- AppController.prototype.pushCallNavigation_ = function(roomId, roomLink) {
- - window.history.pushState({'roomId': roomId, 'roomLink': roomLink}, roomId,
- - roomLink);
- + // window.history.pushState({'roomId': roomId, 'roomLink': roomLink}, roomId,
- + // roomLink);//编译报错
- };
-
- AppController.prototype.displaySharingInfo_ = function(roomId, roomLink) {
- + roomLink=roomLink.replace("http","https"); //浏览器通话跨域问题 :pushState Messages:Failed to start signaling: Failed to execute ‘pushState’ on ‘History’
- this.roomLinkHref_.href = roomLink;
- this.roomLinkHref_.text = roomLink;
- this.roomLink_ = roomLink;

以上修改需要重新在apprtc目录下编译
- cd ~/Desktop/webrtc/apprtc
- sudo grunt build
- sudo mkdir -p /cert
- cd /cert
- # CA私钥
- openssl genrsa -out key.pem 2048
- # 自签名证书
- openssl req -new -x509 -key key.pem -out cert.pem -days 9999
配置文件/usr/local/nginx/conf/conf.d/apprtc-websocket-proxy.conf
- upstream roomserver {
- server 192.168.0.104:8080;
- }
- server {
- listen 443 ssl;
- ssl_certificate /cert/cert.pem;
- ssl_certificate_key /cert/key.pem;
- charset utf-8;
- # ip地址或者域名
- server_name 192.168.0.104;
- location / {
- # 转向代理的地址
- proxy_pass http://roomserver$request_uri;
- proxy_set_header Host $host;
- }
- }

编辑nginx.conf文件,在末尾}之前添加包含文件
include /usr/local/nginx/conf/conf.d/*.conf;
}
完整配置文件:/usr/local/nginx/conf/conf.d/apprtc-websocket-proxy.conf
- map $http_upgrade $connection_upgrade {
- default upgrade;
- '' close;
- }
- upstream websocket {
- server 192.168.0.104:8089;
- }
-
- server {
- listen 8088 ssl;
- ssl_certificate /cert/cert.pem;
- ssl_certificate_key /cert/key.pem;
-
- server_name 192.168.0.104;
- location /ws {
- proxy_pass http://websocket;
- proxy_http_version 1.1;
- proxy_connect_timeout 4s; #配置点1
- proxy_read_timeout 6000s; #配置点2,可以考虑这个时间配置长一点
- proxy_send_timeout 6000s; #配置点3
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection $connection_upgrade;
- }
- }

为能支持webrtc for android的AppRTCMobile.apk能正常和浏览器连接,需要增加一个http的turn访问服务器,通过nodejs启动它,本人将其命名为ice.js,在此之前,需要nodejs安装一下
sudo npm install express
完整的turn web服务代码如下,监听3033端口,将客户端的turn url请求返回正常的turn服务器信息
- var express = require('express')
- var crypto = require('crypto')
- var app = express()
-
- var hmac = function (key, content) {
- var method = crypto.createHmac('sha1', key)
- method.setEncoding('base64')
- method.write(content)
- method.end()
- return method.read()
- }
-
- function handleIceRequest(req, resp) {
- console.log('handleIceRequest louis louis')
- var query = req.query
- var key = '4080218913'
- var time_to_live = 600
- var timestamp = Math.floor(Date.now() / 1000) + time_to_live
- var turn_username = timestamp + ':ninefingers'
- var password = hmac(key, turn_username)
-
- console.log('handleIceRequest req' + req)
-
- return resp.send({
- iceServers: [
- {
- urls: [
- 'stun:192.168.0.104:3478',//根据自身的ip修改
- 'turn:192.168.0.104:3478'//根据自身的ip修改
- ],
- username: turn_username,
- credential: password
- }
- ]
- })
- }
-
- app.get('/v1alpha/iceconfig', handleIceRequest)
- app.post('/v1alpha/iceconfig', handleIceRequest)
-
- app.listen('3033', function () {
- console.log('server started')
- })

直接给出配置文件
- #本地监听的网卡设备,这里根据自己的实际情况填写
- listening-device=ens37 #网卡名
- listening-port=3478 #端口
- #本地用于转发的网卡设备,这里根据自己的实际情况填写
- relay-device=ens37
- #指定的转发端口的分配范围,测试时,可以将防火墙全部关闭,防止 UDP 端口被屏蔽
- min-port=3480
- max-port=3500
- #日志输出级别,turnserver 启动时加上 -v,可以得到更清晰的日志输出
- Verbose
- #消息验证,WebRTC 的消息里会用到
- fingerprint
- #webrtc 通过 turn 中继,必须使用长验证方式
- lt-cred-mech
- # ICE REST API 认证需要(如果打开了这行,turn就不工作了)
- use-auth-secret
- # REST API 加密所需的 KEY
- # 这里我们使用“静态”的 KEY,Google 自己也用的这个
- static-auth-secret=louis
- #用户登录域,下面的写法可以不改变它,因为再启动 turnserver 时,可以通过指定参数覆盖它
- realm=<填写你自己的服务器的IP>#这个特别关键,如果这里不是你的服务器的IP,数据就不通
- #可为 TURN 服务提供更安全的访问(这个我没用,不知道干啥的)
- #stale-nonce
- #在Coturn代码中的/etc/examples/目录下有秘钥文件,可以直接用
- #cert=/home/louis/Desktop/webrtc/turnserver-4.5.0.7/examples/etc/turn_server_cert.pem
- #pkey=/home/louis/Desktop/webrtc/turnserver-4.5.0.7/examples/etc/turn_server_pkey.pem
- cert=/cert/cert.pem
- pkey=/cert/key.pem
- #屏蔽 loopback, multicast IP地址的 relay
- no-loopback-peers
- no-multicast-peers
- #启用 Mobility ICE 支持(不懂)
- mobility
- #禁用本地 telnet cli 管理接口
- no-cli

为了方便启动,本人做了一个shell脚本 start.sh,可以用来启动所有的服务,脚本内容如下:
- #/usr/bin/bash
-
- sudo kill -9 `ps -elf| grep turnserver | awk '{print$4}'`
- sudo kill -9 `ps -elf| grep collidermain | awk '{print$4}'`
- sudo kill -9 `ps -elf| grep dev_appserver.py | awk '{print$4}'`
- sudo kill -9 `ps -elf| grep ice.js | awk '{print$4}'`
-
- cd /home/louis/Desktop/webrtc/apprtc
- sudo grunt build
- cd -
-
- sleep 1
-
- sudo turnserver -L 0.0.0.0 -z -S -u louis:louis -v -f -r 192.168.0.104 -c /home/louis/Desktop/webrtc/turnserver.conf 2>&1 > turnserver.log &
-
- sleep 1
-
- sudo node /home/louis/Desktop/webrtc/apprtc/ice.js &
- sleep 1
- sudo /home/louis/Desktop/webrtc/goworkspace/bin/collidermain -port=8089 -tls=false -room-server="http://192.168.0.104:8080" 2>&1 > signal.log &
- #sudo /home/louis/Desktop/webrtc/goworkspace/bin/collidermain -port=8089 -tls=false -room-server="http://192.168.0.104:8080" &
-
- sleep 1
- #sudo /home/louis/Desktop/webrtc/google_appengine/dev_appserver.py --host=0.0.0.0 /home/louis/Desktop/webrtc/apprtc/out/app_engine --skip_sdk_update_check &
- sudo /home/louis/Desktop/webrtc/google_appengine/dev_appserver.py --host=0.0.0.0 /home/louis/Desktop/webrtc/apprtc/out/app_engine --skip_sdk_update_check 2>&1 > roomserver.log &
-
- sleep 1
- sudo /usr/local/nginx/sbin/nginx -s stop
- sudo /usr/local/nginx/sbin/nginx
-
- sleep 1
- ps -elf | grep -E "turn|dev_app|nginx|http|collidermain|ice.js"
-

此次所有的安装和配置工作都已经完成了,接下来将在“Webrtc系列四——Ubuntu 20.04上Apprtc服务搭建之二”中测试所有的链路和给出本人的所有代码。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。