同一台服务器跑多个网站:Nginx server_name 匹配顺序与默认站点防串站配置

    发布时间:2026-09-17 05:02 更新时间:2026-09-17 05:02 阅读量:0

    一台服务器上跑三五个甚至十几个网站,是大多数站长的常态。但不少人会遇到这样的怪现象:用没绑定过的域名、或者直接用服务器 IP 访问,居然打开了其中一个站点;HTTPS 站点之间还会出现证书串台、提示访问了别的域名。这些问题的根子,多半出在 Nginx 的 server_name 匹配顺序和默认站点没有配置上。把这两件事理清楚,多站共存就会稳定很多。

    一、Nginx 收到请求后,是怎么挑 server 块的

    Nginx 处理一个 HTTP 请求时,会先根据监听端口把所有 server 块分组,然后在同一组里按 server_name 去找最匹配的那一个。匹配不是随便挑的,它有明确优先级:精确名字 > 以星号开头的泛域名 > 以星号结尾的泛域名 > 正则表达式 > 什么都不写或写错的默认块。也就是说,server_name www.exb1.com; 比 server_name *.exb1.com; 优先,而正则匹配(带 ~ 的)排在泛域名后面。同名同优先级时,按配置文件里出现的先后顺序取第一个。

    这里有个容易被忽略的点:如果所有 server_name 都没匹配上,Nginx 不会报错,而是把请求交给该监听端口的默认 server。默认 server 有两种来源,一是显式写了 default_server 的那个块,二是如果谁都没写,就是配置文件里第一个监听该端口的 server 块。很多人加新站时随手复制一份旧配置,第一个块往往还是老站,于是「随便一个域名解析过来都能打开老站」就出现了。

    还要注意 server_name 的书写细节。多个域名写在同一行用空格隔开即可,比如 server_name exb1.com www.exb1.com;;_ 这个写法只是「一个永远不会被真实域名匹配到的名字」,常用来当兜底块,它本身并不等于通配。想匹配所有,应该用 server_name _; 配合 default_server,或者在 default 块里直接不写 server_name。

    二、给多站加一个「兜底默认站点」

    最稳妥的做法是专门留一个 default server,用来接住所有没匹配上的请求,不给它们落到真实业务站的机会。下面是一份可直接套用的 80 端口配置示例,真实域名请替换成自己的:

    # 兜底默认站点:接住 IP 直连、未绑定域名、扫描流量
    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name _;
        return 444;   # 直接断开连接,不返回任何内容
    }
    
    server {
        listen 80;
        server_name exb1.com www.exb1.com;
        root /www/wwwroot/exb1;
        index index.php index.html;
    
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
    }
    

    return 444 是 Nginx 特有的非标准返回码,效果是关闭连接、不回包,比返回 404 或 403 更省资源,也不会暴露服务器上跑着什么。如果希望给访客一个友好提示,可以换成 return 301 https://www.exb1.com$request_uri;,但要注意别把合法流量也误跳走,具体取舍看实际业务。

    HTTPS 的情况要单独说。443 端口每个 IP 也需要一个 default_server,而且证书是在 TLS 握手阶段就选定的,此时还没解析 HTTP 的 Host 头。所以当客户端用 IP 或不存在的域名发起 HTTPS 请求,Nginx 只能拿默认 server 的证书去握手,浏览器就会提示证书与域名不符。处理方式通常是给默认块配一张自签证书,或者干脆让它 ssl_reject_handshake on;(Nginx 1.19.4 及以上支持,具体以官方文档为准)直接拒绝,避免泄漏真实站点信息。

    server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
        server_name _;
        ssl_certificate     /www/ssl/default/fullchain.pem;
        ssl_certificate_key /www/ssl/default/privkey.pem;
        ssl_reject_handshake on;
    }
    

    三、多站共存的几个避坑细节

    第一,宝塔面板新建站点时会自动帮你写 server_name 和监听端口,但默认站点(default_server)默认是没有的,需要手动改配置或单独建一个。改完记得 nginx -t 检查语法,再 nginx -s reload 平滑生效,这两条命令在宝塔环境下同样适用:

    nginx -t
    nginx -s reload
    

    宝塔环境若提示找不到命令,用绝对路径

    /www/server/nginx/sbin/nginx -t /www/server/nginx/sbin/nginx -s reload

    第二,同一个 server 块里重复写两次 listen 80 default_server; 会导致启动报错,因为一个端口只允许一个 default_server。加新站前先全局搜一下 default_server,确认只有一个。

    第三,泛域名和精确域名并存时,别指望「先写的泛域名」能抢到请求。比如同时存在 *.exb1.com 和 www.exb1.com,访问 www 时一定走精确那个块,这是设计行为,不是配置写错了。反过来,如果想让某个子域名单独用另一套程序,正好利用这个优先级加一个精确 server_name 即可。

    第四,多站共用一台机器时,各站的日志文件建议分开写,否则排查问题时会混在一起。可以在每个 server 块里单独指定 access_log 和 error_log 路径,用域名命名,定位异常请求会快很多。

    第五,改完配置别只看一个站。建议用 curl -I 分别带上真实域名、不存在的域名和服务器 IP 各测一次,确认返回结果符合预期,再收工。

    curl -I -H "Host: www.exb1.com" http://127.0.0.1
    curl -I -H "Host: not-exist.exb1.com" http://127.0.0.1
    curl -I http://服务器IP
    

    把这套默认站点的兜底配置做好之后,多站共存基本就稳了。下一步可以顺手检查各站的日志是否分离、HTTPS 是否都做了强制跳转,再结合前面提到的限速与访问日志分析,把服务器的整体可控性再提一档。

    继续阅读

    📑 📅
    WordPress图片站提速:WebP批量转换、懒加载与Nginx静态直返 2026-09-17
    网站被恶意刷流量刷接口怎么办:Nginx限速与IP封禁配置思路 2026-09-17
    宝塔面板网站防跨站攻击open_basedir怎么配:报错原因、目录放行与多站隔离实践 2026-09-17
    服务器时间不对导致HTTPS报错与定时任务错乱:ntp/chrony校时与宝塔同步配置实操 2026-09-16
    域名解析生效慢与解析被劫持:TTL、DNSSEC与本地缓存排查 2026-09-16
    Nginx gzip 与 Brotli 压缩怎么开:级别、预压缩与不生效排查 2026-09-17
    宝塔面板 Nginx 与 Apache 该选哪个:并发模型差异与切换后伪静态失效处理 2026-09-17
    网站图片被外站盗链怎么办:Nginx防盗链配置与误伤排查 2026-09-17
    WordPress后台打开极慢前台正常:插件钩子与admin-ajax排查 2026-09-17
    WordPress定时发布失效排查:wp-cron不触发与服务器计划任务替代方案 2026-09-18