frp配置实践教程

什么是内网穿透
内网穿透,也即 NAT 穿透,进行 NAT 穿透是为了使具有某一个特定源 IP 地址和源端口号的数据包不被 NAT 设备屏蔽而正确路由到内网主机。
说人话就是我们想在不连接家里的wifi的情况下访问我们家里面的电脑和其他设备时,由于家庭宽带没有固定的公网ip使得我们无法向访问云服务器一样
直接访问,这时候我们就需要使用到内网穿透技术,让我们在其他网络下也能访问到处于内网环境的设备。而内网穿透的工具也有很多如:

花生壳

  • nat123
  • ngrok
  • frp

本文主要讲FRP的搭建和使用。

frp简介

frp是一个快速反向代理,可帮助您将NAT或防火墙后面的本地服务器暴露给Internet。现在,当请求可以通过域转发到后向Web服务时,它支持tcp,udp,http和https协议。

2020041905432514.png

github地址:https://github.com/fatedier/frp

安装环境

  1. 一台拥有公网IP的服务器,如果需要使用域名访问直接将域名解析到公网IP。
  2. 系统与frp版本
        Server:CentOS 7.4、frp v0.21.0
        Client:CentOS 7.4、frp v0.21.0

在server端和client端安装frp

1.下载并安装

[root@frp_server src]# wget https://github.com/fatedier/frp/releases/download/v0.21.0/frp_0.21.0_linux_amd64.tar.gz
[root@frp_server src]# ls
frp_0.21.0_linux_amd64.tar.gz
[root@frp_server src]# tar -xvf frp_0.21.0_linux_amd64.tar.gz -C /usr/local/
[root@frp_server src]# mv /usr/local/frp_0.21.0_linux_amd64/ /usr/local/frp_server
[root@frp_server ~]# cd /usr/local/frp_server/
[root@frp_server frp_server]# ls
frpc  frpc_full.ini  frpc.ini  frps  frps_full.ini  frps.ini  LICENSE

  1. 文件说明
frpc                    # 客户端二进制文件
frpc_full.ini           # 客户端配置文件完整示例
frpc.ini                # 客户端配置文件
frps                    # 服务端二进制文件
frps_full.ini           # 服务端配置文件完整示例
frps.in1                # 服务端配置文件

配置frp sever

  1. 配置文件详解
[common]                        # 通用配置段
bind_addr = 0.0.0.0             # 绑定的IP地址,支持IPv6,不指定默认0.0.0.0;
bind_port = 7000                # 服务端口;
bind_udp_port = 7001            # 是否使用udp端口,不使用删除或注释本行;
kcp_bind_port = 7000            # 是否使用kcp协议,不使用删除或注释本行;
# proxy_bind_addr = 127.0.0.1   # 代理监听地址,默认和bind_addr相同;

# 虚拟主机
vhost_http_port = 80            # 是否启用虚拟主机,端口可以和bind_port相同;
vhost_https_port = 443
vhost_http_timeout = 60         # 后端虚拟主机响应超时时间,默认为60s;

# 开启frps仪表盘可以检查frp的状态和代理的统计信息。
dashboard_addr = 0.0.0.0        # frps仪表盘绑定的地址;
dashboard_port = 7500           # frps仪表盘绑定的端口;
dashboard_user = admin          # 访问frps仪表盘的用户;     
dashboard_pwd = admin           # 密码;
assets_dir = ./static           # 仪表盘页面文件目录,只适用于调试;

# 日志配置文件
log_file = ./frps.log           # 日志文件,不指定日志信息默认输出到控制台;
log_level = info                # 日志等级,可用等级“trace, debug, info, warn, error”;
log_max_days = 3                # 日志保存最大保存时间;

token = 12345678                # 客户端与服务端通信的身份验证令牌

heartbeat_timeout = 90          # 心跳检测超时时间,不建议修改默认配置,默认值为90;?

# 指定允许客户端使用的端口范围,未指定则没有限制;
allow_ports = 2000-3000,3001,3003,4000-50000

max_pool_count = 5              # 每个客户端连接服务端的最大连接数;
max_ports_per_client = 0        # 每个客户端最大可以使用的端口,0表示无限制

authentication_timeout = 900    # 客户端连接超时时间(秒),默认为900s;

subdomain_host = frps.com       # 自定义子域名,需要在dns中将域名解析为泛域名;

tcp_mux = true                  # 是否使用tcp复用,默认为true;
                                # frp只对同意客户端的连接进行复用;

  1. 配置示例
[common]
bind_addr = 0.0.0.0
bind_port = 7000

