服务器域名绑定教程

结论: 服务器绑定域名只有两件事:一是在 DNS 服务商处把域名解析到服务器公网 IP(A 记录)或另一个域名(CNAME 记录),二是在 Web 服务器里用 Nginx 的 server_name 或 Apache 的 ServerName 声明这个域名。两步缺一不可——只做解析不开虚拟主机,会落到默认站点;只配 Nginx 不做解析,浏览器根本找不到 IP。

买完服务器、部署好网站之后,很多人卡在最后一步:输入 IP 能访问,输入域名却打不开;或者域名能打开,却跳到了一个陌生的页面。这两个现象,本质上分别是"DNS 没解析到"和"Web 服务器没认领这个域名"。

本教程面向已经拥有一台云服务器(ECS/CVM/轻量应用服务器均可)和域名的读者,以 Ubuntu 24.04 LTS + Nginx 1.26 为基准环境(截至 2026 年),把域名绑定拆成"DNS 侧"和"服务器侧"两条线讲清楚,并覆盖多域名、泛解析、www 跳转、CDN 接入这些真实场景里一定会遇到的分支。

域名绑定到底绑定了什么?先分清 DNS 与 Web 服务器

域名绑定的本质是一次"两段式寻址":DNS 负责把域名翻译成 IP,Web 服务器负责在这个 IP 上区分不同域名对应的站点。 理解这一点,后面所有问题都能自己推导出来。

当一个用户访问 www.example.com 时,流程是这样的:

  1. 客户端向本地 DNS 递归服务器查询 www.example.com 的 A 记录,DNS 系统逐级递归,最终由你的域名权威 DNS 返回服务器公网 IP,例如 203.0.113.10。
  2. 客户端向 203.0.113.10 的 80 端口(HTTP)或 443 端口(HTTPS)发起 TCP 连接并发送 HTTP 请求,请求头里的 Host 字段写着 www.example.com。
  3. 服务器上的 Nginx 收到请求后,拿 Host 去和所有 server_name 做匹配,命中就交给对应的 server 块处理,没命中就交给默认站点(default_server)。

如果只有一台服务器一个站点,其实不配 server_name 也能访问——因为无论 Host 写什么都会落到那个唯一的 server 块。但只要IP 上要跑两个以上站点,server_name 就成了唯一的分流依据。这也是为什么"域名访问到了别人的网站"这种怪事会发生:你解析到某个 IP,而那个 IP 上的默认站点恰好是别人的。

DNS 解析记录类型对照表

DNS 里能加的记录有几十种,日常绑定域名真正用得到的只有下面这些。这张表建议收藏,配置邮件服务、SSL 证书校验时都会回头查。

记录类型作用填写值示例典型用途
A域名指向 IPv4 地址203.0.113.10根域名和 www 指向服务器 IPv4
AAAA域名指向 IPv6 地址2001:db8::10开启 IPv6 访问
CNAME域名指向另一个域名cdn.example.com.接入 CDN、对象存储加速域名
NS指定该域名的权威 DNS 服务器ns1.dnsprovider.com.把 DNS 托管切到第三方(如 Cloudflare)
MX指定接收邮件的服务器10 mail.example.com.企业邮箱,数字为优先级,越小越优先
TXT存放任意文本v=spf1 include:_spf.mail.com ~allSPF/DKIM/DMARC、域名所有权验证、SSL 证书的 DNS-01 校验
CAA指定允许签发证书的 CA0 issue "letsencrypt.org"限制谁能为该域名签发证书
SRV定义某服务在某主机某端口5 0 5269 xmpp.example.com.即时通讯、部分游戏/微服务发现
PTRIP 反向解析到域名mail.example.com.邮件服务器防退信,需在运营商侧申请

几个必须记住的约束:

  • 根域名(@)不能配置 CNAME 记录,这是 RFC 1034 的限制。想让 example.com 也能访问,要么填 A 记录指向 IP,要么使用支持 ALIAS/ANAME/FLATTENING 的 DNS 服务商(Cloudflare、阿里云企业版 DNS 等支持,截至 2026 年)。
  • CNAME 和同一主机名的其他记录互斥,www 配了 CNAME 就不能再配 MX。
  • MX 记录的值必须是主机名,不能直接写 IP。
  • 域名末尾的点(如 cdn.example.com.)表示完全限定域名 FQDN,DNS 面板里不写通常也没问题,面板会自动补全当前域名;但手写 zone 文件时漏了这个点会导致记录变成 cdn.example.com.example.com。

泛解析:一条记录覆盖所有子域名

泛解析(Wildcard DNS)用主机名 * 表示匹配所有未单独配置的子域名。它的典型用途是多租户 SaaS 的每个用户一个子域名,或者临时测试环境。

text
主机记录:  *
记录类型:  A
记录值:    203.0.113.10
TTL:       600

