多站点容器隔离防跨站入侵漏洞:新手也能上手的实战配置
为什么多站点容器隔离能防跨站入侵漏洞
跨站入侵漏洞是指攻击者通过突破一个站点的权限,横向渗透到同一服务器上的其他站点。
传统虚拟主机或面板上的多站点共用 PHP、文件权限等底层环境,一旦某个站点的上传漏洞被利用,整个服务器的其他站点都可能沦陷。
使用容器(比如 Docker)为每个站点创建独立的运行环境,包括独立的文件系统、进程空间和网络栈。
即使某个容器被攻破,攻击者也无法触及宿主机或其他容器内的站点,从根本上隔离风险。
前置准备:需要提前做好的三件事
- 一台 Linux 服务器(CentOS 7+ 或 Ubuntu 20.04+,建议内存 2G 以上)。
- 安装 Docker:执行官方安装脚本(如下)。
curl -fsSL https://get.docker.com | bash
sudo systemctl start docker
sudo systemctl enable docker
- 了解基本域名和端口规划:假设有
site1.example.com和site2.example.com,分别使用宿主机 8081 和 8082 端口对外服务。
分步操作:用 Docker Compose 隔离两个站点
这里我们以两个独立 Nginx + PHP 容器为例。
推荐用 Docker Compose 统一管理,每个站点的服务独立成一个目录。
1. 创建站点目录结构
mkdir -p /data/sites/site1 /data/sites/site2
cd /data/sites
2. 编写 site1 的 docker-compose.yml
在 /data/sites/site1/ 下创建 docker-compose.yml:
version: '3'
services:
web:
image: nginx:alpine
container_name: site1-web
volumes:
- ./html:/usr/share/nginx/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- "8081:80"
restart: always
php:
image: php:7.4-fpm
container_name: site1-php
volumes:
- ./html:/var/www/html
restart: always
注意:这里用 container_name 明确指定容器名,方便后续排查。每个站点使用独立的容器名和端口。
3. 编写 site2 的 docker-compose.yml(仅端口和容器名不同)
version: '3'
services:
web:
image: nginx:alpine
container_name: site2-web
volumes:
- ./html:/usr/share/nginx/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- "8082:80"
restart: always
php:
image: php:7.4-fpm
container_name: site2-php
volumes:
- ./html:/var/www/html
restart: always
4. 启动两个站点的容器
cd /data/sites/site1 && docker-compose up -d
cd /data/sites/site2 && docker-compose up -d
启动后,访问 http://服务器IP:8081 看到 site1 内容,访问 http://服务器IP:8082 看到 site2 内容。
5. 配置 Nginx 反向代理(可选,绑定域名)
如果你有域名,可以在宿主机上安装 Nginx 反向代理到不同端口,或直接用 Docker 的网络互通(新手建议前一种)。
宿主机 Nginx 配置片段:
server {
listen 80;
server_name site1.example.com;
location / {
proxy_pass http://127.0.0.1:8081;
}
}
server {
listen 80;
server_name site2.example.com;
location / {
proxy_pass http://127.0.0.1:8082;
}
}
避坑指南:新手最容易翻车的几个点
- 容器内文件权限:PHP 或 Nginx 容器默认以
www-data用户运行,需要确保宿主机挂载的html目录所属用户 ID 与容器内一致,否则会报 403 或文件无法写入。可用chown -R 1000:1000 ./html快速调整(1000 是容器内www-data的 UID)。 - 端口冲突:如果宿主机已有程序占用 8081/8082,换其他端口(如 8083、8084)。
- 容器间网络隔离:默认情况下,不同
docker-compose网络是隔离的,但如果你手动创建了共享网络,反而可能打破隔离。确保每个站点使用独立的docker-compose.yml,不额外指定network即可。 - 日志查看:容器启动失败时用
docker logs site1-web查看错误日志。
效果验证:如何确认跨站入侵漏洞已被隔离
1. 基础验证:两个站点各自独立
在 site1 的 html 目录放一个 phpinfo.php,在 site2 不放。
访问 http://IP:8081/phpinfo.php 应正常显示,http://IP:8082/phpinfo.php 应返回 404。
说明两个站点的文件系统完全隔离。
2. 模拟入侵测试(不伤害生产环境)
在 site1 的 html 目录创建一个测试脚本 test.php:
此时执行 curl http:,
//localhost:
8081/test.php
应返回 false 或权限错误,
因为 site1 的 PHP 容器内根本看不到 site2 的目录。
3. 验证进程隔离
在宿主机执行 docker exec site1-web ps aux 和 docker exec site2-web ps aux,看到进程列表完全不同,无法相互影响。
高频问题 FAQ
Q:容器隔离后,如何管理数据库?
A:可以为每个站点独立启动 MySQL 容器,或使用外部数据库但通过容器内环境变量连接。建议每个站点独立数据库账户,避免注入后跨库查询。
Q:我的常用面板(如宝塔)可以配合容器使用吗?
A:可以。在面板所在服务器上手动配置反向代理到容器端口,面板只负责域名解析和 SSL 证书管理,运行环境完全交给容器。
Q:容器重启后站点访问不了怎么办?
A:检查 docker ps 是否全部运行,如果没有,执行 docker-compose restart。更多时候是反向代理未配置正确。
Q:免费 SSL 证书怎么办?
A:可以通过宿主机 Nginx + Let's Encrypt 反代容器端口,或直接在容器内配合 certbot 安装证书。新手推荐宿主机方案,证书续签更方便。