打通大內網第三期 固定服務端口 (基于Lucky的STUN穿透)

前言

本教程不適合小白皆辽,本人因為水平有限柑蛇,也無法解決大家遇到的問題,一旦出現問題還得請各位自行摸索驱闷。
首要條件:NAT 類型為 NAT1耻台,即 fullcone饶米;光貓橋接或開啟 dmz种远;路由器能刷機或者開啟 upnp/dmz
建議:路由器能夠控制具體的端口開放與否,而不是只能全開或全關聪铺。
本文中的操作基于 OpenWrt 上的 Lucky扼菠,在其它設備使用或是使用 NATMAP 進行穿透同樣可以類比摄杂。建議在閱讀了第一期與第二期的基礎上閱讀本文。

需解決的問題與思路

STUN穿透的端口不固定循榆,并且更換較為頻繁析恢,雖然在第一期中,我們使用Cloudflare頁面規(guī)則秧饮,將域名重定向到了公網端口映挂,解決了web應用的訪問泽篮;而絕大多數需要連接自建后端的應用程序并不支持重定向,必須指定端口袖肥,甚至部分應用程序不允許修改默認端口咪辱。

我們可以借鑒其它內網穿透軟件的思路振劳,通過一個端口來轉發(fā)其他端口的流量椎组,常見的做法有兩種:

  • 通過frp的stcp和sudp,將內網端口一對一的綁定到異地設備的本機端口上历恐。
  • 通過wireguard或n2n寸癌,將內網整個網段轉發(fā)過去。

因為我的內網服務比較多弱贼,不想讓連teamspeak的朋友都來欣賞我的“學習資料”蒸苇,所以我選擇使用frp。

此處放兩個教程供各位參考吮旅,不過他們用的是NATMAP溪烤。

使用NATMap在NAT-1私網IP寬帶上部署FRP服務
natmap內網穿透讓內網實現公網IP,遠程訪問異地組網庇勃,做frps檬嘀,ssh ,web责嚷,wireguard..

如果你不考慮訪問者的權限鸳兽,僅僅想把整個內網網段轉發(fā)出去,可以考慮使用tailscale罕拂,并利用Lucky將搭建的Derp中繼服務器穿透出去揍异,操作更為簡單,具體方法請參考第四期教程爆班。

第一步 在內網安裝frps和frpc衷掷,并配置stcp

在內網配置的frps和frpc使用官方版即可,此處簡單帶過柿菩。官方文檔

frps

在路由器或nas上下載并安裝frps棍鳖,我是在Unraid里用docker安裝:

配置frps.ini :

[common]
bind_port = 7000
token = your_token

只需配置bind_porttoken就行,也就是frps的訪問端口和令牌碗旅,默認采用TCP協議渡处。

配置完成后運行frps,接下來參考之前的教程祟辟,它創(chuàng)建STUN穿透通道医瘫、配置端口轉發(fā)、開啟防火墻旧困,在外網能ping通后為它設置開機自啟醇份。

frpc

為何在內網中也要frpc稼锅?這跟stcp與sudp的工作方式有關,官網的描述如下:

STCP 和 SUDP 的 (S) 的含義是 Secret僚纷。其作用是為 TCP 和 UDP 類型的服務提供一種安全訪問的能力矩距,避免讓端口直接暴露在公網上導致任何人都能訪問到。

這兩種代理要求在被訪問服務的機器上以及要訪問的用戶的機器上都部署上 frp 的客戶端怖竭。被訪問的服務所在機器叫做服務端锥债,另一端叫做訪問端。

frp 會在訪問端監(jiān)聽一個端口和服務端的端口做映射痊臭。訪問端的用戶需要提供相同的密鑰才能連接成功哮肚,從而保證安全性。

參考官方的使用示例 广匙,配置時根據需要把~~xtcp~~改成~~stcp~~~~sdup~~即可允趟。 官方已經不再推薦使用ini配置文件。

下載安裝官方版frpc后鸦致,編輯frpc.ini潮剪。common中的token必須與frps相同。

[common]
server_addr = 127.0.0.1
server_port = 7000
token = your_token

# jellyfin
[svc_jellyfin]
type = stcp
sk = B9jNFfUy3hDrmi
local_ip = 127.0.0.1
local_port = 8096
use_compression = true
role = server

# nginx
[svc_nginx]
type = stcp
sk = x5Y6f8VBbXQ5NY
local_ip = 192.168.0.115
local_port = 18443
use_compression = true

