实战rfc5766-turn-server和ice4j广域网通讯-码农场

标签: | 发表时间:2019-05-14 17:43 | 作者:
出处:http://www.hankcs.com

前段时间上手了NAT打洞类库ice4j(ICE框架),当时使用了numb.viagenie.ca的公共STUN服务器。最近又编译了rfc5766-turn-server,于是今天将两者结合起来,一个作为服务端,一个作为Peer端的协议,试验广域网穿透多级路由即时点对点通讯,并取得了成功。

服务端

编译安装

rfc5766-turn-server是谷歌推荐的turn开源项目,经常作WebRTC的服务器端使用。关于rfc5766-turn-server在Windows或Ubuntu(Linux)下的编译,请参考  http://www.hankcs.com/program/network/compile-rfc5766-turn-server-to-build-turn-server.html 。这里假定你已经编译完成,输入

$ turnserver -h

得到如下结果说明编译成功:

配置

rfc5766-turn-server是利用配置文件来定义自己的功能表现的,安装完成后,在下列路径都有默认的配置文件:

/usr/local/etc/turnserver.conf.default
rfc5766-turn-server检出目录/examples/etc/turnserver.conf

随便cp一个出来就能用,如果你实在找不到,可以从我这里下载一个 turnserver-conf.zip

配置项很多,但是初级用户用得上的只有两个。

配置外网IP

在配置文件中加入一句

external-ip=180.160.188.246

后面的IP是你的服务器的外网IP,比如:

我的试验条件比较简陋,没有自己的服务器,而是把自己的PC当作了服务器使用。又由于自己的PC是位于局域网中,没有自己的外网IP,所以需要在路由器上做一个端口映射:

其中,192.168.1.103是服务器的内网IP,3478是turnserver服务占用的端口。

配置用户名和密码

在产品级的场景中,rfc5766-turn-server支持数据库和动态增删用户。而在我的这种实验中,我选择静态定义两个用户,在配置文件中加入:

user=u1:p1
user=u2:p2

这代表两个用户,遵从 用户名:密码 的格式。

启动rfc5766-turn-server

sudo turnserver -c /你的路径/turnserver.conf

此时会输出:

0: log file opened: /var/log/turn_2409_2014-11-10.log
0: 
RFC 3489/5389/5766/5780/6062/6156 STUN/TURN Server
Version Citrix-3.2.4.6 'Marshal West'
0: 
Max number of open files/sockets allowed for this process: 4096
0: 
Due to the open files/sockets limitation,
max supported number of TURN Sessions possible is: 2000 (approximately)
0: 

==== Show him the instruments, Practical Frost: ====

0: TLS supported
0: DTLS supported
0: Redis supported
0: PostgreSQL supported
0: MySQL supported
0: OpenSSL compile-time version 0x1000106f: fresh enough
0: Default Net Engine version: 3 (UDP thread per CPU core)

=====================================================

