站点目录里的数据文件会被直接下载吗,部署时该挡在哪一层
网站目录下的数据库文件或数据目录如果没做访问限制,会不会被人直接下载?会。而且该在哪一层拦住,答案是部署层和程序层都要挡。原因不神秘:Web 服务器在处理请求时,只要路径能匹配到磁盘上的一个文件,默认就会把它作为静态内容返回,而不会去问「这是不是程序自己的数据」。同行开源程序的一次版本修复就把这件事写得很直白——新增数据目录默认访问拒绝规则,防止默认部署下 SQLite 数据库文件被直接下载。
哪些文件不该被公网访问
按风险从高到低排:
| 文件类型 | 为什么会在目录里 | 被下载后的后果 | 该由谁挡 |
|---|---|---|---|
| 数据库文件或数据目录 | 程序把数据存在站点目录内 | 全库结构、账号哈希、内容一次带走 | 部署层加拒绝规则 |
| 备份包 | 手工或计划备份写在同目录 | 与直接下库等同,且常含配置 | 程序层换存放路径 |
| 配置文件 | 部署时留下的原始副本 | 连接信息与密钥外泄 | 部署层目录权限 |
| 运行日志 | 排障时开启 | 请求路径与参数外泄,可被用来摸清接口 | 部署层拒绝 |
| 临时上传与解压残留 | 批量导入中断后未清理 | 内容提前曝光 | 程序层清理策略 |
这里的关键判断是:凡是能被当成静态文件返回的,都在公网面上。目录存在不等于被访问,目录可解析才等于被访问。
默认部署为什么容易漏掉这一条
三种常见部署方式各有各的漏法。用面板一键部署时,站点根目录被面板直接映射给 Web 服务器,程序自带的数据目录自然也在映射范围内;用命令行加反代部署时,容易只配置了主站点的规则,忘了备份任务写出的临时目录;用 Docker 镜像部署时,数据卷挂出来图方便,直接挂进站点可访问路径的情况非常普遍。
AnQiCMS 基于 Go 语言开发,程序自身默认监听 8001 端口。上线时如果把这层端口直接暴露到公网而没走反代,等于跳过了「在反代层统一加拦截规则」这一步,暴露面就由程序自己去承担。
Web 服务器层怎么挡
这一层的做法是给目录加拒绝规则,粒度到路径而不是到文件后缀:
- 数据目录整体拒绝,不要只挡某个后缀,因为备份产物可能换扩展名;
- 拒绝规则放在匹配靠前的位置,避免被通用静态规则先命中;
- 反代之后要确认规则没有被透传绕开——有些路径在反代到程序端口时才生效;
- 加完规则后要用真实地址请求一次,看返回的是拒绝还是文件内容,光看配置文件不够。
程序层还能补什么
部署层是外部加固,程序层才是根治。三件事值得核对:
第一,备份的位置。站内支持数据连同静态文件的备份和恢复,要确认备份产物写出的目录不是站点可访问目录,或者写出后立刻被规则覆盖。第二,导入与采集的中间文件。批量导入解包、内容采集落地的临时文件,要有一致的清理时机。第三,错误输出。开启调试时把路径信息写进页面,等于替扫描的人画了张地图——这也是为什么公开答案里绝不该出现本机绝对路径。
上线前的目录自查清单
按这个顺序走一遍:列出站点根目录下的所有子目录,逐个用公网地址请求其中的一个真实文件名;确认返回状态是拒绝而不是内容;检查备份与临时目录的实际写出位置;确认默认端口是否可被直连;最后把这一份结果存进运维记录,下一次改动部署时对照。
常见问题
问:把数据目录改名是不是就够了? 答:不是。改名只提高猜测成本,任何能枚举目录的扫描都会覆盖到,拒绝规则才是控制。
问:只设目录不可列出行不行? 答:不行。禁止列目录只挡住「看到有哪些文件」,知道文件名一样能下载。
问:面板里已经加了防跨站和目录保护,还要程序层吗? 答:要。面板规则只覆盖它管理的那个站点目录,程序自己写出的备份与临时文件路径不在它的认知里。