# teamspeak
[svc_ts1]
type = sudp
sk = khgtqgyCk3u3JZ
local_ip = 127.0.0.1
local_port = 9987
use_compression = false
[svc_ts2]
type = stcp
sk = khgtqgyCk3u3JZ
local_ip = 127.0.0.1
local_port = 10011
use_compression = true
[svc_ts3]
type = stcp
sk = khgtqgyCk3u3JZ
local_ip = 127.0.0.1
local_port = 30033
use_compression = true

我將frpc和frps部署在了同一臺機器上分唾,因此server_addr填的是127.0.0.1抗碰,你要改為frps的內網ip。有網友反映將frps和frpc部署在同一臺機器上可能會出錯鳍寂,但是我沒遇到改含。

為你想要在外網訪問的所有端口都配置frpc的stcp/sudp服務端(如果不指定role則默認為server),local_iplocal_port為相應服務的內網地址和端口迄汛。我這里的添加了本地地址上的jellyfin捍壤、nginx和teamspeak。

如果你需要訪問的所有服務都經過反向代理鞍爱,那也可以只為反向代理配置stcp鹃觉,并在異地機器上修改HOSTS文件。

第二步 解析frps的公網端口

繞了這么一大圈睹逃,還是要面對最頭疼的問題:frps的公網訪問端口不固定怎么辦盗扇?

解決思路

ip4p

NATMAP的作者給出了名為ip4p的方案,也就是將ipv4地址和端口轉化成ipv6地址沉填,添加為一條AAAA記錄疗隶。當公網地址或端口改變時,只要修改該記錄翼闹,即可實現類似DDNS的效果斑鼻。作者也對frpc進行了修改,為它添加了解析ip4p的功能猎荠。支持ip4p的frp

The IP4P address format uses IPv6 special addresses to encode IPv4 addresses and ports for easy distribution through DNS AAAA records.

2001::{port}:{ipv4-hi16}:{ipv4-lo16}
  • ip4p存在的問題

在windows平臺和安卓平臺上坚弱,如果沒有外網ipv6環(huán)境蜀备,那么他程序里使用的LookupIP函數不會獲取AAAA記錄。雖然調用nslookup可以解析AAAA記錄荒叶,但是我懶......

也就是說碾阁,你連不上外網ipv6,就解析不了ip4p些楣,但是如果你連得上ipv6脂凶,為什么不用ipv6直連呢......

TXT記錄

我進交流群向帶佬求助后,帶佬建議我直接把公網ip和端口放進TXT記錄里戈毒。于是我花了倆小時自學了一下golang艰猬,添加了解析TXT記錄的功能横堡。我的做法是埋市,假設公網地址是183.6.66.666:6666,將其用BASE64編碼命贴,變成MTgzLjYuNjYuNjY2OjY2NjY=放進TXT記錄里道宅,供frpc解析。如果你覺得不安全胸蛛,那可以考慮加個AES加密之類的污茵。

創(chuàng)建TXT記錄

進入Cloudflare后臺,在dns - 記錄中創(chuàng)建一條TXT記錄葬项,TTL我設為了一分鐘泞当,不確定是否生效。

將你剛才創(chuàng)建的TXT記錄的域名民珍、Cloudflare的郵箱襟士、Global API Key和域名的區(qū)域id填入下面的指令里(忘記的可以看看第一期第四步和第五步),并在命令行里執(zhí)行嚷量。

curl -s -X GET "https://api.cloudflare.com/client/v4/zones/區(qū)域id/dns_records?type=TXT&name=ip4p.s***********n.online" -H "X-Auth-Email:******@qq.com" -H "X-Auth-Key:f9***********************1b" -H "Content-Type: application/json"

把結果里"id":后面的那一串數字+字母復制下來陋桂,這就是這條記錄的id。

把包括剛才id在內的信息替換到下一行指令里執(zhí)行蝶溶,嘗試對剛才添加的TXT記錄進行修改:

curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/區(qū)域id/dns_records/記錄id" -H "X-Auth-Email:******@qq.com" -H "X-Auth-Key:f9*************************1b" -H "Content-Type: application/json" --data '{"type":"TXT","name":"ip4p.s************.online","content":"changed","ttl":60,"proxied":false}'

再回到Cloudflare后臺嗜历,應該就能看到這條記錄更改了。

部分免費域名無法使用API修改抖所。


配置腳本

在以下腳本中填入Cloudflare的郵箱梨州、Global API key、區(qū)域id田轧、txt記錄的id暴匠。

domain="ip4p.s******n.online"
zone="e7***************************fb"
txt_id="a19***********************8a06"
email="****@qq.com"
key="f9*****************1b"

echo "change txt record"
#base64 encode
addr_64=$(echo -n ${ipAddr} | base64)
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone/dns_records/$txt_id" \
-H "X-Auth-Email: $email" -H "X-Auth-Key: $key" \
-H "Content-Type: application/json" \
--data '{"type":"TXT","name":"'$domain'","content":"'$addr_64'","ttl":60,"proxied":false}'