0: WARNING: Cannot find userdb file: turnuserdb.conf: going without flat file user database.
0: WARNING: cannot find certificate file: turn_server_cert.pem (1)
0: WARNING: cannot start TLS and DTLS listeners because certificate file is not set properly
0: WARNING: cannot find private key file: turn_server_pkey.pem (1)
0: WARNING: cannot start TLS and DTLS listeners because private key file is not set properly
0: NO EXPLICIT LISTENER ADDRESS(ES) ARE CONFIGURED
0: ===========Discovering listener addresses: =========
0: Listener address to use: 127.0.0.1
0: Listener address to use: 192.168.1.103
0: Listener address to use: ::1
0: =====================================================
0: Total: 1 'real' addresses discovered
0: =====================================================
0: NO EXPLICIT RELAY ADDRESS(ES) ARE CONFIGURED
0: ===========Discovering relay addresses: =============
0: Relay address to use: 192.168.1.103
0: Relay address to use: ::1
0: =====================================================
0: Total: 2 relay addresses discovered
0: =====================================================
0: pid file created: /var/run/turnserver.pid
0: IO method (main listener thread): epoll (with changelist)
0: WARNING: I cannot support STUN CHANGE_REQUEST functionality because only one IP address is provided
0: Wait for relay ports initialization...
0:   relay 192.168.1.103 initialization...
0:   relay 192.168.1.103 initialization done
0:   relay ::1 initialization...
0:   relay ::1 initialization done
0: Relay ports initialization done
0: IO method (general relay thread): epoll (with changelist)
0: turn server id=0 created
0: IPv4. TCP listener opened on : 127.0.0.1:3478
0: IPv4. TCP listener opened on : 192.168.1.103:3478
0: IPv6. TCP listener opened on : ::1:3478
0: IO method (general relay thread): epoll (with changelist)
0: turn server id=1 created
0: IPv4. TCP listener opened on : 127.0.0.1:3478
0: IPv4. TCP listener opened on : 192.168.1.103:3478
0: IPv6. TCP listener opened on : ::1:3478
0: IPv4. UDP listener opened on: 127.0.0.1:3478
0: IPv4. UDP listener opened on: 192.168.1.103:3478
0: IPv6. UDP listener opened on: ::1:3478
0: Total UDP servers: 0
0: Total General servers: 2
0: IO method (auth thread): epoll (with changelist)
0: IO method (cli thread): epoll (with changelist)
0: IPv4. CLI listener opened on : 127.0.0.1:5766

这样就成功启动了。

Peer端

检出代码

我已将全部代码开源到 https://github.com/hankcs/IceNAT ,需要读者添加ice4j的依赖项,并参考如下步骤进行试验。

修改配置项

Peer端的基础知识请参考我写的《 试验UDP打洞穿透NAT》,这次我不再使用别人的服务器,编辑IceClient,修改turnServers和stunServers的地址和密码为:

    private String[] turnServers = new String[]{"180.160.188.246:3478"};

    private String[] stunServers = new String[]{"180.160.188.246:3478"};

    private String username = "u1";

    private String password = "p1";

编译一份,备用,我称它为Peer1。Pee1运行于我宿舍的工作站上,外网IP和服务器相同(位于同一局域网),都是:

然后将用户名和密码修改为:

    private String username = "u2";

    private String password = "p2";

拷贝到另一台电脑上去作为Peer2,其中Peer2的外网IP为:

这是校园网的外网IP,全校上万台PC分布在层层路由和防火墙之下,我的另一台PC也是其中一台,我的目标就是穿透障碍,达到广域网通讯的目的。

开始试验

获取信令

Peer1和Peer2运行,分别通过rfc5766-turn-server获取到了自己的SDP信息(信令):

Peer1——

v=0
o=ice4j.org 0 0 IN IP4 180.160.188.246
s=-
t=0 0
a=ice-options:trickle
a=ice-ufrag:2mu8s196cnbrvi
a=ice-pwd:3rapigabe9fl3b1949nb1c9637
m=text 59229 RTP/AVP 0
c=IN 180.160.188.246 IP4
a=mid:text
a=candidate:1 1 udp 2130706431 192.168.1.100 8888 typ host
a=candidate:2 1 udp 2130706431 fe80:0:0:0:38f0:a64b:a7a6:e8b6 8888 typ host
a=candidate:4 1 udp 2113937151 fe80:0:0:0:2891:b74a:6050:22b3 8888 typ host
a=candidate:3 1 udp 2113932031 192.168.124.1 8888 typ host
a=candidate:5 1 udp 1677724415 180.160.188.246 11252 typ srflx raddr 192.168.1.100 rport 8888
a=candidate:6 1 udp 2815 180.160.188.246 59229 typ relay raddr 180.160.188.246 rport 11252

Peer2——

