OpenBTS使用指南
条评论这是15年翻译的官方文档,之后会陆续放出以前翻译的一些文档,以及做的一些笔记给大家参考,转载请注明出处!
另注:此文仅供学习参考,请勿用于非法行为!测试建议在屏蔽室进行,或者在屏蔽试验箱中进行,切勿影响正常通信!!!
初始化配置和测试
0x110 启动服务
1 | start asterisk |
0x120 进入控制台
1 | /OpenBTS/OpenBTSCLI |
0x130 修改Band和ARFCN
Band 频段:全世界共有4个GSM频段,分别为850,900,1800,1900
ARFCN 绝对无线频道编号:每个无线频段都有100多种ARFCN可以用,每个ARFCN对应一个频率,选择正确的频段和频率,可以避免干扰
这些配置都在GSM.Radio中,用config命令可以查看:
1 | OpenBTS> config GSM.Radio |
频段900,ARFCN是C0的参数118,也可以不是用这些配置,在一般情况下,美国用850和1900,世界其他国家用900和1800,具体在维基百科可以看到
低频率覆盖范围更广,如果当地监管机构分配了频段和ARFCN,那就必须遵守规定。
1 | OpenBTS> config GSM.Radio.Band 900 |
修改频段必须要与ARFCN匹配,或者两个都改,改完以后需要重启服务:
1 | OpenBTS> restart |
0x140 调整信号增益
需要修改GSM.Radio.RxGain的参数,如果信号增益太大,会导致设备无法工作,一般设置为最小25:
1 | OpenBTS> devconfig GSM.Radio.RxGain 25 |
或者直接使用rxgain命令调,可以不用重启:
1 | OpenBTS> rxgain 25 |
这时候,在手机中手动搜索运营商可以搜到 Test PLMN 1-1
GSM中,一般同时使用两个频段,方便手机同时具备上行和下行链路,也就是全双工,具体哪个频段可以设置 ARFCN
如果手机可以搜索到基站,就表明网络状态良好,但如果有较强的无线干扰,也就是噪声干扰俗称底噪,手机和基站的链路就可能会有问题。
可以用noise命令检查噪声强度:
1 | OpenBTS> noise |
如果不调节rxgain,可以得到这样结果,实际上在使用时会发现,手机如果距离太近,也无法接入系统。
1 | OpenBTS> noise |
表示检测到的背景噪声RSSI信号强度为-71dB,这个数值越小表明底噪越少。配置的RSSI信号强度为-50dB,也就是说,基站所能提供的最高信号强度为 21 dB。一个好的差值意味着上行链路质量不错。两个数据的差值不同反馈信息也不同,如果差值小于10db,那么就会像前一个反馈的警告信息,提示噪声干扰强度已经接近所配的RSSI,上行链路质量非常有限。如果差值小于0db,会有警告提示噪声干扰比配置的RSSI信号还强,无法建立上行链路。
1 | OpenBTS> noise |
如果出现了这些警告提示,就需要想办法降低噪声干扰或者加大基站发射功率。
在以后的使用中,如果出现手机能搜到基站却无法连接的问题,首先检查下底噪,即使配置文件没做任何改变,但环境的底噪随时都会有变化。
0x150 如何减小底噪
如果基站没有配置成频率双工器,那么上行链路的噪声源可能来自于下行链路。如果没有适当的双工过滤,下行链路通常都是不论是频率还是空间距离最靠近上行链路的。不过,即使没有双工器,还是有一些办法可以降低下行链路对上行链路的噪声干扰。
0x151 天线方向
双工器的作用就是调整天线,让信号不那么容易影响对方,所以如果用的普通的塑料弯折天线,就将天线弯折一下,垂直成90度脚,这样天线的型号辐射图就是互相垂直的:

