广告位 · 页头(后台-模块管理-新建模块后替换此区域)

nginx怎么做域名解析?nginx配置域名解析教程与常见问题详解

域名访问Nginx出现默认页或错误站点,排查方向往往不是DNS没生效,而是Nginx的server_name没有匹配到请求里的Host头。Nginx本身并不负责把域名解析成IP,这个动作由DNS完成;Nginx的职责是在同一个IP和端口上,根据HTTP请求头中的Host字段,把流量分发给不同的虚拟主机。理解这两层机制,配置才不会跑偏。

nginx怎么做域名解析?nginx配置域名解析教程与常见问题详解

一、先区分DNS解析和Nginx的server_name匹配

域名从输入到访问Nginx,通常先经过DNS解析,把www.ipipp.com转换成服务器公网IP。Nginx监听80或443端口后,收到请求时会读取HTTP请求头里的Host字段。这个字段的值就是浏览器地址栏里的域名。Nginx根据Host字段和所有server块中的server_name做匹配,决定由哪个server块处理请求。

server_name支持精确名称、通配符和正则表达式。匹配顺序有明确优先级:先找精确名称,再找以星号开头的起始通配符,比如*.ipipp.com,接着找以星号结尾的末尾通配符,比如www.example.*,最后才尝试正则匹配。如果全部都没匹配上,Nginx会交给默认server处理;没有显式指定default_server时,就使用配置文件中第一个server块。

实际配置中,可以为同一个server_name写多个域名,也可以混用通配符和正则。一个常见的多域名写法如下:

server {
    listen 80;
    server_name www.ipipp.com ipipp.com;
    location / {
        root /var/www/example;
        index index.html;
    }
}

如果要让所有子域名都进入同一个站点,可以使用通配符:

server {
    listen 80;
    server_name *.ipipp.com;
    location / {
        root /var/www/wildcard;
    }
}

注意通配符server_name只能匹配一级子域名,也就是说*.ipipp.com能匹配a.ipipp.com,但不能匹配a.b.ipipp.com。如果需要多级子域名,就要借助正则表达式:

server {
    listen 80;
    server_name ~^user-(?<id>\d+)\.example\.com$;
    location / {
        root /var/www/users;
    }
}

正则里的命名捕获组可以在后续指令中通过变量使用,比如$id可以拿到捕获到的数字。正则匹配虽然灵活,但会略微增加匹配成本,站点数量很多时需要留意。

二、反向代理场景下的域名解析:resolver与proxy_pass

当Nginx作为反向代理时,proxy_pass后面经常会写域名,例如proxy_pass http://backend.ipipp.com:8080;。很多人以为Nginx每次转发请求都会重新解析这个域名,事实并非如此。Nginx在启动或加载配置阶段就会解析proxy_pass中的域名,并把得到的IP地址缓存下来。之后只要Nginx不重新加载配置,即使backend.ipipp.com的DNS记录变了,Nginx仍然会向旧IP转发请求。

这种启动期解析的行为在大多数静态反向代理场景里影响不大,但如果后端使用动态IP、容器平台或故障切换域名,就会出现请求打到旧地址、502或连接超时等问题。解决办法是使用Nginx的resolver指令,并把proxy_pass改写成包含变量的形式:

