coturn 401 Unauthorized問題排查


1 背景

今天在調試webrtc C++設備join webapp 建立的房間時,在交換ICE信息後,開始進行ICE打洞。
發現C++ 收到401 的響應 直接退出了。 很奇怪的現象。因爲使用的coturn,配置好的情況下是不用去管coturn的行爲。所以這裏要調試一波coturn 401 錯誤。

考慮這裏主要是考慮權限的問題。根據錯誤很明顯是涉及到 訪問coturn 服務器 權限出錯。
但出錯的地方看起來很奇怪,因爲user爲空。
啓用use-auth-secret 及 static-auth-secret=north配置後 ,coturn接受的動態用戶名和憑證**,**將直接對每個用戶生成 username 及憑證。
這個行爲與我們預設的動態賬戶密碼機不符。turn 看起來是沒有問題。所以我們找到 什麼情況下才會出現,user 爲空的情況。且user 爲空的情況下 出現401錯誤。

coturn 原生log 在 /var/log 下

user <>: incoming packet message processed, error 401

具體的log如下:

86: handle_udp_packet: New UDP endpoint: local addr 172.31.111.111:3478, remote addr 101.111.111.110:62153
86: session 000000000000000003: realm <demo> user <>: incoming packet BINDING processed, success
86: session 001000000000000002: realm <demo> user <>: incoming packet message processed, error 401: Unauthorized

86: session 001000000000000002: new, realm=<demo>, username=<1570764028>, lifetime=600
86: session 001000000000000002: realm <demo> user <1570764028>: incoming packet ALLOCATE processed, success
86: IPv4. Local relay addr: 172.31.111.111:50809

這裏截取段有代表性的代碼。上面三行爲 STUN的行爲,下面三行爲 TURN 行爲的log。

2 stun與turn 服務測試

用測試stun 工具測試下 server看下log 的變化。
turnutils_stunclient -p 3478 xxxx.xxxx.xxxx.com

1407: handle_udp_packet: New UDP endpoint: local addr 172.31.30.111:3478, remote addr 101.111.111.117:44096
1407: session 000000000000000003: realm <demo> user <>: incoming packet BINDING processed, success

從log 可以看出 在stun 請求的情況下 user 爲空。也就是單獨stun時 會出現user 爲空的情況,所以我們看log 時候不要被stun的log 所幹擾。

這裏在測試下turn
turnutils_uclient -u demo -w xxx -p 3478 xxxx.xxxx.xxxx.com

1534: handle_udp_packet: New UDP endpoint: local addr 172.31.111.111:3478, remote addr 101.204.111.111:56623
1534: session 001000000000000002: realm <demo> user <>: incoming packet BINDING processed, success
1534: session 001000000000000002: realm <demo> user <>: incoming packet message processed, error 401: Unauthorized

1581: session 001000000000000005: realm <demo> user <demo>: incoming packet CHANNEL_BIND processed, success

這裏單獨測試turn時 會發現 它耶好像先進行了一次stun服務。後續才跑的turn的流程。
這裏可以看得出來 turn測試在turn 在relay地址分配之前,導致發生了401 錯誤。且後續turn務的行爲看起來正常。

3 ICE 收集測試

那這裏可以測試下收集ICE信息
https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
使用該網址 測試coturn server

在coturn log中看到如下信息:

1778: handle_udp_packet: New UDP endpoint: local addr 172.31.111.111:3478, remote addr 101.204.111.111:41891
1778: session 000000000000000012: realm <demo> user <>: incoming packet message processed, error 401: Unauthorized
1778: handle_udp_packet: New UDP endpoint: local addr 172.31.111.111:3478, remote addr 101.204.111.111:55573
1778: session 001000000000000009: realm <demo> user <>: incoming packet message processed, error 401: Unauthorized
1778: IPv4. Local relay addr: 172.31.111.111:55244
1778: session 000000000000000012: new, realm=<demo>, username=<demo>, lifetime=3600
1778: session 000000000000000012: realm <demo> user <demo>: incoming packet ALLOCATE processed, success
1778: IPv4. Local relay addr: 172.31.111.111:50538
1778: session 001000000000000009: new, realm=<demo>, username=<demo>, lifetime=3600
1778: session 001000000000000009: realm <demo> user <demo>: incoming packet ALLOCATE processed, success
1778: session 000000000000000012: refreshed, realm=<demo>, username=<demo>, lifetime=0
1778: session 000000000000000012: realm <demo> user <demo>: incoming packet REFRESH processed, success
1778: session 001000000000000009: refreshed, realm=<demo>, username=<demo>, lifetime=0
1778: session 001000000000000009: realm <demo> user <demo>: incoming packet REFRESH processed, success
1779: session 000000000000000012: usage: realm=<demo>, username=<demo>, rp=3, rb=244, sp=3, sb=316
1779: session 000000000000000012: closed (2nd stage), user <demo> realm <demo> origin <>, local 172.31.111.111:3478, remote 101.204.111.111:41891, reason: allocation timeout
1779: session 000000000000000012: delete: realm=<demo>, username=<demo>
1779: session 001000000000000009: usage: realm=<demo>, username=<demo>, rp=3, rb=244, sp=3, sb=316
1779: session 001000000000000009: closed (2nd stage), user <demo> realm <demo> origin <>, local 172.31.111.111:3478, remote 101.204.111.111:55573, reason: allocation timeout
1779: session 001000000000000009: delete: realm=<demo>, username=<demo>

