一个公司可以做两个网站不:从零搭建双站防渗透实战
改个需求建站公司拖一周,这种折磨谁懂?更糟的是,如果你让同一家公司或者同一套服务器跑两个网站,一个被黑,另一个也得陪葬。很多老板觉得省事,把官网和商城,或者中文站和英文站都塞在一个域名或者一台服务器里,甚至用同一个后台账号。这不仅是运维噩梦,更是安全自杀。今天咱们不聊虚的,直接从零搭建双站架构,聊聊怎么在“一个公司两个网站”的现实里,把安全防线立起来,别让黑客觉得你这两个站是“连坐”关系。
威胁场景:双站同源的连锁反应
咱们先还原一个真实得不能再真实的场景。某制造企业,为了省事,把国内官网(Site A)和出口外贸站(Site B)部署在同一台 CentOS 服务器上,共用 Nginx 反向代理,甚至数据库还混在一个 MySQL 实例里,只是库名不同。
黑客怎么打?他不需要攻破你的主站。他扫描发现外贸站(Site B)用的是一个老旧的 CMS 系统,比如某个十年前的 PHP 模板,存在已知的 SQL 注入漏洞。黑客通过这个漏洞拿到了 Web 目录的写权限,上传了 Webshell。这时候,危险才刚开始。
因为两个站共用同一台服务器,甚至可能共用同一个 PHP-FPM 进程池。黑客拿到 Webshell 后,第一件事不是直接删库,而是查看文件权限和系统用户。如果 Web 服务运行在 www-data 或 nginx 用户下,且该用户对系统有一定权限,或者服务器配置不当,黑客可以轻易读取 /etc/passwd,尝试提权。更阴险的是,他可以直接访问 Site A 的后台目录。如果 Site A 的后台路径是默认的 /admin,且没有做 IP 限制,黑客直接用从 Site B 拿到的 Cookie 或者 Session 尝试跨站攻击,或者简单地通过服务器文件系统直接修改 Site A 的关键页面,挂上非法链接、赌博广告。
结果就是:Site B 被挂马,Site A 也跟着挂马。SEO 排名双双暴跌,品牌声誉受损。这时候你再找建站公司,对方只会说:“服务器资源冲突,需要重装。”然后又是拖一周。这就是“一个公司两个网站”如果不做物理或逻辑隔离,面临的典型连锁反应。
漏洞原理:信任边界模糊与权限滥用
为什么会出现这种情况?核心在于信任边界模糊。在单站架构中,黑客突破一层防护,整个站点就沦陷。在双站共享资源架构中,信任边界更是荡然无存。
1. 同源策略(Same-Origin Policy)的局限性与滥用 虽然浏览器有同源策略,但在服务器端,如果两个站点的静态资源、后端接口或者数据库访问凭证混用,同源策略就形同虚设。MDN Web Docs 明确指出,同源策略是浏览器端的安全机制,用于限制文档或脚本如何从其他源加载资源。但如果你的后端 API 没有严格校验来源,或者两个站点共享了同一个 JWT 密钥、同一个 Session ID 生成算法,那么攻击者在一个站点获取的身份凭证,往往可以在另一个站点被复用。
2. 共享数据库的横向移动风险
很多小团队为了节省成本,两个网站共用一个 MySQL 实例。假设 Site A 的数据库用户 user_a 只有 db_a 的权限,但 Site B 的数据库用户 user_b 拥有 db_a 的 SELECT 甚至 DROP 权限(因为运维图省事,给高了权限)。黑客攻破 Site B,获取 user_b 密码,直接连接数据库,就能窃取 Site A 的用户数据、订单信息,甚至修改 Site A 的管理员密码。这就是经典的横向移动。
3. 配置文件的敏感信息泄露
从零搭建时,很多人喜欢把配置文件放在 Web 根目录之外的目录,但通过 Nginx 配置失误,或者 PHP 信息泄露(phpinfo() 未删除),导致数据库连接字符串、API Key 暴露。一旦暴露,两个站点的核心凭证全部泄露。
防护方案:物理隔离与逻辑强化的代码实践
要想安全地运行两个网站,必须从架构层面切断信任链条。我们采取“物理隔离优先,逻辑隔离兜底”的策略。
方案一:独立域名与独立服务器(推荐)
最安全的方式是,两个网站使用独立的服务器(VPS 或云主机),或者至少是独立的容器(Docker)。这样,Site A 被黑,Site B 毫发无伤。
方案二:Nginx 虚拟主机隔离 + 独立应用目录
如果预算有限,必须在一台服务器上跑两个站,务必做到应用级隔离。
错误示范(常见坑):
# /etc/nginx/nginx.conf
server {listen 80;server_name siteA.com;root /var/www/html; # 两个站都在这下面index index.php;location ~ \.php$ {fastcgi_pass unix:/var/run/php-fpm.sock;include fastcgi_params;fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;}
}server {listen 80;server_name siteB.com;root /var/www/html; # 错误:共用根目录,权限混乱index index.php;# ...
}
正确示范(隔离配置):
# /etc/nginx/sites-available/siteA.conf
server {listen 80;server_name siteA.com;root /var/www/siteA/public; # 独立目录index index.php;# 限制访问敏感文件location ~ /\. {deny all;}location ~ \.php$ {# 使用独立的 PHP-FPM 池,或者确保 FastCGI 参数严格限制fastcgi_pass unix:/var/run/php-fpm-siteA.sock;include fastcgi_params;fastcgi_param SCRIPT_FILENAME /var/www/siteA/public$fastcgi_script_name;# 限制上传大小,防止大文件攻击client_max_body_size 10M;}# 禁止访问非 public 目录location / {try_files $uri $uri/ /index.php?$query_string;}
}# /etc/nginx/sites-available/siteB.conf
server {listen 80;server_name siteB.com;root /var/www/siteB/public; # 完全独立的目录index index.php;location ~ \.php$ {# 使用独立的 PHP-FPM 池,实现进程级隔离fastcgi_pass unix:/var/run/php-fpm-siteB.sock;include fastcgi_params;fastcgi_param SCRIPT_FILENAME /var/www/siteB/public$fastcgi_script_name;}
}
关键点解析:
- 目录隔离:
/var/www/siteA和/var/www/siteB权限完全独立,分别由不同用户拥有,或严格限制www-data用户只有读取权限。 - PHP-FPM 隔离:在
php-fpm.conf中配置两个独立的 Pool,www-data-a和www-data-b。这样即使 Site B 的 PHP 进程被注入恶意代码,它也无法直接操作 Site A 的文件系统,因为操作系统层面的用户权限已经隔离。 - Nginx 配置:明确指定
root和SCRIPT_FILENAME,杜绝路径遍历。
数据库隔离
不要共用数据库用户。在 MySQL 中:
-- 创建 Site A 专用用户
CREATE USER 'siteA_user'@'localhost' IDENTIFIED BY 'StrongPass_A_123!';
GRANT ALL PRIVILEGES ON `db_siteA`.* TO 'siteA_user'@'localhost';-- 创建 Site B 专用用户
CREATE USER 'siteB_user'@'localhost' IDENTIFIED BY 'StrongPass_B_456!';
GRANT ALL PRIVILEGES ON `db_siteB`.* TO 'siteB_user'@'localhost';-- 严禁赋予跨库权限
-- GRANT SELECT ON `db_siteA`.* TO 'siteB_user'@'localhost'; -- 绝对禁止
FLUSH PRIVILEGES;
检测与修复:发现漏洞后的应急与加固
假设你已经部署了双站,如何检测是否存在跨站风险?
1. 文件权限审计 登录服务器,执行:
ls -ld /var/www/siteA /var/www/siteB
ls -l /var/www/siteA/public
确保 www-data 用户对 /var/www/siteA 没有写权限。如果 Site B 的 Web 进程以 www-data 运行,而 www-data 能写 siteA 的目录,那就是高危漏洞。
2. 数据库权限审计
使用 siteB_user 登录 MySQL,尝试执行:
SHOW GRANTS;
USE db_siteA;
SELECT * FROM users;
如果成功,说明权限配置错误,立即收回跨库权限。
3. 代码扫描
使用 gitleaks 或 trufflehog 扫描代码仓库,确保没有硬编码的数据库密码或 API Key。确保 .env 文件在 .gitignore 中,且不在 Web 根目录下。
修复步骤:
- 修改文件属主:
chown -R www-data:www-data /var/www/siteA,然后chmod -R 755 /var/www/siteA,确保没有 777 权限。 - 重启服务:重启 Nginx 和 PHP-FPM,确保新配置生效。
- 监控日志:在 Nginx 日志中增加对
/admin、/wp-login.php等敏感路径的访问监控,并设置报警。
安全加固清单:从零搭建的最后一道防线
从零搭建双站,除了上述隔离,还需执行以下加固清单,这是老手与新手的区别所在。
HTTPS 强制跳转与 HSTS 使用 Let's Encrypt 为两个站点分别申请证书。在 Nginx 中配置:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;这能防止中间人攻击,确保用户始终通过加密通道访问。
安全响应头 为两个站点添加以下头部,增强浏览器端安全:
add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always;根据 MDN Web Docs 的建议,
X-Content-Type-Options能防止 MIME 类型嗅探攻击,这在处理用户上传文件时尤为重要。WAF(Web 应用防火墙) 如果流量较大,建议在 Nginx 前增加 ModSecurity 或云厂商的 WAF。配置规则,拦截常见的 SQL 注入、XSS 攻击载荷。针对两个站点,可以设置不同的规则集,比如外贸站可能对某些国家 IP 有封禁需求,而国内站则关注 CC 攻击防护。
日志集中化与告警 不要只看本地日志。使用 ELK(Elasticsearch, Logstash, Kibana)或云日志服务,将两个站点的访问日志、错误日志集中存储。设置告警规则:
- 同一 IP 在短时间内访问 404 超过 50 次(可能是在扫描目录)。
- 访问
/etc/passwd、/shell.php等敏感路径。 - 数据库连接失败次数激增。
定期备份与恢复演练 每天凌晨自动备份两个站点的代码和数据库,备份文件存储在另一个独立服务器或对象存储中。每季度进行一次恢复演练,确保在 Site A 被黑时,能快速从备份恢复,并将 Site B 的流量切换到备用方案,避免业务停摆。
一个公司做两个网站,技术上完全可行,但前提是隔离。不是简单的两个文件夹,而是从网络层、应用层、数据层到日志层的全面隔离。不要为了省那几百块的服务器钱,把整个公司的业务命脉系在一根绳上。
从零搭建的过程,就是建立安全边界的过程。每一个配置项的确认,每一次权限的收紧,都是在为未来的安稳运营买单。
你更倾向模板建站还是定制开发?在双站场景下,定制开发的灵活性在安全隔离上更有优势,但成本也高。欢迎评论区聊聊你的选择。


