F

FRP+Lucky+VPS免端口访问内网主机服务

Captain 网络 2026-10-14

两年前写的草稿一致未整理,今天闲着无聊整理出来分享给家里的宽带无公网IP,需要不带端口内网穿透的新手朋友。老鸟飘过 ......

前置条件
[√] 一个域名(解析好A记录到你的VPS。并申请好泛域名SSL证书),且能关闭 CDN 代理
[√] 一台公网 VPS,推荐VPS:特惠活动 / 洛杉矶-CN2 GIA精品三网直联中国
[√] 内网一台常开设备(N1 / iStoreOS / 飞牛 / 软路由)跑 Lucky 与 frpc
[√] 内网设备能访问要发布的N台主机,本例是两台:

https://nas.example.com 对应内网设备 192.168.0.2:88
https://app.example.com 对应内网设备 192.168.0.2:99

如果你是国内 VPS 域名已完成 ICP 备案(否则 80/443 会被拦截,建议海外 VPS,无需应付三天两头的破事),验证备案是否生效:

# 在任意外网机器上执行,能返回任何 HTTP 响应即说明 80 未被拦
curl -I http://nas.example.com

VPS 安全组与系统防火墙
云控制台安全组放行:

端口来源说明
80/tcp0.0.0.0/0HTTP 入口
443/tcp0.0.0.0/0HTTPS 入口
7000/tcp0.0.0.0/0frpc 接入
7500/tcp仅你的管理 IPfrps 仪表盘(可选,建议调试时打开,跑通后强烈建议关闭)

系统防火墙(firewalld / ufw 二者之一):

# firewalld
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --permanent --add-port=443/tcp
firewall-cmd --permanent --add-port=7000/tcp
firewall-cmd --permanent --add-port=7500/tcp  # 安全起见,调试跑通后强烈建议关闭此端口
firewall-cmd --reload

# 或 ufw
ufw allow 80/tcp && ufw allow 443/tcp && ufw allow 7000/tcp && ufw allow 7500/tcp