# Virtual host configuration
vhost_http_port = 80
vhost_https_port = 443

# Dashboard configuration
dashboard_addr = 0.0.0.0
dashboard_port = 7500
dashboard_user = admin
dashboard_pwd = admin

# logs
log_file = ./frps.log
log_level = info
log_max_days = 3

# auth token
token = 12345678

max_pool_count = 5
max_ports_per_client = 0
authentication_timeout = 900
tcp_mux = true

  1. 启动frps,默认前台启动为提供后台允许参数
[root@frp_server frp_server]# ./frps -c frps.ini

  1. 将frps注册为系统服务
[root@frp_server ~]# vim /usr/lib/systemd/system/frps.service
[Unit]
Description=frp server
After=network.target

[Service]
Type=simple

ExecStart=/usr/local/frp_server/frps -c /usr/local/frp_server/frps.ini
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID

[Install]
WantedBy=multi-user.target
[root@frp_server ~]# systemctl enable frps

[root@frp_server ~]# systemctl start  frps.service
[root@frp_server ~]# systemctl status frps
● frps.service - frp server
   Loaded: loaded (/usr/lib/systemd/system/frps.service; disabled; vendor preset: disabled)
   Active: active (running) since Tue 2018-09-25 17:47:44 CST; 20s ago
 Main PID: 4168 (frps)
   CGroup: /system.slice/frps.service
           └─4168 /usr/local/frp_server/frps -c /usr/local/frp_server/frps.ini

Sep 25 17:47:44 frp_server systemd[1]: Started frp server.
Sep 25 17:47:44 frp_server systemd[1]: Starting frp server...

配置frp client

  1. 配置文件详解
[common]                        # 通用配置段

server_addr = 0.0.0.0           # server的IP地址;支持IPv6
server_port = 7000              # server的端口;

# 如果要通过http或socks5代理连接frps,可以在此处或在全局环境变量中设置代理,只支持tcp协议;
# http_proxy = http://user:passwd@192.168.1.128:8080
# http_proxy = socks5://user:passwd@192.168.1.128:1080

# 客户端日志
log_file = ./frpc.log       # 指定日志文件;
log_level = info            # 指定日志等级;
log_max_days = 3

token = 12345678            # 客户端与服务端通信的身份验证令牌

# 设置管理地址,用于通过http api控制frpc的动作,如重新加载;
admin_addr = 127.0.0.1
admin_port = 7400
admin_user = admin
admin_passwd = admin

pool_count = 5              # 初始连接池的数量,默认为0;

tcp_mux = true              # 是否启用tcp复用,默认为true;

user = your_name            # frpc的用户名,用于区别不用frpc的代理;

login_fail_exit = true      # 首次登录失败时退出程序,否则连续重新登录到frps;

protocol = tcp              # 用于连接服务器的协议,支持tcp、kcp、websocket;

dns_server = 8.8.8.8        # 为frp 客户端指定一个单独的DNS服务器;

# start = ssh,dns           # 要启用的代理的名字,默认为空表示所有代理;

# 心跳检查
# heartbeat_interval = 30   # 失败重试次数
# heartbeat_timeout = 90    # 超时时间

# 配置示例
[ssh]                       # 代理配置段名称,如果配置user=your_name,则显示为your_name.ssh;
type = tcp                  # 协议默认tcp,可选tcp,udp,http,https,stcp,xtcp;
local_ip = 127.0.0.1        # 本地地址
local_port = 22             # 本地端口
use_encryption = false      # 是否加密服务端和客户端的通信信息,默认为不加密;
use_compression = false     # 是否开启压缩,默认不开启;
remote_port = 6001          # 在服务器端开启的远程端口;
# 负载均衡配置
group = test_group          # 负载均衡组名,会将同一组内的客户端进行负载;
group_key = 123456          # 负载均衡组密钥; 
# web示例
[web01]
type = http                 # 使用http
local_ip = 127.0.0.1        
local_port = 80
use_encryption = false
use_compression = true
http_user = admin           # 访问web01页面启用认证,用户名admin
http_pwd = admin            # 密码
subdomain = web01           # 子域名,需要服务端配置了subdomain_host参数;
custom_domains = web02.example.com # web01的域名,和subdomain二选一
locations = /,/pic          # 指定用于路由的URL前缀;
host_header_rewrite = example.com   # 配置http包头域名重写;
header_X-From-Where = frp           # 添加包头信息X-From-Where: frp;

  1. 配置示例
[common]
server_addr = xxx.xxx.xxx.xxx
server_port = 7000
log_file = ./frpc.log
log_level = info
log_max_days = 3
token = 12345678
pool_count = 5
tcp_mux = true
login_fail_exit = true
protocol = tcp

