1 代理
現如今的互聯網世界里,代理服務已經十分常見,它通常作為一個第三方或者說中轉站角色替代用戶取得信息或者服務。
根據代理對象的不同,代理服務可以分為正向代理和反向代理。
1.1 正向代理
我們通常所說的代理一般都指的是正向代理,正向代理的是客戶端或者說訪問者。如下圖所示,在特定網絡環境中,客戶端直接訪問目標服務器會被限制,如果有另外一台可以直接訪問到目標服務器,且客戶端也可以訪問到這台服務器,那么就可以以這台服務器作為代理服務器向目標服務器發起訪問,當目標服務器收到訪問請求時,並不會獲知訪問的真正發起者,只會認為是代理服務器發來的請求,返回的消息也是通過代理服務器發送給客戶端。
這整個過程我們可以用一個通俗的例子來類比:我們想要像土豪舅舅借錢,但是土豪舅舅覺得我們太年輕,怕我們借錢胡來就不想借。這時候我們找上了外婆,由外婆去問土豪舅舅借錢,然后我們從外婆手里拿到了錢。在整個借錢過程中,“我”就是這個發起訪問的客戶端,外婆就是這個正向代理,舅舅就是目標服務器,舅舅並不知道實際上還是我這個外甥在借錢,他只知道錢給了外婆,但是錢還是到了我們手上。
Fiddler、mitmproxy抓包,代理ip網絡爬蟲等應用就是基於正向代理。
1.2 反向代理
正向代理代理的是客戶端,與之相反的反向代理代理的就是服務器端,客戶端也並不知道真正訪問的服務器時哪一台。反向代理在負載均衡等功能實現上有很好的應用,如下圖所示,客戶端向代理服務器發起請求,代理服務器接收到請求之后判斷哪台目標服務器處理當前請求最合適,然后將請求轉發該目標服務器進行處理,最后返回的消息也是再次通過代理服務器發送給客戶端。在這整個過程中,客戶端只知道它的請求發送給了代理服務器,並不知道真正處理請求的是誰。
反向代理在大型web中有廣泛應用,以淘寶為例,如此龐大的一個網站一台服務器肯定承擔不了,但我們通過淘寶網購物時,只需要訪問https://www.taobao.com即可,我們並不關心處理我們訪問請求的服務器是哪一台,只要能訪問淘寶購物即可。
反向代理的應用有很多,例如Ngrok、Nginx,還有本文主要要說的FRP。
2 frp代理
FRP,Fast Reverse Proxy,從英文名上可以看出宗旨是建立一種高性能的反向代理應用,采用GO語言開發,能在多種平台運行,支持 TCP、UDP、HTTP、HTTPS 等多種協議類型。目前,FRP在內網穿透,對外網提供服務有着極其廣泛的應用。
2.1 內網穿透
是否遇到過下面兩種困境:
(1)我們平台在外出差,亦或者回到家中后臨時工作需要訪問公司服務器,但是卻苦於所使用的的網絡環境與公司服務器不在同一局域網內,導致無法訪問。
(2)在公司辦公,突然需要訪問一下家里電腦的某個服務(例如數據庫),但是家里的電腦卻沒有固定IP導致沒法訪問。
上面兩種困境大多數喜歡折騰電腦的人都遇到過,如果你還沒有解決,FRP提供的內網穿透就是一個不錯的選擇。
FRP源碼發布在github上面,同時我們可根據自身系統平台在其release頁面下載,直接解壓即可使用。
注意,在使用前必須有一台有固定公網IP的機器作為代理服務器(假設公網ip為90.190.80.10),然后配置防火牆對外開放兩個端口(假設為7000,6000端口)。
我們以外網機器訪問內網服務器上的mongodb數據為例,搭一個內網穿透應用,結合應用來理解原理。
首先配置代理服務器,新建一個frps_mongodb.ini文件,寫入一下內容:
[common]
bind_port = 7000
通過FRP的frps命令啟動代理服務:
$ ./frps -c frps_mongodb.ini
接下來配置內網中需要被訪問機器,新建一個frpc_mongodb.ini文件,寫入一下內容:
[common] server_addr = 90.190.80.10 server_port = 7000 [mongodb] type = tcp local_ip = 127.0.0.1 local_port = 27017 remote_port = 6000
啟動客戶端代理:
$ ./frpc -c frpc_mongodb.ini
完成上述所有操作后,在外網的機器已經可以通過90.190.80.10機器的6000端口來訪問內網機器27017端口對應的mongodb數據庫了。
上述過程中,FRP工作流程如下圖所示:
到了現在,外網已經可以通過訪問到位於局域網內部的數據庫了,不過,這樣安全嗎?
3 stcp代理與數據庫安全
3.1 stcp代理
我們知道,對於重要數據庫而言,是絕不會暴露給外網的,如上一節的通過內網穿透,將內網中的mongodb數據庫提供給外網訪問的方式,任何人只要知道了代理服務器ip和端口,都可以訪問這個mongodb,這對數據庫來說是非常危險的。
驚喜的是,FRP中提供了一種不錯的解決方案——stcp代理。
與上面介紹過的普通代理方式不同,stcp代理要求在訪問端也運行一個FRP,在通過代理服務器進行通話前,代理服務器將會對比訪問端和被訪問端的sk口令,只有當兩者的sk口令一致時,才允許轉發信息,有效避免通過FRP內網穿透攻擊到數據庫。
使用stcp代理方式時,服務器端配置與上面一樣,不再多說,關鍵在於訪問端配置和內網被訪問端機器配置。
內網中的被訪問端配置,新建frpc_mongodb.ini,內容如下:
[common] server_addr = 90.190.80.10 server_port = 7000 [mongodb] # 指定代理類型 type = stcp local_ip = 127.0.0.1 local_port = 27017 sk = password123
啟動被訪問端frp代理服務:
$./frpc -c frpc_mongodb.ini
如果只需要共一台機器訪問,那么在該機器上新建配置文件frpc_mongo_viditor.ini,內容如下:
[common] server_addr = 90.190.80.10 server_port = 7000 [mongodb_visitor] type = stcp # stcp 的訪問者 role = visitor # 要訪問的 stcp 代理的名字,也就是上面frpc_mongodb.ini中配置的[mongodb] server_name = mongodb # 下面的sk口令必須與上面配置的sk一直才能訪問 sk = password123 # 綁定本機端口用於訪問 mongodb服務 bind_addr = 127.0.0.1 bind_port = 6000
啟動frpc服務:
$./frpc -c frpc_mongodb_viditor.ini
代理服務器、訪問端、內網被訪問端三者的代理服務都開啟后,那么訪問端局域網內所有機器就可以通過192.168.0.10機器的6000端口訪問另一端內網中的mongodb數據庫了,而在其他沒有開啟frp代理或者sk口令不正確的是訪問不了的。
3.2 代理雲服務器數據庫
明白了stcp代理方式后,我們就可以擴展一下這種代理方式的的用途。
在很多時候,數據庫是部署在雲服務器上的,在某些情況下,這些數據庫不得不提供給外界訪問,但如果直接開放端口,將數據庫暴露給外網,卻又給數據庫帶來安全隱患。
此時也可以用stcp代理來解決這一問題。
在上文介紹正向代理和反向代理時說過,經過代理服務器轉發后,服務器只會認為是代理服務器在發起訪問。回到數據庫的問題,以mongodb數據庫為例,數據庫配置為綁定本機IP127.0.0.1和27017端口,那么一切來自其他機器的訪問都會被拒絕,但卻不會拒絕來自本機其他端口的訪問。所以,解決上述問題的思路就是使用FRP的stcp代理方式來代理本機數據庫服務端口,那么其他機器只要具有正確的sk口通過stcp代理方式就可以連接上數據庫。
因為是本機代理本機,所以我們可以修改一下上面的配置,將服務器IP地址改為127.0.0.1,對於frps,配置文件為frps_mongodb.ini,內容如下:
[common] server_addr = 127.0.0.1 server_port = 7000
被訪問端也是本機,只不過也是在雲服務器上啟動,配置文件為frpc_mongodb.ini,內容如下:
[common] server_addr = 127.0.0.1 server_port = 7000 [mongodb] # 指定代理類型 type = stcp local_ip = 127.0.0.1 local_port = 27017 sk = password123
假設訪問端代理服務部署在局域網IP為192.168.0.10服務器上,如果需要讓局域網內所有機器都能夠使用代理來連接數據庫,在該機器上新建配置文件frpc_mongodb_visitor.ini,內容如下:
[common] server_addr = 90.190.80.10 server_port = 7000 [mongodb_visitor] type = stcp # stcp 的訪問者 role = visitor # 要訪問的 stcp 代理的名字 server_name = mongodb sk = password123 # 綁定本機局域網ip、端口,可供局域網內所有機器訪問 bind_addr = 192.168.0.10 bind_port = 6000
4 總結
FRP提供了一種便捷的方式實現內網穿透,使得即是在外網也能夠使用到局域網內部的服務,但數據誠可貴,即使FRP中提供了stcp這種安全的代理方式,誰又能保證使用這種方式后會不會代理新的隱患,慎思之,篤行之。