内网磁盘映射到公网服务器的两种方案
前言
你是否遇到过这样的场景:有一台云服务器,但磁盘空间有限;而本地电脑有大容量硬盘,却因为处于内网环境无法被服务器直接访问。
本文将介绍两种方案来实现这个需求:
- SSH反向隧道:简单快速,无需额外软件,适合临时使用
- frp内网穿透:稳定可靠,适合长期运行
一、场景说明
1.1 需求背景
- 服务器:公网IP,磁盘空间有限(如40G)
- 本地电脑:内网环境,有大容量硬盘(如200G+),无法被外部直接访问
- 目标:让服务器能够访问本地磁盘,并通过Web服务对外提供文件访问
1.2 解决方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| SSH反向隧道 | 无需额外软件、配置简单、安全 | 需要保持SSH连接、断线需手动重连 | 临时共享、轻量级需求 |
| frp | 功能强大、自动重连、支持多种协议、有Dashboard | 需要额外部署服务端和客户端 | 长期稳定的服务暴露 |
| WireGuard | 性能优异、VPN级别访问 | 配置复杂、需要内核支持 | 需要完整网络互通 |
| NFS/SMB | 标准文件系统协议 | 需要公网IP或VPN | 局域网或有固定IP环境 |
方案一:SSH反向隧道
二、SSH反向隧道原理
2.1 什么是SSH反向隧道?
正常情况下,SSH连接是从本地主动连接到远程服务器:
本地电脑 ────────SSH连接────────> 服务器
(本地可以访问服务器)
但服务器无法主动连接本地电脑,因为本地处于内网,没有公网IP。
反向隧道的巧妙之处在于:利用本地主动建立的SSH连接,在其中"偷偷"开一个反向通道,让服务器能通过这个通道访问本地。
┌─────────────┐ ┌─────────────┐
│ 本地电脑 │ │ 服务器 │
│ (内网IP) │ │ (公网IP) │
├─────────────┤ ├─────────────┤
│ │ ① 本地主动建立SSH连接 │ │
│ │ ─────────────────────────> │ │
│ │ │ │
│ │ ② 在连接中开反向通道 │ │
│ │ <───────────────────────── │ │
│ │ │ │
│ SSH服务 │ ③ 服务器通过通道访问本地 │ localhost │
│ (端口22) │ <═════════════════════════ │ (端口2222) │
└─────────────┘ └─────────────┘
2.2 整体架构
┌───────────────────────────┐ ┌───────────────────────────┐
│ 本地电脑 │ │ 服务器 │
│ (内网Debian) │ │ xxx.xxx.xxx.xxx │
├───────────────────────────┤ ├───────────────────────────┤
│ │ │ │
│ /home/user/大硬盘/book │ SSH反向隧道(端口2222) │ localhost:2222 │
│ │◄══════════════════════│ ↓ │
│ │ (加密通道) │ sshfs挂载 │
│ │ │ ↓ │
│ SSH服务 (端口22) │ │ /var/www/html/books │
│ ↑ │ │ ↓ │
│ │ │ 本地主动建立隧道 │ nginx:80 │
│ └─────────────┼──────────────────────┤ ↓ │
│ │ ssh -R 命令 │ http对外访问 │
└───────────────────────────┘ └───────────────────────────┘
三、SSH方案安装配置
3.1 环境要求
- 本地电脑:Linux系统(本文以Debian为例),需要安装SSH服务
- 服务器:Linux系统,需要安装sshfs
- 网络条件:本地能够SSH连接到服务器
3.2 本地电脑配置
步骤1:安装并启动SSH服务
本地需要运行SSH服务,才能接受来自隧道的连接。
# 安装OpenSSH服务端
sudo apt install -y openssh-server
# 启动SSH服务
sudo systemctl start ssh
# 设置开机自启
sudo systemctl enable ssh
# 检查服务状态
sudo systemctl status ssh
说明:如果你的本地电脑已经安装并运行了SSH服务,可以跳过这一步。
步骤2:建立SSH反向隧道
这是整个方案的核心步骤,一条命令搞定:
# 基础命令
ssh -NfR 2222:localhost:22 用户名@服务器IP
参数详解:
| 参数 | 含义 |
|---|---|
-N |
不执行远程命令,仅建立隧道(纯转发模式) |
-f |
后台运行,不会占用当前终端 |
-R 2222:localhost:22 |
反向隧道:服务器2222端口 → 本地22端口 |
2222 |
服务器上开放的端口(可自定义,需未被占用) |
localhost:22 |
本地的SSH服务地址 |
实际使用示例:
# 简单版本
ssh -NfR 2222:localhost:22 myuser@xxx.xxx.xxx.xxx
# 推荐版本(带心跳保活)
ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -NfR 2222:localhost:22 myuser@xxx.xxx.xxx.xxx
心跳参数说明:
ServerAliveInterval=30:每30秒发送一次心跳ServerAliveCountMax=3:3次心跳无响应则断开
这些参数可以防止因为长时间无数据传输导致连接被防火墙或NAT断开。
步骤3:验证隧道是否建立成功
# 本地查看隧道进程
ps aux | grep "ssh.*2222"
# 应该能看到类似输出:
# user 12345 ... ssh -NfR 2222:localhost:22 myuser@xxx.xxx.xxx.xxx
3.3 服务器配置
步骤1:安装必要软件
# 安装sshfs(核心组件)
sudo apt install -y sshfs
# 安装sshpass(可选,用于脚本自动输入密码)
sudo apt install -y sshpass
步骤2:配置FUSE
# 编辑fuse配置文件
sudo sed -i 's/#user_allow_other/user_allow_other/' /etc/fuse.conf
# 验证配置
cat /etc/fuse.conf | grep user_allow_other
# 应输出:user_allow_other
为什么要这个配置?
默认情况下,FUSE挂载的目录只有挂载者本人可以访问。开启user_allow_other后,Web服务器(如nginx)才能读取挂载的文件。
步骤3:创建挂载点并挂载
# 创建挂载目录
sudo mkdir -p /var/www/html/books
sudo chown $USER:$USER /var/www/html/books
# 挂载命令
sshfs 本地用户名@localhost:/本地磁盘路径 /挂载点 -p 2222 -o StrictHostKeyChecking=no,allow_other
# 实际示例
sshfs myuser@localhost:/home/myuser/大硬盘/book /var/www/html/books -p 2222 -o StrictHostKeyChecking=no,allow_other
参数说明:
| 参数 | 含义 |
|---|---|
本地用户名@localhost |
本地电脑的用户名,通过隧道(localhost)连接 |
-p 2222 |
使用隧道端口2222 |
StrictHostKeyChecking=no |
跳过主机密钥验证(隧道场景需要) |
allow_other |
允许其他用户访问挂载目录 |
步骤4:验证挂载
# 查看挂载状态
df -h /var/www/html/books
# 查看文件列表
ls /var/www/html/books
# 测试Web访问
curl http://localhost/books/
方案二:frp内网穿透
四、frp方案原理
4.1 什么是frp?
frp(Fast Reverse Proxy)是一个高性能的反向代理应用,专门用于内网穿透。相比SSH反向隧道,frp具有以下优势:
| 特性 | SSH反向隧道 | frp |
|---|---|---|
| 设计初衷 | 临时会话连接 | 专用内网穿透工具 |
| 断线重连 | 需要外部脚本(autossh/crontab) | 内置自动重连机制 |
| 心跳机制 | 简单的ServerAlive参数 | 完善的心跳检测+多级重试 |
| 状态监控 | 需手动检查进程 | 提供Dashboard可视化 |
| 连接恢复 | 断开后隧道端口可能残留 | 自动清理+重建 |
| NAT穿透 | 依赖SSH连接保持 | 专门优化NAT场景 |
4.2 frp工作原理
┌───────────────────────────┐ ┌───────────────────────────┐
│ 本地电脑 │ │ 服务器 │
│ (运行frpc) │ │ (运行frps) │
├───────────────────────────┤ ├───────────────────────────┤
│ │ │ │
│ │ ① 建立控制连接 │ │
│ frpc ───────────────────────────────> │ frps │
│ │ (端口7000) │ │
│ │ │ │
│ │ ② 注册代理规则 │ │
│ frpc ───────────────────────────────> │ frps │
│ │ "我要暴露22端口" │ │
│ │ │ │
│ │ │ ③ 开放2222端口监听 │
│ │ │ (供外部访问) │
│ │ │ │
│ │ ④ 外部请求到达时 │ │
│ frpc <─────────────────────────────── │ frps │
│ (转发到本地22) │ 转发流量到frpc │ (接收请求) │
└───────────────────────────┘ └───────────────────────────┘
核心概念:
- frps(服务端):运行在有公网IP的服务器上,监听端口,转发流量
- frpc(客户端):运行在内网电脑上,主动连接frps,注册代理规则
- 控制连接:frpc与frps之间的长连接,用于传递控制信息和心跳
- 数据连接:实际传输数据的连接,按需建立
4.3 整体架构
┌───────────────────────────┐ ┌───────────────────────────┐
│ 本地电脑 │ │ 服务器 │
│ (内网Debian) │ │ xxx.xxx.xxx.xxx │
├───────────────────────────┤ ├───────────────────────────┤
│ │ │ │
│ /home/user/大硬盘/book │ │ frps:7000 │
│ │ │ ↓ │
│ │ frp隧道 │ :2222 (映射端口) │
│ frpc ─────────────────────────────────>│ ↓ │
│ │ (自动重连) │ sshfs挂载 │
│ │ │ ↓ │
│ SSH服务 (端口22) │ │ /var/www/html/books │
│ │ │ ↓ │
│ │ │ nginx:80 │
│ │ │ ↓ │
│ │ │ http对外访问 │
└───────────────────────────┘ └───────────────────────────┘
五、frp方案安装配置
5.1 下载frp
frp是一个单文件程序,无需安装,下载解压即可使用。
下载地址 :https://github.com/fatedier/frp/releases
选择对应平台的版本,本文以Linux amd64为例:
# 下载
wget https://github.com/fatedier/frp/releases/download/v0.68.0/frp_0.68.0_linux_amd64.tar.gz
# 解压
tar -xzf frp_0.68.0_linux_amd64.tar.gz
cd frp_0.68.0_linux_amd64
# 查看文件
ls
# frpc - 客户端程序
# frpc.toml - 客户端配置
# frps - 服务端程序
# frps.toml - 服务端配置
5.2 服务器配置(frps)
步骤1:上传frps到服务器
# 方法1:使用scp
scp frps 用户名@服务器IP:~/frp/
# 方法2:直接在服务器上下载
ssh 用户名@服务器IP
mkdir -p ~/frp && cd ~/frp
wget https://github.com/fatedier/frp/releases/download/v0.68.0/frp_0.68.0_linux_amd64.tar.gz
tar -xzf frp_0.68.0_linux_amd64.tar.gz --strip-components=1 frp_0.68.0_linux_amd64/frps
步骤2:创建frps配置文件
在服务器上创建 ~/frp/frps.toml:
# frps.toml - 服务端配置
# frp服务端口(frpc连接此端口)
bindPort = 7000
# 认证token(建议设置,增加安全性)
# auth.token = "your_token_here"
# Dashboard配置(可选,用于查看连接状态)
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "admin123"
# 日志配置
log.to = "/home/用户名/frp/frps.log"
log.level = "info"
log.maxDays = 3
步骤3:启动frps
# 前台运行(测试用)
./frps -c frps.toml
# 后台运行(生产用)
nohup ./frps -c frps.toml > /dev/null 2>&1 &
# 检查是否启动成功
ps aux | grep frps
ss -tlnp | grep 7000
步骤4:设置开机自启(systemd)
创建服务文件 /etc/systemd/system/frps.service:
[Unit]
Description=frps service
After=network.target
[Service]
Type=simple
User=你的用户名
ExecStart=/home/你的用户名/frp/frps -c /home/你的用户名/frp/frps.toml
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
启用服务:
sudo systemctl daemon-reload
sudo systemctl enable frps
sudo systemctl start frps
sudo systemctl status frps
5.3 本地电脑配置(frpc)
步骤1:准备frpc程序
# 创建目录
mkdir -p ~/frp
cd ~/frp
# 下载frp(如果还没下载)
wget https://github.com/fatedier/frp/releases/download/v0.68.0/frp_0.68.0_linux_amd64.tar.gz
tar -xzf frp_0.68.0_linux_amd64.tar.gz --strip-components=1 frp_0.68.0_linux_amd64/frpc
步骤2:创建frpc配置文件
创建 ~/frp/frpc.toml:
# frpc.toml - 客户端配置
# frps服务器地址
serverAddr = "xxx.xxx.xxx.xxx"
serverPort = 7000
# 认证token(需与frps配置一致)
# auth.token = "your_token_here"
# 日志配置
log.to = "~/frp/frpc.log"
log.level = "info"
log.maxDays = 3
# 心跳配置(保持连接稳定)
transport.heartbeatInterval = 30
transport.heartbeatTimeout = 90
# 代理配置 - SSH端口转发
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 2222
配置详解:
| 配置项 | 说明 |
|---|---|
serverAddr |
frps服务器IP地址 |
serverPort |
frps监听端口 |
name |
代理名称,可自定义 |
type |
协议类型,TCP用于SSH |
localIP |
本地服务地址 |
localPort |
本地服务端口(SSH默认22) |
remotePort |
服务器上开放的端口 |
步骤3:启动frpc
# 前台运行(测试用)
./frpc -c frpc.toml
# 后台运行(生产用)
nohup ./frpc -c frpc.toml > /dev/null 2>&1 &
# 检查是否启动成功
ps aux | grep frpc
成功启动后会看到类似输出:
[I] [root.go:139] start frpc service for config file [frpc.toml]
[I] [service.go:299] [xxx] login to server success
[I] [proxy_manager.go:156] [xxx] proxy added: [ssh]
[I] [control.go:173] [xxx] [ssh] start proxy success
步骤4:设置开机自启(systemd)
创建服务文件 /etc/systemd/system/frpc.service:
[Unit]
Description=frpc service
After=network.target
[Service]
Type=simple
User=你的用户名
ExecStart=/home/你的用户名/frp/frpc -c /home/你的用户名/frp/frpc.toml
Restart=always
RestartSec=5s
[Install]
WantedBy=multi-user.target
启用服务:
sudo systemctl daemon-reload
sudo systemctl enable frpc
sudo systemctl start frpc
sudo systemctl status frpc
5.4 验证frp隧道
# 在服务器上检查2222端口是否开放
ss -tlnp | grep 2222
# 应该看到:
# LISTEN 0 4096 *:2222 *:* users:(("frps",pid=xxx,fd=x))
# 测试隧道
ssh -p 2222 本地用户名@服务器IP 'hostname'
# 应该返回本地电脑的主机名
5.5 挂载磁盘
frp隧道建立后,挂载步骤与SSH方案相同:
# 在服务器上执行
sshfs 本地用户名@localhost:/本地磁盘路径 /挂载点 -p 2222 -o StrictHostKeyChecking=no,allow_other
# 示例
sshfs myuser@localhost:/home/myuser/大硬盘/book /var/www/html/books -p 2222 -o StrictHostKeyChecking=no,allow_other
5.6 frp Dashboard监控
如果启用了Dashboard,可以通过浏览器访问:
http://xxx.xxx.xxx.xxx:7500
用户名: admin
密码: admin123
注意:需要确保服务器防火墙开放7500端口:
# 开放端口(如使用ufw)
sudo ufw allow 7500/tcp
在Dashboard中可以查看:
- 当前连接的客户端
- 各代理的状态和流量统计
- 连接日志
安全建议:生产环境建议修改默认密码,或限制只允许内网访问(将webServer.addr改为内网IP)。
通用配置
六、SSHFS挂载配置(两种方案通用)
无论使用SSH隧道还是frp,挂载步骤相同。
6.1 服务器安装sshfs
sudo apt install -y sshfs sshpass
6.2 配置FUSE
sudo sed -i 's/#user_allow_other/user_allow_other/' /etc/fuse.conf
6.3 挂载命令
# 基本挂载
sshfs 用户名@localhost:/本地路径 /挂载点 -p 2222 -o StrictHostKeyChecking=no,allow_other
# 带重连选项(推荐)
sshfs 用户名@localhost:/本地路径 /挂载点 -p 2222 -o StrictHostKeyChecking=no,allow_other,reconnect,ServerAliveInterval=15,ServerAliveCountMax=3
6.4 开机自动挂载
创建systemd服务 /etc/systemd/system/sshfs-mount.service:
[Unit]
Description=SSHFS Mount
After=network.target frps.service
[Service]
Type=oneshot
User=服务器用户名
ExecStart=/usr/bin/sshfs 本地用户名@localhost:/本地路径 /挂载点 -p 2222 -o StrictHostKeyChecking=no,allow_other,_netdev
ExecStop=/usr/bin/fusermount -u /挂载点
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable sshfs-mount
sudo systemctl start sshfs-mount
七、常用操作命令
7.1 挂载管理
# 查看所有sshfs挂载
mount | grep fuse.sshfs
# 卸载挂载
fusermount -u /挂载点
# 强制卸载
fusermount -u -z /挂载点
# 或
sudo umount -l /挂载点
7.2 SSH隧道管理
# 查看隧道进程
ps aux | grep "ssh.*2222"
# 断开隧道
pkill -f "ssh.*2222"
# 重新建立隧道
ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -NfR 2222:localhost:22 用户@服务器IP
7.3 frp管理
# 查看frps/frpc进程
ps aux | grep frp
# 重启frps
sudo systemctl restart frps
# 重启frpc
sudo systemctl restart frpc
# 查看日志
tail -f ~/frp/frps.log
tail -f ~/frp/frpc.log
# 检查端口
ss -tlnp | grep -E "7000|2222"
八、常见问题与解决方案
8.1 SSH隧道连接失败
问题:执行ssh -R命令后,服务器上2222端口无法访问
排查步骤:
# 1. 检查本地SSH服务是否运行
sudo systemctl status ssh
# 2. 检查服务器上端口是否监听
ss -tlnp | grep 2222
# 3. 检查服务器SSH配置是否允许端口转发
sudo grep -i "AllowTcpForwarding" /etc/ssh/sshd_config
# 如果被注释或为no,需要改为yes并重启sshd
8.2 frp连接失败
问题:frpc提示连接frps失败
排查步骤:
# 1. 检查服务器frps是否运行
ps aux | grep frps
ss -tlnp | grep 7000
# 2. 检查防火墙是否开放7000端口
sudo ufw status
sudo ufw allow 7000/tcp
# 3. 检查frpc配置中的服务器地址是否正确
cat ~/frp/frpc.toml | grep serverAddr
# 4. 查看frpc日志
tail -50 ~/frp/frpc.log
8.3 挂载失败:Permission denied
问题:sshfs挂载时提示权限被拒绝
解决方案:
# 1. 确认隧道/frp可用
ssh -p 2222 本地用户名@localhost 'whoami'
# 2. 检查本地用户密码是否正确
# 3. 检查本地SSH服务是否允许密码登录
sudo grep -i "PasswordAuthentication" /etc/ssh/sshd_config
# 应该是 yes 或被注释(默认yes)
8.4 挂载目录无法访问
问题:挂载成功但Web服务无法访问文件
解决方案:
# 1. 检查fuse配置
cat /etc/fuse.conf | grep user_allow_other
# 2. 确认挂载时使用了allow_other选项
mount | grep allow_other
# 3. 重新挂载
fusermount -u /挂载点
sshfs ... -o allow_other
8.5 连接经常断开
SSH隧道方案:
# 使用autossh自动重连
sudo apt install -y autossh
autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -NfR 2222:localhost:22 用户@服务器IP
frp方案:
frp内置自动重连,检查配置:
# frpc.toml中确保有这些配置
transport.heartbeatInterval = 30
transport.heartbeatTimeout = 90
九、安全注意事项
9.1 端口安全
| 端口 | 用途 | 安全建议 |
|---|---|---|
| 22 | 正常SSH服务 | 保持默认,使用密钥认证 |
| 7000 | frp控制端口 | 设置auth.token,限制IP访问 |
| 2222 | 隧道/代理端口 | SSH隧道默认只监听localhost,frp可限制IP |
| 7500 | frp Dashboard | 设置强密码,或绑定内网IP |
9.2 认证安全
SSH方案:
- 生产环境建议使用SSH密钥认证
- 禁用密码登录:
PasswordAuthentication no
frp方案:
- 设置auth.token认证
- Dashboard设置强密码
- 考虑使用HTTPS(配置webServer.tls)
9.3 访问控制
限制代理端口访问(修改frpc.toml):
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 2222
# 限制只有服务器本地可以访问此端口
allowIPs = ["127.0.0.1"]
限制frps控制端口访问(使用防火墙):
# 只允许特定IP连接frps控制端口
sudo ufw allow from 你的本地公网IP to any port 7000
十、方案选择建议
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 临时共享文件(几小时~几天) | SSH反向隧道 | 无需额外软件,一行命令搞定 |
| 长期稳定运行 | frp | 自动重连,有监控Dashboard |
| 需要暴露多个服务 | frp | 支持多代理配置 |
| 追求极致简单 | SSH反向隧道 | 最少的配置步骤 |
| 需要监控连接状态 | frp | Dashboard可视化 |
| 服务器资源紧张 | SSH反向隧道 | SSH已安装,无额外开销 |
十一、总结
本文介绍了两种将内网磁盘映射到公网服务器的方案:
SSH反向隧道方案
- 优点:零依赖、配置简单(一条命令)、安全可靠
- 缺点:需要保持连接、断线需手动重连
- 适用:临时共享、轻量级需求
frp方案
- 优点:自动重连、有Dashboard监控、支持多代理
- 缺点:需要额外部署服务端和客户端
- 适用:长期稳定运行、生产环境
两种方案各有优劣,根据实际需求选择即可。核心的SSHFS挂载部分是通用的,切换方案时只需更换隧道/代理部分。
十二、参考链接
作者声明:本文为原创技术分享,欢迎转载,请注明出处。