使用frp进行敏感业务流量转发与内网业务映射

自从ngrok免费版本不进行维护后,我一直在寻求一款稳定可靠,开源的转发工具来将我内网的业务映射到公网上。

FRP(Github)正好可以满足我的要求。不仅可以实现内网业务的映射,也可以实现服务器端业务的映射,以使得在内网安全稳定地访问公网敏感业务(例如SSH)。同时还支持注册为systemd服务,稳定性更好。

0x00 明确需求

在使用FRP之前我们要搞清楚自己希望通过FRP实现什么。

以一个最简单的拓扑为例:

我有一台公网服务器,我希望内网的业务暴露在公网。业务类型可能是HTTP(s)类业务或者是TCP类业务。我也希望我能够隐藏公网的一些服务(比如SSH),通过FRP自带的STCP功能将流量加密地发回到我的客户端,并通过客户端的特定端口来进行访问。

以我的实际拓扑为例:

我有一台公网服务器用作堡垒机,作为FRP的服务器。我有另一台公网服务器承载业务,我希望通过堡垒机管理这台生产服务器的SSH。

我使用FRP的STCP功能加密SSH流量发到堡垒机上,并在公有云后端的防火墙对SSH端口进行封禁。

我有一台内网服务器,上面是一个ESXi主机,其中我建立了一台Edge Server作为边界节点,Edge上运行了FRP客户端,把公网服务器的SSH流量转发到自己的某个端口。同时客户端还把内网中的其他业务暴露到FRP堡垒机。

最后基于安全配置,我在堡垒机(FRP服务器)上也开启了FRP的客户端,将堡垒机的SSH也转发到自身,并在内网的Edge服务器访问。同时关闭堡垒机侧防火墙公网对SSH端口的访问。

0x01 配置FRP服务器(堡垒机)

0x010 服务器配置

下载回来frp组件,frps是服务器组件,frpc是客户端组件。

针对默认配置,我们做了一些修改。

# [common] is integral section
[common]
# A literal address or host name for IPv6 must be enclosed
# in square brackets, as in "[::1]:80", "[ipv6-host]:http" or "[ipv6-host%zone]:80"
bind_addr = 0.0.0.0
# 这里绑定管理端口
bind_port = 7000


# udp port to help make udp hole to penetrate nat
# 绑定UDP端口
bind_udp_port = 7001

# udp port used for kcp protocol, it can be same with 'bind_port'
# if not set, kcp is disabled in frps
# 绑定KCP端口
kcp_bind_port = 7000

# specify which address proxy will listen for, default value is same with bind_addr
# proxy_bind_addr = 127.0.0.1

# if you want to support virtual host, you must set the http port for listening (optional)
# Note: http port and https port can be same with bind_port
# 进行HTTP(s)流量转发时需要用到这个端口,流量会被打到这个端口上并用二级域名做区分。
vhost_http_port = 6666
vhost_https_port = 8888

# response header timeout(seconds) for vhost http server, default is 60s
# vhost_http_timeout = 60

# set dashboard_addr and dashboard_port to view dashboard of frps
# dashboard_addr's default value is same with bind_addr
# dashboard is available only if dashboard_port is set
# Web管理面板,非必须。0.0.0.0指这个面板可以被任意访问,127.0.0.1指这个面板只能被自己访问。
dashboard_addr = 127.0.0.1
dashboard_port = 6688

# dashboard user and passwd for basic auth protect, if not set, both default value is admin
# 管理面板的用户名、密码
dashboard_user = username
dashboard_pwd = password


# dashboard assets directory(only for debug mode)
# assets_dir = ./static
# console or real logFile path like ./frps.log
log_file = ./frps.log

# trace, debug, info, warn, error
log_level = warn

log_max_days = 3

# disable log colors when log_file is console, default is false
disable_log_color = false

# auth token
# 指定和客户端的通讯密码
token = password

# heartbeat configure, it's not recommended to modify the default value
# the default value of heartbeat_timeout is 90
# heartbeat_timeout = 90

# only allow frpc to bind ports you list, if you set nothing, there won't be any limit
# 允许TCP、UDP流量打到FRP服务器特定的端口组
allow_ports = 6101-6200

# pool_count in each proxy will change to max_pool_count if they exceed the maximum value
max_pool_count = 50

