使用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 myserver@67.89.12.34
    使用如下代码来将内网服务器B的/home/myserver/test.txt文件下载到用户C的机器上
    scp -P 8000 myserver@67.89.12.34:/home/myserver/test.txt ./Desktop/

用户C(用户端),只需要具备ssh连接的软件
frp的系统架构和最终实现的效果如下图

frp-architecture.png

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文件(frps@.service文件只是多了个自定义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 myserver@67.89.12.34
# 此命令实现用户C在他的电脑上远程登录到内网服务器B,
# myserver是内网服务器B的用户名,67.89.12.34是云主机A的ip
# scp -P 8000 ./1.deb myserver@67.89.12.34:/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文件(frpc@.service文件只是多了个自定义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 myserver@67.89.12.34
  • 使用如下代码来将内网服务器B的/home/myserver/test.txt文件下载到用户C的机器上
    scp -P 8000 myserver@67.89.12.34:/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即可配置成功

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342