v=0
o=ice4j.org 0 0 IN IP4 180.160.188.246
s=-
t=0 0
a=ice-options:trickle
a=ice-ufrag:8q3b1196cnip55
a=ice-pwd:7ua73q9prlqn1jbal7143fprsd
m=text 52430 RTP/AVP 0
c=IN 180.160.188.246 IP4
a=mid:text
a=candidate:1 1 udp 2130706431 10.2.203.96 6666 typ host
a=candidate:2 1 udp 2130706431 fe80:0:0:0:448b:e2e1:7f4b:f0b8 6666 typ host
a=candidate:3 1 udp 1677724415 58.32.217.55 6666 typ srflx raddr 10.2.203.96 rport 6666
a=candidate:4 1 udp 2815 180.160.188.246 52430 typ relay raddr 58.32.217.55 rport 6666

同时可以在rfc5766-turn-server的终端看到输出:

7: handle_udp_packet: New UDP endpoint: local addr 192.168.1.103:3478, remote addr 180.160.188.246:10898
7: session 000000000000000001: user <>: incoming packet BINDING processed, success
7: session 000000000000000001: user <>: incoming packet message processed, error 401: Unauthorised
7: IPv4. Local relay addr: 192.168.1.103:54837
7: session 000000000000000001: new, username=<u1>, lifetime=600
7: session 000000000000000001: user <u1>: incoming packet ALLOCATE processed, success

交换信令

由于我还没有实现自己的信令服务器(SIP),所以通过类似电子邮件复制粘贴的方式交换了两者的信令。

交换后,两个Peer开始配对,配对过程的输出请参考‍ ‍交换信息配‍对,这里不再赘述。‍

聊天

之后两者就可以聊天了:

Peer1

/192.168.1.103:52430 says: hello, i am from hello
i get it,hi
/192.168.1.103:52430 says: 试试中文
没问题
/192.168.1.103:52430 says: 我在校园网,似乎不能走p2p,幸亏有turn服务器
对,你的ip是turn服务器的ip,也就是说我这条消息是从turn服务器那里获取的
/192.168.1.103:52430 says: 好吧,这样也算广域网通讯成功了
行,就这样,再见
/192.168.1.103:52430 says: bye

Peer2

hello, i am from hello
/192.168.1.100:8888 says: i get it,hi
试试中文
/192.168.1.100:8888 says: 没问题
我在校园网,似乎不能走p2p,幸亏有turn服务器
/192.168.1.100:8888 says: 对,你的ip是turn服务器的ip,也就是说我这条消息是从turn服务器那里获取的
好吧,这样也算广域网通讯成功了
/192.168.1.100:8888 says: 行,就这样,再见
bye

可以看到虽然两者处于不同的局域网,拥有不同的外网IP,但是由于Peer1(192.168.1.100)与服务器(192.168.1.103)处于同一局域网,所以Peer1一直在用局域网和rfc5766-turn-server通讯。

而Peer2与Peer1直连失败,通过turn服务器中转数据,所以在Peer1看来,Peer2的IP是192.168.1.103,与turn服务器一摸一样。

题外话,我是有多寂寞才能跟自己聊的那么开心的?

Reference

http://blog.wnotes.net/blog/article/stun-server-on-aws-ec2

https://code.google.com/p/rfc5766-turn-server/wiki/turnserver

知识共享许可协议  知识共享署名-非商业性使用-相同方式共享码农场» 实战rfc5766-turn-server和ice4j广域网通讯

相关 [rfc5766 turn server] 推荐:

实战rfc5766-turn-server和ice4j广域网通讯-码农场

- -
启动rfc5766-turn-server. 前段时间上手了NAT打洞类库ice4j(ICE框架),当时使用了numb.viagenie.ca的公共STUN服务器. 最近又编译了rfc5766-turn-server,于是今天将两者结合起来,一个作为服务端,一个作为Peer端的协议,试验广域网穿透多级路由即时点对点通讯,并取得了成功.

ICE协议下NAT穿越的实现(STUN&TURN) - 简书

