域名解析到端口为何无效:Nginx反向代理与四层转发配置指南
上周有位做后端的读者私信我说他把域名解析到了一个 Linux 服务器上但访问时地址栏里那个:8080怎么都去不掉问我域名解析能不能直接指到端口上。说实话这个问题我这些年被问过不下二十次而且问的人里既有刚买云服务器的新手也有写了几年代码、只是没碰过运维的同事。答案有点反直觉域名解析这一步压根就不管端口。DNS 这套体系从设计之初只负责一件事——把人类看得懂的域名翻译成 IP 地址仅此而已。那为什么我们日常见到的https://xxx.com又确实没有端口尾巴因为那是 443 端口做了隐藏前面还站着一个反向代理在替我们转流量。所以把域名解析到指定端口这个需求是真实存在的只是实现它的正确姿势不是改 DNS而是在服务器上做一层转发。这篇就按我自己的实操习惯从原理讲到配置把 Nginx 反向代理、四层转发、SRV 记录、端口占用排查这几条路全部走一遍配置可以直接抄坑我也一并标出来。适合刚上手 Linux 服务器、想让自己项目看起来正规一点的朋友也适合运维顺手补漏。1. 先接受一个反常识的结论DNS 从来不认端口1.1 DNS 查询链路里到底发生了什么很多人对域名解析的印象停留在在控制台填个 IP回车生效。这个印象不能说错但它跳过了中间最关键的几层。完整的解析过程大致是这样你在浏览器里敲下域名并回车浏览器先查自己的缓存再查操作系统的 DNS 缓存再看/etc/hosts有没有手工写死的记录。这几步都没命中请求才会发给操作系统配置的递归解析服务器——也就是resolv.conf里那个 nameserver 地址通常是运营商给的或者你自己指定的公共 DNS。递归服务器拿到查询后如果它也没有缓存就会代替你去逐级问路先找根域名服务器根服务器告诉它去问对应的顶级域服务器顶级域服务器再告诉它去问这个域名的权威域名服务器最后权威服务器返回真正的记录值。整条链路走完递归服务器把结果缓存下来TTL 到期之前同一个域名再来问就直接返回缓存。你可以用dig trace example.com亲眼把这条路走一遍输出会一级一级列出来。重点来了这条链路上无论哪一级返回的记录类型只有 A、AAAA、CNAME、MX、TXT、NS、SRV 这几种。A 记录返回 IPv4 地址AAAA 返回 IPv6 地址CNAME 返回另一个域名MX 管邮件投递TXT 挂各种校验文本NS 指明权威服务器。没有任何一种记录类型里的字段是留给端口的。换句话说DNS 协议本身就没有设计域名指向 8080 端口这种表达能力。1.2 那句解析到端口实际想表达什么把用户的话翻译成技术语言他们的真实诉求通常是这两类一类是我不想在地址栏里看到端口号希望访问app.example.com时能直接打开我跑在 8080 上的服务另一类是我有好几个服务跑在同一台机器上不同端口想用不同子域名分别指过去。这两种需求的共同点是DNS 已经完成了它的工作——域名成功指向了服务器 IP问题出在流量到达服务器之后没有被送到正确的端口上。这里打个生活化的比方。DNS 干的事相当于告诉快递员这个包裹送到某某路 5 号楼至于包裹进了楼以后该放 3 楼还是 8 楼那是楼里电梯和门牌号的事跟快递系统无关。端口就是楼层号它属于传输层的信息由 TCP/UDP 协议头携带DNS 报文里根本没有这个字段。所以我们要做的是在楼里安排一个引导员把所有进楼的包裹按规则送上对应楼层。这个引导员就是反向代理或者端口转发规则。1.3 四条落地路线先摆在一起对比既然改 DNS 无效我们把可行的方案横向摆一下心里先有个谱再动手。下面这张表是我这几年反复用的选型依据注意第三条限制比较多别一上来就往那儿撞。方案适用场景需要条件客户端是否还要带端口复杂度Nginx 反向代理七层网站、API、前后端分离项目装 Nginx有 80/443不需要低Nginx stream / firewalld 端口转发四层SSH、数据库、游戏服、私有协议内核转发开启不需要中DNS SRV 记录SIP、XMPP、部分游戏客户端客户端协议必须支持 SRV看客户端实现高URL 直接带端口访问快速验证、内网环境无需额外配置需要极低看清楚这张表后面的内容就顺了。七层反向代理是绝大多数 Web 场景的最优解因为它不只是转发还能顺手处理 HTTPS 证书、静态资源、请求头、压缩等于花一份力气办好几件事。四层转发解决的是非 HTTP 协议怎么办比如你想让ssh.example.com直接连到服务器这就得靠 stream 模块或者防火墙的 DNAT 规则。SRV 记录是特例中的特例浏览器完全不认它所以做网站的朋友可以直接跳过第三条。至于 URL 带端口那是调试期的临时手段不是最终方案。2. 动手前先摸清地基域名、服务器、端口三件事2.1 A 记录、CNAME 和 TTL 的三分钟速通不管走哪条路第一步永远是让域名正确指向服务器。进入域名注册商的控制台找到 DNS 解析设置新增一条记录记录类型选 A主机记录填app代表app.example.com或者填代表裸域名example.com记录值填服务器的公网 IP。保存之后通常几十秒到几分钟就能生效。这里有个容易被忽略的细节如果你希望www.example.com也能访问需要单独再加一条 A 记录或者加一条 CNAME 指向主域名很多人只加了就开始调服务结果发现 www 打不开白白排查半小时。CNAME 和 A 记录的取舍也值得说一句。A 记录直接指向 IP速度快、层级少CNAME 指向另一个域名好处是主域名换了 IP 时所有 CNAME 记录自动跟着变不用挨个改。我的习惯是裸域名用 A 记录各种业务子域名用 CNAME 指向一个统一的主机名这样以后迁服务器只改一处。TTL 字段控制缓存时长默认六百秒左右调试阶段可以调小到六十秒方便快速验证等服务稳定了再调回大值减少查询压力。顺带提醒一个常见误区改了 DNS 解析本地机器不一定马上生效因为上游递归服务器的缓存还没过期。这时候别急着怀疑配置有问题先用dig 223.5.5.5 你的域名指定一个公共 DNS 查询看返回的 IP 对不对。如果指定的公共 DNS 已经返回新 IP而你自己电脑还是旧 IP那纯粹是本机或运营商缓存的问题等 TTL 到期自然就好。2.2 服务器侧必须先确认的三件事域名这一头搞定转头看服务器。我见过太多人卡在域名能 ping 通但服务访问不了八成是下面三件事没确认。第一件是服务监听地址。用ss -tlnp看一眼你的服务监听在哪个地址上。如果是127.0.0.1:8080那它只接受本机连接外网流量根本进不来——这是新手最常踩的坑尤其是本地开发时图省事写死 localhost 的项目部署上去忘了改。正确的做法是让服务监听0.0.0.0:8080或者直接监听所有网卡。第二件是云服务商的安全组。安全组是云平台层面的第一道墙优先级比系统防火墙还高。默认情况下只有 22 端口SSH是放行的80、443、8080、3000 这些统统要手动加规则。加规则时注意方向选入方向协议选 TCP端口范围可以写单个端口也可以写区间如8000-8100来源建议不要图省事写0.0.0.0/0全开尤其是数据库端口能限制来源 IP 就限制。第三件是系统防火墙。CentOS 系跑 firewalldUbuntu 系一般是 ufw老点的机器可能还在用 iptables。热词里老有人搜centos 防火墙开放 tcp 端口配置文件其实就是想知道 firewalld 怎么加端口。命令不复杂# firewalld 放行 80 和 443 firewall-cmd --permanent --add-port80/tcp firewall-cmd --permanent --add-port443/tcp firewall-cmd --reload # 查看已放行的规则 firewall-cmd --list-all如果是 ufw对应的命令是ufw allow 80/tcp然后ufw reload。别小看这两行它就是很多人安全组开了、服务也起了、就是连不上的最后一道坎。2.3 端口怎么挑才不给自己挖坑选端口这件事看着随意其实有讲究。1024 以下的端口属于特权端口非 root 身份的程序绑不上所以你的服务如果不用 root 启动就只能选 1024 以上。80 和 443 虽然常用但它们是留给 HTTP/HTTPS 标准服务的也就是说如果你打算用 Nginx 做入口那两个端口自然就被 Nginx 占了你的业务服务放到 8080、3000、5000 这类高位端口更合适。注意 macOS 上的 AirPlay 会占用 5000 端口如果你后续用 Mac 做本地调试可能撞车我一般偏向 8080 或者 3000。另外有几个端口是绝对不能随便对外暴露的。MySQL 的 3306、Redis 的 6379、MongoDB 的 27017这些数据库端口一旦暴露到公网快则几小时就会被扫到并尝试爆破。热词里搜索端口被占的人很多搜索nmap 扫描端口命令的也不少我的建议是把 nmap 用在自己的服务器上做个体检nmap -Pn -p 1-10000 你的公网IP看看哪些端口意外地开着。扫描结果里出现数据库端口而你又没主动开放那就要去安全组和防火墙里找原因了。再补一个运维小知识服务器时间不准会引发一堆莫名其妙的故障比如 HTTPS 证书被判定无效、日志时间线错乱、集群节点认证失败。所以新机器上手先配好时间同步指向国内的时间服务器地址同步一下chronyc sources看一眼同步源是否正常。这事跟域名解析没直接关系但属于同一批基础设施体检项顺手做了不亏。3. 方案一Nginx 反向代理Web 场景的最优解3.1 装好 Nginx 并写一份最小可用配置Nginx 在不同发行版的安装方式不太一样。Ubuntu/Debian 系直接apt install nginxCentOS/RHEL 系需要先加 EPEL 源再yum install nginx。国产 Linux 发行版比如麒麟基本也走 yum/dnf 这一套包名一致装完用systemctl enable --now nginx启动并设置开机自启。装完访问一下公网 IP看到 Nginx 的默认欢迎页说明 80 端口这条链路已经通了接下来就是改配置。配置文件的位置各发行版略有差异主配置在/etc/nginx/nginx.conf站点配置通常放在/etc/nginx/conf.d/或者/etc/nginx/sites-available/。我习惯在conf.d/下新建一个以域名命名的文件比如app.example.com.conf写进去server { listen 80; server_name app.example.com; location / { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 300s; } }写完务必执行nginx -t检查语法看到syntax is ok和test is successful再systemctl reload nginx。这一步养成习惯能省掉大量改完没生效还以为是自己写错了的时间。重启和 reload 的区别也顺带说一下reload 是平滑重载不断开已有连接restart 是直接重启会短暂中断服务。生产环境优先用 reload。3.2 逐行拆解那些 proxy_set_header 到底在干嘛配置能跑不等于配置正确。上面那几行proxy_set_header看着像模板套话实际每一行都在解决一个具体问题缺了就出 bug我把它们挨个说清楚。proxy_pass http://127.0.0.1:8080是核心指令意思是把所有匹配到location /的请求转发给本机的 8080 端口。注意这里写的是127.0.0.1因为后端服务和 Nginx 在同一台机器上走回环网卡最快也最安全不用绕公网。proxy_set_header Host $host解决的是后端收到的主机名是错的这个问题。如果不加这行后端程序看到的 Host 头会是127.0.0.1:8080而不是用户实际访问的域名。很多框架会拿 Host 来生成跳转链接或者做域名校验Host 一错就会出现登录后跳回 127.0.0.1、跨域校验失败这类诡异现象。这行基本属于必加项。X-Real-IP和X-Forwarded-For是为了让后端拿到用户真实 IP。经过代理之后后端看到的来源 IP 都是 Nginx 本机地址如果程序里有按 IP 限流、记录访问日志的需求就必须靠这两个头把原始 IP 透传下去。X-Forwarded-Proto则告诉后端用户走的是 http 还是 https避免后端生成混合内容链接被浏览器拦截。proxy_http_version 1.1加上Upgrade和Connection两个头是为了让 WebSocket 能正常工作。默认情况下 Nginx 用 HTTP/1.0 转发不支持长连接升级如果你的项目里有实时推送、聊天、进度条这类功能不加这三行会一直连不上。这套组合拳我一般是作为默认模板直接带上不等到出问题再回头补。3.3 让 443 接管一切顺手上 HTTPS80 端口跑通之后强烈建议把 HTTPS 也配上。原因不只是安全还有一个很实际的体验问题现在浏览器对 http 站点会在地址栏打上不安全标记而且很多前端能力比如定位、摄像头、剪贴板在非安全上下文里直接被禁用。上 HTTPS 之后用户访问https://app.example.com端口更是天然隐形。证书获取有两条路。一条是用 Lets Encrypt 的自动签发工具另一条是用云服务商提供的免费证书下载下来手工配置。我一般推荐前者因为续期全自动省心。签发工具装好之后它会自动读取你 Nginx 配置里的server_name自动申请证书并回写配置全程不用手写。生成的配置大致是这样server { listen 443 ssl; server_name app.example.com; ssl_certificate /etc/nginx/ssl/app.example.com.pem; ssl_certificate_key /etc/nginx/ssl/app.example.com.key; location / { proxy_pass http://127.0.0.1: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; proxy_set_header X-Forwarded-Proto $scheme; } } server { listen 80; server_name app.example.com; return 301 https://$host$request_uri; }第二个 server 块的作用是把所有 http 请求永久重定向到 https这样用户不管怎么输都能落到安全连接上。注意重定向用的是 301浏览器会记住这个规则后续直接走 https减少一次往返。注意证书文件路径要对权限也要对。私钥文件建议设成 600 权限且属主为 rootNginx 用 root 启动 worker 进程时才能读到。如果nginx -t报权限错误八成是私钥权限放太开了或者属主不对。3.4 安全组和防火墙域名通了但服务不通的第一元凶Nginx 配好了证书也装了结果浏览器转圈圈——这时候按顺序掐三处。第一处是安全组去云控制台确认 80 和 443 的入方向规则存在且生效。第二处是系统防火墙用firewall-cmd --list-ports或ufw status看端口是否放行。第三处是服务本身是否在监听ss -tlnp | grep -E :(80|443)能看到 Nginx 的 master 进程就说明它起来了。有个细节值得单独提如果你用的是云厂商的负载均衡或者 CDN 在前、源站在后安全组的来源可能被限制成只允许负载均衡的地址段访问。这种情况下你用自己电脑 curl 直连源站 IP 会失败但通过域名访问又是正常的别被这个现象误导。判断方法是curl -I http://你的公网IP如果直连失败、走域名成功基本可以确定是这个原因。再补充一个 SELinux 相关的坑CentOS 系机器上特别常见。SELinux 默认策略不允许 Nginx 主动向外发起网络连接于是反向代理到本地 8080 时会被拦下来日志里报 permission denied错误码一般是 502。解决办法是放行这个布尔值getsebool -a | grep httpd_can_network setsebool -P httpd_can_network_connect on-P参数表示持久化重启后依然生效。不加-P只是临时打开重启就白干了这个细节很多人会漏。4. 方案二四层转发让 SSH、数据库也能隐藏端口4.1 用 Nginx stream 模块转发 TCP 流量HTTP 场景用七层代理就够了但如果你想让ssh.example.com直接连着登录服务器或者想把数据库端口包装成一个域名那就得用四层转发。Nginx 从 1.9 版本开始内置了 stream 模块能转发 TCP 和 UDP。关键点在于stream 块必须和 http 块平级写在 nginx.conf 的顶层不能塞进 http 里面。这一点和 server 块的写法完全不同新手经常写错位置导致语法检查直接失败。一个典型配置如下stream { upstream sshd_backend { server 127.0.0.1:22; } server { listen 2222; proxy_pass sshd_backend; proxy_timeout 600s; proxy_connect_timeout 10s; } }这份配置的意思是Nginx 监听 2222 端口把所有 TCP 连接转发到本机的 22 端口。用户执行ssh -p 2222 userexample.com就能登录。有人会问那能不能直接让 22 端口对外可以是可以但公网 22 端口每天会被扫描器敲几千次日志里全是爆破记录。换个高位端口再配上限流和密钥登录骚扰量能下降九成以上。proxy_timeout这个参数要留意默认值只有十分钟SSH 挂久了会被切断。如果你要长时间开着终端跑任务调大一些更稳妥。proxy_connect_timeout控制连接后端的超时设短点能让故障暴露更快。4.2 firewalld 和 iptables 的端口转发写法不想装额外模块的话直接用系统自带的防火墙做转发也行。原理是网络地址转换——在数据包进入本机时把目标端口改写成另一个端口。用 firewalld 的写法# 开启转发功能 firewall-cmd --permanent --add-masquerade firewall-cmd --permanent --add-rich-rulerule familyipv4 forward-port port80 protocoltcp to-port8080 firewall-cmd --reload老一点的机器上还在用 iptables对应的规则是# 先确保内核开启转发 sysctl -w net.ipv4.ip_forward1 # 把进入 80 端口的流量重定向到 8080 iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080这里有个非常容易忽略的点iptables 的规则是临时的重启就没了。要持久化得用iptables-save把规则写进配置文件或者装iptables-services用服务方式管理。很多人调通了很开心第二天重启服务器发现又不行了就是栽在这里。另外注意REDIRECT和DNAT的区别。REDIRECT是把流量转到本机的另一个端口适合本机转发DNAT-j DNAT --to-destination 目标IP:端口能把流量转到另一台机器适合做内网跳板。用错指令会出现规则加了但不生效的情况特别是目标地址写成本机公网 IP 时由于回环路径问题效果和预期完全不同。4.3 四层和七层到底该选哪个这两种方式不是替代关系而是分工。七层代理看得懂 HTTP 协议所以能做基于域名的路由、能改请求头、能缓存、能自动配 HTTPS代价是它只能处理 HTTP/HTTPS。四层转发只管搬运字节不关心内容所以任何基于 TCP/UDP 的协议它都能转包括 SSH、MySQL、Redis、自研的二进制协议、游戏服务端等等。我的实际判断标准很简单如果这个服务是给浏览器访问的一律走 Nginx 七层反向代理如果是给专门的客户端连的比如数据库工具、SSH 客户端、游戏客户端走四层转发。同一个域名下既有网页又有 WebSocket七层也能一并处理因为 WebSocket 本质上还是 HTTP 升级来的。只有当你需要同时转发的端口数量很多、协议很杂的时候才考虑上专业的四层负载组件。提示不要用四层转发把数据库端口暴露给公网。即使换了域名、换了端口扫描器照样能发现。数据库远程访问更稳妥的做法是走 SSH 隧道或者限定来源 IP 白名单。5. 方案三SRV 记录和URL 直带端口的真相5.1 SRV 记录能做什么不能做什么SRV 记录是 DNS 里唯一一个能携带端口信息的记录类型格式大致是_service._proto.name TTL IN SRV 优先级 权重 端口 目标主机。看到那个端口字段很多人眼睛一亮——这不就是我想要的吗先别高兴太早。SRV 记录能不能用完全取决于客户端实现认不认它。浏览器不认curl 不认绝大多数的 HTTP 客户端都不认。真正支持 SRV 的是那些在协议规范里明确写了要走 SRV 查询的服务比如部分即时通讯协议、目录服务、Minecraft 客户端等。所以如果你的目标是让域名访问网站不带端口SRV 记录这条路可以直接放弃别浪费时间。它的存在价值是在那些协议层面约定好了的场景里让服务发现更灵活比如同一个域名下多个服务实例按权重分配流量。这属于进阶话题日常做 Web 项目基本用不上。写 SRV 记录时还有两个坑一是主机记录里必须带上服务名前缀和下划线比如_sip._tcp写成别的形式解析不出来二是目标主机最好写完整域名并且以点结尾否则有些解析器会自动追加当前域名后缀导致指向错误的地址。这两点在控制台里没有校验写错了不会报错只会静默失效。5.2 URL 里带端口的正确姿势和它带来的麻烦回到最原始的方式直接访问http://example.com:8080。这种方式确实不需要任何服务器配置域名解析生效 端口放行就能用适合调试期快速验证。但它有几个实实在在的麻烦迟早会逼着你上反向代理。第一个麻烦是端口冲突和记忆负担。项目一多你得记住哪个服务在哪个端口团队协作时天天要复述端口号。第二个麻烦是前端跨域。如果你的页面在 80 端口接口在 8080 端口浏览器会判定为跨域请求需要后端配合配置跨域头多一层不必要的复杂度。第三个麻烦最隐蔽有些第三方服务在回调地址里不接受带端口的 URL比如支付回调、登录回调填了端口直接被拒。这意味着你迟早得挪到标准端口上。还有一个细节值得说清楚HTTP 和 HTTPS 的默认端口不一样浏览器对它们的处理也不同。访问https://example.com:443时浏览器会自动隐藏 443同理http://example.com:80会隐藏 80。有人因此误以为自己解析到端口成功了其实是恰好用了默认端口。换成:8080试试端口号立刻显形。理解这一点你就明白为什么上 Nginx 加 HTTPS 之后端口尾巴自然而然就没了。6. 全链路验证从 dig 到浏览器逐层排查6.1 分层验证法别一出问题就盲改配置我排查这类问题有一套固定顺序从不跳步。整套链路可以拆成六层DNS 解析层、网络可达层、端口监听层、防火墙层、代理配置层、应用层。每一层都有对应的验证命令从下往上依次确认问题出在哪一层立刻就能定位比漫无目的地改配置高效得多。# 第一层解析是否生效 dig short app.example.com dig 223.5.5.5 app.example.com # 第二层网络是否可达 ping -c 3 app.example.com traceroute app.example.com # 第三层端口是否监听 ss -tlnp | grep :8080 ss -tlnp | grep -E :(80|443) # 第四层端口是否放行 firewall-cmd --list-ports nmap -Pn -p 80,443,8080 你的公网IP # 第五层代理是否正常响应 curl -I http://app.example.com curl -v --resolve app.example.com:80:你的公网IP http://app.example.com # 第六层应用是否健康 curl -I http://127.0.0.1:8080这里重点说curl --resolve这个参数它是我最爱用的调试利器。它的作用是强制让 curl 把某个域名解析到指定 IP绕过系统 DNS 缓存。这样你可以立刻验证是不是解析还没生效——如果加了这个参数能访问、不加就不行那百分之百是 DNS 缓存问题跟服务器配置无关。这招能帮你省下无数个怀疑人生的夜晚。6.2 常见故障速查表前面讲了原理这里把高频问题和排查动作整理成表遇到问题直接对号入座按顺序试。现象最可能的原因排查动作域名 ping 不通解析未生效或缓存未过期dig 公共DNS 域名对比结果等 TTLping 通但网页打不开端口未放行或服务未启动ss -tlnp查监听firewall-cmd --list-ports查放行报 502 Bad Gateway后端服务挂了或端口写错curl -I http://127.0.0.1:端口直连验证报 504 Gateway Timeout后端处理超时或死锁调大proxy_read_timeout查后端日志报 403 Forbidden目录权限或 SELinux 拦截查 Nginx 错误日志检查httpd_can_network_connect静态资源 404路径前缀没对上检查location匹配规则和 root 路径走 IP 能访问、走域名不行安全组来源限制或 Host 校验去掉proxy_set_header Host试试WebSocket 连不上缺 Upgrade 相关头补proxy_http_version 1.1和升级头换行符问题导致脚本报错文件是 Windows 换行sed -i s/\r$// 文件名表格里最后一行值得展开说一句。热词里老有人搜linux 解压文件乱码这通常也是换行符或者编码的问题Windows 上传的 shell 脚本带\r换行放到 Linux 上执行会报命令未找到或各种莫名其妙的语法错误。用file命令看一眼文件类型如果是 CRLF 就用sed或者dos2unix转一下问题立刻消失。这类看起来像业务 bug、实际是环境问题的坑在服务器上非常普遍。6.3 我踩过的几个真实坑第一个坑是改完配置忘了 reload。有次我调 Nginx 的转发规则改了三遍都不生效最后发现是只保存了文件没执行重载改的全是磁盘上的配置运行中的进程还在用旧规则。现在我养成习惯任何配置改完先nginx -t再reload两步连着做。第二个坑是Host 头丢失导致重定向跑偏。项目里用了 OAuth 登录走代理之后回调地址总是跳到127.0.0.1查了半天才发现是没设proxy_set_header Host $host后端拿到的 Host 是内网地址于是按内网地址生成了跳转链接。加上那一行之后立刻正常。这个坑很典型凡是涉及根据域名生成链接的功能都要检查 Host 头。第三个坑是端口占用。有次部署新服务启动就报地址已被使用ss -tlnp一查发现是之前一个没清理干净的进程还占着端口。用kill干掉之后又发现它被 systemd 自动拉起来了最后是systemctl stop加禁用才彻底解决。所以遇到端口冲突别只在应用层找从进程和服务两个维度一起查。第四个坑是云服务器重启后转发规则失效。前面提过iptables 规则不持久化用firewall-cmd加的规则如果不带--permanent也一样。我现在加规则一律先用--permanent加最后统一--reload避免重启后一脸茫然。7. 上线之后还要盯住的两件事安全和维护配置跑通只是开始真正让服务稳定的是后续的维护习惯。安全方面有几条底线能不开到公网的端口坚决不开数据库、缓存、消息队列这些组件一律只监听回环地址或者内网网段SSH 尽量改成密钥登录并换个高位端口顺便装个失败登录封禁工具能挡掉绝大部分自动化扫描定期用 nmap 扫一遍自己服务器的公网端口看看有没有意外暴露的服务这个自查动作每个月花五分钟收益极高。代理层面要注意超时参数和连接数限制。默认的proxy_read_timeout是 60 秒遇到耗时较长的接口很容易 504我一般调到 300 秒并配合后端做异步处理。client_max_body_size默认只有 1M上传大文件会直接被拒并返回 413这个参数必须根据业务实际调很多人第一次做文件上传功能都会栽在这里。连接数方面如果并发量上来了还得调整 worker 连接数配置。日志是排障的第一手资料务必要会用。Nginx 的访问日志和错误日志默认在/var/log/nginx/下访问日志能看到每一个请求的来源 IP、状态码和转发目标错误日志能直接指出配置问题。养成习惯出问题的第一时间不是猜而是tail -f跟一下这两份日志答案通常就在里面。应用侧的日志同样重要后端服务日志加上请求 ID 透传能把整条链路的调用串起来。证书续期也是容易被忘掉的一环。自动签发的证书有效期通常是九十天自动续期任务如果因为某种原因失败到期后网站会直接打不开。我的做法是在日历里设个提醒或者写个简单的检测脚本定期检查证书剩余天数少于十五天就告警。这件事平时看不见一旦出事就是全站级别的故障。我个人在实际操作中的体会是所谓把域名解析到端口这件事本质上是个认知问题而不是技术问题。想通了 DNS 只管名字到 IP 的映射剩下的就是选一个合适的引导员——Web 服务交给 Nginx 七层代理其他协议交给四层转发或系统防火墙。配置本身十几行就够真正花时间的是把每一层验证清楚、把每个参数调到位。下次再有人问你这个问题你可以直接把dig和ss -tlnp这两条命令甩过去让他自己看链路断在哪一环。