要让nginx同时支持内网域名和外网域名访问,核心方案是配置DNS双解析(split-horizon DNS)并在nginx中使用统一的server_name匹配规则,配合合理的监听端口和访问控制策略,即可实现内外网域名指向同一服务但走不同网络路径的效果。
内外网域名访问nginx的核心原理
很多运维新手会遇到一个困惑:明明nginx配置没问题,内网通过http://server.local访问正常,外网通过http://www.example.com访问却超时或报错,这背后其实是DNS解析路径和网络路由两个层面的问题,nginx本身反而只是执行者。
- DNS解析差异:内网DNS服务器会把
server.local解析为内网IP(如192.168.1.10),而外网DNS服务器会把www.example.com解析为公网IP(如203.0.113.5),同一个域名在不同网络环境下指向不同IP,这是”双解析”的核心机制。 - 网络路径差异:外网请求经过公网路由、防火墙NAT映射后到达nginx,内网请求则直接通过局域网交换到达nginx,nginx收到请求后只关心HTTP头部中的Host字段(即域名),并不关心请求是从哪条网线进来的。
- nginx匹配逻辑:无论请求来自内网还是外网,nginx都会根据
server_name指令匹配对应的server块,然后执行相同的location路由规则,所以只要域名解析正确,nginx配置可以完全复用。
行业共识认为,90%以上的内外网访问异常问题,根源不在nginx配置,而是DNS解析不完整或防火墙NAT映射缺失。
nginx内网域名和外网域名双解析怎么配置
要让内外网域名正常访问nginx服务,需要把DNS配置和nginx配置作为一个整体来设计,下面按步骤拆解。
第一步:规划域名解析方案
有两种主流做法,根据企业实际网络环境选择:
- 方案A:同一域名,多IP解析,内网DNS把
www.example.com解析为内网IP,外网DNS把同一域名解析为公网IP,优点是用户不用记两个域名,缺点是内网用户访问时流量不会经过防火墙NAT,公网IP的端口映射只对外部生效,需要在nginx层面区分来源做访问控制。 - 方案B:不同域名,内网专属子域名,例如内网用
intra.example.com,外网用www.example.com,两个域名都指向同一个nginx服务器(通过内网IP和公网IP分别到达),优点是通过域名天然区分访问入口,便于日志分析和权限隔离,缺点是用户需要记住两个地址。
推荐生产环境使用方案A,因为用户心智最简单,且nginx可以借助$remote_addr变量判断来源IP段,一步完成场景区分。
server {
listen 80;
server_name www.example.com;
location / {
# 内网IP段直接放行
allow 192.168.1.0/24;
allow 10.10.0.0/16;
deny all; # 其余来源(即外网)需要额外鉴权
proxy_pass http://backend_service;
}
}
第二步:确认nginx监听配置不阻塞回环
nginx默认监听0.0.0:80,即所有网卡地址,但要确认配置文件中没有误写为具体IP,比如listen 192.168.1.10:80,那样公网IP的请求即使到了服务器也无法进入nginx,正确的监听写法:
# 默认监听所有IPv4/IPv6地址 listen 80; listen [::]:80; # 如使用HTTPS,同理 listen 443 ssl; listen [::]:443 ssl;
第三步:配置server_name匹配规则
nginx匹配server_name的优先级是:精确匹配 > 最长通配符前缀匹配 > 最长通配符后缀匹配 > 正则匹配 > 默认server,内外网域名配置建议:
# 内网域名专用配置块(可放置于本配置或单独conf文件)
server {
listen 80;
server_name server.local intra.example.com;
# 内网专属优化:禁用缓存、直连后端
proxy_cache off;
proxy_pass http://127.0.0.1:8080;
}
# 外网域名专用配置块
server {
listen 80;
server_name www.example.com example.com;
# 外网入口:启用压缩、缓存、WAF等
gzip on;
proxy_cache my_cache;
proxy_pass http://127.0.0.1:8080;
}
第四步:配置内网白名单与外网访问隔离
如果你的服务对内外网暴露的功能差异较大(比如内网能看管理后台,外网只能看静态页面),可以在同一个server块里用location配合if实现分流:
server {
listen 80;
server_name www.example.com;
location /admin {
allow 192.168.0.0/16;
allow 10.0.0.0/8;
deny all;
proxy_pass http://admin_backend;
}
location / {
proxy_pass http://public_backend;
}
}
这里的关键是allow和deny的顺序:nginx按从上到下顺序匹配,先放行内网段,最后拒绝所有其他来源,外网普通用户只能访问下的资源,无法触碰/admin路径。
外网访问不了nginx内网域名是什么原因
即使nginx配置完全正确,实际部署中仍然会遇到”外网访问不了内网域名”的情况,下面按排查优先级列出最常见原因。
NAT映射遗漏或端口不一致
外网用户访问www.example.com:80时,请求先到达路由器或云安全组,若只映射了22端口(SSH)而忘记映射80/443端口,nginx收不到任何请求,排查命令:
# 在nginx服务器上执行,观察外网IP的80端口是否有SYN请求进来 tcpdump -i eth0 port 80
若完全没有输出,说明请求根本没到服务器,问题出在防火墙或NAT。云服务器需要在安全组入方向放行80/443端口,物理服务器则检查iptables规则:
iptables -L -n | grep :80
nginx默认server块抢占请求
如果配置文件中有多个server块,且没有一个server_name与外网域名精确匹配,请求会落到default_server,很多默认配置的default_server会返回404或403,排查方法:
nginx -T | grep server_name # 查看所有域名 nginx -T | grep default_server # 查看默认入口
建议行为:为外网域名设置一个独立的、配置完整的server块,避免与其他配置混淆。
DNS解析缓存导致内外网IP错乱
内网用户在切换网络环境(如从公司内网切到家中网络)后,系统DNS缓存可能还保留内网IP,导致访问超时,内网DNS服务器如果没有配置正确的转发器,外网用户查询域名时可能拿到内网IP从而路由失败,验证命令:
# 在外部网络环境执行,确认返回公网IP nslookup www.example.com 8.8.8.8 # 在内网执行,确认返回内网IP nslookup www.example.com 192.168.1.1
nginx监听IPv6但公网未分配地址
现代nginx默认同时监听IPv6([::]:80),若服务器公网只有IPv4,而DNS解析返回的是IPv6地址,外网访问会失败,此时需要显式关闭IPv6监听:
listen 80; # 不写 listen [::]:80 即可
或用ip -6 addr确认服务器是否有IPv6地址,没有就不配置IPv6监听。
负载均衡或CDN层面的回源地址限制
如果外网域名接了CDN或云负载均衡,nginx看到的$remote_addr是CDN节点的IP,而不是真实用户IP,此时若nginx配置了内网IP白名单,CDN回源请求会被nginx拒绝,解决方法是配置set_real_ip_from信任CDN回源IP段:
set_real_ip_from 100.64.0.0/10; # 简米云CDN回源IP段示例 real_ip_header X-Forwarded-For;
内外网共用nginx服务的进阶优化配置
在基础双解析跑通后,可以进一步优化nginx配置,让内外网访问体验更好、更安全。
内网域名访问启用HTTP/2,外网强制HTTPS
内网用户直连IP+HTTP/2有性能损耗但可接受,外网用户必须走证书加密:
# 内网HTTP/2配置
server {
listen 80 http2;
server_name intra.example.com;
# 内网不走TLS,性能优先
location / {
proxy_pass http://127.0.0.1:8080;
}
}
# 外网HTTPS配置
server {
listen 443 ssl http2;
server_name www.example.com;
ssl_certificate /etc/nginx/certs/wildcard.example.com.pem;
ssl_certificate_key /etc/nginx/certs/wildcard.example.com.key;
# 强制HSTS,提升外网安全评级
add_header Strict-Transport-Security "max-age=31536000" always;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
内外网域名对应不同后端服务版本
有些团队希望内网体验最新开发版,外网稳定版,可以在nginx中做基于域名的路由分流:
upstream dev_backend {
server 10.10.1.20:8080; # 开发环境
}
upstream prod_backend {
server 10.10.1.30:8080; # 生产环境
}
server {
listen 80;
server_name intra.example.com www.example.com;
location / {
if ($host = "intra.example.com") {
proxy_pass http://dev_backend;
break;
}
proxy_pass http://prod_backend;
}
}
注意:nginx的if在location内使用时需要配合break,避免发生异常重写,实际生产环境中更推荐拆分为两个server块分别配置,可读性和维护性更好。
内外网访问日志分离
为便于审计和问题排查,可以将内外网请求日志写入不同文件:
server {
listen 80;
server_name intra.example.com;
access_log /var/log/nginx/intra_access.log;
error_log /var/log/nginx/intra_error.log;
# ...
}
server {
listen 80;
server_name www.example.com;
access_log /var/log/nginx/public_access.log;
error_log /var/log/nginx/public_error.log;
# ...
}
关于nginx内外网域名配置的真实场景避坑
配置在大多数情况下能直接解决问题,但有一类特殊场景容易踩坑:
公司同时有多个公网IP出口,且内网访问外网域名时经过出口NAT,此时如果用户访问www.example.com,请求会先到内网网关→NAT成公网IP→回到防火墙→再到nginx,nginx看到的就是公网IP,allow内网段配置失效,这时需要用nginx的geo模块结合内网出口IP段判断:
geo $trusted_client {
default 0;
192.168.1.0/24 1;
10.10.0.0/16 1;
# 若内网用户经NAT访问,需定义出口网关IP段
203.0.113.0/24 1;
}
server {
listen 80;
server_name www.example.com;
if ($trusted_client = 1) {
# 内网用户逻辑
set $backend http://dev_backend;
}
if ($trusted_client = 0) {
set $backend http://prod_backend;
}
proxy_pass $backend;
}
使用宝塔面板或AMH等控制面板时,nginx配置修改后会被面板覆盖,务必通过面板的”配置文件”入口修改,而非直接操作/etc/nginx目录,宝塔的面板也提供域名绑定功能,但内外网双解析仍建议手工改配置,面板自动生成规则比较简单粗暴。
如果你的nginx版本较旧(低于1.18),对listen ... http2的支持存在差异,旧版本需要用listen 443 ssl;再加http2 on;指令,否则可能报不识别参数的错误,可以在服务器上执行nginx -v查看当前版本。
从整体运维成本角度考虑,内外网域名双解析方案是一次配置、长期受益的,相比在代码里硬编码IP、在不同网络环境切换hosts文件,这种方案的扩展性和可维护性都要好得多。DNS双解析配合nginx统一入口,可以让内外网差异化需求在反向代理层集中解决,后端服务只需关心业务逻辑,不必感知网络环境差异,这也是当前主流的混合云部署方案中推荐的实践路径。
常见问题解答
问:nginx内网域名和外网域名可以配置同一个HTTPS证书吗?
可以,只要证书的SAN(Subject Alternative Name)字段同时包含内网域名和外网域名,或者使用通配符证书(如.example.com),nginx的多个server块即可复用同一份证书文件,如果内网域名是.local结尾的私有域,则无法申请公开受信任的证书,建议内网使用自建CA或HTTP明文(内网环境风险可控),行业共识是:内外网域名尽量使用同一主域名下的二级域名,例如www.example.com(外网)和intra.example.com(内网),这样申请一张通配符证书就能覆盖两个域名,申请证书时需要确保该域名可以通过公网DNS验证所有子域名的归属权。
问:修改nginx配置后如何平滑重载不掉线?
执行nginx -t检查配置语法无误后,使用nginx -s reload进行平滑重载,该命令会启动新的worker进程处理新连接,旧worker进程在完成当前请求后自动退出,不会中断正在进行的HTTP长连接,内网域名和外网域名共享nginx进程时,这个操作也不会影响任何请求,注意:修改listen端口或调整worker_processes等核心参数时,reload可能无法完全生效,需重启nginx,但内外网域名配置只涉及server_name和location层面的调整,reload是安全的。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/612981.html





