一、前言
閱讀本文前需要先搞懂NAT、PAT、端口映射幾個概念,前面我有寫了一篇關於這幾個概念的博文。根據之前的博文我們已經知道,內網寬帶中的主機可以訪問公網寬帶主機,反之不可以訪問;公網寬帶主機可以和公網寬帶主機雙向訪問;內網寬帶中的主機和內網寬帶中的主機互相無法訪問。那么內網寬帶中的客戶機和公網寬帶中的客戶機如何訪問另一個內網寬帶中的服務器呢?這里就需要用到內網穿透技術。
二、應用場景
家里或公司是運營商內網ipv4寬帶或公網IP在防火牆后,且需要在外訪問家里或公司的電腦、NAS、樹莓派、攝像頭等網絡設備或遠程控制等情況下。
三、詳細原理
3.1 傳統內網穿透(服務器中轉數據穿透)原理
對於在NAT之后的服務器來說,其不是不能主動訪問公網端口,而是不能反過來有效的被公網訪問。所以可以在中間架設一個公網服務器,讓在NAT之后的服務器持續主動訪問這個擁有公網IP地址的服務器,,這樣內網服務器就成功與公網中轉服務器建立了一個連接通道。然后當有任何其他NAT后的客戶端主動連接公網中轉服務器時,公網服務器接收到連接請求之后馬上把這連接請求通過先前建立好的隧道轉發到內網服務器,內網服務器將響應數據包再原路轉發回去,最終到達公網中轉服務器,然后返回給其他NAT后的客戶端。
3.2 點對點穿透原理
在內網穿透傳輸大量數據時如果都經過服務器中轉的話,這樣會對服務器端帶寬壓力比較大。只要是數據量很大,而一般利用中轉服務器又需要一定規模投入的應用,我們都可以考慮用P2P技術。
1.UDP打洞技術
最為常見的實現P2P的方式是采用UDP打洞技術,UDP打洞技術是通過中間服務器的協助在各自的NAT網關上建立相關的表項,使P2P連接的雙方發送的報文能夠直接穿透對方的NAT網關,從而實現P2P客戶端互連。如果兩台位於NAT設備后面的P2P客戶端希望在自己的NAT網關上打個洞,那么他們需要一個協助者——集中服務器,並且還需要一種用於打洞的Session建立機制。
Session建立機制:
假定客戶端A要發起對客戶端B的直接連接,具體的“打洞”過程如下:
(1)A最初不知道如何向客戶端B發起連接,於是A向集中服務器(本質上是一台被設置在公網上的服務器,建立P2P的雙方都可以直接訪問到這台服務器。位於NAT網關后面的客戶端A和B都可以與一台已知的集中服務器建立連接,並通過這台集中服務器了解對方的信息並中轉各自的信息)發送消息,請求集中服務器幫助建立與客戶端B的UDP連接。
(2)集中服務器將含有B的外網和內網的地址二元組發給A,同時,集中服務器將包含有A的外網和內網的地址二元組信息的消息也發給B。這樣一來, A與B就都知道對方外網和內網的地址二元組信息了。
(3)當A收到由集中服務器發來的包含B的外網和內網的地址二元組信息后,A開始向B的地址二元組發送UDP數據包,並且A會自動鎖定第一個給出響應的B的地址二元組。同理,當B收到由集中服務器發來的A的外網和內網地址二元組信息后,也會開始向A的外網和內網的地址二元組發送UDP數據包,並且自動鎖定第一個得到A回應的地址二元組。一旦A與B都向對方的NAT設備在外網上的地址二元組發送了數據包,就打開了A與B之間的“洞”,A與B向對方的外網地址發送數據,等效為向對方的客戶端直接發送UDP數據包了。一旦應用程序確認已經可以通過往對方的外網地址發送數據包的方式讓數據包到達NAT后面的目的應用程序,程序會自動停止繼續發送用於“打洞”的數據包,轉而開始真正的P2P數據傳輸。
當然,UDP轉換協議提供的“洞”不是絕對可靠的,多數NAT設備內部都有一個UDP轉換的空閑狀態計時器,如果在一段時間內沒有UDP數據通信,NAT設備會關掉由“打洞”過程打出來的“洞”。如果P2P應用程序希望“洞”的存活時間不受NAT網關的限制,就最好在穿越NAT以后設定一個穿越的有效期。2.TCP打洞技術
從現在的主流應用的角度上來看,基於TCP的P2P應用顯然不如基於UDP的應用那么廣泛,但是也存在打洞的需求。TCP相對於UDP而言要復雜的多,TCP連接的建立要依賴於三次握手的交互,所以NAT網關在處理TCP連接的時候,需要更多的開銷。但是,由於TCP協議完備的狀態機機制,TCP反而比UDP更能精確的獲取某個Session的生命期。
一種新的代理類型 XTCP 能解決這個問題,實現方式可以是采用搭建FRP服務器的方式,在傳輸數據的兩端都部署上FRP客戶端用於建立直接的連接。
3.3 延伸一個內網滲透知識
為了安全起見,通常會在網絡中加入防火牆,防火牆有入站規則和出站規則。如果不是非常嚴格的安全管控,通常是不會設置出站規則的,但是入站規則一般都會設置的,比如說外部可以通過80端口傳入內網的WEB服務器訪問網頁,但是不能通過3389端口登陸內網的遠程桌面。而在內網滲透的過程中碰到這種情況,我們也可以借助上面內網傳統的方式實現穿透防火牆的入站規則。因為防火牆通常只攔截了入站,沒有攔截出站,那么我們可以讓內網服務器主動出站(主動連接到黑客的服務器),與黑客自己的服務器打通隧道,最終繞過防火牆連上3389遠程桌面。
還有一種情況就是我們已經拿下了內網其中一台並沒有做任何防火牆規則的白名單服務器,但是我們想連上內網另一台做了入站規則的目標服務器,那么我們可以讓這台白名單服務器作為一個跳板,讓他先監聽自身任意一個端口,然后在有任何用戶連上這個端口之后,白名單服務器就主動連上內網的目標服務器,然后借助這台白名單服務器打通黑客和目標服務器的連接隧道。而在黑客工具中大名鼎鼎的lcx原理也就是如此,前者的實現是lcx的listen和slave命令,后者的實現是lcx的tran命令。
3.4 穿透原理總結
內網穿透傳統方式會出現服務器和客戶機之間的數據傳輸全部經過中轉服務器,傳輸速度將受制於中轉服務器的上下行帶寬,不過穩定性很好,對於自己要購置的雲主機要求就是大帶寬,一般這種雲主機按流量計費,傳輸的數據量越大價格自然越貴。所以點對點穿透便能解決流量帶來的困擾,點對點可以實現服務器和客戶機之間打洞直接進行數據通信,這種方式一般用於udp協議的傳輸,比如應用於遠程NAS看視頻聽歌,但這種方式需要服務器和客戶機都安裝穿透工具,對用戶訪問端來說不夠方便,而且這種方式受復雜網絡環境影響較大,不能100%實現,穩定性欠缺。
四、方法實現
4.1 幾款主流工具實現
1.frp(開源):
FRP使用 Go 語言開發,可以支持 Windows、Linux、macOS、ARM 等多平台部署。frp內網穿透無需多復雜的配置就可以達到比較好的穿透效果,具有較強的擴展性,支持tcp, udp, http, https 協議,並且 web 服務支持根據域名進行路由轉發。此外,FRP 提供了一種新的代理類型 XTCP ,可以在傳輸大量數據時讓流量不經過服務器中轉,用於實現點對點穿透,當然,此功能並不能保證在你的網絡環境 100% 可用,成功率較低,而且還要求訪問端也得運行 FRP 客戶端 (目前手機端ios沒有frp客戶端軟件)。由於實現條件較多,所以有文件傳輸需求的朋友但必須用frp的朋友還是建議買帶寬稍大一點的 VPS 會比較省心。frp適合有linux基礎的個人,且需要自購一個雲主機做中轉,企業追求穩定可以考慮其他方式。
2.ngrok(開源):
ngrok是一個反向代理,通過在公共的端點和本地運行的Web服務器之間建立一個安全的通道。ngrok可捕獲和分析所有通道上的流量,便於后期分析與響應。主要用途是給網站或者安裝開發提供部署環境,但是也同樣可以用來進行端口轉發。ngrok適合有linux基礎的個人,和frp類似,但比frp配置稍復雜,且需要自購一個雲主機做中轉,企業追求穩定可以考慮其他方式。
3.zerotier(開源/商業):
ZeroTier官方解釋為將整個世界轉變為單個數據中心或雲區域,將所有設備,虛擬機和應用程序聯接起來,就像在同一個交換機接入所有設備一樣。zerotier類似VPN,為內網服務器所在NAT網絡和客戶機所在NAT網絡各虛擬出一個VLAN,這樣倆個VLAN就可以通過ZeroTier建立連接,在通過UDP打洞技術就可以實現內網服務器和內網客戶機直接交互數據。目前ZeroTier提供的點對點穿透技術成功率還是比較高的,可以應付大多數網絡,國內長城寬帶無法點對點穿透。而zerotier因為是國外的項目,官方提供的中轉服務器在國外,國內連接延遲高甚至連不上,所以官方給出了moons概念,可以自己搭建中轉服務器。另外ZeroTier 支持 Windows、macOS、Linux 三大主流平台,iOS、Android 兩大移動平台,以及 QNAP(威連通)、Synology(群暉)、Western Digital MyCloud NAS(西部數據)三個 NAS 平台,還支持 LEDE 開源路由器項目,支持客戶端真的很多。zerotier適合有linux基礎的個人,一般用於NAS,為了穩定性需要自購一個雲主機做中轉,服務器和客戶機都需要安裝zerotier,企業追求穩定可以考慮其他方式。
4.花生殼(商業):
花生殼既是內網穿透軟件、端口映射軟件。功能比較齊全,比較簡單,也是大家比較耳熟了,支持tcp,udp.https.http,socket5應用。流量還是得走傳說中的rootnode,所以是限流1G,分的等級比較多商業版、旗艦版、鉑金版,需要根據不同需求付費開通相關功能。安裝使用門檻低,無需自購雲主機做中轉,企業商用追求穩定可以選擇花生殼付費版本。
5.Nat123(商業):
nat123是內網端口映射與動態域名解析(DDNS)軟件,在內網啟動映射后,可在外網訪問連接內網網站等應用。安裝使用門檻低,無需自購雲主機做中轉,企業商用追求穩定可以選擇此方式付費版。
6.NATAPP(商業):
natapp是基於ngrok的國內收費內網穿透工具,類似花生殼,有免費版本,比花生殼好。免費版本:提供http,https,tcp全隧道穿透,隨機域名/TCP端口,不定時強制更換域名/端口,自定義本地端口。安裝使用門檻低,無需自購雲主機做中轉,企業商用追求穩定可以選擇此方式付費版。
7.向日葵、teamviewer、anydesk(遠程桌面):
這三款比較特殊,都是用來遠程桌面使用,原理就是基於點對點穿透+傳統穿透,三款軟件都有免費版本,經本人長期工作使用發現,teamviewer免費版穩定性和連通性可以說是最好的,但“懷疑商業用途”不時彈出加上近年來爆出的漏洞,而anydesk使用過程中會經常斷連,所以現在很多國內用戶都轉用了免費版的向日葵,本人使用中發現移動網絡環境下使用向日葵很卡。
8.VPN(加密穿透):
原理類似zerotier,利用組建虛擬網絡,局域網VLAN通信的方式,不同的是不打洞,流量均走中間服務器,內網服務端和客戶端均需要安裝vpn軟件,但是它大量使用了OpenSSL加密庫中的SSLv3/TLSv1協議函數庫,數據通信全程加密,非常適用於企業內網資料供員工在外網訪問,一般使用開源的openvpn,因相關規定這里就不做過多描述和搭建介紹了。對了,VPN還有個作用就是用來正向代理,游戲加速器就是基於VPN正向代理原理,有興趣的童鞋可以自行查找相關資料,而正向代理典型的工具是S..,不能說了,再說下去這篇博文就要被刪了...
4.2 方法實現總結
商業付費版暫不具體闡述,只能說花錢的就是好,有專業團隊維護,且使用簡單方便,但要注意由於數據包會流經第三方,因此對數據安全也是一大隱患。那么對於個人有動手能力的用戶或者中小型企業小規模使用可以選擇開源方式,綜合軟件配置復雜度、穿透能力等因素,個人覺得目前最好的選擇就是frp用於對流量轉發不大的場景,而需要大量udp傳輸的場景選擇zerotier。
五、案例配置
經過前面的介紹,相信大家對內網穿透的幾個實現方法有了大概的了解,那么接下來就針對frp和zerotier分別做下安裝配置的講解。
5.1 frp安裝配置
1)中轉服務器frps安裝配置:
FRP 安裝非常容易,只需下載對應系統平台的軟件包並解壓就可用了。這里以centos7系統為例:
安裝腳本:
#!/bin/bash
#0.33.0是frp的版本號 (截稿為止最新版本)
export FRP_VERSION=0.33.0
sudo mkdir -p /etc/frp
cd /etc/frp
sudo wget "https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_linux_amd64.tar.gz"
sudo tar xzvf frp_${FRP_VERSION}_linux_amd64.tar.gz
sudo mv frp_${FRP_VERSION}_linux_amd64/* /etc/frp
如上在/etc/frp目錄下關注4個文件,分別是frpc、frpc.ini和frps、frps.ini,前者兩個文件是客戶端所關注文件,后者兩個文件是服務端所關注兩個文件。這里配置服務端(公網服務器),首先刪掉frpc、frpc.ini兩個文件,然后再進行配置,vi ./frps.ini,FRP 默認提供了2個服務端配置文件,一個是簡化版的frps.ini,包含了基礎配置,另一個是完整版的frps_full.ini,包含了frp其他功能配置,這里不做詳細介紹,感興趣的小伙伴可以自行去官方查看,初學者只需用簡版配置即可,在簡版 frps.ini 配置文件里,默認設置了監聽端口為 7000,你可以按需修改它。來看看簡化版的:
> $ vi frps.ini
[common]
bind_port = 7000 #隧道端口,默認配置中監聽的是 7000 端口,可根據自己實際情況修改。
subdomain_host = frp.abc.top #配置中轉服務器域名綁定,可選配置,如果域名多可以設置一個
authentication_method = token #啟用token驗證,frpc也需要加此參數
token = changeit #token密碼
vhost_http_port = 80 #內網服務器http映射的端口,內網可以有多個網站使用這個端口
vhost_https_port = 443 #內網服務器https映射的端口,內網可以有多個網站使用這個端口
dashboard_port = 7500 #配置Dashboard監控frp狀態的端口,后面可以直接訪問http://frp.abc.top:7500/或http://中轉服務器公網IP:7500/
dashboard_user = admin #監控訪問賬戶
dashboard_pwd = admin #監控訪問密碼
前台啟動frps
./frps -c ./frps.ini
配置自動啟動:首先
sudo vi /lib/systemd/system/frps.service
在frps.service里寫入以下內容
[Unit]
Description=fraps service
After=network.target network-online.target syslog.target
Wants=network.target network-online.target
[Service]
Type=simple
#啟動服務的命令(此處寫你的frps的實際安裝目錄)
ExecStart=/etc/frp/frps -c /etc/frp/frps.ini
[Install]
WantedBy=multi-user.target
這時候就可以用centos7的systemctl命令了,設置開機啟動
sudo systemctl enable frps
請一定要記住,你需要將服務器的系統防火土嗇,以及阿里雲、騰訊雲后台里找到“安全組策略”的相關配置,設置 7000 7500或你修改過的對應端口的「允許入站和出站」,否則會一直連接不上的哦!!!這個切記!!
如服務器使用 Win 系統,假設解壓到 c:\frp 文件夾,那么只需這樣啟動:
c:\frp\frps.exe -c c:\frp\frps.ini
這里可以為frp添加進程守護,防止訪問因意外導致frp進程終止,我們寫個腳本來監控frp運行
#!/bin/bash
#添加本地執行路徑
export LD_LIBRARY_PATH=/etc/frp/
while true; do
server=`ps aux | grep frpc | grep -v grep`
if [ ! "$server" ]; then
nohup ./frpc -c ./frpc.ini &
fi
sleep 60
done
2)內網服務器frpc安裝配置:
設置好中轉服務器上 Frp 服務端后,我們就需要在內網服務器上安裝 Frp 的客戶端了。 這里安裝方式和中轉服務器一樣,此處省略。當然內網服務器可以是 Windows 電腦、Linux 設備 (比如樹莓派) 或者 NAS,甚至部分路由器等設備上。Linux 客戶端的安裝和啟動與服務器端沒有太多區別,只是對應運行程序是 frpc 而不是 frps。前面介紹了Linux安裝,這里就以內網服務器為 Windows 電腦來安裝 Frp 客戶端,因為 Frp 是綠色程序,下載軟件包回來解壓后,啟動 frpc.exe 即可。但在啟動前,我們需要先修改配置文件,首先刪掉frps、frps.ini、frps_full.ini幾個文件。假設你的 FRP 中轉服務端所在的 VPS 公網 IP 為 1.2.3.4或為域名 frp.abc.top, 而客戶端是 Win 電腦,我們來修改 frpc.ini 配置文件:
[common]
server_addr = 1.2.3.4或者frp.abc.top #公網服務器ip或域名
server_port = 7000 #隧道端口,與服務端bind_port一致
authentication_method = token #啟用token驗證,frps也需要加此參數
token = changeit #token密碼
[ssh] #公網通過ssh訪問內部服務器(這一種ssh是最簡單暴露公網不太安全的映射,如果需要安全的ssh,可以看后面的配置[secret_ssh])
type = tcp #連接協議tcp
local_ip = 192.168.1.30 #內網服務器在局域網中的 IP (如是本機,也可使用 127.0.0.1)
local_port = 22 #內網服務器ssh端口號
remote_port = 6000 #自定義的訪問中轉服務器映射的ssh端口號,客戶機訪問中轉服務器IP:6000即可到達本機ssh
[secret_ssh] #公網通過ssh加密訪問內部服務器,注意這種方式還需要在客戶機 [secret_ssh_visitor]
#上安裝配置frpc.ini(客戶機配置請看右邊[secret_ssh_visitor]) type = stcp
type = stcp #連接協議stcp role = visitor
sk = abcdefg #客戶端連接ssh的秘鑰 server_name = secret_ssh
local_ip = 127.0.0.1 sk = abcdefg
local_port = 22 bind_addr = 127.0.0.1
remote_port = 6000 bind_port = 6000
[web] #公網訪問內部web服務器以http方式
type = http #訪問協議
local_port = 80 #內網web服務的端口號
custom_domains = repo.iwi.com #所綁定的中轉服務器IP的域名,一級、二級域名都可以,此域名會映射給中轉服務端,客戶機訪問http://repo.iwi.com:8000即可到達本機web
remote_port = 8000 #自定義的訪問中轉服務器映射的web端口號,客戶機訪問中轉服務器IP:8000或域名:8000即可到達本機web。如果中轉服務器配置了vhost_http_port = 80和vhost_https_port = 443,這里可以省略,不省略則訪問端口以這里配置為准。
[RDP] #Windows 遠程桌面控制
type = tcp
local_ip = 192.168.1.30 #內網服務器在局域網中的 IP (如是本機,也可使用 127.0.0.1)
local_port = 3389
remote_port = 7002
# 如果內網服務器是https,還需要做以下配置(frp對於https的映射代理原理在后面會有工作流程圖介紹)
[web_https] #Https服務,映射的是服務端https443端口
type = https #服務方式
local_ip = 127.0.0.1 #內網服務器在局域網中的 IP (如是本機,也可使用 127.0.0.1)
local_port = 443 #內網web服務的端口號
custom_domains = test.test.com #所綁定的中轉服務器IP的域名,一級、二級域名都可以,此域名會映射給中轉服務端,客戶機訪問https://test.test.com:443即可到達本機web
#配置https插件部分(這里都配置在了內網服務器端,即frp客戶端,實際是有缺陷的,后面https工作原理介紹會提到,還可以在中轉服務器,即frp服務端結合nginx配置,我個人推薦選擇中轉服務器端結合nginx做配置,后面會有詳細配置介紹)
plugin = https2http #配置插件,將https請求轉換成http請求后再發送給本地服務
plugin_local_addr = 127.0.0.1:80 #轉換http后的端口,這里端口號為前面設置[web]的local_port,即內網服務器http的web服務的端口號
remote_port = 8001 #同http配置,這一句可選加
#內網服務器證書相關配置
plugin_crt_path = C:\Users\Administrator\Desktop\test.test.com\fullchain1.crt #linux下生成的證書為fullchain.pem格式,復制到Windows上改成.crt后綴即可
plugin_key_path = C:\Users\Administrator\Desktop\test.test.com\privkey1.key #linux下生成的證書為privkey.pem格式,復制到Windows上改成.key后綴即可
plugin_host_header_rewrite = 127.0.0.1 #這里必須寫成 127.0.0.1
plugin_header_X-From-Where = frp #指定代理方式為 frp
這樣就在本地上新增了“ssh”和“web”以及“RDP”“https”幾個可供公網訪問的服務了 (它們名稱可以自己取)。如果你需要添加更多的設備和服務供外網訪問,那么只需要照葫蘆畫瓢,指定正確的 IP 地址和端口號即可。
注意放行端口:每個服務的 remote_port 是遠程訪問時要用到的端口號,注意這些端口號也要在服務器的防火土嗇和安全組里放行才能順利訪問的,如上面的 6000、7002、8000。關於https穿透工作流程介紹:
訪客在瀏覽器中輸入網址 https://123.blog.com 后,瀏覽器會查詢 的 IP,查詢到之后,向此 IP 的 443 端口發送 https 請求。frp 服務端收到此請求后檢查訪問的域名,發現曾經連接此 frp 服務端的一個客戶端配置了此域名的反向代理。於是將請求轉發給此客戶端。frp 客戶端在收到轉發的 https 請求后,使用 SSL 證書將 https 解密成 http 請求,然后修改 http 頭添加或修改額外的信息。最后,frp 客戶端將修改后的 http 請求轉發給本機的真正的 Web 服務程序。當 Web 服務程序處理完 Web 請求后,響應沿着原路返回。這里值得注意的是,由於 frp 反向代理系統中,使用 SSL 證書的一端在 frp 客戶端,這意味着 frp 服務端完全無法得知此 https 請求的內容。於是在轉發后也無法得知此請求的真實來源(訪客 IP),這樣,真實的 Web 服務將無法得知真實的訪客信息。這也是 frp 在此設計下必然出現的缺陷。如果你希望你的 Web 服務在 https 下破除這些限制,那么建議使用其他的反向代理服務器。關於其他配置 https 的方法,我建議在中轉服務器中使用 Nginx 為你的 Web 服務添加 https 支持,這種方法可以獲得真實的訪客信息。
介紹下中轉服務器中Nginx+frp實現https轉發配置:
中轉服務器中nginx的安裝就不做介紹了,yum、docker都可以快速安裝。這里直接上nginx.conf配置
server
{
listen 443 ssl; # https對應端口,注意因為有nginx也有frps,以nginx這里的端口為准,frps中的vhost_http**s**_port不用配置
ssl_certificate /etc/letsencrypt/live/test.test.com/fullchain.pem; # 證書存放位置
ssl_certificate_key /etc/letsencrypt/live/test.test.com/privkey.pem; # 證書存放位置
server_name *.test.test.com; # ip,域名,我這里以泛域名舉例,畢竟是做反向代理,http就不用配置了
rewrite ^(.*) https://$server_name$1 permanent; # 可以做個http強制轉換為https
# https還可以做其他安全配置,需要的去看其他文章
location / {
proxy_pass http://127.0.0.1:12369; # 映射的frp服務端frps.ini的 vhost_http_port端口
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_max_temp_file_size 0;
proxy_redirect off;
proxy_read_timeout 240s;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
修改完nginx配置后重啟nginx
sudo nginx -s reload
修改中轉服務器frps.ini配置
[common]
................. #其他配置省略
..................
vhost_http_port = 12369 #客戶端http映射的端口,就是上面Nginx的proxy_pass對應端口
..................
................
配置完之后還是運行服務端測試一下Linux :
/etc/frp/frps -c /etc/frp/frps.ini
內網服務器,即frp客戶端frpc.ini配置:
..............
................
[test_http] #Http服務,映射的是服務端http80端口
type = http #服務方式
local_ip = 127.0.0.1 #服務端ip,可寫本地,局域網等做反向代理的ip
local_port = 80 #服務端端口
#custom_domains = test.test.com #需要反向代理的域名,就是服務端要代理的域名,因為我們只需要https穿透,在nginx中已經做了https的域名配置,這一句可以不用添加
配置完之后運行,Linux :
/etc/frp/frps -c /etc/frp/frps.ini
啟動frpc,windows:
c:\frp\frpc.exe -c c:\frp\frpc.ini
之后看到 “start proxy success”字樣就表示啟動成功了。
至此,https配置完成,網頁輸入https://任何字符.test.test.com即可訪問成功。
3)進行遠程訪問:
按照上面的配置,我們想要遠程桌面連接到家里的 Windows 電腦,那么打開“微軟遠程桌面客戶端”后,在地址欄里填入中轉服務器公網IP:7002 即可連接。同理其他連接根據中轉服務器IP:設置的端口號來訪問就可以了。由此,借助 Frp,你就能輕松地為本地局域網內網的設備提供公網直接訪問的能力了,你可以用 Frp 來轉發包括但不限於 ssh、http、https、轉發 Unix 域套接字等服務。上面只是最基礎的教程,Frp 還有很多很多高級功能,比如給 Web 增加密碼保護、點對點內網穿透、設置端口白名單等等,Frp 官網上也提供了很詳細的文檔,感興趣的朋友可以去研究一下。
5.2 zerotier安裝配置
免費版支持客戶端多。連入同一個網絡的客戶端不超過100個就都免費。所以我們自用NAS遠程訪問完全夠了,這里以安裝配置免費版為例:
ZeroTier相當於軟交換機,需要在內網服務器和客戶機上安裝ZeroTier one軟件,然后在官方給的中轉服務端或者自己搭建的雲主機中轉服務器(moon)中配置VLAN和路由,這樣就把倆個VLAN連在了一起,里面的設備便可以互相訪問。
正是因為如此,zerotier不支持域名和ddns,也就是說必須以虛擬IP互相訪問,moon節點僅支持固定公網IP,且未來2.0版本依然維持此設定,如果需要用域名訪問內網web服務器,此方法不可用,這也是目前我想到的這個方法唯一一個不滿足的場景。
官方中轉服務端或moon配置:
1.點擊注冊ZeroTier賬號並登陸(此處省略)
2.登錄后配置網絡(這里默認是官方免費中轉服務器,可以免費創建多個network,每個network實現一個局域網)
這樣就進入了網絡設置界面,網絡設置界面可以配置很多東西,但是這里只介紹需要用到的部分,就是 NetworkID 和下面的 Members。NetworkID 是在連入新設備時需要用到的標識符,每個設備連接這個虛擬的局域網時都要輸入這個ID。Members 則是連入網絡的設備列表,按照默認的設定,當有一個新設備接入網絡時,用戶需要在這個頁面進行授權。這里其實可以不用自己做額外配置,默認就好,下面還是把其中一些重要參數截圖說明下:
下面插入 一個概念:moon。
先簡單提一下 UDP 打洞的原理,UDP 打洞的本質是讓 NAT 后面的機器 A 和 B 先連接一個有公網 IP 的中間服務器,然后中間服務器經過一番操作之后讓 A 和 B 直接互聯,這樣之后的數據傳輸就是 A 和 B 之間直接傳輸,不再通過中間服務器。但是出於節省資源和增強健壯性的角度,A 和 B 服務器直接打出來的「洞」並不是永久的,而是維持一段時間后釋放,下次連接時重新打洞。這樣就帶來一個問題,Zerotier 是一款國外的項目,他提供的中間服務器到大陸的網絡狀況並不好,有很高的延遲,並且很可能丟包,這就導致我們每次「打洞」都有很高的延遲。為了解決這個問題,Zerotier 提供了一個 moons 的概念,官方文檔中提供了詳細的解釋和配置方法。
如果需要moon,則要做另外配置,這里再說明下如何搭建配置中轉機器(moon)centos為例:
給自己的中轉主機安裝 zerotier-one 這個軟件包:
curl -s https://install.zerotier.com/ | sudo bash
之后就完成了安裝,然后我們要啟動zerotier,並且讓他開機自啟動,運行:
sudo systemctl start zerotier-one.service
sudo systemctl enable zerotier-one.service
進官方網絡設置頁面,復制這個Network ID
然后在自己的moon中轉機器上執行:
sudo zerotier-cli join 83048a0632246d2c
加入之后就啟動了,但是還連不進我們創建的網絡,因為我們選擇了 Private(私有網絡) ,還需要到官方網絡設置頁面對接入的機器打勾,拉到 Members 這一節,把前面的勾勾選上。這個時候執行一下 ip a 你會發現多了一個叫做 ztuzethlza 或者類似名字的設備,還有IP地址,這就是zerotier組建的局域網的IP地址。
此時自己的中轉服務器已經被加入到了zerotier虛擬的局域網下。接下來就是對我們自己的中轉服務器進行配置moon。
執行:
cd /var/lib/zerotier-one/
sudo zerotier-idtool initmoon identity.public > moon.json
此命令會在當前目錄下生成一個文件 moon.json,文件內容如下:
{
"id": "deadbeef00",
"objtype": "world",
"roots": [
{
"identity": "deadbeef00:0:34031483094...",
"stableEndpoints": []
}
],
"signingKey": "b324d84cec708d1b51d5ac03e75afba501a12e2124705ec34a614bf8f9b2c800f44d9824ad3ab2e3da1ac52ecb39ac052ce3f54e58d8944b52632eb6d671d0e0",
"signingKey_SECRET": "ffc5dd0b2baf1c9b220d1c9cb39633f9e2151cf350a6d0e67c913f8952bafaf3671d2226388e1406e7670dc645851bf7d3643da701fd4599fedb9914c3918db3",
"updatesMustBeSignedBy": "b324d84cec708d1b51d5ac03e75afba501a12e2124705ec34a614bf8f9b2c800f44d9824ad3ab2e3da1ac52ecb39ac052ce3f54e58d8944b52632eb6d671d0e0",
"worldType": "moon"
}
其中 id 為我們自己中轉服務器在 ZeroTier 中的 id,本文為 deadbeef00。接下來編輯moon.json,把 "stableEndpoints": [] 這一節里加入我們自己的中轉機器的公網IP,例如 "stableEndpoints": ["1.2.3.4/9993"],其中 9993是默認監聽的端口,接下來要把9993端口的防火牆放開(注意是UDP),如果你的機器外邊還有防火牆的話,也要一起放開,例如阿里雲的機器就有防火牆規則,要一起把對應端口的UDP流量放行,如:
"stableEndpoints": [ "1.2.3.4/9993","2001:abcd:abcd::1/9993" ]
若公網機器沒有 IPv6 地址,則將其修改為
"stableEndpoints": [ "1.2.3.4/9993" ]
此后,我們要生成moon的簽名文件:
sudo zerotier-idtool genmoon moon.json
此命令會生成一個簽名文件在當前目錄下,文件名如 000000deadbeef00.moon (我們自己的中轉服務器 id 為 deadbeef00)
接下來將 moon 節點加入網絡
在我們自己的中轉服務器中的 ZeroTier 目錄中建立子文件夾 moons.d
不同系統下的 ZeroTier 目錄位置:
Windows: C:\ProgramData\ZeroTier\One
Macintosh: /Library/Application Support/ZeroTier/One (在 Terminal 中應為 /Library/Application\ Support/ZeroTier/One)
Linux: /var/lib/zerotier-one
FreeBSD/OpenBSD: /var/db/zerotier-one
將前面生成的 000000deadbeef00.moon 拷貝進 moons.d 文件夾中,並重啟 ZeroTier(此步好像有些許 bug,重啟電腦為佳)
注意: windows需要重啟服務,而不是重啟程序,按住windows鍵+r,在彈出的對話框中輸入services.msc並回車,找到ZeroTier One,右鍵選擇重新啟動即可
sudo systemctl restart zerotier-one
sync && sync && reboot
這樣我們自己的中轉服務器moon配置就完成了,下面還要將內網服務器和內網客戶端加入moon,這里我自己的內網服務器用的centos7,需要先安裝好zerotier-one並加入網絡,和我們自己中轉服務端安裝方式一樣,我的客戶機是ios,ios需要用國外的apple賬號在applestore下載zerotier one,國內商城這個app被下架了。
這里先查看前面moon.json中的id是多少,下面這個命令可查看並返回結果為“ "id": "xxxxxxxxxx",”:
grep id /var/lib/zerotier-one/moon.json | head -n 1
接着先說下我的內網centos7服務器如何加入moon節點:
復制前面查到的id,然后在內網centos7機器執行:
sudo zerotier-cli orbit xxxxxxxxxx xxxxxxxxxx
注意,xxxxxxxxxx 要兩遍。此后重啟 zerotier one,完畢。等一會兒之后,zerotier局域網內的機器就可以互相訪問了,延時非常低:
sudo systemctl restart zerotier-one
要驗證是否moon生效,只需要在客戶端zerotier程序目錄下,執行以下命令即可:
zerotier-cli listpeers
若有類似地址,即可證明moon連接成功
200 listpeers abcdefgh00 1.1.1.1/9994;4242;4038 224 1.2.12 MOON
接下來再說下內網客戶端ios如何加入moon節點:
!!!其實這里是個大問題,移動端如何加入moon節點,目前還沒研究出來...
內網服務器端和客戶端安裝配置:
前面介紹moon安裝配置的時候已經描述了centos整個安裝過程,參考我們自己的中轉服務器安裝配置過程即可,這里針對Windows做個簡短的安裝介紹。
進官網下載Windows的msi安裝包后直接安裝;
安裝完后打開,在桌面下方可以看到黃色的圖標,鼠標右擊選擇"join Network"
彈出一個小的會話框,三個選項全部勾選上並在上面填入中轉服務器的Network ID后,點擊 “join”
稍等片刻,會彈出此窗口,選擇“是”即可
最后刷新官網中Network配置頁面,在下方的“member”區域中勾選將其注冊到網絡中
好了,到這里關於zerotier的服務端和客戶端安裝配置都做完了,zerotier網絡組建成功后,相當於里面的設備在同一局域網下或倆個不同VLAN下,所以也就意味着里面的所有設備只要開放了端口互相就能訪問,而不需要像frp那樣對單獨的某個端口最設置,這一點也說明zerotier和vpn相似。
最后針對zerotier,有網友對它點對點穿透模式做過穿透效果測試,這里引用了過來,供參考:
"事實上 Zerotier 的打洞效果好的令我驚訝,我的網絡環境 A 是上行 20M 下行 100M 的電信網絡,B 則是移動贈送的 50M 上下行對等移動網絡。晚高峰時段,在兩邊都開啟 bbr 的情況下,互相下載文件可以跑到網絡峰值的 60%~70%。電信拖移動能跑3MB/s,反過來則是 1.4MB/s 左右。延遲的話「打洞」完成之后穩定在 90ms,丟包率在 8% 左右。順便吐槽一下,一開始看到 90ms 的延遲我還以為打洞出了問題,結果直接從移動 ping 了一下電信的公網 IP(我的電信網絡環境是有公網 IP 的,但是我並沒有在路由器設置端口轉發,因此測試效果仍然是打洞的效果),發現延遲也在 90ms 上下,通過 traceroute 命令追蹤路由發現數據包先從隔壁的 H 省進入移動骨干網,然后進入電信骨干,再從另一個方向隔壁的 S 省回到本地電信,難怪會有這么高的延遲。同樣,8% 也是晚高峰電信和移動互聯本身的延遲。換而言之,Zerotier 的打洞非常成功,延遲和丟包率基本都和公網差距不大,但是由於本身移動和電信晚高峰時段的互聯效果較差,因此效果並沒有想象中完美。從延遲的角度,本地電信到香港阿里雲服務器的延遲尚在 50ms 以下,到洛杉磯的 CN2 服務器也不過 150ms,然而與本地移動互聯延遲竟然高達 90ms,國內 ISP 互聯還是任重道遠啊。"
六、總結
以上基本把內網穿透原理和實現方法很詳細的介紹了一遍,還是針對不同實現方法做個總結吧。
1.如果是企業內網資料需要員工遠程訪問就用VPN。
2.自己家里NAS或遠程桌面直接用zerotier,我自己沒有額外搭建moon,有點延遲但可以接收,還有遠程桌面也優先用zerotier。
3.一些頁面訪問用frp,比如測試用的web服務、路由器管理界面、NAS管理界面等等。
4.最后如果覺得麻煩,資金允許可以直接花生殼之類的收費穿透。