如果天线是互相平行的,信号可以很容易的从发射天线干扰接收天线,但当天线形成90度直角以后,信号的发射和接收在不同的平面。可以通过调整天线角度观察底噪的变化,这么简单的调节可以降低多达10db的底噪。
0x152 下行链路的接收灵敏度
再就是降低从发射天线到接收天线的信号强度。如果接收灵敏度比发射信号强度还高,降低接收灵敏度是很有效的。降低接收灵敏度可以清掉太强的上行信号。不过,降低接收灵敏度,会减小基站信号覆盖范围,在实验室环境可能看不出来。用power命令可以查看接收灵敏度。
1 | OpenBTS> power 0 |
当前最大接收灵敏度为0db,如果要降低灵敏度,比如降低20db,执行命令:
1 | OpenBTS> power 20 |
用noise命令可以看出明显的差别:
1 | OpenBTS> power 0 |
0x153 提高手机的功率
手机可以通过调整GSM.Radio.RSSI和GSM.Radio.SNR的键值来加大功率。这些键值默认大小可以满足绝大多数情况下的使用。但如果遇到信号波动比较大的情况(比如在地下室墙角附近转悠),就需要增大这些键值来提供更宽泛的信号强度适应。提升手机功率能够提高上行链路质量,当然也会更加耗电,缩短手机续航时间,有得必有失。
如果调了这些以后,底噪还是太大,回到网络设置那里修改ARFCN,改到一个底噪更小的频率。
0x160 第一次连接
在验证了上行和下行链路以后,为了确保所有的设置能够生效,需要重启OpenBTS:
1 | stop openbts |
在手机接入网络之前还需要做的步骤是找到手机的特性参数,用来做网络准入。
0x161 寻找IMSI
所要找的最主要的特性参数是IMSI(国际移动用户识别码),这是存储在SIM卡中的14-15位数字,类似网络中的手机用户名。但手机通常不会泄露自己的SIM卡中的IMSI,有个别特殊手机在设置菜单可以看到,有个别特殊手机要在工程模式才能看到,总之要得到SIM卡的IMSI挺麻烦的。不过,还有其他方法。OpenBTS需要IMSI和它交互,而且你可以控制网络准入条件,那就可以强制手机进行网络交互的测试,然后在网络上执行LUR更新请求,类似注册。这和从运营商列表中选择网络一样简单。
在进行LUR注册之前,需要启动SIPAuthServe守护进程来处理这些请求:
1 | start sipauthserve |
现在在用手机搜索下运营商,然后再列表中选择测试网络,过一会儿后会提示注册网络失败。
实际上,如果注册网络成功,会收到一条提示短信,短信内容包括IMSI还有分配的号码(前提是有添加过号码)。所以只要没收到短信,就知道没有注册进入网络。
注意: 如果手机离基站太近是无法接入网络的,在log中会提示:
1 | Transceiver.cpp:414:pullRadioVector: Clipping detected on RACH input |
OpenBTS会记住这些LUR交互,用来进行IMSI/TMSI(临时识别码 )的变换。将IMSI变换为TMSI是为了保护用户的隐私,防止IMSI被窃取。这个变换功能的选项默认是关闭的(需要将Control.LUR.SendTMSIs选项打开)。之后,可以用tmsis命令查看这些信息。现在可以看到最近一段时间手机进行的LUR交互:
1 | OpenBTS> config Control.LUR.SendTMSIs 1 |
1 | OpenBTS> tmsis |
这些条目按时间排序,越近的交互信息越靠上。所有的交互信息中AUTH都是0,因为手机不是已知用户导致LUR交互失败。如果有手机成功接入到网络,那么对应的LUR交互信息中的AUTH就是1了。
0x162 寻找IMEI
在一个数据量较大的环境下,很难确定手机对应列表中的哪个条目。要匹配IMSI到一个特定的硬件,可以使用IMEI,这是手机的硬件唯一标识,类似网卡的mac地址。
手机的IMSI一般印刷在手机后面电池下面的外壳上或者其他很靠近SIM卡的位置,现在有些手机也会印刷在包装盒上(所谓的三码合一、四码和一都包含IMEI码),在手机的设置或者工程模式一般也都看得到,也可以在拨号键盘输入*#06#获得。
IMEI值通常只在生产环境用来做报告和检测被盗,可以用来很方便的确认哪张SIM卡在这个手机中。不过,你手机的IMEI最后一位数字可能和OpenBTS上看到的不同,这是一个校验位,在OpenBTS中是0。
0x163 添加用户
你现在应该有了创建一个测试网络的新用户所需的所有必要信息。
还需要两个字段,这个可以自由选择:Name和MSISDN(移动台ISDN号码),Name字段仅仅是这个用户的名称,用来关联手机或者用户的,MSISDN字段的含义和用户的手机号码差不多。以为你并没有连接到公共电话网络,所以可以设置成任何号码。
添加用户用的脚本是nmcli.py。这是NodeManager APIs的一个很简单的客户端,可以用它通过JSON格式的命令来更改配置参数、添加用户以及状态监控等等。
nmcli.py 就在源码编译后的目录,进入目录:
1 | cd dev/NodeManager |
使用nmcli.py有两种方式可以添加用户:
第一种方法使用缓存的认证信息。
1 | ./nmcli.py sipauthserve subscribers create name imsi msisdn |
第二种方法使用完整的认证信息。
1 | ./nmcli.py sipauthserve subscribers create name imsi msisdn ki |
如果IMSI是用户名,那么密码就是手机的Ki码。如果没有得到Ki码,就只能用第一种方法添加用户。如果你有在烧写SIM卡,那肯定知道自己的Ki码,那就可以用第二种方法添加用户。比如说:
1 | ./nmcli.py sipauthserve subscribers create "iPhone4s" IMSI460022016844078 6055551001 |
输出:
1 | raw request: {"command":"subscribers","action":"create","fields":{"name":"iPhone4s","imsi":"IMSI460022016844078","msisdn":"6055551001","ki":""}} |
再加入另一个:
1 | ./nmcli.py sipauthserve subscribers create "Nexus" IMSI460019839814046 6055551002 |
检查下添加的用户:
1 | ./nmcli.py sipauthserve subscribers read |
如果有输入错误的,删除对应的IMSI
1 | ./nmcli.py sipauthserve subscribers delete imsi IMSI460019839814046 |
现在就可以将这两台手机加入到测试网络了,iPhone4s手机号为6055551001,Nexus手机号为6055551002
0x164 接入网络
在手机中选择运营商再次加入网络,LUR交互应该会成功。这时候通过tmsis命令可以看到AUTH的值为1了。对于IMSI列表如下:
1 | OpenBTS> tmsis |
恭喜,到现在为止,手机已经成功注册到了私人移动网络,以后可以随意注册任何手机到这个网络中了。
0x170 短信测试
手机注册进网络以后,就可以进行一些更有意思的测试,首先是网络中的短信的简单测试。
负责接收、路由转发和调度的应用服务是SMQueue,所以需求先启动这个服务:
1 | start smqueue |
0x171 短信编写(411)
在手机中,写一条短信发给411。这是SMQueue中的一个简码处理流程,只管回显,不管其他接收、网络及用户信息等整个流程所用任何信息。发送给411的短信的可以是任意内容,可以是任意的文字或者数字或者字母。这个可以用来帮你确认哪条消息在回应时候出错。
编写一条发往411短信,点击发送,几秒钟之后,应该会出现应答,举例如下:
1 | “1 queued, cell 0.1, IMSI460022016844078, phonenum 6055551001, at Sep 8 02:30:59, |
0x172 直接发送短信
在OpenBTS上也可以用sendsms命令直接发送短信进行测试。在OpenBTSCLI中,可以看下这条命令的帮助信息:
1 | OpenBTS> help sendsms |
消息发送到指定IMSI,发件人号码src#,短信内容message。比如:
1 | OpenBTS> sendsms 460019839814046 12345 direct SMS test |
过几秒后,手机会收到短信,Nexus手机收到发自12345的短信,内容为direct SMS test,iPhone4s 收到发自67890的短信,内容也是direct SMS test。
这种方式创建的短信不通过SMQueue服务的路由,而是直接通过GSM的空中接口发送给手机,因此,这种方式发的短信不会被重发,如果手机处于离线状态或者无法接入网络,这些短信就会被丢弃。所以,在通信质量不可靠的网络环境下,SMQueue服务会对短信进行重发。
0x173 双方互发短信
如果在网络中加入了多台手机,可以给相互发几条短信试试,号码就是之前注册进网络时候设置的号码。如果号码错误,会收到收到短信提示说无法发送短信到xxx(给101发送8-10位数字,基站就会回复这台手机所注册的手机号)。
0x180 语音通话测试
还有测试语音通话的服务,和短信类似,OpenBTS不直接处理语言通话,需要运行额外的服务,启用asterisk服务:
1 | start asterisk |
和测试短信一样,用你的手机进行语音通话方面的验证。这是通过配置range-asterisk-config包,进行几项测试的。测试范围是内部号码,外网的电话无法接入。
0x181 呼叫测试(2602)
第一个呼叫测试听到的只是一段连续的声音,尽管听起来不是很爽,但至少可以确认一些东西:
- asterisk服务正常工作
- 语音呼叫路由正常工作
- 语音的下行链路正常
用手机拨打2062,听听语音,可以感觉到声音音调的改变,这些音调的变化是因为下行语音链路中丢了一些数据。在这里,语音测试的最主要应用是测试下行链路的质量。一个下行链路在生产环境有3%丢包率,那么在正常使用时候会有5%-7%的丢包率。
0x182 回音测试(2600)
第二个呼叫测试是一个”回音测试”,也就是你说什么,就能听到什么,基本上能把所有接收到的语音通话即时的回放给发送者。回声测试除了可以用来测试语音通话,还能测试网络中延时情况和上行链路质量。
用手机拨打2600,然后对着手机麦克风说话,就可以听到自己说的话,有一点延迟是正常的,但延迟如果太长就会感觉在用对讲机。人类的大脑能够处理大约200ms的延迟,如果超过这个时间,两边都会感觉不舒服,从而挂断电话。
0x183 双方通话
如果网络中有好几台手机,可以互相拨打电话,接到电话后回拨一个。
0x190 链路质量测试
在OpenBTS CLI中有一个很方便的命令工具chans,用这个命令可以客观的量化用户所感知到的基础链路质量。
比如说,在拨打2602测试语音通话,10秒后执行chans命令(注意时间栏),然后将两个手机一个拿远一米一个拿近一米,再执行chans命令,就能很明显的看到区别:
1 | OpenBTS> chans |
在很多地方,这些数据很有用,不过在这里我们主要关注SNR(信噪比),TXPWR(发送功率),RXLEV_DL(接收灵敏度)。这后面两个参数,代表一个活动的信道,SNR是基站上行链路的信噪比测量值,这个数值越大越好。当手机被拿远后,这个数值反而提高了,这是为何?原因在于TXPWR的值,这个数值是手机反馈的上行链路功耗,第二次读的时候,一个手机的这个参数从7变成15,这说明手机在上行链路启用了更大功耗,这就可以解释为何基站SNR更高。
这个私人独立网络会告知不同的要连接基站所需手机的功耗,而手机为何基站附近的手机的信号强度都差不多,因为这样解调更容易,毕竟是同一个基站,所有手机下行链路的信号强度都差不多。
另外,RXLEV_DL所在那一列中的数值,都是手机下行链路信号强度。第二次读的时候,手机挪远以后,这个数值从-80dBm降到-96dBm,因为手机挪远以后距离基站更远,收到的下行链路数据的信号更弱。
使用help可以看到这个命令的参数列表:
1 | OpenBTS> help chans |
0x1A0 继续配置系统
在本章节中,你已经熟悉了几个OpenBTS命令,其中绝大多数最重要的就是配置。在配置之前,有些参数需要做一下调整。
0x1A1 config
你可以用config命令查看所有可以配置的选项以及当前对应的参数。也可以查看某一个配置项及对应的参数,只要加上配置项完整的名称。比如:
1 | OpenBTS> config SIP.Proxy.SMS |
0x1A2 devconfig
devconfig和config类似,但这个命令可以操控更多选项,每个键值都可以看到不同用户(普通用户、开发人员、出厂设置)对应不同的参值。使用devconfig命令可以访问很多很敏感的键值,比如协议定时器:
1 | OpenBTS> config GSM.Timer |
0x1A3 rawconfig
rawconfig命令调整的参数范围比devconfig要大一些,并且会移除所有的输入验证。如果有想将某个配置项的参数调到正常范围以外,就需要用rawconfig命令。rawconfig命令的另一个用途就是可以在数据库中定义一个全新的自定义的键值/参数,这在创建一个新的功能时候很有用。
1 | OpenBTS> rawconfig My.New.Setting zebra |
0x1A4 unconfig
有一些可控可调的参数选项是可以禁用的,用unconfig命令就可以将某些参数选项禁用。
1 | OpenBTS> config Control.LUR.FailedRegistration.Message |
这时候用unconfig命令就可以将这个选项禁用,并反馈禁用成功。
1 | OpenBTS> unconfig Control.LUR.FailedRegistration.Message |
0x1A5 rmconfig
如果想把某个键值恢复到默认值,用rmconfig命令:
1 | OpenBTS> rmconfig SIP.Proxy.SMS |
这个命令也可以用来删除用rawconfg自定义的键值/参数:
1 | OpenBTS> rmconfig My.New.Setting |
0x1B0 个性化网络定制
你的网络能正常运行,并且知道如何控制它,这是一个很好的开端。这是你自己的私人网络,所以应该定制一个符合你口味的网络。这里将要讲述的就是如何个性化定制私人网络。
###短名称
短名称就是手机搜索运营商时候看到的运营商名称,这是人们搜索运营商网络时候第一个注意到的信息,所以需要将OpenBTS的默认名Range改一下:
1 | OpenBTS> config GSM.Identity.ShortName |
注意,只能包含数字和字母,不能包含空格和特殊符号。
0x1B1 注册短信提示
在之前手机注册入网的时候,可以注册失败,可以让手机收到registration failed短信。其实这样的反馈短信有好几种,分别用来针对不同的事件。
可以看下配置列表,然后搜索Registration.Message配置项,里面有对应的名称:
1 | OpenBTS> config Registration.Message |
注册失败的短信提示挺有用,但有点土,可以用config命令改个cool点的:
1 | OpenBTS> config Control.LUR.FailedRegistration.Message Hello,World! |
或者还可以用unconfig命令来禁用注册失败的短信提示。
1 | OpenBTS> unconfig Control.LUR.FailedRegistration.Message |
另外还有一种短信,Control.LUR.NormalRegistration.Message选项,默认这个选项是关的,作用是每次手机入网时候都给它发一条提示短信。
如果将基站部署在一个生产环境,对于实验室很有用,特别是在调多个基站的时候,这个短信可以作为更新注册或者切换网络的通知。
1 | OpenBTS> config Control.LUR.NormalRegistration.Message Welcome to WhiteBTS |
为了测试它,将手机打开电源并循环开关飞行模式,每当手机重新获得基站信号并注册入网,就会收到一条入网提示短信。
故障排除和性能优化
当你的网络准备付诸实用的时候,你需要一些额外的技术来帮助调试它们的问题。除了一些错误配置导致的问题,很多问题都不明显。依据部署状况和网络模式,存在的问题可能是性能达不到预期,这种情况下就需要对网络进行调优。所以故障解决和调优,总让人不爽。
0x210 stats状态命令
有一个可以简单快捷的观察OpenBTS运行状态的命令stats。假如有几十个事件需要跟踪,先看整个列表,执行不带参数的stats命令:
1 | stats |
每一个事件类型的键值名称和键值/参数以及相对应的时间,都被存储在一个小的sqlite3数据库里面,只保留最后一次统计的数据,之前的都被清掉了。清掉之前的数据库来统计你所需要的事件记录,用以下命令:
1 | OpenBTS> stats clear |
现在,如果你从一台手机给另一台手机发条短信,然后搜索短信的记录,可以看到以下内容:
1 | OpenBTS> stats SMS |
OpenBTS.GSM.MM.CMServiceRequest.MOSMS表明一个手机信号向移动基站发起初始短信请求(MOSMS),OpenBTS.GSM.SMS.MOSMS.Start和Complete键值表明图个MOSMS请求的开始和完成,前三个键值都是从手机发送到基站,后两个键值表示从基站到目标手机的结束短信请求(MTSMS)的开始和完成。
0x220 运行日志
所有的日志都存储在/var/log/OpenBTS.log文件,如果想实时监控日志变化,用一下命令:
1 | tail -f /var/log/OpenBTS.log |
如果只想监控某些关键字相关日志,可以跟上grep命令,比如只想查看包含sipauthserve关键字的日志,可以执行:
1 | tail -f /var/log/OpenBTS.log | grep sipauthserve |
如果只想查看现有日志文件中的历史记录,可以执行:
1 | grep sipauthserve /var/log/OpenBTS.log |
日志包含很多不同的条目信息。下面是OpenBTS产生日志的示例项:
1 | Jan 28 16:20:30 (none) openbts: NOTICE 3025:3025 2015-01-28T16:20:30.9 GSMConfig.cpp:136:regenerateBeacon: regenerating system information messages, changemark 27 |
0x221 日志级别
默认情况下,日志等级只设置在NOTICE及在它之上等级,一般这些信息就足够调试一些典型的错误,比如掉线和高干扰率。在OpenBTS系统中一共有8个等级的日志报告:
EMERG
报告硬件故障或者服务故障引起的严重故障
ALERT
报告因为错误配置或者连接质量差引起的服务连接断开
CRIT
报告比如服务降级一类的异常事件
ERR
报告异常情况下可能会导致服务降级的软件内部错误
WARNING
报告异常情况下可能会导致正常服务降级的标识
NOTICE
报告异常情况,哪怕不会影响正常服务,但网络管理员可能比较感兴趣的信息
INFO
报告一般事件
DEBUG
会降低系统性能,只有开发人员才会使用
调整不同的日志等级,可以得到不同的系统信息输出。
比如INFO等级,会报告一般事件(包含NOTICE以及之上等级的信息)。这些正常时间的信息能够推断出可能出现错误的地方。要更改日志等级,执行以下命令:
1 | OpenBTS> config Log.Level INFO |
一旦在本地日志中发现了一些可疑的行为,就能从日志字段中代码的那一部分获取更多的信息。比如前面例子中的事件,就是从GSMConfig.cpp中发出的,如果想要将这个代码文件开启DEBUG等级日志需要执行:
1 | OpenBTS> rawconfig Log.Level.GSMConfig.cpp DEBUG |
需要用rawconfig命令来定义这个键值/参数,因为这不在标准配置中。所需如果要从配置数据库中删除这个键值/参数,需要用rmconfig命令:
1 | OpenBTS> rmconfig Log.Level.GSMConfig.cpp |
从OpenBTS 5.0开始,可以给OpenBTS的各个子系统组分别定义日志等级,共包括以下组:
1 | Log.Level.Control |
同样的,这些都是自定义的键值/参数,必须用rawconfig命令进行配置,然后删除用rmconfig命令:
1 | OpenBTS> rawconfig Log.Level.SIP DEBUG |
如果给范围组件使用DEBUG级别产生太多了信息,会影响OpenBTS系统运行,所以DEBUG级别只能用于单个源文件或者日志组。
0x230 环境调优
让OpenBTS适应所部署运行的环境是很重要的一个步骤,周围的建筑、树木、天气、所在高度、天线的选择、电缆长度和功放功率都会有影响。在商业化运作都靠这个领域专业的技术和硬件,但这方面太宽泛了,所以在这里介绍一个比较有效的方法。任何有效的部署,都需要做软件和硬件方面的调优。现在就介绍下OpenBTS软件中提供的控件。
0x231 未入网手机
如果你在部署时候用了RF信号放大器让信号更强干扰更小,并且区域内其他的载波信号很弱甚至没有,那当地所有的未入网手机都会试图接入网络,因为它们没有别的网络可以接入,这个问题在农村地区很普遍。而大多数人都有手机,当区域内突然有一个基站时候,可能会有几千台手机同时请求入网,基站会被DDOS导致正常的入网请求无法响应。有超过20种方法拒绝这些请求,关键是需要正确的部署配置。默认情况下OpenBTS使用很友好的拒绝方式(0x04),可以允许该手机在几分钟后重试。你需要告知手机拒绝入网的原因,让它离开一段时间防止LUR认证服务不被拥堵到无法使用的地步。
有两个参数用来定义拒绝入网原因:
1 | OpenBTS> config RejectCause |
Control.LUR.404RejectCause键值的含义是,当一个未知用户试图接入网络的时用什么理由拒绝它,不管实际是什么理由拒绝,这里统一用一个参数表示拒绝理由,具体参加对应关系见下表:
| 参数 | 描述 |
|---|---|
| 0x02 | IMSI unknown in HLR |
| 0x04 | IMSI unknown in VLR |
| 0x05 | IMEI not accepted |
| 0x0B | PLMN not allowed |
| 0x0C | Location area not allowed |
| 0x0D | Roaming not allowed in this location area |
| 0x11 | Network failure |
| 0x16 | Congestion |
| 0x20 | Service option not supported |
| 0x21 | Requested service option not subscribed |
| 0x22 | Service option temporarily out of order |
| 0x26 | Call cannot be identified |
| 0x30 | Retry upon entry into a new cell |
| 0x5F | Semantically incorrect message |
| 0x60 | Invalid mandatory information |
| 0x61 | Message type nonexistent or not implemented |
| 0x62 | Message type not compatible with the protocol state |
| 0x63 | Information element nonexistent or not implemented |
| 0x64 | Conditional IE error |
| 0x65 | Message not compatible with the protocol state |
| 0x6F |
每种参数在手机上可能会有多种效果,经过测试,一些比较常用的,比如0x0C和0x0D,都是告诉非许可手机长时间不再尝试加入网络,且不会影响手机接入其他网络,改这两个值可以极大的减少LUR认证的负载。
1 | OpenBTS> config Control.LUR.404RejectCause 0x0C |
0x232 覆盖区域
另一种方法就是让手机无法找到你的网络,这是通过硬件和软件的调整来改变覆盖区域的。
短信和注册服务的覆盖区域大概是语音服务的4倍(2倍半径),因为只要服务正常运行,哪怕丢帧也会再重传的。
OpenBTS硬件具备功率控制机制,能够对发射功率进行衰减调节,从而扩大或者缩小覆盖范围,检查基站的当前衰减级别,用power命令:
1 | OpenBTS> power |
要调节衰减级别,在power命令后面加参数就行了,如果想基站具备最大功率从而覆盖最大范围,应该将调整为衰减0db:
1 | OpenBTS> power 0 |
相反,如果想增大衰减级别减小功耗缩小覆盖区域:
1 | OpenBTS> power 20 |
还有另一种物理层次的电源控制机制。手机会调整给发送数据的功率,使基站收到的所有手机的信号强度差不多。基站控制着手机和基站通讯的功耗,我们可以限制这个范围。手机是不能控制自己的功率的,所以我们告诉它们所用的功率范围是可以限制的。所用的键值是MS.Power:
1 | OpenBTS> config MS.Power |
尽管这种方法很少用到,但至少是一种方法。
0x233 策略性收缩
利用物理方法收缩区域可能会影响高负载情况下的网络稳定,还有一个参数可以派上用场,GSM.MS.TA.MAX:
1 | OpenBTS> config GSM.MS.TA |
TA的意思是Timing Advance(定时提前),定时提前是GSM用来给距离基站非常远的手机的补偿方法,越远的手机TA值越大。这个值告诉手机提前多少时间发送脉冲信号,那样当基站给手机分配时隙的时候刚好到达。电磁波的传输速度很快,但仍然不是瞬间到达。
回到参数设定:比如将GSM.MS.TA.MAX设置成10,OpenBTS会默默的忽略任何TA大于10的无线电信号。TA经过一种叫信号周期的测试大概每单位对应550m距离。将GSM.MS.TA.MAX设置为10,表示OpenBTS会忽略范围5.5km之外的任何手机信号。
但覆盖区基本都不是正圆,就是由于策略限制,如果信号塔在一个山谷,高处的三个方向会被抑制,但其余的方向就能收到更远基站的信号。你不想降低功率,因为山坡上也有用户,所以,这种情况下就能通过策略开限制覆盖区域。
0x234 信号失真
信号失真是受安装地形周围环境的严重影响,缺省配置下,OpenBTS的配置成全力消除多路失真。它通过尽量开大时间窗来抵消信号失真,这是很费系统资源的计算。
如果你是在地势很开阔的地段,没有任何建筑和树木,可以通过调整GSM.Radio.MaxExpectedDelaySpread来降低CPU负载,区域覆盖越小,参数数值越小:
1 | OpenBTS> config Delay |
这个键值决定了检查的符号周期,如果把参值调小之后效果不好,就调回默认值4。
0x235 信号更强,抗干扰更佳
为了有效的增大生产环境网络覆盖面,你需要一个信号放大器和空腔双工器,因为GSM手机一般有2W以上的发射功率,但你的SDR只有100mW的发射功率,所以基站成为限制覆盖区域的主要因素。上行链路的信号是从手机发往基站的,但下行链路型号是从基站到手机的,这个信号对手机来说太弱了。基站和手机之间功率不对称,示意图如下:

