1. 程式人生 > 實用技巧 >使用frp實現內網穿透

使用frp實現內網穿透

內容轉載自我的部落格

目錄

1. 目的和機器資訊

雲主機A(服務端),購買於雲伺服器提供商,以下IP、埠、使用者名稱、密碼均為示例:

IP: 67.89.12.34
預設開啟ssh的22埠,使用者名稱為ubuntu,密碼為Test&123456+pwd
手動配置安全組,放通7000、8000-8100、8888埠的TCP連線(埠可任意設定,不與其他服務衝突即可)
7000埠用於服務端(frps.ini中的bind_port)與客戶端(frpc.ini中的server_port)建立基本通訊、鑑權等
         一個服務端可以用同一個埠連線不同的客戶端
8000-8100埠用來進行轉發,只在客戶端的配置檔案frpc.ini中設定remote_port,每個埠轉發不同的服務
         可以是一臺內網伺服器有多個服務;也可以是多臺內網伺服器,每臺有不同數量的服務
8888埠用來配置frps的管理面板(80、443埠預設開啟)

內網伺服器B(客戶端),自己購買的配置較高的伺服器,但是沒有公網地址,所以只能區域網訪問,安裝ssh以便於其他使用者可以ssh連線到本機:

IP: 192.160.0.135
內網伺服器B安裝ssh,選擇22埠,使用者名稱為myserver,密碼為Myser123456ver
將內網伺服器B的22埠,轉發到雲主機A的8000埠
    則使用者C可以使用如下程式碼來遠端ssh連線內網伺服器B
    ssh -p 8000 [email protected]
    使用如下程式碼來將內網伺服器B的/home/myserver/test.txt檔案下載到使用者C的機器上
    scp -P 8000 [email protected]:/home/myserver/test.txt ./Desktop/

使用者C(使用者端),只需要具備ssh連線的軟體
frp的系統架構和最終實現的效果如下圖

2. 雲主機A下載和配置frp-server

在github倉庫frp下載linux-amd64版本,解壓為資料夾frp_linux_amd64並放在/home/ubuntu/目錄下,在frp_linux_amd64資料夾建立log目錄用於儲存日誌。修改frps.ini檔案為如下

[common]
# 繫結的IP地址,支援IPv6,不指定預設0.0.0.0
bind_addr = 0.0.0.0
# 服務埠
bind_port = 7000

# 設定伺服器與客戶端的鑑權方式
authentication_method = token
# 客戶端與服務端通訊的身份驗證令牌
token = ToKen&pwd+123for56

# 開啟frps儀表盤可以檢查frp的狀態和代理的統計資訊
# frps儀表盤繫結的地址
dashboard_addr = 0.0.0.0
# frps儀表盤繫結的埠
dashboard_port = 8888
# 訪問frps儀表盤的使用者 
dashboard_user = example_admin
# 使用者密碼 
dashboard_pwd = AdMinVgfsHT67TFg
# 儀表盤頁面檔案目錄,只適用於除錯
# assets_dir = ./static

# 日誌配置檔案
# 日誌檔案,不指定日誌資訊預設輸出到控制檯
log_file = /home/ubuntu/frp_linux_amd64/log/frps.log
# 日誌等級,可用等級“trace, debug, info, warn, error”
log_level = info
# 日誌儲存最大儲存時間
log_max_days = 7

# 每個客戶端連線服務端的最大連線數
max_pool_count = 5
# 每個客戶端最大可以使用的埠,0表示無限制
max_ports_per_client = 0
# 自定義子域名,需要在dns中將域名解析為泛域名
# subdomain_host = example.cn
# 是否使用tcp複用,預設為true
tcp_mux = true

3. 雲主機A安裝使用nginx(dashboard自定義域名,可選)

更新軟體源:sudo apt-get update
安裝nginx:sudo apt-get install nginx
訪問雲主機的ip確認nginx安裝成功
修改nginx配置檔案:sudo vi /etc/nginx/nginx.conf
http{}合適位置新增以下程式碼,這裡的8888埠與frps.inidashboard_port一致
一定要將http{}裡面的最後兩個include行註釋掉,修改才會生效

    server{
        listen 80;
        # 如果需要ssl,參考https://blog.whuzfb.cn/blog/2020/07/07/web_https/
        # listen 443 ssl;
        # include ssl/example.cn.ssl.conf;
        # 此時支援http與https
        server_name frp.example.cn;
        access_log /home/ubuntu/frp_linux_amd64/log/access.log;
        error_log /home/ubuntu/frp_linux_amd64/log/error.log;
        location /{
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_redirect off;
            proxy_buffering off;
            proxy_pass http://127.0.0.1:8888;
        }
    }

不重啟重新載入最新配置檔案內容:sudo service nginx reload
停止nginx服務:sudo service nginx stop
重啟nginx服務:sudo service nginx restart
為域名example.cn新增一條名為frp的A記錄解析到67.89.12.34

4. 雲主機A設定frps開機自啟動(systemd)

