GNUGK 作为Gatekeeper穿透防火墙和NAT

背景信息

由于内部使用Polycom的视频会议,在北、上、深各有办事处也用polycom ,偶尔需要和外部的视频会议互联,发现直接把视频会议设备在防火墙上开端口实在是太困难,首先大堆的动态端口,这个防火墙的例外开的实在太多了,而且防火墙和视频设备的NAT之间的兼容太差劲,调试的时候,我都差点把所有端口例外了,把h323相关的防火墙特别设置取消了,还是不能正常的视频。

之前用Juniper防火墙的时候抓了下正常的包和不正常视频状态的包,对比发现是NAT的问题,Hack一下做了个半nat 才把视频调通,但是端口暴露还是挺多啊。现在换了paloalto ,结果死活调不通。每次开个会要大动干戈。我的要求并不多,只需要能各个视频会议室能方便外联,然后又能保证安全即可。

然后没办法开始看h323的协议,找到了这个站点https://www.h323.net,发现竟然有gnugk 这么个好东西,虽然GNUGK官方的文档还算全,但是例子少啊。但是h323.net 上提供的信息不少。

准备开始

要求:

1. 从北、上、深任意一个点可以拨外面的点。

2. 北、上、深三点之间可以互拨,多点的话由于其中一个点带MCU,所以也没有问题。

3. 网络环境,gatekeeper 和视频会议点之间路由可达,在企业防火墙或者nat后面,gatekeeper 需要能访问互联网。大概如下图所示(用了h323.net上的图)

4. gatekeeper不需要在企业防火墙上开放任何端口。所以设置非常方便,这个和h323.net上的示例稍微不一样(因为我们暂时没有被呼入的需要)。

GNUGK 作为Gatekeeper穿透防火墙和NAT

安装:

操作系统选择ubuntu 16.04 lts,因为官方的x64编译版本是ubuntu 14.04 ,我发现编译的版本在16.04上也可以用,就选择16.04作为最终版本。

gnugk的机器使用了一个虚拟机,网卡只分配了一个。

使用gnugk 的编译版本前有个技巧,就是使用apt-get install gnugk ,这个步骤是为了安装gnugk使用的很多依赖包,然后apt-get remove gnugk(这个ubuntu自带的版本太旧了,所以卸载后用最新的版本)

下载最新编译好的gnugk-4.7-linux-x86_x64,解压