为了说明问题,在基站的发射链路上加一个2W的信号放大器来增大覆盖范围,但接收链路的问题也要注意,因为接收天线从发射天线收到的信号强度也会大大增加,这会损坏SDR的电路。至少,想要解调一个干净的信号是不大可能的,因为发送端2W的信号放大器产生的噪声足以淹没任何远处的手机,要想解决这个问题,还需要一个空腔双工器。
空腔双工器连接到发射和接收的天线接口,然后从双工器引出一根天线,连接示意图如下:
GSM发射和接收是在不同的频率,所以双工器能够干净的分离出发射和接收信号,这样可以防止不必要的发射链路信号回环到接收链路。因为这个分离是基于频率的,所以双工器必须选择能够匹配GSM频段850,900,1800以及1900的。
从单路到多路
一个基站就可以建立移动网络,但当到了某个程度时候,不管那个那个基站如何调优,都不能有效的覆盖目标区域。由于OpenBTS是用同一套软件实现不同大小区域的覆盖,甚至可以在一台树莓派上运行。现在可以抛弃传统手机信号塔的模式了,你甚至可以把基站装进鞋盒或者和Wifi热点结合到一起。
这里就介绍如何将移动网络扩展到多个物理基站,但仍然是在一个逻辑网络里面,这个逻辑网络可以便捷移动以及迅速部署成运营网络。
0x310 移动性、切换和漫游
目前这个方面的概念有些混乱,虽然它们的意思很明白的事情,但即使这个领域的专家围绕这个一起讨论,也很难让别人接受他们的看法,所以为了杜绝不确定性,每个名词都做了简要概述:
0x311 移动性
移动性是指一个手机能够收到不同物理基站提供的不同运营商网络。假如一个手机在三维空间中移动时候,它收到来自附近基站的信号强度和质量就会波动,而手机在收到附近一个更强的基站信号时,就会发送一个LUR入网注册请求或者入网请求,不同的是,在同一个基站中周期性的LUR会更新注册信息,如果是在一个新的基站,LUR就是接入并切换到这个网络的请求了。
除非两个基站有不同的位置区编码LACs,LUR请求是不会被执行的。在传统的GSM网络中,在一个特定的区域里所有的基站都有一样的LAC。但目前的OpenBTS要求所有的基站都具有唯一的LAC,所以手机在两个基站之间移动时候LUR会被执行。这会触发一个更新SIP REGISTER信息的请求,并且给这个新基站的IP一个注册用户的更新请求。
移动性是网络的一个功能,并且由手机决定接入哪个基站。另外,这只可能是手机没在进行短信或者电话等业务执行的时候。移动性也可以称为入网空闲模式。
0x312 切换
切换是保证一个有效的语音通话能在两个基站之间切换的能力。流动性是切换的先决条件,但不同的是,这是是由网络决定并执行的。
传统GSM网络通过基站控制器BSC控制切换,而OpenBTS省去了BSC用一种新的端对端协定传输技术P2PP技术。周边频率信息、身份信息、活动信息都通过这个协议交换,极大简化了结构体系的部署。
决定切换还有几个因素。首先,来自基站的下行链路信号对当前手机必须够弱;其次,附近基站的信号强度也必须超过能够提供基站服务的阈值;最后,附近信号最强的基站现在没有因为拥护拒绝所有的切换请求。满足这些条件后,现在服务的基站会发出一个切换请求给附近信号最强的基站。
0x313 漫游
漫游是跨运营商的移动,它需要那些运营商和通用接口技术的管理协议,通常GSM移动通信应用部分(MAP)发送SS7指令网络。所以,在你自己的私人网络里面是不可能实现漫游功能的。
0x320 拓扑结构
到现在为止,你已经建立了一个单点网络 (Network-in-a-Box)的拓扑结构,可以在每一个逻辑实体、服务器节点的组件上。在一个多节点网络中存在两种逻辑实体:中控服务器和信号塔。你迄今为止所熟悉的组件需要重新部署一下才能支持这种结构。中控服务器需要安装SIPAuthServe,SMQueue和Asterisk服务,为了简单起见,在这部分内容里这三种服务统称中控服务。信号塔只允许OpenBTS。
下图是一个单中控服务器和多信号卡的多节点拓扑结构示意图:

信号塔数据通过IP发回中控服务器,这样就可以覆盖多个区域并且互相共享注册用户的数据库和配置。
下面的说明中,中控服务器IP为192.168.158.100,信号塔的IP从192.168.158.201开始。
0x330 中控服务器配置
不是说从现有的单节点网络中提取中控服务,把OpenBTS的硬件和应用迁移到新环境更简单。这样就不需要迁移SIPAuthServe,SMQueue和Asterisk服务的用户数据以及配置。
0x331 卸载OpenBTS
为了确保OpenBTS不被开机自动启动,防止因为没有硬件导致启动失败并不断重试,我们需要卸载掉OpenBTS:
1 | apt-get remove openbts |
0x332 配置日志记录
每个独立的信号塔和中控服务一样,都会产生日志信息,所以需要设置一下中控服务,来接收整个网络所有信号塔的日志到一个文件。
这一步不是建立一个多节点网络,但在调试时候非常有用,在多个日志文件中跟踪多个信号塔的错误日志是一个很坑的事情。
1 | vi /etc/rsyslog.conf |
这两行配置的意思rsyslog服务开启514端口的UDP服务来接收日志。要启用这个配置需要重启服务:
1 | service rsyslog restart |
0x333 SIPAuthServe,SMQueue和Asterisk服务
这些服务不需要重新配置,它们不管OpenBTS是通过硬件进行通信还是IP网络进行通讯。
0x340 信号塔配置
重新配置一个系统并运行各个服务器组件,不管是在物理机还是虚拟机,不过必须要用不同的主机名用来区分日志。另外,可以只安装OpenBTS服务来节省时间。
信号塔和中控服务器必须在同一网段,在信号塔上启用日志之后,确保可以ping通中控服务器:
1 | ping -c 4 192.168.158.100 |
0x341 配置SIP代理
OpenBTS使用SIP连接其他组件的,现在这些组件安装在别的机器上,所以SIP.Proxy键值需要做相应调整。默认情况下Openbts连接服务的IP地址都是本地localhost。SIP.Local.IP键值可以设置其他服务连接OpenBTS时或者回复它们的请求时应该使用的IP地址。设置信号塔命令如下:
1 | OpenBTS> config SIP.Local.IP 192.168.158.201 |
设置完成后需要重启OpenBTS服务才能生效:
1 | stop openbts |
现在每个SIP.Proxy键值都会更新到转向中控服务器,同样的,注册、语音、短信服务都要从本地改为中控服务器:
1 | OpenBTS> config SIP.Proxy.Registration 192.168.158.100:5064 |
注意:一定要确定包括端口信息,每个组件都运行在不同的端口,如果在错误的端口请求路由会影响功能。
用手机手动选择并注册这个新的拓扑做下测试,走动之前确认下语音和短信都能用。
0x342 配置日志记录
每个信号塔产生的日志信息都会被发送到中控服务器,在中控服务器的日志守护进程已经修改过配置能够接收这些数据,现在我们告诉我们的信号塔发送日志:
1 | vi /etc/rsyslog.d/OpenBTS.conf |
这行配置的意思是,日志信息除了会记录到硬盘上的/var/log/OpenBTS.log文件,还会发送到中控服务器的日志记录。要启用这个设置,也需要重启服务:
1 | service rsyslog restart |
0x343 拓扑网络重构
到目前为止,现在网络的功能和之前是相同的,依然是一个由中控服务器和逻辑信号塔构成的覆盖区域,仅仅是从一个物理机分割成两个独立的物理机。下一步将把附近的信号塔添加到网络,并让它们显示成同一个RAN。
0x350 添加附近信号塔
你现在可以重复添加很多个物理信号塔,每一个都配制成功能极少的独立信号塔,并且在网络内充当合适位置的信号塔。此外,每个已有信号塔必须知道新的信号塔。
假设现在你的网络里只有一个信号塔,一个刚刚从单点网络调整过来,先看看它的参数:
1 | OpenBTS> config Identity |
这些参数中,有一些必须是唯一的而其他的必须是所有信号塔完全相同的,下面是一个配置列表,告诉你那些键值必须是唯一的哪些必须是统一的。
1 | 统一 |
展现一些潜藏的信息,理解每个参数,再依据一步步的指引配置你的下一个信号塔。
0x351 必须统一
GSM.Identity.MCC和GSM.Identity.MNC键值对于任何网络都是最高级别的认证,表明这个网络是哪个国家的哪个运营商在运营。这两个ID是监管机构分配的。测试网络通常用的分别是001和01。如果这不是一个测试网络,你必须注意这个参数,否则你可能需要花钱购买许可。
GSM.Identity.BSIC.NCC是你的网络色码(NCC),一段手机用来快速确定否能访问网络的信息。在指定区域内的所有运营商必须具有唯一的色码。
最后一个关键的键值是GSM.CellSelection.NCCsPermitted,这个键值是在和其他网络合作时候告知”不只我这个NCC OK,还有其他的一些NCC是可用的”,NCCsPermitted键值是按位标志而不是一个整数值。总之,所有的信号塔的NCCsPermitted配置必须相同。
GSM.Identity.ShortName键值也是所有信号塔相同的,但这不是必要条件,在部署调试一个多节点网络时候,为了调试的方便一般会给每个信号塔一个独特的短名,这样你可以知道你手机目前驻留在那个信号塔然后离开它。
设置步骤
这部分的说明很简单很基础,就是确保在同一个网络中现有的信号塔的这些键值都相同。
0x352 必须唯一
第一个键值,GSM.Radio.C0必须是唯一的,因为这是ARFCN并且由此决定这个信号塔的RF频段。如果物理上两个相近的信号塔用相同频率,会在重叠区域内产生干扰并且拒绝这个区域内所有用户的服务。
注意:C0 ARFCNs不仅仅要求唯一还要求不相邻,因为信道间隔只有200KHz而信道宽度有270KHz,相邻的ARFCN也会重叠。所以部署相邻的信号塔至少要间隔1个ARFCN(比如塔1用ARFCN151,塔2用ARFCN153)。
GSM.Identity.BSIC.BCC相邻的信号塔也必须是不同的,这代表基站色码BCC,是一个3位二进制,一共有7个不同的值。
你得到许可的C0 ARFCNs和BCC的数量很有限,参照下面的彩图对塔的参数分配很有帮助。彩图标识了所有信号塔的地理位置以及分配的颜色,每种颜色对应一种ARFCN和BCC。如果你的规划没有两个相邻的信号塔会有同样的颜色,那么移动性和切换就不会因为ARFCNs或者BCC所阻碍。

