FRP TLS 安全传输的配置指南

涵盖 默认加密、单向认证、双向认证(mTLS) 三种模式,以及证书生成方法。


一、TLS 默认行为(v0.50.0+)

v0.50.0 开始,frp 默认启用 TLS 加密:

  • frpc 默认开启 TLS 加密,但不校验 frps 证书
  • frps 若未配置证书,则使用随机生成的自签名证书加密流量

注意 :启用 TLS 后,除 xtcp 外,可以不用再设置 useEncryption 重复加密。


二、TLS 配置项对照表

配置项 作用域 类型 说明
transport.tls.force frps bool 强制只接受 TLS 连接的客户端。若 trustedCaFile 有效,会自动开启
transport.tls.certFile 双端 string TLS 证书文件路径
transport.tls.keyFile 双端 string TLS 私钥文件路径
transport.tls.trustedCaFile 双端 string 受信任的 CA 证书文件路径,用于验证对方身份
transport.tls.enable frpc bool 客户端显式启用 TLS(v0.50.0+ 默认 true)

三、三种 TLS 模式配置

3.1 模式一:默认 TLS 加密(不验证身份)

无需额外配置,frp 默认使用随机证书加密通信。适用于信任网络环境。

toml 复制代码
# frps.toml - 无需额外 TLS 配置
bindPort = 7000

# frpc.toml - 无需额外 TLS 配置
serverAddr = "x.x.x.x"
serverPort = 7000

3.2 模式二:frpc 单向校验 frps 身份

frpc 验证 frps 的服务器证书,防止中间人攻击。

toml 复制代码
# ========== frps.toml ==========
bindPort = 7000

# frps 提供 TLS 证书
transport.tls.certFile = "/etc/frp/ssl/server.crt"
transport.tls.keyFile = "/etc/frp/ssl/server.key"

# ========== frpc.toml ==========
serverAddr = "x.x.x.x"
serverPort = 7000

# frpc 通过 CA 验证 frps 证书
transport.tls.trustedCaFile = "/etc/frp/ssl/ca.crt"

原理 :frpc 使用 ca.crt 验证 frps 的 server.crt 是否由可信 CA 签发,且服务器域名/IP 需在证书的 SAN 中。


3.3 模式三:双向 TLS 认证(mTLS)⭐ 推荐

frpc 和 frps 互相验证对方身份,安全性最高,适合生产环境。

toml 复制代码
# ========== frps.toml ==========
bindPort = 7000

# 强制 TLS + 服务端证书
transport.tls.force = true
transport.tls.certFile = "/etc/frp/ssl/server.crt"
transport.tls.keyFile = "/etc/frp/ssl/server.key"

# 验证客户端证书
transport.tls.trustedCaFile = "/etc/frp/ssl/ca.crt"

# ========== frpc.toml ==========
serverAddr = "x.x.x.x"
serverPort = 7000

# 客户端证书
transport.tls.certFile = "/etc/frp/ssl/client.crt"
transport.tls.keyFile = "/etc/frp/ssl/client.key"

# 验证服务端证书
transport.tls.trustedCaFile = "/etc/frp/ssl/ca.crt"

关键点:理论上 frpc 和 frps 的 CA 证书可以不同,只要能验证对方身份即可。但实际部署建议使用同一 CA 签发。


四、证书生成完整脚本(OpenSSL)

4.1 创建 OpenSSL 配置文件

bash 复制代码
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

4.2 生成 CA 根证书

bash 复制代码
# 生成 CA 私钥
openssl genrsa -out ca.key 2048

# 生成自签名 CA 证书(有效期约13年)
openssl req -x509 -new -nodes -key ca.key \
  -subj "/CN=example.ca.com" \
  -days 5000 -out ca.crt

4.3 生成服务端证书

⚠️ 服务端证书必须包含 SAN(Subject Alternative Name),否则客户端校验会失败。

bash 复制代码
# 1. 生成服务端私钥
openssl genrsa -out server.key 2048

# 2. 生成证书签名请求(CSR),替换为你的服务器 IP 和域名
openssl req -new -sha256 -key server.key \
  -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=server.com" \
  -reqexts SAN \
  -config <(cat my-openssl.cnf \
    <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:你的服务器公网IP,DNS:example.server.com")) \
  -out server.csr

# 3. 使用 CA 签发服务端证书
openssl x509 -req -days 3650 -sha256 \
  -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
  -extfile <(printf "subjectAltName=DNS:localhost,IP:你的服务器公网IP,DNS:example.server.com") \
  -out server.crt

4.4 生成客户端证书

bash 复制代码
# 1. 生成客户端私钥
openssl genrsa -out client.key 2048