需要注意两点:第一,泛解析的优先级低于精确匹配,www.example.com 单独配了 A 记录时,访问 www 走的是那条精确记录而不是 *;第二,泛解析会让任何人都能猜到并访问你的未启用子域名(例如 admin.example.com、test.example.com),如果 Nginx 上没有兜底策略,这些域名会落到默认站点,存在信息泄露风险。

绑定前需要准备好的四样东西

开工前请确认四件事齐备:服务器的公网 IP、域名的 DNS 管理权限、服务器上已有一个能跑的 Web 服务、云厂商安全组已放行 80/443 端口。 缺任何一样都会导致最后一步卡住。

  • 服务器公网 IP:注意区分公网 IP 和内网 IP。阿里云 ECS、腾讯云 CVM 控制台显示的是公网 IP,但如果你用的是 NAT 网关或弹性网卡,要填真正对外可达的那个地址。可以在服务器上执行 curl -s ifconfig.me 反查出口 IP 做交叉验证。
  • DNS 管理权限:如果域名是在注册商处注册但想用第三方 DNS,需要先把 NS 记录改成第三方提供的地址,等待 NS 生效(最长 48 小时)后再添加解析记录。
  • Web 服务可用性:先确认 http://你的公网IP 能返回内容。如果 IP 访问都不通,先排查 Nginx 是否运行、安全组是否放行,域名绑定再正确也没用。
  • 备案要求:中国大陆境内节点(不含香港、新加坡等境外地域)的服务器,域名必须先完成 ICP 备案并接入备案,80/443 端口才会被放行。截至 2026 年,阿里云、腾讯云均提供备案管家服务,个人备案周期通常 5~15 个工作日。

第一步:在 DNS 服务商处添加解析记录

最简配置是两条 A 记录:主机记录 @ 和 www,都指向服务器公网 IP。 这是 90% 场景下的标准做法,配完即可进入下一步。

以常见的域名为例,假设服务器 IP 为 203.0.113.10,需要在 DNS 面板中添加:

主机记录记录类型记录值TTL
@A203.0.113.10600 秒
wwwA203.0.113.10600 秒
blogA203.0.113.10600 秒
mailCNAMEmail.mxprovider.com.3600 秒
@MX10 mail.example.com.3600 秒

关于 TTL(Time To Live)的选择,直接影响变更生效速度:

  • 调试期建议设 600 秒甚至 60 秒,改错了能快速纠正。
  • 稳定运行后建议设 3600 秒,减少递归 DNS 的查询压力,也能略微提升访问速度。
  • 换服务器前 24 小时建议先把 TTL 调低到 300 秒,这样真正切换 IP 时,大部分用户的缓存会在几分钟内过期,避免长时间访问中断。

生效时间是新手最容易焦虑的点。正常情况下,新增记录在阿里云/腾讯云 DNS 上秒级到 10 分钟内生效;修改记录则最长需要等待原 TTL 到期。各地运营商的 Local DNS 不严格遵守 TTL 是常态,个别线路可能拖延到 24~48 小时。只要权威 DNS 查询已经返回正确结果,剩下的就是等。

第二步:在 Nginx 里认领这个域名

Nginx 侧的关键是 server_name 必须与请求头里的 Host 严格一致,且必须显式定义一个 default_server 兜底。 前者决定能否被正确路由,后者决定陌生人乱填 Host 时会不会落到你的站点。

先确认 Nginx 配置文件的组织方式。Ubuntu 24.04 通过 apt 安装的 Nginx 采用 sites-available / sites-enabled 的软链接结构:

bash
# 查看 Nginx 加载了哪些配置文件
nginx -T | grep -E '^# configuration file'

# 建立站点配置文件
sudo vim /etc/nginx/sites-available/example.com.conf

# 启用站点(软链接到 sites-enabled)
sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/

# 语法检查 + 平滑重载
sudo nginx -t && sudo systemctl reload nginx

下面是一个同时服务三个域名、带默认站点的完整示例。注意 default_server 单独占一个 server 块返回 444(Nginx 自定义状态码,直接断开连接,不返回任何内容),这是防止 IP 直连、恶意域名解析的最佳实践。

nginx
# 兜底:IP 直连或未知域名,直接断开
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 444;
}