可以很明顯的看出ICE 收集過程中也出現了這個問題。所以401 錯誤出現ICE收集過程中。到這裏也看不出爲什麼會出現401錯誤。所以下步開始閱讀標準。

4 標準文檔中的流程

RFC5766 ICE標準文檔:
https://datatracker.ietf.org/doc/rfc5766/

第2.2 節 Turn服務器 分配流程

 TURN                                 TURN           Peer          Peer
  client                               server          A             B
    |-- Allocate request --------------->|             |             |
    |                                    |             |             |
    |<--------------- Allocate failure --|             |             |
    |                 (401 Unauthorized) |             |             |
    |                                    |             |             |
    |-- Allocate request --------------->|             |             |
    |                                    |             |             |
    |<---------- Allocate success resp --|             |             |
    |            (192.0.2.15:50000)      |             |             |
    //                                   //            //            //
    |                                    |             |             |
    |-- Refresh request ---------------->|             |             |
    |                                    |             |             |
    |<----------- Refresh success resp --|             |             |
    |                                    |             |             |

客戶端在沒有憑據的情況下向服務器發送了分配請求。由於服務器要求使用STUN的長期憑證機制對所有請求進行身份驗證,因此服務器拒絕該請求並顯示401(未經授權)錯誤代碼。客戶端然後再次嘗試,這次包括憑證(未顯示)。這次,服務器接受分配請求,並返回分配成功響應,該響應包含(除其他事項外)分配給分配的relay傳輸地址。稍後,客戶端決定刷新分配,因此發送刷新請求到服務器。刷新被接受,並且服務器以刷新成功響應進行回覆。

PS:401(未經授權):如果客戶端遵循了長期憑據機制的過程,但仍然收到此錯誤,則服務器不接受客戶端的憑據。在這種情況下,客戶認爲當前交易失敗,應該通知用戶或操作員。除非客戶端認爲問題已解決,否則客戶端不應向該服務器發送任何進一步的請求

所以問題原因找到了,按照標準文檔中的行爲描述,如果第一次不帶憑證訪問coturn 是後放回401錯誤,但後續立刻攜帶憑證則會正常分配 符合我們所預期行爲。

按照說明 401 錯誤是開啓長期憑證導致的? 那如何不開啓長期憑證,長期憑證由lt-cred-mech屬性控制,在coturn config中註釋中說明的很清楚。 不啓用該屬性且不啓用任何權限校驗即可。所以正常情況下都會開啓長期憑證,所以按照文檔說明401錯誤就會出現。

#lt-cred-mech
# This option is opposite to lt-cred-mech. 
# (TURN Server with no-auth option allows anonymous access).
# If neither option is defined, and no users are defined,
# then no-auth is default. If at least one user is defined, 
# in this file or in command line or in usersdb file, then
# lt-cred-mech is default.
#

5 結論

coturn 地址分配 出現401 Unauthorized的 首先應該排查,是否使用靜態用戶名或密碼。比如
turnutils_uclient -u demo -w xxx -p 3478 xxxx.xxxx.xxxx.com
u 和 w 填錯了, 這個可以很容易從coturn 的log中看出來

第二個則則可能是SSL 證書配置問題。

第三個,在turn 過程中出現一次401 是正常流程因爲按照文檔中的默認行爲第一次沒有攜帶憑證訪問,是戶被拒絕,但第二次攜帶憑證拿到releay地址成功。則說明turn 服務仍然是正常的,符合標準的。所以這個401錯誤不用去處理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章