# 2. 生成 CSR
openssl req -new -sha256 -key client.key \
  -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=client.com" \
  -reqexts SAN \
  -config <(cat my-openssl.cnf \
    <(printf "\n[SAN]\nsubjectAltName=DNS:client.com,DNS:example.client.com")) \
  -out client.csr

# 3. 使用 CA 签发客户端证书
openssl x509 -req -days 365 -sha256 \
  -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
  -extfile <(printf "subjectAltName=DNS:client.com,DNS:example.client.com") \
  -out client.crt

4.5 最终文件清单

文件 用途 部署位置
ca.crt 根证书 frps + frpc 的 trustedCaFile
ca.key CA 私钥 仅用于签发,不部署到任何端
server.crt + server.key 服务端证书 frps 的 certFile / keyFile
client.crt + client.key 客户端证书 frpc 的 certFile / keyFile

重要ca.key 是 CA 私钥,绝对不能放到 frps 或 frpc 上,仅用于签发证书。


五、Dashboard HTTPS 证书(独立配置)

Dashboard 的 HTTPS 与传输层 TLS 是两套独立配置:

bash 复制代码
# frps.toml - Dashboard 启用 HTTPS
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "admin"

# Dashboard 专用 TLS 证书(可以是 Let's Encrypt 等公网证书)
webServer.tls.certFile = "/path/to/dashboard.crt"
webServer.tls.keyFile = "/path/to/dashboard.key"

六、Windows 路径注意事项

Windows 系统配置证书路径时,反斜杠需转义:

bash 复制代码
# ❌ 错误
transport.tls.certFile = "C:\Users\test\server.crt"

# ✅ 正确
transport.tls.certFile = "C:\\Users\\test\\server.crt"

七、完整生产环境配置示例

frps.toml(服务端)

bash 复制代码
bindAddr = "0.0.0.0"
bindPort = 7000

# 认证
auth.method = "token"
auth.token = "your-strong-token-here"

# 强制 TLS + 双向认证
transport.tls.force = true
transport.tls.certFile = "/etc/frp/ssl/server.crt"
transport.tls.keyFile = "/etc/frp/ssl/server.key"
transport.tls.trustedCaFile = "/etc/frp/ssl/ca.crt"

# Dashboard
webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "your-dashboard-password"

# 日志
log.to = "/var/log/frps.log"
log.level = "info"
log.maxDays = 7

frpc.toml(客户端)

bash 复制代码
serverAddr = "your-server-ip"
serverPort = 7000

# 认证
auth.method = "token"
auth.token = "your-strong-token-here"

# TLS 双向认证
transport.tls.enable = true
transport.tls.certFile = "/etc/frp/ssl/client.crt"
transport.tls.keyFile = "/etc/frp/ssl/client.key"
transport.tls.trustedCaFile = "/etc/frp/ssl/ca.crt"

# 代理示例
[[proxies]]
name = "web"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8080
remotePort = 8080

八、常见问题排查

错误 原因 解决
certificate signed by unknown authority CA 证书不匹配或未被信任 确认 trustedCaFile 指向正确的 ca.crt
ERR_SSL_UNRECOGNIZED_NAME_ALERT 服务端证书 SAN 不包含连接地址 确保证书 SAN 包含服务器 IP 或域名
open /path/ca.key: no such file 误将 ca.key 配置为 trustedCaFile trustedCaFile 应配置 ca.crt,不是 ca.key
session shutdown 证书验证失败或 TLS 配置不匹配 检查双端 TLS 配置是否对应,证书是否过期

参考:GitHub Issue #4463 和 #4812 中详细讨论了证书配置问题。


九、参考来源

相关推荐
Flynt13 小时前
npm v12 来了:allowScripts 默认关闭,我的项目差点跑不起来
安全·npm·node.js
冬奇Lab5 天前
Skill 系列(02):Skill 安全风险——三类攻击面的实战测试
人工智能·安全·开源
Aphasia3118 天前
VPN 与内网穿透
安全
Mr_愚人派10 天前
当"Claude"不再是 Claude:一次第三方 API 代理引发的 AI 身份伪造排查实录
人工智能·安全
DaLi Yao10 天前
【无标题】
人工智能·安全
Alsn8610 天前
等待学习-学习目录:Docker 容器安全攻防
学习·安全·docker
网络研究院10 天前
2026年网络安全
网络·安全·法律·法规·趋势·发展
treesforest10 天前
AI安全系统如何识别异常访问?IP风险识别正在成为关键能力
网络·人工智能·tcp/ip·安全·web安全
零零信安10 天前
零零信安荣登数世咨询《新质·数字安全专精百强(2026)》暗网情报领域,彰显专业实力与创新引领
安全·网络安全·数据泄露·暗网·零零信安
开发小能手-roy10 天前
StringBuilder vs StringBuffer:2024年还需要线程安全字符串吗?
开发语言·python·安全