server {
    listen 80;
    server_name api.ipipp.com;
    resolver 223.5.5.5 valid=30s ipv6=off;
    set $backend_upstream backend.ipipp.com;
    location / {
        proxy_pass http://$backend_upstream:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

这里resolver指定了Nginx运行时使用的DNS服务器,valid=30s表示解析结果缓存30秒。proxy_pass中使用变量后,Nginx会在每次请求时通过resolver重新解析域名,从而感知DNS变化。不过要特别注意,当proxy_pass中使用变量时,URI的传递行为和直接写域名时不同。直接写proxy_pass http://backend.ipipp.com:8080;会把原始请求URI完整拼接到后端地址,而使用变量时,如果location后面没有写具体路径,Nginx会原样转发请求URI;如果写了路径,变量的写法可能导致路径拼接不符合预期,需要谨慎测试。

另外,resolver指令也可以放在http或server层级,具体取决于作用范围。如果Nginx转发的是upstream块中定义的服务器组,那个域名解析同样是在配置加载时完成,无法通过resolver改变,需要把动态域名直接写在proxy_pass变量里。

三、完整多站点域名解析配置示例

下面给出一个比较完整的配置片段,包含默认站点拦截、静态站点和动态反向代理三种典型场景。假设域名www.ipipp.com和ipipp.com指向同一台服务器,api.ipipp.com需要代理到后端服务。

http {
    resolver 223.5.5.5 valid=30s;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    server {
        listen 80 default_server;
        server_name _;
        return 444;
    }
    server {
        listen 80;
        server_name www.ipipp.com ipipp.com;
        location / {
            root /var/www/example;
            index index.html;
        }
    }
    server {
        listen 80;
        server_name api.ipipp.com;
        set $upstream_api backend.internal.ipipp.com;
        location / {
            proxy_pass http://$upstream_api:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

第一个server块使用listen 80 default_server和server_name _,它的作用不是匹配下划线,而是作为默认虚拟主机。当请求的Host头没有命中任何server_name时,Nginx会走到这里并返回444状态码,直接关闭连接。这样可以避免未备案域名或陌生Host头访问到正式站点。

第二个server块同时监听www.ipipp.com和ipipp.com,用于静态站点。第三个server块负责API反向代理,通过变量和resolver实现后端域名的动态解析。实际生产环境中还需要根据情况配置HTTPS证书、HTTP跳转和安全头部,但域名匹配和解析的核心逻辑不变。

四、练习题与解析

几道练习题可以帮助验证对Nginx域名解析配置的理解。先看下面四个问题,再对照解析检查。

问题一:server_name *.ipipp.com能匹配a.b.ipipp.com吗?

问题二:直接写proxy_pass http://backend.ipipp.com:8080;,修改DNS记录后Nginx会立即把流量切到新IP吗?

问题三:请求Host没有匹配任何server_name时,Nginx会怎么处理?

问题四:在proxy_pass中使用变量并配置resolver后,还需要注意什么?

解析一:不能。通配符星号只能代表一段标签,所以*.ipipp.com可以匹配a.ipipp.com,但不能匹配a.b.ipipp.com。解析二:不会立即切换。Nginx会在启动或加载配置时解析并缓存该域名对应的IP,修改DNS后需要重新加载Nginx配置,或者改用resolver加变量方式让Nginx运行时动态解析。解析三:会交给默认server处理。如果没有显式配置default_server,就使用配置文件中的第一个server块。解析四:需要注意URI传递行为的变化,以及resolver的DNS服务器可用性和缓存时间设置,避免解析失败或缓存过久导致后端切换不及时。

五、常见问题与注意事项

配置Nginx域名解析时,有几个高频问题值得提前注意。首先是server_name匹配顺序。很多人配置了通配符和精确域名,结果发现精确域名没有优先生效,排查后发现是server块位置或default_server设置导致的。实际上Nginx有明确的优先级,只要理解精确、通配、正则的顺序,就能快速定位。

其次是DNS与Nginx的缓存叠加。域名A记录修改后,除了DNS服务器自身的TTL缓存,Nginx也可能缓存了proxy_pass中的IP。排查时可以先在服务器上用dig或nslookup确认DNS已经更新,再检查Nginx是否使用了变量形式做动态解析。如果两者都确认无误,还要检查系统DNS缓存和resolver配置中的valid参数。

最后是HTTPS证书与server_name的关系。在TLS握手阶段,Nginx会根据SNI扩展中的域名选择证书,这同样依赖server_name配置。如果证书覆盖的域名和server_name不一致,浏览器会报证书错误。多站点HTTPS场景下,要确保每个server块的server_name与证书SAN或CN字段匹配,必要时为不同域名配置独立证书。

另外,如果Nginx只是作为静态站点服务器,不需要在配置里写DNS解析相关指令;域名解析交给DNS服务商即可。只有反向代理后端使用域名,并且需要动态感知IP变化时,resolver才是必要的。

广告位 · 文章底部(后台-模块管理替换此区域)