拋出問題
你是否遇到過這樣的問題:以前一個(gè)運(yùn)行得好好的系統(tǒng),突然在某個(gè)時(shí)刻(2021年9月21日之后)用戶反饋說用不了了。如果用戶允許你F12進(jìn)行網(wǎng)絡(luò)交互或者控制臺(tái)輸出查看時(shí),你會(huì)發(fā)現(xiàn)這樣的錯(cuò)誤:
Access
to XMLHttpRequest at 'http://[some_url]' from origin
'http://[some_url]' has been blocked by CORS policy: The request client
is not a secure context and the resource is in more-private address
space 'private'.
然后請(qǐng)求就中斷了,后續(xù)的邏輯自然也就沒辦法進(jìn)行了。乍一看是跨域策略(CORS policy)的問題,趕緊去看看接口的Response Header與跨域相關(guān)的配置:
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With, Content-Range, Content-Type
Access-Control-Expose-Headers: Range
和跨域相關(guān)的配置也都返回了(要不然以前的系統(tǒng)也不能正常地運(yùn)行),怎么突然就報(bào)錯(cuò)了呢?如果你遇到了相同的疑問,那么這篇文章就繼續(xù)讀下去吧。
復(fù)現(xiàn)問題
首先,你操作的業(yè)務(wù)系統(tǒng),其域名一定指向的是一個(gè)公網(wǎng)IP地址。這里我們假設(shè)名為"out.com";
其次,在上述業(yè)務(wù)系統(tǒng)中調(diào)用了另外一個(gè)系統(tǒng)的接口,該子系統(tǒng)域名指向的是一個(gè)內(nèi)網(wǎng)IP(無(wú)論A類B類還是C類子網(wǎng))地址(localhost, 127.*.*.*, [::1]除外)。這里我們假設(shè)名為“in.com”。
最后,一定是上述兩個(gè)系統(tǒng)都采用http協(xié)議進(jìn)行訪問。
舉個(gè)例子*:
ping out.com
來(lái)自 110.242.68.66 的回復(fù): 字節(jié)=32 時(shí)間=12ms TTL=48
ping in.com
來(lái)自 10.29.10.136 的回復(fù): 字節(jié)=32 時(shí)間=12ms TTL=48
操作頁(yè)面:http://out.com/article/process,在該頁(yè)面中有如下JS:
$.ajax({url:"http://in.com/api/auditors", method:"GET", success:function(ret) {}})
那么此時(shí)就會(huì)復(fù)現(xiàn)文章開頭描述的問題。
*注:以上數(shù)據(jù)經(jīng)過脫敏處理,所涉及域名和IP地址并非真實(shí)數(shù)據(jù),僅供內(nèi)容闡述之用。
問題原因
為什么升級(jí)到Chrome 94開始就有問題了呢?在這一版中,它禁止了公共非安全上下文(廣義上說,不通過 HTTPS 或來(lái)自私有 IP 地址的網(wǎng)站)向私有網(wǎng)絡(luò)發(fā)出請(qǐng)求。聽起來(lái)很難理解。讓我們抽出這句話的關(guān)鍵詞:公共上下文 / 請(qǐng)求 / 私有網(wǎng)絡(luò)。
這里不得不聊一下現(xiàn)在的網(wǎng)絡(luò)應(yīng)用背景。越來(lái)越多的家庭出現(xiàn)了嵌入式設(shè)備。而這些設(shè)備的安全性普遍都不是很高。僅僅提供一個(gè)簡(jiǎn)單的http配置界面給用戶。如果訪問了一個(gè)外網(wǎng)別有用心的網(wǎng)頁(yè),里面被嵌入了一個(gè)內(nèi)網(wǎng)的ajax請(qǐng)求,那么這些家庭中的嵌入式設(shè)備就很容易遭到攻擊。下面是我總結(jié)的一張表格,含義是外網(wǎng)資源采用不同的協(xié)議訪問內(nèi)網(wǎng)資源時(shí)的組合情況。
外網(wǎng)訪問內(nèi)網(wǎng) | http | https |
http | Chorme 94禁止 | Chorme 94禁止 |
https | 安全內(nèi)容加載不安全內(nèi)容,禁止 | 取跨域策略 |
這里可以給大家舉個(gè)例子。部分型號(hào)的TP-Link路由器,為了方便用戶進(jìn)行配置,只要連接上(通過有線或者無(wú)線),瀏覽器輸入:tplogin.cn就可以自動(dòng)打開管理界面(域名自動(dòng)解析到默認(rèn)網(wǎng)關(guān))。在Chrome 94之前,當(dāng)用戶打開了一個(gè)“精心設(shè)計(jì)”的http頁(yè)面,內(nèi)部編寫了一套針對(duì)tplogin.cn的攻擊JS。那么處于內(nèi)網(wǎng)的路由器就有被侵入的風(fēng)險(xiǎn)。
其實(shí)由此可以聯(lián)想到現(xiàn)在的智能手機(jī),在iOS中,如果應(yīng)用需要網(wǎng)絡(luò)權(quán)限,用戶可以選擇蜂窩和無(wú)線網(wǎng)絡(luò),而無(wú)線網(wǎng)絡(luò)又可以選擇是否允許訪問本地網(wǎng)絡(luò)。此功能與Chrome本次的跨域策略升級(jí)其實(shí)是基于同樣的考量。
解決方法
方案一:同時(shí)升級(jí)外部系統(tǒng)和內(nèi)部系統(tǒng),都采用https協(xié)議訪問;
方案二:如果你有權(quán)限控制外部系統(tǒng),讓外部系統(tǒng)在公司內(nèi)網(wǎng)中也解析為內(nèi)網(wǎng)地址。
如果你不得不采用http方式訪問(例如:沒有對(duì)應(yīng)的https證書),那么用戶可以在瀏覽器中禁用掉這一策略。在chrome中打開此地址:
chrome://flags/#block-insecure-private-network-requests
將Block insecure private network requests配置禁用掉(Disable)。但是一定要注意,修改了配置后必須點(diǎn)擊Chrome此時(shí)在右下角出現(xiàn)的“重啟”(Restart)按鈕才能生效。自己主動(dòng)關(guān)閉瀏覽器全部頁(yè)面再打開是不會(huì)觸發(fā)Chrome更新配置的。
參考文獻(xiàn)
[1]Titouan Rigoudy,Private Network Access update: Introducing a deprecation trial
[EB/OL].https://developer.chrome.com/blog/private-network-access-update/,2022-02-10.