jsproxy基于瀏覽器端 JS 實(shí)現(xiàn)的在線代理
jsproxy 是一個(gè)基于瀏覽器端 JS 實(shí)現(xiàn)的在線代理
安裝
curl https://raw.githubusercontent.com/EtherDream/jsproxy/master/i.sh | bash
-
自動(dòng)安裝目前只支持 Linux x64,并且需要 root 權(quán)限
-
安裝過程中 80 端口能被外網(wǎng)訪問(申請(qǐng) HTTPS 證書)
無法滿足上述條件,或想了解安裝細(xì)節(jié),可嘗試手動(dòng)安裝。
測(cè)試: https://服務(wù)器IP.xip.io:8443(具體參考腳本輸出)
部署
Fork 本項(xiàng)目,進(jìn)入 gh-pages 分支,編輯 conf.js 文件:
-
節(jié)點(diǎn)列表(
node_map字段,包括節(jié)點(diǎn) id 和節(jié)點(diǎn)主機(jī)) -
默認(rèn)節(jié)點(diǎn)(
node_default字段,指定節(jié)點(diǎn) id)
訪問 https://用戶名.github.io/jsproxy 預(yù)覽。
GitHub 支持自定義域名。也可以將文件發(fā)布到自己的 Web 服務(wù)器上。
維護(hù)
# 切換到 jsproxy 用戶 su - jsproxy # 重啟服務(wù) ./run.sh reload # 關(guān)閉服務(wù)(參數(shù)和 nginx -s 相同) ./run.sh quit # 啟動(dòng)服務(wù) ./run.sh # 查看代理日志 tail server/nginx/logs/proxy.log
目前暫未實(shí)現(xiàn)開機(jī)自啟動(dòng)。
禁止外鏈
默認(rèn)情況下,代理接口允許所有 github.io 子站點(diǎn)調(diào)用,這可能導(dǎo)致不必要的流量消耗。
如果希望只給自己網(wǎng)站使用,可編輯 allowed-sites.conf。(重啟服務(wù)生效)
安全策略
如果不希望代理訪問內(nèi)網(wǎng)(避免 SSRF 風(fēng)險(xiǎn)),可執(zhí)行 setup-ipset.sh:
/home/jsproxy/server/setup-ipset.sh
需要 root 權(quán)限,依賴
ipset命令
該腳本可禁止 jsporxy 用戶訪問保留 IP 段(針對(duì) TCP)。nginx 之外的程序也生效,但不影響其他用戶。
項(xiàng)目特點(diǎn)
相比傳統(tǒng)在線代理,本項(xiàng)目具有以下特點(diǎn):
服務(wù)端開銷低
傳統(tǒng)在線代理幾乎都是在服務(wù)端替換 HTML/JS/CSS 等資源中的 URL。這不僅需要對(duì)內(nèi)容做大量的分析和處理,還需對(duì)流量進(jìn)行解壓和再壓縮,消耗大量 CPU 資源。并且由于邏輯較復(fù)雜,通常使用 Python/PHP 等編程語言自己實(shí)現(xiàn)。
為降低服務(wù)端開銷,本項(xiàng)目使用瀏覽器的一個(gè)黑科技 —— Service Worker。它能讓 JS 攔截網(wǎng)頁產(chǎn)生的請(qǐng)求,并能自定義返回內(nèi)容,相當(dāng)于在瀏覽器內(nèi)部實(shí)現(xiàn)一個(gè)反向代理。這使得絕大部分的內(nèi)容處理都可以在瀏覽器上完成,服務(wù)器只需純粹的轉(zhuǎn)發(fā)流量。
因此本項(xiàng)目服務(wù)端直接使用 nginx,并且轉(zhuǎn)發(fā)過程不修改內(nèi)容(只修改 HTTP 頭),避免了內(nèi)容處理產(chǎn)生的巨大開銷。同時(shí)得益于 nginx 豐富的功能,很多常用需求無需重新造輪子,通過簡(jiǎn)單配置即可實(shí)現(xiàn)。并且無論性能還是穩(wěn)定性,都遠(yuǎn)高于自己實(shí)現(xiàn)。
API 虛擬化
傳統(tǒng)在線代理大多只針對(duì)靜態(tài) URL 的替換,忽視了動(dòng)態(tài) URL 以及和 URL 相關(guān)的網(wǎng)頁 API。例如 a.com 反向代理 google.com,但頁面中 JS 讀取 document.domain 得到的仍是 a.com。這可能導(dǎo)致某些業(yè)務(wù)邏輯出現(xiàn)問題。
為緩解這個(gè)問題,本代理在頁面頭部注入一個(gè) JS,用以重寫絕大部分和 URL 相關(guān)的 API,使得頁面中的 JS 獲取到的仍是原始 URL:
對(duì)于有些無法重寫的 API,例如 location,本代理會(huì)將代碼中字面出現(xiàn)的 location 替換成 __location,從而將操作轉(zhuǎn)移到自定義對(duì)象上。當(dāng)然對(duì)于非字面的情況(例如 this['lo' + 'cation']),目前還無法處理。