网络中所有的信号塔的GSM.Identity.LAC键值必须各不相同,当手机在跨区域移动时候会感觉到位置区码LAC在发生变化,然后会执行LUR请求,这个LUR请求会发送一个SIP REGISTER注册请求,SIPAuthServe服务收到后会更新这个手机可以接入的信号塔的IP地址。这个唯一性要求只针对于OpenBTS,传统网络的LACs了包含大的多的区域里面很多个信号塔。
GSM.Identity.CI指的是小区识别码CI,同样要求全网唯一。
设置步骤
给新的信号塔分配颜色,并使用相对应的C0和BCC:
1 | OpenBTS> config GSM.Radio.C0 168 |
由于有足够多的LAC和CI值,只需每个塔的值递增一下:
1 | OpenBTS> config GSM.Identity.LAC 1001 |
重启OpenBTS服务是变更生效:
1 | stop openbts |
0x353 附近基站列表和命令
你的信号塔现在已经配置完了,按照它们逻辑规划的ID编号通过物理方法传输它们的频率会很麻烦,它们还必须告知彼此自己的配置,这就需要用GSM.Neighbors键值完成。每个信号塔必须有和IP地址一致的GSM.Neighbors键值,用来设置出自身以外的所有信号塔的空间隔离清单。
在你的新信号塔192.168.158.202,需要输入以下命令告诉它你原来的信号塔:
1 | OpenBTS> config GSM.Neighbors 192.168.158.201 |
同样的在你的原信号塔你需要告诉它新信号塔:
1 | OpenBTS> config GSM.Neighbors 192.168.158.202 |
还是在你的原信号塔192.168.158.201,用检查附近信号塔的命令:
1 | OpenBTS> neighbors |
OpenBTS会依据对等协议从GSM.Neighbors中自动查询附近的基站信息。用neighbors命令可以看到C0 ARFCN,噪声等级,ARFCN总数和可用业务信道(TCHs)。
0x354 Neighbor-Enabled命令
现在,你有一些功能有效的附近基站,用chans命令也能在通话过程中显示很多有用的信息。这个信息包含了手机报告的附近最强信号的信号塔提供的信号接收等级,用chans -l命令就可以看到:
1 | OpenBTS> chans -l |
0x355 覆盖范围重叠
单独调节每个信号塔,最棘手的就是处理它们之间的关系,再看下面这张图,塔1和塔2的重叠区域很重要。这个区域必须足够宽,使得手机只要通过切换就能与两个塔中任何一个进行可靠的通信,必须考虑这个区域的地形以及手机潜在的速度。但同样的,如果重叠区域太大就浪费了资源。所以,寻找可靠的重叠区域以及优化整体区域的平衡是关键。同样的,商业化运营就建立在这些专业且有深度的知识上,都在这本”getting started”书里面。