開啟frp_linux_amd64資料夾下的systemd目錄,編輯frps.service檔案([email protected]檔案只是多了個自定義ini檔案的功能),將其中的user=nobody改為user=ubuntu(即本機的使用者名稱),如果不改,啟動時候會報錯無法寫入日誌檔案,許可權禁止
然後修改ExecStart、ExecReload中的路徑為自己的檔案路徑
將修改後的frps.service檔案複製到/etc/systemd/system/sudo cp ./frps.service /etc/systemd/system/
啟用frps開機啟動:systemctl enable frps
手動執行frps服務:systemctl start frpsservice frps start
手動停止frps服務:systemctl stop frpsservice frps stop
手動重啟frps服務:systemctl restart frpsservice frps restart
檢視frps執行狀態:systemctl status frpsservice frps status
關閉frps開機啟動systemctl disable frps

5. 雲主機A設定frps開機自啟動(init.d)

建立start_frp.sh檔案:vi start_frp.sh,內容如下(註釋不可刪除):

#!/bin/sh
### BEGIN INIT INFO
# Provides:          svnd.sh
# Required-start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the svnd.sh daemon
# Description:       starts svnd.sh using start-stop-daemon
### END INIT INFO
/home/ubuntu/frp_linux_amd64/frps -c /home/ubuntu/frp_linux_amd64/frps.ini

給予執行許可權: chmod 775 start_frp.sh
複製到指定位置: sudo cp ./start_frp.sh /etc/init.d/
重新整理即可: sudo update-rc.d start_frp.sh defaults 90
重啟即可發現自啟動程序: ps -ef | grep frp
取消frps自啟動(/etc/init.d/)

sudo rm /etc/init.d/start_frp.sh
sudo update-rc.d -f start_frp remove

6. 內網伺服器B安裝配置frp-client

在github倉庫frp下載linux-amd64版本,解壓為資料夾frp_linux_amd64並放在/home/myserver/目錄下,在frp_linux_amd64資料夾建立log目錄用於儲存日誌。修改frpc.ini檔案為如下

[common]
# 雲主機的公網ip
server_addr = 67.89.12.34
# 雲主機端frps.ini檔案中的bind_port
server_port = 7000

# 客戶端與服務端通訊的身份驗證令牌
token = ToKen&pwd+123for56

# 設定管理地址,用於通過http api控制frpc的動作,如重新載入
# admin_addr = 127.0.0.1
# admin_port = 7400
# admin_user = admin
# admin_passwd = admin

# 初始連線池的數量,預設為0
pool_count = 5

# 客戶端日誌儲存位置
log_file = /home/myserver/frp_linux_amd64/log/frpc.log
# 儲存日誌的等級trace, debug, info, warn, error
log_level = info
# 最大儲存天數
log_max_days = 7

# 是否啟用tcp複用,預設為true
tcp_mux = true

# 代理配置段名稱,如果上面配置user=your_name,則顯示為your_name.ssh
[ssh_B1_00]
# 協議預設tcp,可選tcp,udp,http,https,stcp,xtcp
type = tcp
# 本地地址
local_ip = 127.0.0.1
# 本地埠
local_port = 22
# 在伺服器端開啟的遠端埠,即使用者使用自己電腦ssh連線時的埠
remote_port = 8000
	
# 雲伺服器管理面板建立安全組
# 0.0.0.0/0	TCP:7000,8000-8100,8888	允許

# 從第三臺機器上直接用ssh即可連線本機,即:
# 雲主機A安裝frps,內網自己配的伺服器B安裝frpc
# 使用者不需要安裝frp,使用者直接使用ssh連線即可
# ssh -p 8000 [email protected]
# 此命令實現使用者C在他的電腦上遠端登入到內網伺服器B,
# myserver是內網伺服器B的使用者名稱,67.89.12.34是雲主機A的ip
# scp -P 8000 ./1.deb [email protected]:/home/myserver/Desktop/
# 此命令實現使用者本機檔案上傳到內網伺服器B

# 若內網還有伺服器B2,則雲主機A的frps不需要動
# 在內網伺服器B2上面安裝frpc即可,注意其配置為:
# [common]
# server_addr = 67.89.12.34
# server_port = 7000
# 不要與內網伺服器B重名
# [ssh_B2_00]   
# type = tcp
# local_ip = 127.0.0.1
# local_port = 22
# 新的用於ssh訪問內網伺服器B2的埠
# remote_port = 8001

7. 內網伺服器B設定frpc開機自啟動(systemd)

開啟frp_linux_amd64資料夾下的systemd目錄,編輯frpc.service檔案([email protected]檔案只是多了個自定義ini檔案的功能),將其中的user=nobody改為user=myserver(即本機的使用者名稱),如果不改,啟動時候會報錯無法寫入日誌檔案,許可權禁止
然後修改ExecStart、ExecReload中的路徑為自己的檔案路徑
將修改後的frpc.service檔案複製到/etc/systemd/system/sudo cp ./frpc.service /etc/systemd/system/
啟用frpc開機啟動:systemctl enable frpc
手動執行frpc服務:systemctl start frpcservice frpc start
手動停止frpc服務:systemctl stop frpcservice frpc stop
手動重啟frpc服務:systemctl restart frpcservice frpc restart
檢視frpc執行狀態:systemctl status frpcservice frpc status
關閉frpc開機啟動systemctl disable frpc

