写在前面: 在服务器“毛坯房”装修进入深水区后,单纯的防火墙配置已经无法满足复杂网络环境下的安全与效率需求。本文记录了如何完成服务器环境的高阶配置,主要包括内核网络优化(BBR)与组建虚拟局域网 。核心目标是开启 Linux 内核自带的 BBR 拥塞控制算法以提升网络吞吐量,并使用 Tailscale 将本地电脑与云服务器组建成一个加密的局域网 。
阶段一:VPS 内核网络优化 (BBR 拥塞控制算法)#
目的: 榨干服务器的网络吞吐量,降低高延迟环境下的丢包率。
操作过程:
检查默认状态:通过
sysctl net.ipv4.tcp_congestion_control命令,发现系统默认使用的拥塞控制算法是相对保守的cubic。修改系统内核变量:在终端执行以下命令,将队列调度算法改为
fq,并将拥塞控制算法改为BBR:
echo "net.core.default_qdisc=fq" | sudo tee -a /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" | sudo tee -a /etc/sysctl.conf- 应用并验证:使用
sudo sysctl -p使配置生效,随后通过lsmod | grep bbr确认内核模块已成功加载。
小结:这是提升服务器网络物理性能的基础操作,完成后肉眼可见 SSH 连接的响应变得更加顺滑。
阶段二:组建零信任虚拟局域网 (Tailscale 双端部署)#
背景痛点:
由于在本地开发时,常处于移动蜂窝网络(手机热点)或校园网的复杂 NAT 结构之后,没有固定的公网 IP。每次连接服务器或测试内网服务,都要添加新的防火墙白名单(当然,没有防火墙就没有这个困扰,但 Tailscale 的功能远不止这些)。引入基于 WireGuard 协议的 Tailscale 可以彻底解决动态 IP 带来的困扰。
操作过程:
VPS 端安装与授权:
- 在服务器终端通过一键脚本完成安装:
curl -fsSL https://tailscale.com/install.sh | sh。 - 执行
sudo tailscale up启动服务。终端返回了一串包含授权参数的 URL。 - 将 URL 复制到本地浏览器,使用个人谷歌账号完成登录授权,将服务器拉入专属的 Tailnet(虚拟局域网)。
- 在服务器终端通过一键脚本完成安装:
本地 Windows 端部署:
- 在本地电脑下载 Windows 版 Tailscale 客户端。
- 关键步骤:使用与 VPS 端完全一致的谷歌账号登录。
- 登录成功后,系统托盘出现 Tailscale 图标,本地电脑获得了一个
100.x.x.x开头的内网 IP。
测试连通性:在本地 cmd 中直接 ping 服务器分配的 100 开头的 IP,收到稳定延迟的回复。至此,本地电脑与远端 VPS 已无视物理网络限制,宛如插在同一台路由器上。
阶段三:端口防护#
注意:Docker 默认会绕过系统防火墙。
当在 Linux 系统里配置好 UFW 防火墙,并设置了“拒绝所有公网访问 3306 端口”,然后用 Docker 跑起了一个 MySQL 容器。这时,Docker 为了实现容器通信,会直接去修改更底层的 iptables 规则。而它的优先级高于常规的 UFW,等于在防火墙上开了一扇面向全公网的窗。
不出几个小时,全网的嗅探脚本就能顺着你的公网 IP 摸进来,开始疯狂爆破你的数据库密码。(AI说的,听起来挺可怕的,但其实在做这个防护前我已经拥有这个VPS一段时间了,我也不知道会出现什么问题)
解法:利用 Tailscale 进行网卡级绑定
既然防不住 Docker 开窗,那就从源头上掐断它连接公网的可能。当组建好 VLAN 后,再也不需要把端口映射到 0.0.0.0(允许所有网络接口访问),而是绑定在 Tailscale 分配的内网 IP 上。
实操演示(以 docker-compose.yml 为例):
修改前:
services:
mysql:
image: mysql:8.0
ports:
- "3306:3306" # 默认等同于 0.0.0.0:3306,全网皆可扫描修改后:
services:
mysql:
image: mysql:8.0
ports:
- "100.x.x.x:3306:3306" # 替换为自己 VPS 的 Tailscale IP效果: 修改重启后(记得重启啊),这个 MySQL 容器在互联网上彻底“蒸发”了。公网的扫描器连这个端口的存在都探测不到。只有处于同一个 Tailscale 虚拟局域网(VLAN)中并获得授权的设备,才能通过 100.x.x.x:3306 畅通无阻地直连数据库。
这不仅解决了动态 IP 下无法设置固定防火墙白名单的痛点,更是现代微服务架构中零信任网络(Zero Trust)的实践。无论是跑数据库、Redis 还是内部调用的后端 API,统统用这个方法藏进内网,再也无需为弱密码爆破而焦虑。
阶段四:进阶探索 —— Funnel 公网穿透本地 Vue 项目#
在搭建好虚拟局域网后,尝试利用 Tailscale 的 Funnel(漏斗)功能,将本地正在开发的 Vue 项目临时暴露到公网,以便在不走 CI/CD 部署流程的情况下直接向他人展示 UI 效果。
1. 穿透操作与表象成功
- 启动本地前端服务:在 VS Code 终端运行
npm run dev,Vite 服务正常启动在http://127.0.0.1:5173/。 - 开启公网穿透:在管理员模式的 cmd 中执行
tailscale funnel 5173。 - 终端提示 Success,并分配了一个带有 HTTPS 的专属公网域名(如:
https://idyq.tailxxxx.ts.net/)。 (首次使用可能需要二次登录确认)
2. 遭遇报错(“Blocked request”)
满怀期待地用浏览器打开该公网链接,却遭遇了直接拦截,页面抛出错误:
Blocked request.
This host (“idyq.tailxxxx.ts.net”) is not allowed.
To allow this host, add “idyq.tailxxxx.ts.net” to
server.allowedHostsin vite.config.js.
3. 排查与底层原理
网络隧道已打通却被拦截,问题在于 Vite 框架的 DNS 重新绑定防御机制。
出于安全考虑,Vite 开发服务器默认只信任请求头(Host)中来源为 localhost 或 127.0.0.1 的请求。当我们通过 Tailscale 分配的 ts.net 域名访问时,Host 字段不符,Vite 直接将其判定为潜在的安全风险并切断了响应。
4. 解决办法
根据报错提示,在 Vue 项目根目录下的 vite.config.js 文件中,手动配置 server 选项,将该专属公网域名加入白名单:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
// 允许 Tailscale 分配的公网域名访问本地开发服务器
allowedHosts: [
'idyq.tailxxxx.ts.net'
]
// 也可以简单粗暴地写成 allowedHosts: true 或 'all' 来允许所有域名访问
}
})保存配置文件后,Vite 自动热更新。再次刷新浏览器的公网链接,报错消失,本地 Vue 页面完美呈现在公网环境中。展示完毕后,只需在终端敲下 tailscale funnel off 即可安全闭合大门。










