一、为什么要使用 TLS 加密 FRPS 与 FRPC 通信
transport.useEncryption 和 STCP 等功能能有效防止流量内容在通信过程中被盗取,但是无法判断对方的身份是否合法,存在被中间人攻击的风险。为此 frp 支持 frpc 和 frps 之间的流量通过 TLS 协议加密,并且支持客户端或服务端单向验证,双向验证等功能。
二、如何使用 TLS 加密 FRPS 与 FRPC 通信
ℹ️
本文使用的frps/frpc版本为 v0.63.0,此时frp的配置文件已转为 toml 而非 ini
2.1、生成证书
ℹ️
go 1.15 版本开始废弃 CommonName,因此推荐使用 SAN 证书。
❌
我部署的环境 Frpc 是通过 IP 地址连接至 Frps ,如你的部署环境与我不同,请自行斟酌。
我已经编写了自动生成 CA 证书、服务端证书、客户端证书的脚本,脚本会生成一个 CA 证书和对应的服务端、客户端证书。你可以直接使用这个脚本生成证书。
#!/bin/bash
set -e
# === 参数 ===
CA_CN="example.ca.com"
SERVER_CN="server.com"
CLIENT_CN="client.com"
SERVER_IP="X.X.X.X" # 将此替换为你的Frps服务端 IP 地址
# === 清理旧文件 ===
rm -f ca.key ca.crt ca.srl \
server.key server.csr server.crt \
client.key client.csr client.crt \
my-openssl.cnf
echo "[+] 创建简化 openssl 配置文件 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
# === 生成 CA ===
echo "[+] 生成 CA 证书..."
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=${CA_CN}" -days 3650 -out ca.crt
# === 生成服务端证书 ===
echo "[+] 生成 frps 证书..."
openssl genrsa -out server.key 2048
openssl req -new -sha256 -key server.key \
-subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=${SERVER_CN}" \
-reqexts SAN \
-config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=IP:${SERVER_IP},DNS:${SERVER_CN}")) \
-out server.csr
openssl x509 -req -days 825 -sha256 \
-in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-extfile <(printf "subjectAltName=IP:${SERVER_IP},DNS:${SERVER_CN}") \
-out server.crt
# === 生成客户端证书 ===
echo "[+] 生成 frpc 证书..."
openssl genrsa -out client.key 2048
openssl req -new -sha256 -key client.key \
-subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=${CLIENT_CN}" \
-reqexts SAN \
-config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:${CLIENT_CN}")) \
-out client.csr
openssl x509 -req -days 825 -sha256 \
-in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-extfile <(printf "subjectAltName=DNS:${CLIENT_CN}") \
-out client.crt
echo "[✓] 所有证书和私钥生成完毕。"
ℹ️
脚本生成的证书和私钥文件会生成在脚本同目录下。
✅
将生成的证书和私钥文件 CA 文件放到 frps 和 frpc 的配置文件中指定的路径下。
脚本生成的证书和私钥文件指定使用了 2048-bit 密钥与 SHA-256 签名,保证了强加密与安全性。
2.2、frps.toml 配置
# frps监听设置
# TLS 加密配置
transport.tls.force = true # 强制frpc连接至frps时使用 TLS 加密并验证证书
transport.tls.certFile = "/etc/frp/ssl/server.crt"
transport.tls.keyFile = "/etc/frp/ssl/server.key"
transport.tls.trustedCaFile = "/etc/frp/ssl/ca.crt"
# 其他配置
2.3、frpc.toml 配置
# frpc连接设置
# TLS 加密配置
transport.tls.certFile = "/to/cert/path/client.crt"
transport.tls.keyFile = "/to/key/path/client.key"
transport.tls.trustedCaFile = "/to/ca/path/ca.crt"
# 其他配置
2.4、启动 frps 和 frpc
这个不用我教了吧。
