其實(shí)我早就知道騰訊云上有ALG,只是都想辦法繞過(guò)了,沒(méi)有進(jìn)一步核實(shí)。
欠下的債總是要還的,今天,又折騰了半天。
XSWITCH云平臺目前建設在騰訊云上。今天在調試Kamailio,收到SIP包后發(fā)到另一臺VM上的FreeSWITCH中,中間通過(guò)公網(wǎng)IP發(fā)送。然后遇到了pike模塊告警,說(shuō)數據包太多。pike模塊是Kamailio里的限流模塊,將閾值調高了一倍還是不行,遂抓包找原因,最后發(fā)現是網(wǎng)絡(luò )層篡改了Route字段,將里面的公網(wǎng)IP改成了私網(wǎng)IP,造成了SIP消息在公網(wǎng)和私網(wǎng)IP間無(wú)限循環(huán),直到遇到限流(幸虧開(kāi)了限流模塊)。
找到原因就好辦了,有無(wú)數的辦法可以繞過(guò)該問(wèn)題:
- 用TCP
- 用TLS
- 不走公網(wǎng)IP,直接走私網(wǎng)IP
- 調整Kamailio腳本,接受私網(wǎng)IP為最終目的地
首先要核實(shí)問(wèn)題,發(fā)現從我本地電腦發(fā)出的數據包也有此問(wèn)題,但這也可能是由于我本地的路由器引起的。檢查本地路由器沒(méi)有開(kāi)啟ALG功能。又重新核實(shí)。在兩臺騰訊云服務(wù)器上通過(guò)公網(wǎng)IP測試。
A上收:
ngrep -p -q -Wbyline port 1001
B上發(fā):
nc -u -p5060 A的IP 1001 < test.sip
其中,test.sip是純文本的INVITE消息,里面有個(gè)Route字段。
發(fā)現,如果A的IP是公網(wǎng)IP,到達對方后Route字段會(huì )被改為私網(wǎng)IP,而如果用私網(wǎng)IP就不受影響。
進(jìn)一步可以發(fā)現,TCP也不受影響,受影響的是UDP,但大多數人跑SIP還是用UDP。
給騰訊提了工單,響應挺快,只是溝通了很多次,工程師說(shuō)是騰訊云默認沒(méi)有開(kāi)ALG,然后定位到問(wèn)題,聯(lián)系產(chǎn)品給我加了個(gè)ALG功能,然后讓我把公網(wǎng)IP遷移到EIP或買(mǎi)個(gè)EIP,在EIP上開(kāi)啟ALG就可以了。
我直接就不懂了,然后詳細說(shuō)明我認為的ALG是“篡改”包的內容的,如果沒(méi)開(kāi)就不會(huì )篡改,何來(lái)再開(kāi)啟一說(shuō)?
最后經(jīng)過(guò)電話(huà)溝通才把問(wèn)題說(shuō)明白。騰訊云默認確實(shí)是開(kāi)了“篡改”功能的,如果想關(guān)掉,那就得再“開(kāi)啟”另一個(gè)“ALG穿透”功能(實(shí)際上控制臺頁(yè)面上叫“設置ALG”),讓數據包透明的過(guò)。他們認為這才叫“開(kāi)啟”。
好吧,負負得正,反正能解決問(wèn)題就行了。我相信應該能解決問(wèn)題,但是沒(méi)有驗證,因為目前在生產(chǎn)環(huán)境上動(dòng)EIP有點(diǎn)風(fēng)險。
這里關(guān)鍵的問(wèn)題是認知不同。我們先說(shuō)說(shuō)什么是ALG。
ALG的全稱(chēng)是Application Layer Gateway,即應用層網(wǎng)關(guān)。我們都知道,網(wǎng)絡(luò )有個(gè)OSI七層模型,網(wǎng)絡(luò )交換機和路由器其實(shí)是工作在2層和3層,即他們最多只知道IP包里的源IP地址和目的IP地址,而不知道數據包里具體傳的是什么。著(zhù)名的Web服務(wù)器和反向代理軟件如Apache和Nginx工作在七層,理解HTTP協(xié)議,因而可以修改消息內容,并轉發(fā)。所以,其實(shí)他們就是應用層的網(wǎng)關(guān)。最近比較火的專(zhuān)門(mén)做API轉發(fā)的API網(wǎng)關(guān)也是工作在七層的。
其實(shí),路由器上也是有ALG功能的,但功能一般都比較弱。路由器上的ALG功能一般用于解決FTP和SIP這樣的奇葩協(xié)議。FTP協(xié)議需要兩個(gè)端口才能傳輸文件,有主動(dòng)模式和被動(dòng)模式等,在有的NAT網(wǎng)絡(luò )中不容易通過(guò),因而,路由器上的ALG功能可以提供幫助,細節不多說(shuō)。
SIP協(xié)議更奇葩,一個(gè)INVITE消息里有好幾個(gè)IP地址,在NAT網(wǎng)絡(luò )中有時(shí)候就不通了,甚至,有時(shí)候信令通了,通話(huà)建立了,卻沒(méi)有聲音,也多半是NAT惹得禍。因而,路由器上的SIP ALG也可以深度解析SIP包,企圖(注意這里用了貶義詞)修復里面的IP地址。但是很不幸,很多ALG實(shí)現都有Bug。即使ALG沒(méi)有Bug,SIP協(xié)議很復雜,ALG根本Cover不住,你無(wú)法預測它在什么情況下改哪個(gè)地方,所以,大多數時(shí)候,它帶來(lái)的幫助比帶來(lái)的問(wèn)題多得多。除非,除非路由器上的ALG功能有很多配置選項來(lái)應對各種問(wèn)題,比如用Kamailio實(shí)現個(gè)ALG。但這是不現實(shí)的,所以,你應該關(guān)掉它!
事實(shí)上,我在《FreeSWITCH權威》指南里也講到過(guò),要關(guān)掉ALG。
好吧,到了這里,我們應該可以明確,如果路由器上開(kāi)啟了ALG功能,數據包有被“篡改”的風(fēng)險,所以我們需要關(guān)掉。
問(wèn)題是,騰訊云上這一功能是默認開(kāi)啟的。所以,他們又在控制臺上實(shí)現了一個(gè)“ALG設置”功能,如果“開(kāi)啟”以后,就關(guān)掉了。他們的技術(shù)支持工程師會(huì )告訴你“ALG默認是不開(kāi)啟的,你可以在EIP上開(kāi)啟”,“開(kāi)啟”后,就好用了……長(cháng)時(shí)間無(wú)語(yǔ)中。
發(fā)了個(gè)朋友圈吐槽了一下(不要誤會(huì ),我本身是騰訊云的TVP,吐槽是我的職責),很多人就建議我遷到阿里云或華為云。其實(shí),騰訊云本身非常不錯,他們的技術(shù)支持也很及時(shí),只是,在這一問(wèn)題上,不同的人有不同的認知。也許那個(gè)工程師并不懂SIP,也許他只是站在他們產(chǎn)品的角度,“設置ALG”這一功能就是沒(méi)有開(kāi)啟嘛。所以,每個(gè)人都有自己看問(wèn)題的角度。溝通,需要擺事實(shí)講道理才行。但無(wú)論如何,給騰訊提個(gè)建議,把這個(gè)功能改成“關(guān)閉ALG”,就沒(méi)有歧義了。因為在默認情況下,數據包應該是暢通無(wú)阻的,既然有人從中做梗,那就應該“關(guān)閉”它,而不是要繞一圈搞個(gè)“負負得正”。
再說(shuō)到SIP的ALG。除了上面說(shuō)到功能很雞肋外,其實(shí)不管是FreeSWITCH還是Kamailio,都在NAT上做了大量的工作保證在NAT環(huán)境下可用。ALG不僅僅是雞肋功能,簡(jiǎn)直是SIP公敵。所以,默認在網(wǎng)絡(luò )環(huán)境下開(kāi)啟這一功能是不負責任的。
如果你的SIP服務(wù)器運行在騰訊云上,標準的做法是使用EIP并“開(kāi)啟ALG”(再說(shuō)一遍,實(shí)際上是關(guān)閉@#^&$@#$@?$x)。(如果你從未來(lái)穿越到現在看到這篇文章,現在是2020年)
XSWITCH用戶(hù)也注意,我們目前還沒(méi)有遷移到EIP,因為這可能會(huì )影響我們很多租戶(hù)。如果您有問(wèn)題,請嘗試使用TCP,已知TCP的SIP消息不會(huì )被篡改。再有問(wèn)題請與我們聯(lián)系,我們也會(huì )盡快完成EIP遷移。事實(shí)上,我們希望所有UDP用戶(hù)都遷移到TLS上。