- -
之前写了篇关于WebRTC的文章:. iOS下音视频通信-基于WebRTC. ,由于它是基于点对点连接的,自然而然需要NAT穿越的技术,否则消息将无法传递. 在WebRTC使用了ICE协议框架,里面提到了. TURN两个协议,而NAT穿越实现就是由这两个协议共同协调完成的. 原来这是因为IPV4引起的,我们上网很可能会处在一个NAT设备(无线路由器之类)之后.

SQL Server--索引

- - CSDN博客推荐文章
         1,概念:  数据库索引是对数据表中一个或多个列的值进行排序的结构,就像一本书的目录一样,索引提供了在行中快速查询特定行的能力..             2.1优点:  1,大大加快搜索数据的速度,这是引入索引的主要原因..                             2,创建唯一性索引,保证数据库表中每一行数据的唯一性..

SQL Server 面试

- - SQL - 编程语言 - ITeye博客
在SQL语言中,一个SELECT…FROM…WHERE语句称为一个查询块,将一个查询块嵌套在另一个查询块的WHERE子句中的查询称为子查询. 子查询分为嵌套子查询和相关子查询两种. 嵌套子查询的求解方法是由里向外处理,即每个子查询在其上一级查询处理之前求解,子查询的结果作为其父查询的查询条件. 子查询只执行一次,且可以单独执行;.

什么是Server SAN? Server SAN精解

- - 云存储技术网--光头老蒋
Server SAN是现在一个全新的概念,现在给出的概念都太笼统. 按照老蒋的想法:Server San应该是一个利用软件将基于DAS存储(包含闪存卡,直连存储)的集合,做成一个能共享的SAN存储网络.      SAN存储区域网,大家都很熟悉. 普遍使用的就两种: FC SAN;ISCSI SAN.

weblogic server启动慢

- - Linux - 操作系统 - ITeye博客
(1)较好的解决办法: 在Weblogic启动参数里添加 “-.   Djava.security.egd=file:/dev/./urandom” (/dev/urandom 无法启动). 修改Linux上Weblogic使用的jdk $JAVA_HOME/jre/lib/security/java.security 文件.

Server-Sent Events 教程

- - 阮一峰的网络日志
服务器向浏览器推送信息,除了 WebSocket,还有一种方法:Server-Sent Events(以下简称 SSE). 严格地说, HTTP 协议无法做到服务器主动推送信息. 但是,有一种变通方法,就是服务器向客户端声明,接下来要发送的是流信息(streaming). 也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来.

译|High-Performance Server Architecture

- - 掘金 架构
本文的目的是分享我多年来关于如何开发某种应用程序的一些想法,对于这种应用程序,术语“服务”只是一个无力的近似称呼. 更准确地说,将写的与一大类程序有关,这些程序旨每秒处理大量离散的消息或请求. 网络服务通常最适合此定义,但从某种意义上讲,实际上并非所有的程序都是服务. 但是,由于“高性能请求处理程序”是很糟糕的标题,为简单起见,倒不如叫“服务”万事大吉.

X.Org Server 1.11正式发布

- xing - cnBeta.COM
X.Org Server 1.11正式版于昨日晚间发布了. 因为发布管理员Keith Packard的母亲不幸去世(节哀顺变),新版发布比原计划推迟了一周. 这是一次比较重大的更新,汇聚了过去六个月的增强,并修复了大量bug,但却没有带来什么新特性. 支持触摸操作的X Input 2.1被推迟到了下一个X.Org Server版本或者更晚,也没有任何RandR扩展.

Apache HTTP server 2.2.21发布

- tinda - Solidot
两周前,Apache软件基金会发布了Apache 2.2.20版,修正了被广泛讨论的字节范围头(range-header)拒绝服务漏洞. 现在,它发布了v 2.2.21,修正了另一个拒绝服务安全漏洞,以及对V 2.2.20版所修正漏洞的进一步修复. Apache鼓励所有旧版本用户升级到新版本.