手机的移动性只有GSM.CellSelection.CELL-RESELECT-HYSTERESIS键值需要配置,这个键值表明手机在准备重新入网时候,选择附近信号强多少的信号塔。
OpenBTS可以直接控制切换,有几个键值是用来调整切换操作的:
1 | OpenBTS> config Handover |
GSM.Handover.Margin类似GSM.CellSelection.CELL-RESELECT-HYSTERESIS用于切换操作,这两个设置要注意,如果参值设置的太高(意思是信号塔要比切换前的强太多),可能会导致手机无法在规定时间内跳转过去,如果参值设置的太低(意思是信号塔只比切换前的强一点点),手机可能会在这个区域流量峰值时候在两个信号强度相近的信号塔之间来回跳转。
如果你想测试OpenBTS里面的切换算法的权重,可以用devconfig查看更多参数:
1 |
|
GPRS
移动网络已经在世界上很多地方普及了,缺少的是数据网络。比如WhatsApp和Skype这样的OTT服务只需要一个不论什么载体的数据通道。使用者的费用也不取决于地理位置,不像本地的长途费用。
GPRS的传输速度对于双向视频流来说是太慢了,但足够支撑低质量的语音通话。它的速度足够email和OTT文字短信使用。世界上的传感器和基础设置比如热流量传感器和电力停车计时器都需要数据连接。这些低带宽的M2M设备现在被称为IOT物联网的设备,普遍使用GPRS。
GPRS实际不是GSM的一部门,它是在GSM已经标准化后才开发的,通常被称为2.5G,区别于纯2G的GSM。OpenBTS尽量模糊了这些差异,并提供了一个统一的配置。
0x410 启用/禁用
默认情况下,OpenBTS中GPRS服务是禁用的,要启用这个服务需要配置GPRS.Enable键值:
1 | OpenBTS> config GPRS.Enable 1 |
启用GPRS需要重启OpenBTS服务:
1 | stop openbts |
重启OpenBTS服务以后,可以用gprs list确认OpenBTS建立了几个GPRS通道:
1 | OpenBTS> gprs list |
0x420 中控服务
GPRS不依赖其他任何组件,但Linux主机上的一些配置必须正确才能正常工作。这些在range-configs包被安装时候就已经做好了,但还是需要进行复查。
手机的IP流量是通过OpenBTS建立的一个名为sgsntun虚拟网卡进行通讯的,可以用ifconfig sgsntun命令检查:
1 | ifconfig sgsntun |
这个虚拟网卡需要先配置路由和iptables转发规则。规则样例在/etc/OpenBTS/iptables.rules,需要按照时间情况修改网关和网卡名,默认用的是eth0,使规则生效用的命令:
1 | iptables-restore < /etc/OpenBTS/iptables.rules |
如果想让系统的eth0网卡启动时候能够自动加载规则,就在/etc/network/interfaces网卡配置文件中eth0网卡配置那网卡加上pre-up规则。
1 | auto eth0 |
Linux主机就是作为管道设备通过规则转发让GPRS上网。
0x430 连接
当你的手机发送LUR请求加入网络时候会做一个备份,因为可能会有额外的步骤来做GPRS的认证和使用。
在GPRS中不叫LUR,叫做GPRS Attach,手机可能会因为几个原因不做Attach操作。
如果你用的是其他运营商的SIM卡,手机的GPRS子系统可能会在加入OpenBTS网络时认为自己漫游了,如果手机没有设置”使用数据漫游”,GPRS子系统不会去尝试接入网络。
请仔细检查你手机的APN接入点设置,OpenBTS不管名称、用户名和密码有什么内容,但手机可能不会在确认这些信息之前发送Attach请求。
Android在APN条目有个很奇怪的Bug,在某些版本中,你可以添加一个新的APN,但不会被保存,除非MCC移动国家码和MNC移动网络码和SIM卡中相匹配。这种故障没有提示也没有声音,新的APN设置也不会被启用,也不会在设备的APN列表中显示,但如果你更换了一1个与SIM卡相匹配的MMC和MNC,你的APN信息就会神器的出现。
总之,有些手机会需要好几分钟时间来Attach,在放弃并发起Attach请求之前,它们可能会发送旧的网络访问信息给OpenBTS,当Attach成功后,用sgsn list可以看到手机的IP地址:
1 | OpenBTS> sgsn list |
0x440 故障排除
如果你可以连接但是没得到一个IP地址,可能是因为防火墙的设置。一般这都不是问题,但可能和不同的Linux系统以及IP网络配置有关。可以禁用防火墙再重启OpenBTS服务:
1 | OpenBTS> config GGSN.Firewall.Enable 0 |
手机联网还会通过OpenBTS检测你的DNS服务器,如果发现你的手机无法解析域名,请尝试手动设置DNS服务器并重启OpenBTS服务:
1 | OpenBTS> config GGSN.DNS 8.8.8.8 |
网关GPRS支持节点(GGSN)和服务GPRS支持节点()在常规GSM网络中是分离的,但在这里是被直接嵌入到OpenBTS中的。为了更深入的了解这些组件中的发生的事情,可以配置一个独立的日志文件,用来观察网络中手机和GPRS服务的交互。将GGSN.Logfile.Name键值设置为你将要写入的日志文件的路径,然后重启OpenBTS服务:
1 | OpenBTS> devconfig GGSN.Logfile.Name /tmp/GGSN.log |
现在,GPRS网络上的活动都会经过GGSN,新的条目都会记录到这个日志文件,用tail -f命令监控日志文件:
1 | tail -f /tmp/GGSN.log |
0x450 性能调优
OpenBTS尝试智能划分资源分配给信令用的独立专用控制信道(SDCCH)和媒体用的业务信道(TCH)。但是,它并没有一种用来平衡不同类型TCH用途的机制。
0x451 语音和GPRS
语音和GPRS流量是用的时隙都是由TCH逻辑信道承载,如果网络要被部署成GPRS服务而不是语音服务,就需要调整GPRS.Channels.Min.C0键值,这个键值指定用于GPRS的TCH时隙的最小数量,默认是2。要查看当前可用信道数目可以用命令:
1 | OpenBTS> load |
在这里我们可以看到,一共有7个TCH信道可供选择:5个用于GSM语音(GSM:TCH/F)和2个用于GPRS数据(GPRS:PDCHs)。为了最大限度的提高网络的GPRS优先级,将GPRS.Channels.Min.C0设置为TCH信道的最大数量7,然后重启OpenBTS服务:
1 | OpenBTS> config GPRS.Channels.Min.C0 7 |
重新执行load命令,可以看到所有的TCH信道都被分配给了GPRS:
1 | OpenBTS> load |
OpenBTS允许你在手动调整时候修改所有的时隙分配,你可以调整组合1(TCH)和组合7(SDCCH)时隙的数量配比,还可以调整这些时隙的顺序,并且其中GPRS时隙应该出现在多ARFCN系统中,查看所有键值搜索Channels:
1 | OpenBTS> config Channels |
0x452 单一手机吞吐量
多个手机可以会使用多于1个时隙同时访问GPRS网络,支持上行链路和下行链路的并行时隙的数量被策划那个做多时隙等级。默认情况下,OpenBTS设置的多时隙等级为3+2:3个并行时隙用于下行链路2个用于上行链路。这不是说一个手机会占用全部5个并行时隙,但你可以看到添加尽可能多的时隙对于以GPRS为重点的网络是很重要的。更高的多时隙等级可以给一个手机更快的数据传输速度,但在多个手机使用时网络会很快的拥堵。
你可以调整这两个键值来调整多时隙等级:
1 | OpenBTS> config Multislot |
0x453 覆盖范围和吞吐量
GPRS定义了四种不同的编码方案(CSs)用于数据传输,它们分别是CS1,CS2,CS3和CS4。CS1具有最低的吞吐量和最高的可靠性,它被分配了更多的数据比特用于恢复无线传输过程中的误差。而CS4具备最高的吞吐量,但在传输过程中容易出差错。这些传输误码率限制了每个编码方案的覆盖范围。
OpenBTS只支持CS1和CS4,你可以选择配制成低吞吐但可靠性高并且可以覆盖更大范围,还是高吞吐但有少量错误修正并且覆盖范围小。默认情况下OpenBTS同时启动,但它们可以在上行链路或者下行链路单独进行调整:
1 | OpenBTS> devconfig Codecs |
0x454 预期
GPRS网速不快,但毕竟是数据,在没有WiFi的地方,很大一部分区域都在用调制解调器的速度上网,不管是用于M2M/IOT设备还是人们用来和亲戚朋友联系。一台手机的预期吞吐量如下表:
1 | 多时隙等级和编码方案吞吐量 |
这是最佳吞吐量,依赖于网络阻塞情况,包括无线局域网传输和互联网上行链路。
不可否认,OpenBTS对GPRS的支持还不完善。GSM语音和短信对于OpenBTS的用途基本算完善,但GPRS还可以做改进和优化。大多数改进都是在无线电方面的算法及分包规则,对这些的优化能极大的改善OpenBTS中的GPRS的体验。
开放注册
OpenRegistration是OpenBTS的一个特殊功能,相当于移动网络用的强制网络认证。强制网络认证就类似于机场或者酒店的公共WiFi,一般都不能直接用来上网,直到回答一个问题、看一个广告或者输入Pin码才行。
同样的,OpenRegistration允许一个手机加入到移动网络,但担忧初始的访问限制。它可能可以拨出电话但没有分配的号码,所以不能不能被网络中的其他手机呼通,但它可以通过短信来提供它自己的号码。
这种类型的点对点网络非常有用,在任何用户都是临时的或者流动性大的网络或者直接就是临时网络,比如应急响应、远程办公区、旅游景区、大型活动等等。
由于管理员不需要创建用户分配号码,所以OpenRegistration网络更容易部署并且对于用户很有用。
0x510 启用
要开始使用一个OpenRegistration网络,必须先启用这个功能,先看看键值参数:
1 | OpenBTS> config OpenRegistration |
要启用OpenRegistration,Control.LUR.OpenRegistration键值必须设置成正则表达式。正则表达式是通过定义规则进行匹配的。对于这些有几个标准,更多的信息可以在维基百科中找到。IMSI如果符合正则表达式的匹配就能获得网络的访问权限。几个范例和它们的作用如下表:

按照这个表,OpenRegistration可以接受它所遇到的任何IMSI访问:
1 | OpenBTS> config Control.LUR.OpenRegistration .* |
有一个附加键值,可以拒绝特定的IMSI,这样可以很方便的许可除特定组之外所有的IMSI。按照上表设置排除l来自中国移动的任何IMSI:
1 | OpenBTS> config Control.LUR.OpenRegistration.Reject ^46002 |
注意:确保在野外部署时候,确信你了解这些模式是如何工作。噩梦般的情况是,有个患有心脏病的人无意之间加入了你的开放网络,心脏病发作时候不能拨打紧急服务,因为你的网络不支持。仔细检查你的网络的GSM.RACH.AC的值仍旧是默认的0x400,这会在你的信号塔标识出不支持紧急呼救电话(Emergency Calls Not Supported)。
0x520 个性化
用户加入你的网络会得到内容为Control.LUR.Open Registration.Message键值的迎接,你可以用下面的命令改变:
1 | OpenBTS> config Control.LUR.OpenRegistration.Message Welcome to IslandNet! Call or text 101 for assistance. Your IMSI is: |
这指示新加入的成员通过拨打101寻求帮助,你的网络应该有一个人分配到101号码提供人工服务或者实现一个自助语音服务。用户也可以按照提示发送号码的短信给101。默认情况下SMQueue服务有一个处理短号101,用来和想要分配自己想要号码的手机进行对话。在SMQueue服务的控制参数中,SC.Register.*参数决定用哪个短号、短信内容以及用户选好范围。SMQueue服务没有在CLI界面,但nmcli.py可以用于读取和修改这些参数:
1 | ./nmcli.py smqueue config read |
如果你想用特殊号码比如101,就得在OpenBTS中的将Control.LUR.OpenRegistration.ShortCode设成新的号码。这个键值设置了欢迎短信的源地址。如果已经设置到新的帮助号码,用户可以简单的回复初始化信息。
0x530 禁用
要再次禁用OpenRegistration,接受和拒绝模式设置必须复位:
1 | OpenBTS> unconfig Control.LUR.OpenRegistration |
OpenBTS现在已经恢复使用用户数据库授权或者拒绝用户访问,而不是IMSI模式。
NodeManager APIs
NodeManager是一个面对OpenBTS,SMQueue,SIPAuthServe的通用控制接口,用于系统配置和监控。所有的组件都支持一些常用的功能(比如配置操作),通过提供用于特定任务或者数据源的特定API接口。NodeManager API分成两大类:请求/响应和流。这两种类型都使用JSON格式信息并通过ZeroMQ进行通信,有一个库用来创建这两个进程之间简单和可靠的socket连接。使用NodeManager API是用来简化远程管理多个OpenBTS实例,就像SMQueue和SIPAuthServe那样的中控服务。
API是互联网的一个正常组成部分,所以看起来不是那么新奇,不管怎样,后面讲到PhysicalStatus API时候记住前面传统GSM通信原理图。不用去看几十页的协议和实例,软件无线电的核心数据现在可以直接使用JSON格式信息流。在以后的版本中会有更多的API添加到NodeManager接口中。
0x610 nmcli.py
这个名叫nmcli.py是一个包含在NodeManager库中的一个小的Python程序。它需要安装一些依赖关系,在build.sh脚本中应该已经做了。为了确保你已经安装了,可以再手动执行一遍命令:
1 | add-apt-repository -y ppa:chris-lea/zeromq |
nmcli.py用于不断扩展新的NodeManager API的实施。要看当前nmcli.py的功能,执行不带任何参数的命令:
1 | cd ~/dev/NodeManager |
nmcli.py的实施效用并不像一个专业的NodeManager API接口,更像一个开发工具,可以快速格式化消息以及测试新的API端点。本章将会讲述各种不同的API端点。首先,nmcli.py用法类似一个清单,随后转换成JSON格式的消息。
0x620 API版本
所有组件的实施版本,一个请求/响应的API。这是一个微不足道的API,但对于在远程节点上运行的组件来说,这个信息非常重要:它的当前版本。用nmcli.py问询SMQueue当前版本:
1 | ./nmcli.py smqueue version |
0x630 配置API
所有的组件的配置实现,都是通过请求/响应API,这个API用于修改每个组件的配置参数。每个组件的配置模式生效之前,都会通过这个API更新对应SQLite3数据库中对应值。
0x640 查看所有键值
使用nmcli.py询问SMQueue所有可配置选项:
1 | ./nmcli.py smqueue config read |
会请求一个config命令和read行为:
1 | raw request: {"command":"config","action":"read","key":"","value":""} |
之后SMQueue会响应它所支持的每个配置项的很大的支持列表:
1 | raw response: { |
0x650 查看某一个键值
这个API还支持低于特定一个键值,用nmcli.py询问SMQueue中SC.Register.Code键值:
1 | ./nmcli.py smqueue config read SC.Register.Code |
会请求一个config命令和read行为,还有一个新的键值字段SC.Register.Code:
1 | raw request: {"command":"config","action":"read","key":"SC.Register.Code","value":""} |
之后SMQueue会响应这个特定键值的关键配置项和参数信息:
1 | raw response: { |
如果这个键值的请求不存在,会从组件中响应一个404返回。
1 | { |
0x660 更新
如果一个API配置不允许设置新的参值,那就没有用处。一个消息字段变更为更新,那么这个新的键值字段的更新必定包含所指定的改变。用nmcli.py更新前面所说的SC.Register.Code键值从101为555`,
1 | ./nmcli.py smqueue config update SC.Register.Code 555 |
注意新的值有更新行为:
1 | raw request: {"command":"config","action":"update","key":"SC.Register.Code","value":"555"} |
响应包括两条信息:
1 | raw response: { |
204代码表示操作成功但没有数据反馈。这个例子告诉你没有那个应用的配置是全静态的,你的配置是灵活的。如果配置不为0,那么该组件需要重启才能应用更改。以下是其他反馈代码和含义:
1 | 304: nothing to change, old and new values match |
0x670 物理状态API
OpenBTS只有一个API流来实现PhysicalStatus组件。默认情况下它是不生效的。使用NodeManager.API.PhysicalStatus键值启用它。为了确保向后兼容,PhysicalStatus API支持不同的释放模式。目前只支持0.1,设置这个键值0.1将会激活PhysicalStatus API并使用0.1模式的流事件数据。现在你已经可以熟练使用nmcli.py,就可以激活这个API:
1 | ./nmcli.py openbts config update NodeManager.API.PhysicalStatus 0.1 |
流激活以后,你需要连接客户端查看所产生的数据。在OpenBTS的apps目录有一个名为JSONEventsClient.cpp的样例客户端。在编译OpenBTS时候会默认被编译,但在安装包的时候没有安装进系统。这个客户端会连接由NodeManager.Events.Port定义的ZeroMQ端口,然后等待API发布事件。
进入你的OpenBTS源码目录然后进入client所在目录:
1 | cd dev/openbts/apps |
没有什么特殊的情况发生,直到你的OpenBTS有活动。
在手机上循环关机,发短信或者打电话,PhysicalStatus就会开始在控制台显示活动情况。举个例子如下:
1 | { |
这些输出显示了手机和基站之间业务流的物理无线电脉冲信息。这些输出作为GSM标准的一部分在后台生成,也被称为测量报告。它们提供了手机调整发送功率所需的基站信息、触发切换的信息以及计算定时提前量Timing Advance。
那么,这些数据的价值在哪里?很多应用可以利用这些网络的无线电环境的原始元信息,来做出更智能的电力功耗决策,负载均衡等等。
这个目前被用于搜救行动,冰岛的直升机已经配备了运行OpenBTS的便携基站,运到没有信号的偏远地区用来寻找迷路的徒步旅行者。OpenRegistration配置为允许该地区所有的手机自动加入网络,网络通过发出的测试短信不断的记录基站和手机的无线电接收等级和发射功率都。和无线电信息一起的还有经度、纬度和高度值都被直升机记录下来。然后这些信息通过算法进行分析,可以65m精度在高达35km区域内定位任何手机。更多的项目相关信息可以在http://bit.ly/11vKaT7找到。
步步高升
希望你已经看完这本书,成功实现了你所感兴趣的领域。这里还有一些出发点用于进一步的研究和实验。
0x710 连接到外面的世界
连接你的手机与外界”真实”的电话,您需要一个网络电话业务提供商(ITSP),ITSP可以桥接你网络中的SIP信令和RTP媒体到他们的PSTN。
0x720 语音
找到ITSP的语音服务很简单,现在这些提供按分钟包月通话服务的公司网上都有目录。入网手机号或者直拨入网电话(DID),全世界大部分国家都提供这项服务。许多公司还提供了Asterisk服务安装及使用技术支持。
0x730 短信
短信的支持比较困难,很少有ITSP提供SIP MESSAGE用于短信服务。供应商提供这种服务也一般不会提供配对的语音DID,这样一个手机会有不同的电话号码用于打电话和发短信。这种情况正在改善,但现在需要替代方案。
有的供应商会提供SMPP网关或者HTTP REST API接口网关,再或者,有些DID无法使用或者需要额外的SIP MESSAGE连接。
一个比较成功的使用API的案例是nexmo。
0x740 频谱规则
这是这本书无法解决的问题之一,无线电管制具备法律有效性。虽然历来获得无线电频率许可的都是通信巨头,但现在这个情况开始有所改变。监管部门的压力在于要将可用频段划分的更细,然后分配给各自需要使用的领域。
频谱政策最有前卫的似乎是欧洲。英国,荷兰和瑞典已经将最有价值的几个ARFCN频段分配给公众使用,其中包括GSM频段。任何人在没有执照的情况下都可以在有限的功率下使用这些频率。美国FCC似乎有计划在2015年拍卖大量频谱,并将放出高达28MHz的保护频段可以在特定区域随意使用,比如动态频谱联盟(Dynamic Spectrum Alliance)这样的团体对GSM空白研究活动,从政治上或者技术上解决频谱接入问题。
0x750 切换调整
OpenBTS正在使用标准的SIP信令也需要,很必要,主要用来替换GSM和UMTS认证算法替代MD5。
到目前为止,整合一直在开始第一步,但已经在努力加快步伐。OpenBTS中的Asterisk和FreeSWITCH打过补丁后直接支持注册和语音呼叫,这个都已经写入各自的项目阶段。Kazoo平台(http://wiki.2600hz.org)已经拥有最完整的支持,注册、语音和短信都能正常运行。
0x760 3G数据
OpenBTS-UMTS 1.0已经在2014年10月份发布,这是我们所知道的第一个UMTS开源堆栈,添加了3G的数据传输速度,对于这个新的混合网络的功能列表,更多信息请查看http://openbts.org/w/index.php/OpenBTS-UMTS
0x770 开源硬件
如果你是一个硬件设计师并且很好奇SDR是怎么做的,那你很幸运,你不仅仅是在使用开源软件来构建移动网络,他们还在设计开源硬件。好几种SDR的原理图都是完全开放的,在他们的GitHub上:
1 | Fairwaves UmTRX |
0x780 社区
·OpenBTS·社区可以提供很多学科方面的专业支持,可以订阅邮件列表。参加者有很多不同的背景:制造商、黑客、研究员还有集成商都很受欢迎。
0x790 革命
现代化移动网络应该是什么样子,是不是设计成一个标准的互联网世界?我们开始意识到这个问题的答案:极度简化,极其灵活,开放所有的新思路,极少的花费。
这是第一次,普通人可以下载一些软件,然后拿起一台无线电设备,就可以建立一个移动网络。欢迎一起革命!
快速参考
下面是分散在书中很多实例的快速参考。我发现自己在看这些东西的时候不断的想把这些放在一个统一的部分讲讲。
0x810 GSM层次
这本书不能在短短几章里面教会你·GSM·。但有一个很有用的办法从宏观到微观层面掌握·GSM·术语。
带天线的信号塔大家都很熟悉,有时候伪装成仙人掌或者树桅杆。每个塔都可以分成多个扇区,这些扇区合起来360º(比如一个塔分成4个90º扇区),单个扇区360º全覆盖。每个扇区都能分配一个或者多个·ARFCN·,有时候也成为载体,因为它们实际一对频率,用于数据进行物理交互。
每个·ARFCN·有8个时隙,每个时隙有分配给它的组合,每个组合有多个逻辑信道。这些逻辑信道被分为信令和媒体两个主要类别。·SDCCH(独立专用控制信道)·用来传送信令,比如手机注册消息和短信消息。·TCH(业务信道)·用来承载媒体,比如·GPRS·数据或者语音消息。逻辑信道是由多个帧信号以及帧信号组成的脉冲构成。
看整个系统的进程,其实就是GSM Timeslot和Channel Visualizer。
0x820 分贝和毫瓦分贝
分贝用来表述两个值的对比或者单一基站时的绝对值比率。写作·dB·时候只表述一个比率,比如·10dB·的·SNR·意味着信号比噪声强·10x·倍。写作·dBm·时候,表述的是以毫瓦为单位的绝对值,比如·GSM·手机最大发送功率是·33dBm·或者·2W·。
一个很方便的记忆方法是,每出现·3dB·的改变,无线电信号翻倍或者减半。


0x830 网络端口

0x840 文件路径