# max ports can be used for each client, default value is 0 means no limit
max_ports_per_client = 0

# if subdomain_host is not empty, you can set subdomain when type is http or https in frpc's configure file
# when subdomain is test, the host used by routing is test.frps.com
# 用作HTTP流量转发的子域名
subdomain_host = frp.iam.lc

# if tcp stream multiplexing is used, default is true
tcp_mux = true

# custom 404 page for HTTP requests
# custom_404_page = /path/to/404.html

将这个配置文件保存到 /etc/frp/frps.ini

然后我们开始写systemd脚本:

# /etc/systemd/system/frps.service
[Unit]
Description=Frp Server Service
After=network.target

[Service]
Type=simple
User=root
Restart=always
RestartSec=5s
ExecStart=/usr/bin/frps -c /etc/frp/frps.ini

[Install]
WantedBy=multi-user.target

配置好自启动,服务器端就配置完成了。

0x011 安全组配置与端口放通

关于端口放通,我们需要放通以下端口:

7000 TCP+UDP 主通信端口

7001 UDP UDP通信端口

6666 TCP HTTP虚拟主机端口

8888 TCP HTTPS虚拟主机端口

6101-6200 TCP+UDP 客户端业务注册端口

6688 TCP 管理面板端口

0x012 域名设置

基于七层HTTP的业务映射,FRP允许我们使用 A.frp.iam.lc 子域名来进行访问。A可以自行定义。而基于TCP的端口业务映射,我们也通常给予一个域名 frp.iam.lc 来进行访问。

我们需要添加以下两条A记录到你的DNS解析:

*.frp.iam.lc -> 堡垒机IP

frp.iam.lc -> 堡垒机IP

至此,服务器侧配置完成。

0x02 内网客户端映射到FRP服务器

在内网的linux服务器安装好frpc客户端,我们开始写配置文件:

/etc/frp/frpc.ini

[common]
server_addr = 1.2.3.4 # 服务器IP
server_port = 7000
token = password
pool_count = 4
protocol = kcp

以上是每个客户端的公共配置部分。这将作为基础连接参数,被下面要添加的各种服务引用。

下面我们要把内网的NAS存储转发到公网,内网的NAS IP是192.168.1.230,我们打算转发到公网的6101端口,并使用TCP映射。

[local_nas]
type = tcp
remote_port = 6101
local_port = 443
local_ip = 192.168.1.230

这样我们就把NAS的HTTPS端口映射到了frp.iam.lc:6101上。

而我们转发的实际上是HTTPS流量,我们还需要在证书扩展背景名称中将frp.iam.lc加进来。(仅适用于自签名证书)

0x03 将生产服务器的SSH安全转发到本地

在生产服务器,我们部署frpc客户端后,进行配置。

首先添加公共模块,如上所示。

然后我们添加SSH的STCP转发:

[stcp_ssh] # 对应Server Name,在客户端用到
type = stcp
sk = your-secret # 密钥
local_ip = 127.0.0.1 # 转发本地流量,也可以转发其他主机流量
local_port = 22 # 转发端口,这里以SSH为例
tls_enable = true # tls加密
use_compression = true # 启用压缩

值得一提的是,STCP流量并不要求我们指定端口。

回到内网的Edge服务器,我们添加以下配置:

[stcp_ssh_client]
type = stcp
role = visitor
server_name = stcp_ssh
sk = your-secret
bind_addr = 0.0.0.0 # 如果绑定0.0.0.0则会被内网所有主机访问。如果只想被自己访问则绑定127.0.0.1
bind_port = 6101 # 这是绑定到Edge的端口,和服务器无关。
use_encryption = true
use_compression = true

至此,我们可以通过frp在内网通过堡垒机加密流量,ssh到公网服务器了。

假设Edge Server的IP是192.168.1.250,我们可以通过以下命令连接到公网服务器SSH:

ssh -p6101 192.168.1.250

0x04 客户端的自启动配置

非常简单,类似服务器配置:

# /etc/systemd/system/frpc.service
[Unit]
Description=Frp Client Service
After=network.target

[Service]
Type=simple
User=root
Restart=on-failure
RestartSec=5s
ExecStart=/usr/bin/frpc -c /etc/frp/frpc.ini
ExecReload=/usr/bin/frpc reload -c /etc/frp/frpc.ini

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now frpc

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注