# 主站:同时接受根域名与 www,并把 www 301 跳转到根域名
server {
    listen 80;
    listen [::]:80;
    server_name www.example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 80;
    listen [::]:80;
    server_name example.com;

    root /var/www/example.com;
    index index.html index.htm;

    access_log /var/log/nginx/example.com.access.log;
    error_log  /var/log/nginx/example.com.error.log;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

# 博客子域名,独立目录
server {
    listen 80;
    listen [::]:80;
    server_name blog.example.com;

    root /var/www/blog;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

server_name 的写法有三种形式,按需选择:

  • 精确匹配:server_name example.com www.example.com; —— 多个域名用空格分隔,最常用。
  • 通配符:server_name *.example.com; —— 只匹配一级子域名,不匹配 example.com 本身;server_name .example.com; 是前者的简写且同时匹配裸域名。
  • 正则:server_name ~^(?.+)\.example\.com$; —— 匹配结果可通过 $subdomain 变量使用,适合动态多租户。

匹配优先级是:精确 > 前导通配符 > 后导通配符 > 正则 > default_server。当多个 server 块的 listen 地址端口都相同时,Nginx 按上述顺序挑唯一一个作为该地址端口的默认站点。

第三步:www 与根域名跳转,到底该留哪个?

建议统一选一个主域名,另一个做 301 永久跳转,绝大多数团队选裸域名(example.com)作为主域名。 两个域名都能 200 直接访问属于重复内容,搜索引擎会分散权重,SEO 上明确扣分。

跳转的正确写法有两条原则:用 return 301 而不是 rewrite,跳转要不惜一切代价保留 $request_uri。

nginx
# 推荐:把 www 统一跳到裸域名
server {
    listen 80;
    listen [::]:80;
    server_name www.example.com;
    return 301 https://example.com$request_uri;
}

# 不推荐但可用:rewrite 写法,性能略差且容易写错捕获组
# rewrite ^/(.*)$ https://example.com/$1 permanent;

原因是 return 在 Nginx 的 rewrite 阶段直接返回,不进入后续的 location 匹配流程,开销最小;而 rewrite ... permanent 需要执行正则匹配再重定向。另外,Host 头末尾可能带冒号加端口(如某些扫描器发的 example.com:),严谨的写法是用 $host 配合正则清理,但对绝大多数站点直接用确定的域名字符串最安全,避免 Host 头注入。

第四步:接入 CDN 之后,域名绑定的逻辑变了

接入 CDN 后,用户不再直接连你的源站 IP,DNS 记录因此不再指向源站,而是指向 CDN 提供的 CNAME。 这是唯一的核心变化,但由此带来两个必须处理的配置。

DNS 侧的改法:

主机记录接入前接入后(CDN)
@A → 203.0.113.10CNAME → example.com.cdn.dnsv1.com.(Cloudflare 用户可用 CNAME Flattening 保持 A 记录形态)
wwwA → 203.0.113.10CNAME → example.com.cdn.dnsv1.com.
源站无需额外配置另设一个源站域名 origin.example.com → A → 203.0.113.10

服务器侧必须做的两件事:

  1. 源站 Nginx 要接收 CDN 回源时的 Host 头。回源 Host 默认是 CDN 的加速域名,所以 CDN 控制台里的"回源 Host"必须配成 origin.example.com 或源站已配置的域名,否则源站找不到匹配的 server_name,会返回默认站点或 404。
  2. 用 real_ip 模块还原真实客户端 IP,否则日志里全是 CDN 节点 IP,CC 防护和限流全部失效。
nginx
# 放在 nginx.conf 的 http 块或站点 server 块内
# 以常见 CDN 回源段为例,务必按厂商公布的最新 IP 段更新
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

# 若 CDN 使用自定义回源头,则改为:
# real_ip_header X-Real-IP;

安全上还有一点:建议用防火墙只放行 CDN 的回源 IP 段访问源站 80/443,禁止普通用户绕过 CDN 直连源站。目前不少 CDN 厂商提供回源 IP 段 API 或固定 IP 列表,可以配合脚本定期同步更新。

解析生效了吗?四个命令自证

判断 DNS 是否生效的第一原则:先查权威 DNS,再查本地递归,最后查实际连通性。 顺序错了会把缓存问题误判成配置错误。

bash
# 1) 直接向域名的权威 DNS 查询,绕过所有缓存,结果为权威答案
dig example.com NS +short
dig @ns1.example-dns.com example.com A +short

# 2) 看完整解析链路,确认每一级返回的都是你期望的结果
dig example.com A +trace

# 3) 检查本机实际拿到的 IP
nslookup example.com
getent hosts example.com

# 4) 验证 HTTP 层:Host 头是否正确打到目标 server 块
curl -I http://example.com
curl -sI -H "Host: blog.example.com" http://127.0.0.1 | head -5

如果 DNS 已经正确但访问仍异常,用下面的顺序快速收敛问题:

bash
# 端口是否可达(本机)
ss -tlnp | grep -E ':80|:443'

# 云厂商安全组是否放行(在另一台机器或手机 4G 网络下测)
nc -zv 203.0.113.10 80
nc -zv 203.0.113.10 443

# Nginx 是否真的加载了你的配置,以及有没有被其他文件抢占默认站点
nginx -T | grep -n 'server_name\|default_server'

# 实时看访问日志,确认请求到达了哪个 server 块
tail -f /var/log/nginx/example.com.access.log