在公网服务器搭建frps(service),在内网本地机子搭建frpc(client),流量通过访问公网ip,经过frps服务端转发到fprc客户端,fprc再转发到本地web应用。
官方下载地址 https://github.com/fatedier/frp/releases
官方文档地址https://gofrp.org/docs/
服务端:frp_0.44.0_linux_amd64.tar.gz
客户端:frp_0.44.0_windows_amd64.zip
一、http
服务端frps(公网服务器)
这里我用虚拟机模拟了一台公网服务器:192.168.111.201
-
# 解压
-
tar -xzvf frp_0.44.0_linux_amd64.tar.gz
-
cd frp_0.44.0_linux_amd64
-
# 配置服务端
-
vi frps.ini
配置 frps.ini
-
[
common]
-
# frp服务端的端口,frp客户端需要连接这个端口握手
-
bind_port =
7000
-
# 公网服务端对外提供的http端口
-
vhost_http_port=
8080
启动服务端
./frps -c frps.ini
后台启动运行服务端
nohup ./frps -c frps.ini >/dev/null 2>&1 &
客户端frpc(内网本地)
配置 frpc.ini
-
[common]
-
# frps服务端的ip和端口
-
server_addr =
192.168.
111.201
-
server_port =
7000
-
-
[web01]
-
type = http
-
# 本地web应用的ip和端口
-
local_ip =
127.0.
0.1
-
local_port =
8080
-
#公网服务器的ip或域名
-
custom_domains =
192.168.
111.201
到解压根目录启动客户端
frpc -c frpc.ini
访问公网ip已经可以反向代理到本地web服务了。
以上就是一个简单的内网穿透 http 例子。
二、https
使用官方推荐的如下配置:
frps.ini
-
[
common]
-
bind_port =
7000
-
vhost_https_port =
443
frpc.ini
-
[common]
-
server_addr =
192.168.
111.201
-
server_port =
7000
-
-
[plugin_https2https]
-
type = https
-
custom_domains =
192.168.
111.201
-
plugin = https2https
-
plugin_local_addr =
127.0.
0.1:
8443
-
#plugin_crt_path = ./server.crt
-
#plugin_key_path = ./server.key
-
plugin_host_header_rewrite =
127.0.
0.1
-
plugin_header_X-
From-
Where = frp
结果一直报如下错误,没找到解决办。
三、tcp实现https
研究了好久,才反应过来,http协议在应用层,tcp在传输层,且http是基于tcp的。
既然https失败了,直接转发tcp就是,把ssl放在本地web应用中就可以了,frp只做tcp流量转发。
frps.ini
-
[
common]
-
bind_port =
7000
frpc.ini
-
[common]
-
server_addr =
192.168.
111.201
-
server_port =
7000
-
-
[tcp]
-
type = tcp
-
# 本地web应用的ip和端口
-
local_ip =
127.0.
0.1
-
local_port =
8443
-
# 公网服务器提供给外网访问的端口
-
remote_port =
443
四、安全加固
上面有2个不安全的地方:
1、frpc 和 frps 之间的身份验证不安全,默认为 token,这种方式存在被中间人攻击的威胁。
2、frpc 和 frps 之间的流量未加密,可以通过 TLS 协议加密,解决被中间人攻击的威胁。
frps.ini
-
[
common]
-
#frps服务端监听的端口,frpc客户端要来连接。
-
bind_port =
7000
-
#密码设置复杂点,frps服务端密码和frpc客户端密码要一致。
-
token = mm123456789
frpc.ini
-
[common]
-
# frps服务端的ip和端口
-
server_addr =
192.168.
111.201
-
server_port =
7000
-
#密码设置复杂点,frps服务端密码和frpc客户端密码要一致。
-
token = mm123456789
-
-
[tcp]
-
type = tcp
-
# 本地web应用的ip和端口
-
local_ip =
127.0.
0.1
-
local_port =
8443
-
# 公网服务器提供给外网访问的端口
-
remote_port =
443
双向验证
双向验证即 frpc 和 frps 通过本地 ca 证书去验证对方的身份。理论上 frpc 和 frps 的 ca 证书可以不同,只要能验证对方身份即可。
frps.ini
-
# frps.ini
-
[common]
-
#frps服务端监听的端口,frpc客户端要来连接。
-
bind_port = 7000
-
#密码设置复杂点,frps服务端密码和frpc客户端密码要一致。
-
token = mm123456789
-
-
tls_cert_file = ./server.crt
-
tls_key_file = ./server.key
-
tls_trusted_ca_file = ./ca.crt
frpc.ini
-
# frpc.ini
-
[common]
-
# frps服务端的ip和端口
-
server_addr = 192.168.111.201
-
server_port = 7000
-
#密码设置复杂点,frps服务端密码和frpc客户端密码要一致。
-
token = mm123456789
-
-
# frpc开启TLS加密功能
-
tls_enable =
true
-
tls_cert_file = ./client.crt
-
tls_key_file = ./client.key
-
tls_trusted_ca_file = ./ca.crt
-
-
[tcp]
-
type = tcp
-
# 本地web应用的ip和端口
-
local_ip = 127.0.0.1
-
local_port = 8443
-
# 公网服务器提供给外网访问的端口
-
remote_port = 443
-
生成SAN 证书
1、准备默认 my-openssl.cnf 配置文件于当前目录
-
cat > my-openssl.cnf << EOF
-
[ ca ]
-
default_ca = CA_default
-
[ CA_default ]
-
x509_extensions = usr_cert
-
[ req ]
-
default_bits =
2048
-
default_md =
sha256
-
default_keyfile
= privkey.
pem
-
distinguished_name
=
req_distinguished_name
-
attributes
=
req_attributes
-
x509_extensions
=
v3_ca
-
string_mask
= utf8only
-
[ req_distinguished_name ]
-
[ req_attributes ]
-
[ usr_cert ]
-
basicConstraints = CA:
FALSE
-
nsComment
=
"OpenSSL Generated Certificate"
-
subjectKeyIdentifier =
hash
-
authorityKeyIdentifier
= keyid,issuer
-
[ v3_ca ]
-
subjectKeyIdentifier =
hash
-
authorityKeyIdentifier
= keyid:always,
issuer
-
basicConstraints
= CA:
true
-
EOF
2、生成默认CA
-
openssl genrsa -out ca.
key
2048
-
openssl req -x509 -
new -nodes -
key ca.
key -subj
"/CN=example.ca.com" -days
3650 -out ca.crt
3、生成服务端证书
将 192.168.111.201 改成自己的服务端的ip
-
openssl genrsa -out
server.key
2048
-
-
openssl req -
new -sha256 -key
server.key \
-
-subj
"/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=192.168.111.201" \
-
-reqexts SAN \
-
-config <(cat my-openssl.cnf <(printf
"\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:server.com,IP:192.168.111.201")) \
-
-out
server.csr
-
-
openssl x509 -req -days
3650 -sha256 \
-
-
in
server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-
-extfile <(printf
"subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:server.com,IP:192.168.111.201") \
-
-out
server.crt
4、生成客户端证书
使用 who 命令查询客户端的ip地址。我这里是192.168.111.1
将 192.168.111.1 改成自己的客户端的ip
-
openssl genrsa -
out client.key
2048
-
openssl req -new -sha256 -key client.key \
-
-subj
"/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=192.168.111.1" \
-
-reqexts SAN \
-
-config <(cat my-openssl.cnf <(printf
"\n[SAN]\nsubjectAltName=DNS:client.com,IP:192.168.111.1")) \
-
-
out client.csr
-
-
openssl x509 -req -days
3650 -sha256 \
-
-
in client.csr -CA ca.crt -
CAkey ca.key -
CAcreateserial \
-
-extfile <(printf
"subjectAltName=DNS:client.com,IP:192.168.111.1") \
-
-
out client.crt
最终生成了10个文件。
server.crt、server.key、ca.crt 拷贝到 frp服务端解压目录下。
client.crt、client.key、ca.crt 拷贝到 frp客户端解压目录下。
转载:https://blog.csdn.net/u014644574/article/details/128303747