拷贝二进制文件sudo cp gnugk-4.7-linux-x86_x64/bin/* /usr/sbin

Sudo chmod a+x /usr/sbin/gnugk

Sudo chmod a+x /usr/sbin/addpasswd

拷贝sudo cp gnugk-4.7-linux-x86_x64/etc/gnugk.ini /etc/gatekeeper.ini

修改gatekeeper.ini 的内容(详细内容后面贴出)

编辑下面内容为gnugk.service并放入 /etc/systemd/system/ ,注意-ttttt 部分,初始测试的时候这个详细程度开到最大,生产稳定的时候,建议两个t或者三个t

; place into /etc/systemd/system/ as gnugk.service

[Unit]

Description=GNU Gatekeeper

After=network-online.target

[Service]

Type=simple

ExecStart=/usr/sbin/gnugk -c /etc/gatekeeper.ini -ttttt -o /var/log/gnugk.log

ExecReload=/usr/bin/killall -HUP gnugk

LimitRTPRIO=100

[Install]

WantedBy=multi-user.target

启用gnugk 服务

                 sudo systemctl enable gnugk.service

                 sudo systemctl start gnugk.service

监听端口一览:

7000 是监视端口,配置为只可以本机telnet,1718,1719,1720等用于h323连接建立

gatekeeper.ini 详细内容:

[Gatekeeper::Main]

Name=gk1

#Home=

#NetworkInterfaces=

TimeToLive=600

CompareAliasType=0

CompareAliasCase=0

#TotalBandwidth=100000

#MinimumBandwidthPerCall=1280

#MaximumBandwidthPerCall=100000

# 状态监控端口

StatusPort=7000

# 状态监控的信息详细程度,最大和默认都为2

StatusTraceLevel=2

UseBroadcastListener=0

UnicastRasPort=1719

UseMulticastListener=1

MulticastPort=1718

MulticastGroup=224.0.1.41

EndpointSignalPort=1720

ListenQueueLength=1024

TimestampFormat=RFC822

[GkStatus::Auth]

# 只允许127.0.0.1 连接状态监控端口

rule=explicit

127.0.0.1=allow

default=forbid

Shutdown=allow

[RoutedMode]

# 开启route mode

GKRouted=1

# 对h245 启用route

H245Routed=1

# 该设置没有设置时,遇到一个问题,和远端连接300秒后会自动RST,设置后问题消失,影响h245 隧道建立。

H245TunnelingTranslation=1

RemoveH245AddressOnTunneling=1

AcceptNeighborsCalls=1

# 允许未注册的终端呼叫(如果要接受外部呼叫这个可以打开)

AcceptUnregisteredCalls=1

SupportNATedEndpoints=1

DropCallsByReleaseComplete=1

CallSignalPort=1720

CallSignalHandlerNumber=5

RtpHandlerNumber=1

RemoveCallOnDRQ=1

SendReleaseCompleteOnDRQ=0

ForwardOnFacility=1

ShowForwarderNumber=1

Q931PortRange=20000-20999

H245PortRange=30000-30999

SetupTimeout=8000

SignalTimeout=15000

AlertingTimeout=60000

TcpKeepAlive=1

TranslateFacility=1

SocketCleanupTimeout=5000

ActivateFailover=1

FailoverCauses=1-15,21-127

CpsLimit=10

CpsCheckInterval=5

GenerateCallProceeding=1

UseProvisionalRespToH245Tunneling=1

# 启用h46017,h46018,h46019  h460和nat穿越有关系

EnableH46017=1

EnableH46018=1

EnableH46023=1

# 由于h46017,18,19需要STUN服务器,因此我们使用公开可用的STUN服务器,这里使用ekiga 和qq的stun

H46023STUN=stun.ekiga.net,stun.qq.com

#H46023PublicIP=1

# 下面这个配置后,发现内部之间无法互联,禁用

#NATStdMin=18

#EnableH460P=1

AutoProxyIPv4ToIPv6Calls=0

[Proxy]

# 启用代理模式

Enable=1

T120PortRange=40000-40999

RTPPortRange=50000-59999

ProxyForNAT=1

ProxyForSameNAT=0

EnableRTPMute=1

RTPDiffServ=46

[RoutingPolicy]

default=explicit,internal,srv,dns

[RasSrv::RRQFeatures]

# 这段是抄gnugk 关于polycom部分的优化设置。

AliasTypeFilter=terminal;dialeddigits

AliasTypeFilter=gateway;h323id

[RasSrv::LRQFeatures]

AcceptNonNeighborLCF=1

AcceptNonNeighborLRQ=1

[LogFile]

# 日志文件每天23:59 rotate,也就是每天一个log

Rotate=Daily

RotateTime=23:59

[Gatekeeper::Auth]

# 注册认证方式,我使用了fileIPAuth,就是直接根据IP地址来限定是否能注册。因为终端比较少。

FileIPAuth=required;GRQ,RRQ,LRQ,Setup

; Put only allowed IPs, the rest will be rejected by the "required" rule specifier

[FileIPAuth]

# 这里设置允许注册的IP地址

#10.0.0.15=allow

any=reject

# 配置记录CDR 通话详情记录到/var/log/gnugkcdr.log,每天23:59 rotate

[Gatekeeper::Acct]

FileAcct=required

[FileAcct]

DetailFile=/var/log/gnugkcdr.log

Rotate=daily

RotateTime=23:59

Polycom 设置:

需要配置h323网闸,polycom 防火墙和nat 都不需要配置了。

检测视频终端注册状态:

在gnugk (网闸gatekeeper)本地telnet 127.0.0.1 7000,输入rv ,查看已经注册成功的终端,我这里显示有两个终端注册上来了。当然你可以通过tail –f /var/log/gnugk.log 看更详细

外部资源

公共的可测试站点及账号

用于测试的资源非常少,但是找到了这个lifesize的站点,有15天免费测试账号,也有公开的测试账号,放出来方便大家测试。

Video only:

370608@lifesizecloud.com [Demo - Austin Skyline]

3559827@lifesizecloud.com [Demo - Austin Skyline 2]

3559407@lifesizecloud.com [Demo - Dancing Fountains]

506387@lifesizecloud.com [Demo - Fish Tank 1]

359905@lifesizecloud.com [Demo - Fish Tank 2]

371343@lifesizecloud.com [Demo - Fish Tank 3]

506457@lifesizecloud.com [Demo - Fish Tank 4]

367535@lifesizecloud.com [Demo - Gear Clock 1]

3538953@lifesizecloud.com [Demo - Gear Clock 2]

3418926@lifesizecloud.com [Demo - Sydney Harbour]

Video + Audio:

368004@lifesizecloud.com [Demo - Video w/ Audio 1]

482867@lifesizecloud.com [Demo - Video w/ Audio 2]

368032@lifesizecloud.com [Demo - Video w/ Audio 3]

482888@lifesizecloud.com [Demo - Video w/ Audio 4]

公共的可用的STUN服务器

STUN 服务器

用来让客户端探测自己的NAT类型,及NAT 的公网IP和端口。

List of 263 public STUN servers from EmerCoin project: http://olegh.ftp.sh/public-stun.txt.

gnugk 排错一例

使用gnugk 对外进行呼叫时发现连接对方5分钟(300s) 后会自动断开,由于之前测试一直都是使用lifesize 进行的测试,但并没有发现这个问题。所以这个问题有点棘手。gnugk的log记录的关于这个断开的信息很简单,就是yasocket.cxx(918) Q931d xxx.xxx.xxx.xx:1720 Error(0) Input/output Error(12:104)

第一这个肯定和防火墙或者网络绝对有关系,因为300秒太有规律了。

第二怀疑是远端防火墙导致了该问题。所以当时做了两个测试,拿我方连接lifesize(没有断开问题),拿lifesize 连对方(也没有断开问题)

这个时候有点无法判断是哪方问题。但怀疑lifesize的可能在公网上,可能没有nat问题。这个应该还是nat 穿越或者防火墙问题,无奈只有抓包对比吧。正常情况抓一个,不正常的抓一个

对比发现了倪端。对方的地址发了一个RST的包过来,这个时间和视频会议的断开时间一致。但是为什么会300s后发过来?

进一步发现了问题,对方IP地址在和我方建立了会议之后,也就是下面图中382数据包之后,到165543 数据包之间差不多正好300s, 165543 数据包是RST数据包,这个问题很明了了,就是会议建立后由于和对方IP交互少于300秒,对方防火墙认为你已经不再连了,所以断开了。但是会议依旧是开的,而且有音视频在传输,但为什么没有用对方IP进行传输,这里有点奇怪,应该还是和nat或者proxy 有关。

参考查找gnugk proxy 和routed 模式里的各个参数及意思。改一个测试一下。终于找到这个。问题解决。

H245TunnelingTranslation=1

Default: 0

Allow one side of a call to use H.245 tunneling even if the other side does not, with the gatekeeper performing the appropriate H.245 message conversion. This will reduce the number of ports required on the tunneling side of the connection.

本文转自 yoke88 51CTO博客,原文链接:

http://blog.51cto.com/yoke88/1972096

上一篇:【实战演练】只需一行代码,轻松解决Docker 和UFW 防火墙的安全漏洞
下一篇:linux命令:iptables、modprobe装载模块、网络防火墙服务