静态文件与目录响应
Host 映射可以不经过反向代理,直接用 fn-knock 网关所在文件系统中的一个文件或目录响应请求。它适合发布下载文件、静态文档、小型站点或只读文件目录,不需要另外运行 Web Server。
静态响应仍是完整的 Host 路由:要求登录、高级认证、网关可见性、WAF、定时开放、请求日志和网关节流会在读取文件前生效。它不提供服务器端重写或单页应用(SPA)回退;需要把任意未知路径都返回 index.html 时,应继续使用支持该能力的上游 Web Server。
选择响应类型
添加或编辑业务 Host 时,在 响应类型 中选择:
| 响应类型 | 请求行为 | 典型用途 |
|---|---|---|
反向代理 | 把请求转发到 HTTP、HTTPS 或 WebSocket Target | 动态 Web 应用和 API |
单个文件 | 只在当前 Host 的根路径 / 返回指定文件 | 下载入口、说明文件、固定资源 |
目录 | 把 URL 路径映射到指定目录中的文件和子目录 | 静态站点、文档和文件浏览 |
从反向代理切换到静态响应时,页面会要求确认并清除只属于代理的 Target、路径响应、上游 Basic Auth、保留 Host 和目标路径模式。Host 的认证、可见性、WAF、可用时段、标题、图标和分组会保留。关闭编辑窗口前切回反向代理,可以恢复本次尚未保存的代理草稿。
静态映射不会从文件内容自动提取标题或图标。需要在传送门、映射列表或书签中显示友好名称时,手工填写 展示标题 并上传自定义图标。
配置步骤
- 使用
子域模式或内网穿透 → 子域映射,并确保业务 Host 已进入 fn-knock 网关。 - 在
子域映射添加或编辑业务 Host,选择单个文件或目录。 - 在
服务器路径旁点击浏览。可以逐级浏览网关服务器,也可以在地址栏输入绝对路径后按 Enter 前往。 - 目录响应进入目标目录后点击
使用当前文件夹;单文件响应先选择普通文件,再点击使用所选文件。 - 目录响应按需调整默认文档、目录列表和 README 渲染。
- 配置
要求登录、网关可见性、WAF、可用时段、标题和图标,然后保存。 - 从实际访问链路请求根路径、一个文件和一个不存在的路径,并在请求分析中核对路由类型与状态码。
浏览服务器路径
路径浏览器显示的是 fn-knock 网关进程可见的文件系统,不是打开管理后台的电脑。已有路径会作为起点;路径为空时,POSIX 平台从 / 开始,Windows 则先显示可用的本机盘符。文件系统根位置只用于导航,不能选作静态目录。Docker 中只能浏览已挂载到容器内的内容,浏览器不会读取宿主机路径,也不会创建或修改挂载。
地址栏支持输入绝对路径,旁边提供根位置、上一级、面包屑和刷新操作。列表始终把目录排在普通文件之前,每页最多显示 100 项,并提供前后翻页;单文件模式只允许选择普通文件,目录模式则使用当前文件夹。项目过多而无法在安全上限内扫描时,整个目录会显示错误,不会只返回一份可能误导选择的截断列表。
浏览器会省略以 . 开头的隐藏名称、以 __ 开头的内部保留名称、特殊文件、无法安全打开的项目,以及受保护路径和它们的后代。受保护路径的上级目录仍可用于前往其他位置,但不能选作静态根目录。符号链接只有在解析后仍位于当前浏览目录内,且没有进入隐藏或受保护位置时才会显示。
点击 使用当前文件夹 或 使用所选文件 时,系统会再次确认该精确路径仍然存在、可读且类型匹配;确认成功只会把路径写回当前映射草稿,仍需保存映射才会生效。这是即时检查,不会锁定文件或挂载点。新建静态映射,或修改服务器路径、响应类型时,保存也会探测路径;只调整目录选项不会重复探测。即使选择和保存时都通过,路径之后仍可能被删除、替换或失去读取权限,网关会在每次请求时重新打开并校验。
单个文件响应
单文件映射只响应 Host 根路径:
download.example.com/ -> /srv/downloads/manual.pdf
download.example.com/other -> 404网关根据服务器文件名扩展名设置 Content-Type,支持 GET、HEAD、范围请求和常见的条件缓存请求。文件内容变化后,ETag 与修改时间会随文件状态更新。URL 不需要包含服务器文件名;查询参数不会改变所选文件。
目录响应
目录映射把请求路径逐级映射到配置根目录:
docs.example.com/ -> /srv/docs/
docs.example.com/assets/app.css -> /srv/docs/assets/app.css
docs.example.com/manual/ -> /srv/docs/manual/请求命中目录但 URL 末尾没有 / 时,网关会永久重定向到带斜杠的规范地址;请求命中普通文件但 URL 末尾多了 / 时,会永久重定向到去掉斜杠的地址。两种重定向都会保留查询参数。进入目录后按配置顺序查找默认文档;初始顺序为 index.html、index.htm,最多可配置 16 个。名称只能是可见的单个文件名,不能包含路径分隔符;清空列表会关闭默认文档查找。
未找到默认文档时:
目录列表关闭:返回404;目录列表开启:生成当前目录的文件列表;渲染 README.md只在目录列表开启时可用,并把当前目录的README.md安全渲染在列表下方。
目录列表默认按名称排序,并始终把目录放在普通文件之前。页面可按名称、大小或修改时间切换升降序,带面包屑导航、明暗主题和前后翻页;每页最多显示 100 项。索引界面当前使用英文标签,修改时间固定按北京时间(UTC+8)显示。它不会显示隐藏名称、特殊文件或无法安全打开的条目。
README 使用 GitHub 风格 Markdown,单个文件最大 1 MiB。原始 HTML 和不安全内容会被过滤;图片只允许同源相对地址,外部链接会增加安全属性。只有在没有命中默认文档、实际显示目录列表时才会渲染 README。
目录响应不执行扩展名改写、动态压缩、尾路径回退或 SPA History Fallback,也没有为静态目标配置自定义响应头或缓存策略的入口。请求的文件不存在时直接返回 404。
认证、WAF、日志与缓存
静态 Host 与反向代理 Host 使用相同的入站策略:
要求登录和高级认证在文件读取前检查;局域网来源仍可能命中local_exempt,公网策略应从真实外部网络验证。- 网关可见性、通用黑名单、扫描拦截、反向代理节流和可用时段继续生效。
- 当前 Host 的
启用 WAF打开且全局 WAF 已启用时,请求会先经过 WAF,再读取静态内容。 - 请求日志和 WAF 日志把路由类型分别记录为
静态文件或静态目录,上游目标为空;日志不会写入服务器文件系统路径。
公开静态文件使用需要重新验证的公共缓存策略。需要认证或已经带有认证结果的响应使用 private, no-store,避免受保护内容进入共享缓存。生成的目录列表、重定向和错误响应同样不进入公共缓存。
文件系统安全边界
服务器路径 必须是绝对路径,并指向可见的普通文件或目录。网关拒绝文件系统根目录、隐藏目标、父目录穿越、控制字符、Windows UNC / 设备命名空间,以及与 fn-knock 配置、数据、日志、密钥或系统目录重叠的路径。过于宽泛、会把受保护目录包含在内的父目录也会被拒绝。
文件系统名称会按精确拼写处理。在 POSIX 平台(Linux、macOS 等),路径分量开头或结尾的空格不会被自动裁掉,因此 /srv/docs 与 /srv/docs 是两个不同目标;只有完全由空白组成的输入会被拒绝。应优先避免这类容易混淆的名称,并在复制路径时保留真实字符。Windows 仍会拒绝以空格或点结尾的名称、保留设备名和其他不安全名称。
目录内只响应可见的普通文件和子目录;点文件、点目录和 .well-known 不可用。符号链接必须在静态根目录内解析到安全目标;逃出根目录、进入隐藏位置或在校验期间发生变化时,请求会失败。FIFO、Socket、设备文件等特殊类型不会作为下载内容打开。
这些限制不能判断业务内容是否适合公开。仍应为每个站点准备独立的最小目录,使用只读权限,并避免把备份、环境变量、私钥、数据库或应用配置复制到静态根目录。公开目录列表前,应先检查所有子目录和 README 中的链接与图片。
Docker 与平台路径
路径始终从 fn-knock 进程的视角解释:
- Docker 必须先把宿主机内容只读挂载到容器,再填写容器内路径;宿主机路径本身不可直接使用。
- Linux、macOS、OpenWrt、飞牛 FPK / Lite 和群晖需要让对应软件包账号拥有目录遍历与文件读取权限。
- Windows 使用本机盘符绝对路径,例如
C:\Sites\docs;网络共享路径和设备命名空间不受支持。
Docker Compose 示例:
services:
fn-knock:
volumes:
- /srv/public-site:/srv/public-site:ro修改挂载后重新创建容器,再在管理后台点击 浏览。路径浏览器应能看到 /srv/public-site;进入该目录并点击 使用当前文件夹,然后保存映射。不要为了读取静态内容而把宿主机根目录、/etc 或 fn-knock 数据卷整体挂载进容器。
静态映射只读取已有文件,不会创建 DNS 记录、开放防火墙端口或改变容器挂载。外部可达性仍由当前部署平台的网关入口、DNS、证书、路由器或隧道决定。
状态码与排错
| 现象 | 检查项 |
|---|---|
| 保存时提示路径不可用 | 绝对路径、文件 / 目录类型、读取权限、受保护路径和 Docker 挂载 |
| 路径浏览器看不到文件或目录 | 当前查看的是否为网关 / 容器文件系统、名称是否隐藏或保留、读取权限、受保护路径和符号链接目标 |
| 路径浏览器提示目录项目过多 | 改用更小的专用内容目录;不要把宽泛的共享目录直接选作静态根目录 |
根路径返回 503 | 配置根目录或单文件当前不存在、不可读或不再安全;响应带短暂重试提示 |
子路径返回 404 | 文件不存在、名称被安全规则隐藏、目录列表关闭,或单文件映射收到了非根路径 |
返回 405 | 静态响应只接受 GET 和 HEAD |
| 目录显示列表而不是站点首页 | 默认文档名称或优先级不正确,或者对应文件不可读 |
页面刷新后前端路由 404 | 静态目录没有 SPA 回退;改用支持 History Fallback 的上游 Web Server |
| 请求日志没有上游地址 | 静态响应由网关直接读取文件,这是预期行为 |
排查时先在编辑窗口打开 浏览,重新定位目标并执行 使用当前文件夹 或 使用所选文件,再从 fn-knock 运行环境确认权限和挂载,最后查看请求日志中的 Host、路由类型、认证结果、WAF 动作与状态码。不要通过扩大到系统目录或授予不必要的 root 权限来绕过路径检查。
相关配置见子域映射、Docker Compose 部署、WAF和安全边界与基线。