然后編輯穿透規(guī)則,開啟自定義腳本觸發(fā)涯鲁,把它粘貼到自定義腳本中巷查。

第二步剩余內容已經過時有序,僅留作記錄,請?zhí)恋谌?/p>


配置腳本

Lucky從2.5.1起岛请,支持STUN地址改變時調用腳本旭寿,本節(jié)內容失效。

在第二期創(chuàng)建的webhook服務器的腳本目錄下創(chuàng)建frp.sh崇败,并填入Cloudflare的郵箱盅称、Global API key、區(qū)域id后室、txt記錄的id缩膝。我的ip4p.s********n.online域名除了txt記錄外,還添加了ip4p的aaaa記錄岸霹;如果你需要疾层,請仿照上一步手動添加一條aaaa記錄,并填入這條記錄的id贡避,如果不需要那就把對應的部分注釋掉痛黎。

#!/bin/bash
# param is ip,port,addr

domain="ip4p.s********n.online"
zone="e7***************************************fb"
ip4p_id="96************************************1b93"
txt_id="a19*********************************8a06"
email="******@qq.com"
key="f9*************************1b"

echo "change ip4p record"
array=(${ip//./ })
ip4p=2001::$(printf '%x:%x%x:%x%x\n' $port ${array[0]} ${array[1]} ${array[2]} ${array[3]})
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone/dns_records/$ip4p_id" \
-H "X-Auth-Email:$email" -H "X-Auth-Key:$key" \
-H "Content-Type: application/json" \
--data '{"type":"AAAA","name":"'$domain'","content":"'$ip4p'","ttl":60,"proxied":false}'

echo ""
echo "change txt record"
# base64 encode
addr_64=$(echo -n $addr | base64)
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone/dns_records/$txt_id" \
-H "X-Auth-Email:$email" -H "X-Auth-Key:$key" \
-H "Content-Type: application/json" \
--data '{"type":"TXT","name":"'$domain'","content":"'$addr_64'","ttl":60,"proxied":false}'

在Lucky中設置webhook

Lucky從2.5.1起,支持STUN地址改變時調用腳本刮吧,本節(jié)內容失效湖饱。

打開Lucky后臺,編輯stun的穿透規(guī)則杀捻,打開webhook井厌,將接口地址設置為http://webhookd的ip地址:wenhookd的端口/frp?ip=#{ip}&port=#{port}&addr=#{ipAddr}(webhook服務器地址、端口和腳本名稱根據實際情況來)致讥,接口調用成功包含的字符串填"success":true仅仆。

第三步 在異地電腦上配置frpc

異地電腦上的frpc必須使用魔改版,如需解析txt記錄拄踪,可以使用我改的版本蝇恶,但我只在Windows上編譯過,其它平臺請自行編譯惶桐。

配置frpc.ini

修改frpc.ini撮弧,server_addr填添加了ip4p或TXT記錄的域名,server_port不用填姚糊,建議指定dns_server贿衍。

[common]
server_addr = ip4p.s******n.online
token = your_token
dns_server = 8.8.8.8

# jellyfin
[vst_jellyfin]
type = stcp
role = visitor
server_name = svc_jellyfin
sk = B9jNFfUy3hDrmi
bind_ip = 127.0.0.1
bind_port = 38096
use_compression = true

# nginx
[vst_nginx]
type = stcp
role = visitor
server_name = svc_nginx
sk = x5Y6f8VBbXQ5NY
bind_ip = 127.0.0.1
bind_port = 18443
use_compression = true

# teamspeak
[vst_ts1]
type = sudp
role = visitor
server_name = svc_ts1
sk = khgtqgyCk3u3JZ
bind_ip = 127.0.0.1
bind_port = 9987
use_compression = false
[vst_ts2]
type = stcp
role = visitor
server_name = svc_ts2
sk = khgtqgyCk3u3JZ
bind_ip = 127.0.0.1
bind_port = 10011
use_compression = true
[vst_ts3]
type = stcp
role = visitor
server_name = svc_ts3
sk = khgtqgyCk3u3JZ
bind_ip = 127.0.0.1
bind_port = 30033
use_compression = true

訪問端必須手動指定rolevisitor,必須指定連接的服務端名稱server_name救恨,并且sk應與服務端相同贸辈。

如果bind_ip填為127.0.0.1,則僅有本設備能訪問肠槽。若想讓其它設備訪問擎淤,則填為0.0.0.0奢啥。

在Windows上將frpc注冊為服務

這一步面向零基礎使用者。(也就是你的小白朋友)

先嘗試運行一次

打開frpc.exe所在文件夾嘴拢,在資源管理器空白處右鍵 - 打開命令提示符桩盲。

輸入.\frpc.exe并按下回車。如果沒有出現錯誤席吴,可以嘗試訪問所有的服務赌结。

如果發(fā)現有的服務訪問不上,打開frpc.ini孝冒,找那個服務到對應的bind_port柬姚,記下這個數字。

創(chuàng)建文件檢查端口是否占用.ps1庄涡,代碼如下量承。右鍵 - 使用PowerShell運行

while(1)  
{  
    $port = Read-Host "請輸入需要查詢的端口,輸入0退出:"
    IF ($port -eq 0) {exit}
    $res=$(Get-NetTCPConnection | ? {$_.LocalPort -eq $port})
    if ($res){
        echo $res
        Get-Process -Id (Get-NetTCPConnection -LocalPort $port).OwningProcess
    }
    else {echo "未被占用"}
}

你可以輸入剛才記下的數字,查看該端口是否被占用啼染、被什么程序占用宴合,然后選擇關閉該程序或者選擇另一個沒有被占用的端口(1025-65535之間)焕梅。

一旦關閉命令提示符窗口迹鹅,frpc就會關閉。

注冊服務

可以使用nssm將程序注冊為服務贞言。

先將frpc關閉斜棚。在資源管理器中打開nssm.exe所在目錄。32位系統打開win32目錄该窗,64位系統打開win64目錄弟蚀。

在資源管理器空白處右鍵 - 打開命令提示符,輸入.\nssm.exe install frpc酗失。

會彈出NSSM service installer窗口义钉,Application Path選擇frpc.exeStartup directory選擇frpc.exe所在目錄规肴,Arugments不填捶闸,點擊Install service。

任務管理器 - 服務 - 打開服務彈出窗口中找到frpc拖刃。右鍵frpc删壮,點擊屬性,將啟動類型改為自動兑牡,并點擊確定央碟。再右鍵frpc,點擊啟動均函。

魔改版frp使用問題總結

如果你的應用強制要求https連接(如BitWarden)亿虽,可以在frp中添加反向代理的端口菱涤,并在異地電腦上修改hosts劫持域名。

我尚未解決的問題記錄如下:

  • 我嘗試讓frp使用QUIC協議洛勉,訪問端可以連接到服務端狸窘,可以ping通,但是幾乎收不到包坯认;
  • 部分常用第三方遠程桌面無法正常使用(moonlight可以)
    • RustDesk的ID服務器可以連接翻擒,但是中繼服務器無法連接;
    • parsec無法打洞(不過我也不覺得能成功)牛哺。
  • 安卓手機若無root陋气,開了穿透軟件就無法魔法上網。

結語

至此引润,我們補上了STUN內網穿透的最后一塊拼圖巩趁,基本解決了大內網環(huán)境下的所有痛點,近似達到了擁有公網ip的效果淳附。但使用體驗仍不能稱得上完美议慰,期待之后能有更好的方案出現。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末奴曙,一起剝皮案震驚了整個濱河市别凹,隨后出現的幾起案子,更是在濱河造成了極大的恐慌洽糟,老刑警劉巖炉菲,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異坤溃,居然都是意外死亡拍霜,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門薪介,熙熙樓的掌柜王于貴愁眉苦臉地迎上來祠饺,“玉大人,你說我怎么就攤上這事汁政〉劳担” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵烂完,是天一觀的道長试疙。 經常有香客問我,道長抠蚣,這世上最難降的妖魔是什么祝旷? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上怀跛,老公的妹妹穿的比我還像新娘距贷。我一直安慰自己,他們只是感情好吻谋,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布忠蝗。 她就那樣靜靜地躺著,像睡著了一般漓拾。 火紅的嫁衣襯著肌膚如雪阁最。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天骇两,我揣著相機與錄音速种,去河邊找鬼。 笑死低千,一個胖子當著我的面吹牛配阵,可吹牛的內容都是我干的。 我是一名探鬼主播示血,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼棋傍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了难审?” 一聲冷哼從身側響起瘫拣,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎剔宪,沒想到半個月后拂铡,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡葱绒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了斗锭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片地淀。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖岖是,靈堂內的尸體忽然破棺而出帮毁,到底是詐尸還是另有隱情,我是刑警寧澤豺撑,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布烈疚,位于F島的核電站,受9級特大地震影響聪轿,放射性物質發(fā)生泄漏爷肝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望灯抛。 院中可真熱鬧金赦,春花似錦、人聲如沸对嚼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纵竖。三九已至漠烧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間靡砌,已是汗流浹背沽甥。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留乏奥,地道東北人摆舟。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像邓了,于是被迫代替她去往敵國和親恨诱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容