[web]
type = http
local_ip = 127.0.0.1
local_port = 80
use_encryption = false
use_compression = true
custom_domains = xxx.xxx.xxx.xxx
header_X-From-Where = frp

  1. 启动frpc
[root@test frp_client]# ./frpc -c frpc.ini 

请注意,除了’start’之外,[common]部分中的参数不会被修改。

测试

1.访问仪表盘


image.png

查看http服务


image.png

2. 访问后端服务

image.png
image.png

下面是frp github介绍中一些配置示例

ssh

修改frps.ini:

# frps.ini 
[common] 
bind_port = 7000

启动frps:./frps -c ./frps.ini
修改frpc.ini,server_addr是你的frps的服务器IP:

# frpc.ini 
[common] 
server_addr = xxxx
server_port = 7000

[ssh] 
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000

启动frpcz:./frpc -c ./frpc.ini
假设用户名为test,则通过ssh连接到LAN中的服务器:ssh -oPort=6000 test@x.x.x.x

通过自定义域访问LAN中的Web服务

有时我们希望将NAT网络后面的本地Web服务公开给其他人以使用您自己的域名进行测试,但是无法将域名解析为本地IP。我们可以使用frp公开http或https服务。

修改frps.ini,配置http端口8080:

# frps.ini 
[common] 
bind_port = 7000
vhost_http_port = 8080

启动frps:./frps -c ./frps.ini
修改frpc.ini并将远程frps服务器的IP设置为xxxx这local_port是您的Web服务的端口:

# frpc.ini 
[common] 
server_addr = xxxx
server_port = 7000

[web] 
type = http
local_port = 80
custom_domains = www.yourdomain.com

启动frpc:./frpc -c ./frpc.ini
解析域名到frp的IP地址,然后使用url访问您的本地Web服务http://www.yourdomain.com:8080

转发DNS查询请求

修改frps.ini:

# frps.ini 
[common] 
bind_port = 7000

修改frpc.ini,将远程frps的服务器IP设置为xxxx,将dns查询请求转发到google dns服务器8.8.8.8:53:

# frpc.ini 
[common] 
server_addr = xxxx
server_port = 7000

[dns] 
type = udp
local_ip = 8.8.8.8
local_port = 53
remote_port = 6000

通过dig发送dns查询请求:

dig @x.x.x.x -p 6000 www.google.com

转发unix域套接字,使用tcp端口连接unix域套接字,如docker守护进程。

配置与上面相同的frps。
配置frpc.ini

# frpc.ini 
[common] 
server_addr = xxxx
server_port = 7000

[unix_domain_socket] 
type = tcp
remote_port = 6000
plugin = unix_domain_socket
plugin_unix_path = /var/run/docker.sock

通过curl命令获取docker版本:curl http://x.x.x.x:6000/version

公开一个简单的http文件服务器

配置与上面相同的frps
配置启动frpc:

# frpc.ini 
[common] 
server_addr = xxxx
server_port = 7000

[test_static_file] 
type = tcp
remote_port = 6000
plugin = static_file
plugin_local_path = /tmp/file
plugin_strip_prefix = static
plugin_http_user = abc
plugin_http_passwd = abc

访问http://x.x.x.x:6000/static/,输入正确的用户和密码,就可以查看文件/tmp/file

在安全性中公开您的服务

对于某些服务,如果直接将它们暴露给公共网络将存在安全风险。stcp(secret tcp)帮助您创建代理,避免任何人可以访问它。
配置与上面相同的frps。
启动frpc,转发ssh端口并且remote_port没用:

# frpc.ini 
[common] 
server_addr = xxxx
server_port = 7000

[secret_ssh] 
type = stcp
sk = abcdefg
local_ip = 127.0.0.1
local_port = 22

启动另一个要连接此ssh服务器的frpc:

# frpc.ini 
[common] 
server_addr = xxxx
server_port = 7000

[secret_ssh_visitor] 
type = stcp
role = visitor
server_name = secret_ssh
sk = abcdefg
bind_addr = 127.0.0.1
bind_port = 6000

假设用户名为test,则通过ssh连接到LAN中的服务器:
ssh -oPort=6000 test@127.0.0.1

P2P模式

xtcp旨在直接在两个客户端之间传输大量数据。现在它无法穿透所有类型的NAT设备。如果xtcp不起作用,您可以尝试使用stcp。

配置xtcp的udp端口:

bind_udp_port = 7001

启动frpc,转发ssh端口并且remote_port没用:

# frpc.ini 
[common] 
server_addr = xxxx
server_port = 7000

[p2p_ssh] 
type = xtcp
sk = abcdefg
local_ip = 127.0.0.1
local_port = 22

启动另一个要连接此ssh服务器的frpc:

# frpc.ini 
[common] 
server_addr = xxxx
server_port = 7000

[p2p_ssh_visitor] 
type = xtcp
role = visitor
server_name = p2p_ssh
sk = abcdefg
bind_addr = 127.0.0.1
bind_port = 6000

假设用户名为test,则通过ssh连接到LAN中的服务器:
ssh -oPort=6000 test@127.0.0.1

认证

  1. 从v0.10.0开始,您只需要token在frps.ini和frpc.ini中进行设置。
  2. 请注意,frpc和frps服务器之间的持续时间不得超过15分钟,因为时间戳用于身份验证。然后,可以通过设置authentication_timeoutfrps的配置文件来修改此超时持续时间。它的defalut值是900,意味着15分钟。如果它等于0,则frps将不检查身份验证超时。

端口重用

现在vhost_http_port和vhost_https_portfrps可以使用相同的端口bind_port。frps将检测连接的协议并相应地处理它。
我们希望尝试允许多个代理在将来使用不同的协议绑定相同的远程端口。

支持KCP协议

frp支持kcp协议,自v0.12.0起。
KCP是一种快速可靠的协议,可以实现将平均延迟降低30%至40%并将最大延迟降低三倍的传输效果,其代价是浪费10%至20%的带宽浪费比TCP。
在frp中使用kcp:

#frps.ini 
[command] 
bind_port = 7000
kcp_bind_port = 7000 # KCP需要绑定一个UDP端口

配置frpc中使用的协议连接frps:

# frpc.ini 
[command] 
SERVER_ADDR = XXXX
SERVER_PORT = 7000
protocol = KCP

负载均衡

支持负载均衡group。此功能仅适用于tcp现在的类型。

# frpc.ini 
[test1] 
type = tcp
local_port = 8080
remote_port = 80
group = web
group_key = 123

[test2] 
type = tcp
local_port = 8081
remote_port = 80
group = web
group_key = 123

同一组中的代理将随机接受来自端口80的连接。

重写主机标头

转发到本地端口时,frp根本不会修改隧道HTTP请求,它们会在收到时逐字节地复制到服务器。某些应用程序服务器使用Host标头来确定要显示的开发站点。因此,frp可以使用修改后的主机头重写您的请求。使用该host_header_rewrite开关重写传入的HTTP请求。

# frpc.ini 
[web] 
type = http
local_port = 80
custom_domains = test.yourdomain.com
host_header_rewrite = dev.yourdomain.com

如果host_header_rewrite指定,则将重写主机头以匹配转发地址的主机名部分。

在HTTP请求中设置标头

您可以为代理类型设置标头http。

# frpc.ini 
[web] 
type = http
local_port = 80
custom_domains = test.yourdomain.com
host_header_rewrite = dev.yourdomain.com
header_X-From-Where = frp

请注意,具有前缀的参数header_将添加到http请求标头中。在此示例中,它将标头设置X-From-Where: frp为http请求。

获取客户端真正的IP

仅限http代理的功能。
你可以从HTTP请求头获取用户的真实IP X-Forwarded-For和X-Real-IP。请注意,现在您只能在每个用户连接的第一个请求中获取这两个标头。

URL路由

frp支持通过url路由将http请求转发到不同的后向Web服务。
locations指定用于路由的URL前缀。frps首先搜索由文字字符串给出的最具体的前缀位置,而不管列出的顺序如何。

# frpc.ini 
[web01] 
type = http
local_port = 80
custom_domains = web.yourdomain.com
locations = /

[web02] 
type = http
local_port = 81
custom_domains = web.yourdomain.com
locations = / news,/ about

HTTP与URL前缀请求/news和/about将被转发到web02和他人WEB01。

范围端口映射

代理名称前缀range:将支持映射范围端口。

# frpc.ini 
[range:test_tcp] 
type = tcp
local_ip = 127.0.0.1
local_port = 6000-6006,6007
remote_port = 6000-6006,6007

frpc将生成8个代理test_tcp_0, test_tcp_1 … test_tcp_7。

插件

frpc默认只向本地tcp或udp端口转发请求。而插件提供了丰富的功能。内置的插件有unix_domain_socket,http_proxy,socks5,static_file。

指定plugin参数使用的插件。插件的配置参数应该以plugin_。local_ip并且local_port对插件没用。

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

推荐阅读更多精彩内容