8. 內網伺服器B設定frpc開機自啟動(init.d)

建立start_frp.sh檔案:vi start_frp.sh,內容如下(註釋不可刪除):

#!/bin/sh
### BEGIN INIT INFO
# Provides:          svnd.sh
# Required-start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the svnd.sh daemon
# Description:       starts svnd.sh using start-stop-daemon
### END INIT INFO
/home/myserver/frp_linux_amd64/frpc -c /home/myserver/frp_linux_amd64/frpc.ini

給予執行許可權: chmod 775 start_frp.sh
複製到指定位置: sudo cp ./start_frp.sh /etc/init.d/
重新整理即可: sudo update-rc.d start_frp.sh defaults 90
重啟即可發現自啟動程序: ps -ef | grep frp
取消frpc自啟動(/etc/init.d/)

sudo rm /etc/init.d/start_frp.sh
sudo update-rc.d -f start_frp remove

9. SSH保活的幾種方法

ssh保活

10. 測試內網穿透

保證frps.servicefrpc.service處於執行狀態,使用者C(可以是linux系統、Windows系統等)在本機使用ssh命令即可連線到內網伺服器B:

  • 使用如下程式碼來遠端ssh連線內網伺服器B
    ssh -p 8000 [email protected]
  • 使用如下程式碼來將內網伺服器B的/home/myserver/test.txt檔案下載到使用者C的機器上
    scp -P 8000 [email protected]:/home/myserver/test.txt ./Desktop/

11. frp暴露多個內網web服務

本部分是針對jupyterlab搭建瀏覽器開發環境的過程

雲主機配置

修改frps.ini檔案,新增以下內容:

# 不需要和frpc.ini一致,與frpc的埠無關
vhost_http_port = 6888
subdomain_host = example.cn

[myjupyter]
type = http
subdomain = myjupyter

[web02]
type = http
subdomain = web02

然後修改nginx的配置檔案sudo vim /etc/nginx/nginx.conf

    server{
        listen 80;
        server_name myjupyter.example.cn;
        # 如果需要ssl,參考https://blog.whuzfb.cn/blog/2020/07/07/web_https/
        # listen 443 ssl;
        # include ssl/example.cn.ssl.conf;
        # 此時支援http與https
        access_log /home/ubuntu/frp_linux_amd64/log/access_jupyter.log;
        error_log /home/ubuntu/frp_linux_amd64/log/error_jupyter.log;
        location /{
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_redirect off;
            proxy_buffering off;
            proxy_pass http://127.0.0.1:8888;
        }
        location /api/kernels/ {
            proxy_pass            http://127.0.0.1:8888;
            proxy_set_header      Host $host;
            # websocket support
            proxy_http_version    1.1;
            proxy_set_header      Upgrade "websocket";
            proxy_set_header      Connection "Upgrade";
            proxy_read_timeout    86400;
        }
        location /terminals/ {
            proxy_pass            http://127.0.0.1:8888;
            proxy_set_header      Host $host;
            # websocket support
            proxy_http_version    1.1;
            proxy_set_header      Upgrade "websocket";
            proxy_set_header      Connection "Upgrade";
            proxy_read_timeout    86400;
        }
    }

    server{
        listen 80;
        server_name web02.example.cn;
        # include ssl/example.cn.ssl.conf;
        access_log /home/ubuntu/frp_linux_amd64/log/access_web.log;
        error_log /home/ubuntu/frp_linux_amd64/log/error_web.log;
        location /{
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_redirect off;
            proxy_buffering off;
            proxy_pass http://127.0.0.1:8888;
        }
        location /api/kernels/ {
            proxy_pass            http://127.0.0.1:8888;
            proxy_set_header      Host $host;
            # websocket support
            proxy_http_version    1.1;
            proxy_set_header      Upgrade "websocket";
            proxy_set_header      Connection "Upgrade";
            proxy_read_timeout    86400;
        }
        location /terminals/ {
            proxy_pass            http://127.0.0.1:8888;
            proxy_set_header      Host $host;
            # websocket support
            proxy_http_version    1.1;
            proxy_set_header      Upgrade "websocket";
            proxy_set_header      Connection "Upgrade";
            proxy_read_timeout    86400;
        }
    }

內網伺服器配置

修改frpc.ini檔案,新增以下內容:

[myjupyter]
type = http
# 此埠執行web服務
local_port = 7777
subdomain = myjupyter

[web02]
type = http
# 此埠執行web服務
local_port = 7778
subdomain = web02

分別重啟nginx、frps與frpc即可配置成功