安全提醒:
1、上面的 40600 端口只给本机 Nginx 反代用(proxy_pass http://127.0.0.1:40600),绝不能对公网放行。一旦开放,任何人 curl -H "Host: nas.example.com" http://你的VPS:40600 就能绕过 Nginx 的 HTTPS 和全部访问控制,直接摸到你内网机器。
2、FRPS-FRPC 通信端口7000强烈建议修改为不常用端口,定期更换 token 并定期查看FRPS登录日志(VPS端执行):

docker logs frps | grep "login"

查看返回值 client login info: ip [ ] 里的IP是不是你FRPC的IP。

VPS 端:部署 frps
方式 A:Docker(推荐,好升级好迁移)

mkdir -p /etc/frp

方式 B:二进制

# 以 0.61.1 为例,按需替换版本号与架构
cd /tmp
curl -fLO https://github.com/fatedier/frp/releases/download/v0.61.1/frp_0.61.1_linux_amd64.tar.gz
tar -zxvf frp_0.61.1_linux_amd64.tar.gz
install -m 755 frp_0.61.1_linux_amd64/frps /usr/local/bin/frps

frps.toml(完整代码)
先用命令行生成token

openssl rand -hex 32

将生成的 token 复制到下面的 auth.method 字段里
写进 /etc/frp/frps.toml:

cat > /etc/frp/frps.toml <<'EOF'
bindAddr = "0.0.0.0"
bindPort = 7000             # 默认 frpc 接入端口,可以自行修改,但两端必须一致
vhostHTTPPort  = 40600      # 80/443 已被宝塔 Nginx 占用,frps 只需一个本机端口收明文
auth.method = "token"
auth.token  = "前文生成的token"
# 只接受 TLS 连接,防止被"降级"成明文
transport.tls.force = true
log.to      = "console"
log.level   = "info"

# 可选:Dashboard(安全起见调试完毕后删除)
webServer.addr     = "127.0.0.1"
webServer.port     = 7500
webServer.user     = "admin"
webServer.password = "设置一个强密码"
# 可选:HTTP 请求超时(大文件下载慢可调大)
# vhostHTTPTimeout = 60
EOF

说明:上面为什么只配置了 vhostHTTPPort ,没有配置 vhostHTTPSPort,应为 TLS 已在 Nginx 终止,进 frps 的已是明文,443 与 frps 无关。frpc 端只配置 type="http",Lucky 不需要证书了。

FRPS启动与自启
Docker 启动(host 网络,才能独占 80/443)

docker run -d --name frps --restart always \
  --network host \
  -v /etc/frp/frps.toml:/etc/frp/frps.toml:ro \
  snowdreamtech/frps:latest

注意:必须是 --network host。用 bridge + -p 80:80 时,frps 内部看到的真实客户端 IP 会变成网桥地址,SNI/Host 匹配之外的日志、限流都会失真;host 模式最省事。
二进制方式的自启(systemd):

cat > /etc/systemd/system/frps.service <<'EOF'
[Unit]
Description=frp server
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
Restart=on-failure
RestartSec=3s
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload && systemctl enable --now frps

验证(在VPS上操作,这一步不通后面全白搭)

ss -lntp | grep -E ':(7000|40600)\b'

查看输出(二个端口都在,且进程名是 frps):

LISTEN 0 4096 0.0.0.0:7000     users:(("frps",pid=...))
LISTEN 0 4096 0.0.0.0:40600    users:(("frps",pid=...))

VPS堡塔面板添加反向代理
1、面板 → 网站 → 添加站点:域名填 nas.example.com 和 app.example.com(换行分隔可一次填两个)。根目录随便,纯做转发用。
2、申请SSL证书,打开“强制 HTTPS”。
3、该站点 → 反向代理 → 添加反向代理:
代理名称:frp-home
目标 URL:http://127.0.0.1:40600(VPS 防火墙不要放行此端口,不安全!!!)
发送域名: $http_host 或 $host (frps 靠 Host 选路由)这里填错全盘泡汤。
缓存:关闭

啰嗦一下:关于 $host 和 $http_host 两者都能用,但有区别:

变量值说明
$hosta.example.com不带端口,Host 缺失时回落 server_name
$http_hosta.example.com:443原始 Host,带端口

继续

内网端部署 frpc(Docker)
frpc.toml(全文)
切记:localPort 必须指向 Lucky 的“Web服务规则监听端口”(示例 1660 ),不能填 Lucky 管理后台端口,否则域名只会返回 Are you ok?。
写进 /etc/frp/frpc.toml:

cat > /etc/frp/frpc.toml <<'EOF'
serverAddr = "161.190.133.90" # VPS 公网IP
serverPort = 7000
auth.method = "token"
auth.token  = "你生成的"   # 与 frps 完全一致
transport.tls.enable = true

log.to    = "console"     # 默认值 console
log.level = "info"

[[proxies]]
name          = "lucky-http"
type          = "http"
localIP       = "127.0.0.1"
localPort     = 1660                      # Lucky「Web服务」中未开 TLS 的那条规则的监听端口
customDomains = ["nas.example.com", "app.example.com"] # 你解析的对应内网需要访问的两个二级域名
EOF

部署FRPC
Docker Compose (推荐)
/etc/frp/docker-compose.yml:

services:
  frpc:
    image: snowdreamtech/frpc:latest
    container_name: frpc
    restart: always
    network_mode: host                # 关键:host 网络下 127.0.0.1 才是 N1 本机
    volumes:
      - /etc/frp/frpc.toml:/etc/frp/frpc.toml:ro
    command: ["-c", "/etc/frp/frpc.toml"]

启动:

   docker compose -f /etc/frp/docker-compose.yml up -d

验收:

   docker logs -f frpc
   # 或只输出10行 docker logs --tail 10 frpc

日志尾部必须出现下面输出,否则白瞎:

   [lucky-http] start proxy success

如果出错,检查一下配置文件是否很上面的内容一样:

   docker exec frpc cat /etc/frp/frpc.toml

设置Lucky(Lucky 侧不需要证书)
登录Lucky --> Web服务 --> 添加Web服务规则:
Web服务规则名称:lucky-http
规则开关:启用
监听类型:IPV4
监听端口:1660 (必须与配置文件frpc.toml里的 lucky-http项localPort 一致)
IP过滤规则:禁用
防火墙自动放行:关闭
TLS:禁用
CorazaWAF:无

【默认规则】
服务类型:关闭连接

【子规则列表】里添加:
子规则名称:nas(根据你的实际二级域名填写)
子规则开关:启用
服务类型:反向代理
前端地址:nas.example.com(根据你的实际二级域名填写)
后端地址:http://192.168.0.2:88
CorazaWAF:无
万事大吉:启用
忽略后端TLS证书验证:是
客户端IP获取设置
优先从Header头部获取:启用
信任的IP代理网段:127.0.0.1 (这里是个巨坑,不写的话访问者的IP永远是127.0.0.1)
包含客户端IP的头部字段:X-Real-IP
其余默认
安全设置(可选):基本认证或网页认证二选一
认证信息设置:用户名与密码之间用E文冒号隔开
如果需要穿透内网一台以上设备,接着继续点击【添加子规则】否则,至此完毕,本例是两条规则。

【子规则列表】里添加:
子规则名称:app(根据你的实际二级域名填写)
子规则开关:启用
服务类型:反向代理
前端地址:app.example.com(根据你的实际二级域名填写)
后端地址:http://192.168.0.2:99
CorazaWAF:无
万事大吉:启用
忽略后端TLS证书验证:是
客户端IP获取设置
优先从Header头部获取:启用
信任的IP代理网段:127.0.0.1 (这里是个巨坑,不写的话访问者的IP永远是127.0.0.1)
包含客户端IP的头部字段:X-Real-IP
其余默认
安全设置(可选):基本认证或网页认证二选一
认证信息设置:用户名与密码之间用E文冒号隔开

填写完成后点击【修改WEB服务规则】保存。

至此全部设置完毕,打开浏览器输入域名:
nas.example.com
自动加上https前缀连接到内网设备 192.168.0.2:88
app.example.com
自动加上https前缀连接到内网设备 192.168.0.2:99

码字不易,转贴请注明出处。谢谢!

PREV:IP blacklist - 2026.10.21更新
NEXT:Ubuntu服务器Nginx + PHP-FPM 环境一键修改网站目录权限脚本