# 部署计划：基于 Tailscale Funnel 的 Linux 受限文件公网共享服务

> 当前状态：待实施。本文描述目标方案，不代表 Linux 设备已启用公网文件共享；执行前先更新 [计划总表](README.md) 的状态、白名单目录、鉴权方式和关闭时间。

| 字段 | 内容 |
|------|------|
| **文档版本** | v1.0 |
| **日期** | 2026-10-08 |
| **场景** | 内部工具/临时演示/轻量文件分发 |
| **目标平台** | Linux（Debian/Ubuntu 等 systemd 发行版） |

---

## 1. 需求背景
在缺乏固定公网 IP、不愿配置路由器端口映射、不想购买域名和手动管理 TLS 证书的前提下，需要将 Linux 服务器上的**指定文件夹**安全地暴露至公网，使外部协作者（无需安装 Tailscale 客户端）通过浏览器即可访问或下载文件。

## 2. 范围界定

### 2.1 范围内（In Scope）
- 在 Linux 主机上部署 Tailscale 及 Funnel 功能。
- 将**预先指定的本地目录**（非全磁盘）通过公网 HTTPS URL 提供访问。
- 支持多文件夹通过不同子路径（或独立端口）对外服务。
- 提供开机自启与基础进程保活。
- 实现最小权限隔离与基础安全防护。

### 2.2 范围外（Out of Scope）
- 自定义域名（仅使用 `*.ts.net` 默认域名）。
- 高并发、大带宽生产级文件分发（不作为 CDN 替代）。
- 复杂的用户管理系统或细粒度权限控制（如多租户）。
- 路由器配置、ISP 网络改造。

## 3. 功能需求（FR）

| 编号 | 需求描述 |
|------|----------|
| FR-01 | 系统应能通过 `https://<机器名>.<tailnet>.ts.net` 提供 HTTPS 访问入口。 |
| FR-02 | 外部用户（无 Tailscale 客户端）可直接通过浏览器访问指定文件夹，无需登录 Tailscale。 |
| FR-03 | 仅允许访问**白名单目录**（如 `/srv/funnel/public`、`/srv/funnel/docs`），禁止遍历上级目录或访问系统文件。 |
| FR-04 | 支持目录列表展示（autoindex）与文件下载。 |
| FR-05 | （可选）支持多文件夹通过不同 URL 子路径（如 `/public/`、`/docs/`）区分访问。 |
| FR-06 | 服务应支持开机自启，并在进程意外退出后自动恢复。 |
| FR-07 | 管理员可通过简单命令查看 Funnel 运行状态、开启/关闭公网暴露。 |

## 4. 非功能需求（NFR）

| 类别 | 要求 |
|------|------|
| **安全** | 1. 禁止将 Funnel 指向 `/home`、`/etc`、`/root` 等敏感路径。<br>2. 默认不暴露管理后台或可执行接口。<br>3. 对外目录设为只读，禁止任意上传或执行。<br>4. 公网暴露的目录应具备可选的 HTTP Basic 认证或前置鉴权能力。 |
| **可用性** | 1. 依赖的 Tailscale 服务异常时应有重连机制。<br>2. 后端文件服务（Nginx/Python）崩溃后由 systemd 自动拉起。 |
| **性能** | 1. 单节点支持并发访问 ≥ 10 人。<br>2. 单个文件大小建议 ≤ 2GB（受 Funnel 带宽限制，不做硬性上限但需提示）。 |
| **可维护性** | 1. 所有配置集中存放，便于备份。<br>2. 提供一键清理/重置 Funnel 配置的脚本或命令。 |

## 5. 总体技术方案概述（高层）

采用 **“Tailscale Funnel + 本地 Web 服务”** 的分层架构：

1. **网络接入层**：Tailscale Funnel 作为公网 HTTPS 终结点，负责 TLS 证书自动签发与续期，将流量通过加密隧道导回本机。
2. **本地反代/文件服务层**：Linux 本机运行轻量 Web 服务器（如 Nginx 或 Python http.server），监听 `127.0.0.1` 的特定端口，负责目录索引、文件读取和路径路由。
3. **存储层**：在本地文件系统中规划独立的对外目录（如 `/srv/funnel/`），与系统用户目录、应用配置完全隔离。
4. **控制层**：通过 `tailscale funnel` CLI 命令管理公网映射，通过 systemd 管理服务生命周期。

---

## 6. 待讨论/待定事项（具体实现细节）

> 以下细节需要在实施前进一步确认，以便形成最终部署方案：

### 6.1 本地 Web 服务选型
- **方案 A：Nginx**（推荐生产/长期使用）—— 稳定、支持子路径路由、易加鉴权。
- **方案 B：Python http.server**（推荐临时/极简场景）—— 无需额外安装，但性能弱、无原生鉴权。
- **方案 C：Caddy**（若未来需自动 HTTPS 到非 ts.net 域名）—— 当前 Funnel 场景下优势不明显。

### 6.2 目录与路径映射规则
- 对外目录统一放在 `/srv/funnel/` 下还是其他路径？
- 多文件夹是通过 **子路径区分**（`/` → public， `/docs/` → docs）还是 **不同端口** 暴露？
- 是否需要根路径（`/`）直接指向某个默认文件夹？

### 6.3 鉴权与访问控制
- 是否需要对公网目录增加密码保护（如 Nginx `auth_basic`）？
- 是否考虑集成 Authelia/Authentik 等 SSO（复杂度较高，视需求而定）？
- ACL 策略是用 `autogroup:member` 全放开，还是严格用 `tag:public` 标签限制？

### 6.4 端口与 Funnel 配置
- 公网入口端口选择：默认 443，还是改用 8443/10000？
- 是否启用 `--proxy-protocol` 以传递真实访客 IP 给后端日志？

### 6.5 自启与运维细节
- 后端服务统一用 systemd 管理，还是用 `nohup` + 简单脚本？
- 是否需要配置日志轮转（logrotate）？
- 监控方案：仅依赖 `tailscale funnel status`，还是需要接入 Prometheus/健康检查？

### 6.6 清理与应急
- 演示/任务结束后，是手动执行 `tailscale funnel reset`，还是设置定时自动关闭？
- 是否需要编写一键部署/一键卸载脚本？

---

## 7. 验收标准
1. 在非 Tailscale 网络的设备上，浏览器打开 `https://<机器名>.<tailnet>.ts.net` 能正常加载页面。
2. 页面中仅展示白名单目录内的文件，无法访问 `/etc/passwd` 等系统文件。
3. 重启 Linux 主机后，服务自动恢复，公网 URL 仍可访问。
4. 执行清理命令后，公网 URL 立即失效。
