修复 Nginx 'Connection Refused' 错误:实用故障排除指南
在使用 Nginx 访问其后端服务时,遇到“Connection Refused”(连接被拒绝)错误是一种常见但令人沮丧的经历。与暗示网络延迟或数据包丢失的“Timeout”(超时)错误不同,“Connection Refused”错误是明确的:操作系统立即拒绝了连接尝试,因为在指定的端口和 IP 地址上没有应用程序在主动监听。
这种立即拒绝将问题指向几个关键领域:服务已停止、防火墙在本地阻止了流量,或者配置将流量导向了一个不存在的端口。本指南提供了一个系统的、分为四个阶段的方法来诊断和解决“Connection Refused”错误,确保您能够快速恢复服务连接。
阶段 1:检查 Nginx 服务器状态(主要监听器)
连接被拒绝最根本的原因是 Nginx 服务本身没有运行或配置不当。
1. 验证 Nginx 服务状态
使用您系统的服务管理器(通常是 systemd)来确认 Nginx 处于活动并正在运行。如果此处失败,将直接导致主监听端口(通常是 80 或 443)上的连接被拒绝。
sudo systemctl status nginx
预期输出(成功): 查找 Active: active (running)。
可操作的修复: 如果状态显示 inactive 或 failed,请尝试启动服务并检查日志以获取失败详细信息。
sudo systemctl start nginx
sudo journalctl -xe | grep nginx
2. 确认活动监听端口
使用 ss(socket statistics)或 netstat 工具来验证 Nginx 实际上是否绑定到预期的 IP 地址和端口(例如,0.0.0.0:80 或 127.0.0.1:8080)。
# 使用 ss(在现代 Linux 发行版上首选)
sudo ss -tuln | grep 80
# 使用 netstat
sudo netstat -tuln | grep 80
如果您没有看到 Nginx 相关进程 (PID) 下列出的预期端口(例如 :80 或 :443),则表示 Nginx 绑定失败,这很可能是由于配置错误或另一个服务已占用该端口。
提示: 如果其他服务正在占用端口,您必须要么停止该服务,要么修改 Nginx 配置以监听不同的可用端口。
阶段 2:防火墙和网络配置
如果 Nginx 正在运行并本地监听,则连接拒绝可能发生在服务外部,通常是由于防火墙规则阻止了入站流量。
1. 检查本地服务器防火墙
确保 Nginx 正在监听的端口(例如 80、443)已通过主机的防火墙(UFW、firewalld 或 iptables)明确允许。
UFW 示例 (Ubuntu/Debian)
sudo ufw status verbose
# 如果已关闭,允许端口:
sudo ufw allow 'Nginx Full'
# 或具体地:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Firewalld 示例 (CentOS/RHEL)
sudo firewall-cmd --list-all
# 如果已关闭,添加服务:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
2. 验证云提供商安全组
如果您的服务器托管在云环境(AWS EC2、Azure VM、GCP Compute Engine)中,则连接拒绝可能源于虚拟网络的安全性层。
- AWS 安全组 (SG): 检查关联的安全组,并确保入站规则允许来自源 IP 地址(通常是
0.0.0.0/0用于公共访问)的流量通过端口 80 和 443。 - Azure 网络安全组 (NSG): 验证入站端口规则。
阶段 3:Nginx 配置验证
不正确的配置指令可能导致 Nginx 尝试监听不可用的端口或 IP,从而导致启动失败和随后的连接拒绝。
1. 审查 listen 指令
检查您的主配置文件(通常是 /etc/nginx/nginx.conf)以及任何相关的服务器块(通常在 /etc/nginx/conf.d/ 或 /etc/nginx/sites-enabled/ 中)。确保 listen 指令正确无误。
正确配置的 listen 块示例:
server {
listen 80;
listen [::]:80;
server_name example.com;
# ... other directives
}
如果 Nginx 配置为仅监听 127.0.0.1(localhost),但您尝试使用公共 IP 访问它,则连接将被拒绝。
2. 运行配置语法检查
在重新启动 Nginx 之前,请务必验证配置语法。解析错误将阻止服务启动,从而导致拒绝。
sudo nginx -t
如果测试失败,请修复已识别的错误,重新运行测试,然后重新加载或重新启动 Nginx。
sudo systemctl reload nginx
阶段 4:排查反向代理(上游)问题
如果 Nginx 在端口 80/443 上成功运行,但访问特定路径(/api/)导致“Connection Refused”错误,则问题出在 Nginx 和后端服务(上游)之间。
在这种情况下,Nginx 接受了初始连接,但当它尝试代理请求时,与后端服务的连接被拒绝。错误日志将证实这一点。
1. 检查 Nginx 错误日志
在尝试失败的连接后,立即检查 Nginx 错误日志(通常是 /var/log/nginx/error.log)。查找与 proxy_pass 指令相关的消息,特别是提及连接错误的消息。
tail -f /var/log/nginx/error.log
您可能会看到如下条目:
[error] connect() failed (111: Connection refused) while connecting to upstream
2. 验证后端服务状态
这是代理场景中最常见的修复方法:后端应用程序(例如 Node.js、Python Gunicorn、Apache)已停止运行或未在 Nginx 预期的地方监听。
可操作的步骤:
a. 检查后端服务状态: 确认后端应用程序正在运行。
b. 验证后端监听端口: 在托管后端服务的服务器上使用 ss -tuln 来确认应用程序正在监听 Nginx 的 proxy_pass 指令中指定的 IP/端口。
3. 直接测试后端连接
使用 curl 或 telnet 测试从 Nginx 服务器到后端的连接,以便将问题与 Nginx 分离。
假设您的 proxy_pass 设置为 http://127.0.0.1:8080:
# 测试从 Nginx 服务器到后端端口的连接
curl -v http://127.0.0.1:8080
# 或使用 telnet
telnet 127.0.0.1 8080
- 如果
curl或telnet失败: 后端服务绝对是问题所在(它没有监听,或者其内部防火墙阻止了 127.0.0.1 访问)。 - 如果
curl或telnet成功: 问题可能出在您的proxy_pass指令中的细微错误(例如,缺少分号、不正确的主机名解析,或者协议不匹配——HTTP 与 HTTPS)。
常见的 proxy_pass 错误
确保 proxy_pass 中的 IP 地址与后端实际绑定的地址匹配。如果后端绑定到特定 IP(例如 192.168.1.10:8080),而 Nginx 使用 localhost:8080,则如果绑定是限制性的,连接将会失败。
关键故障排除步骤总结
- 系统检查: Nginx 是否正在运行 (
systemctl status nginx)? - 端口检查: Nginx 是否正在正确的 IP/端口上监听 (
ss -tuln)? - 防火墙检查: 主机防火墙(UFW, iptables)上是否打开了入站端口?
- 配置检查:
nginx -t是否通过,并且listen指令是否正确? - 代理检查(如果适用): 上游服务是否正在运行并监听
proxy_pass中定义的精确 IP/端口?使用curl直接测试连接。
通过遵循这一系统化的过程,您可以快速识别“Connection Refused”错误是由于服务停止、限制性防火墙还是配置错误的反向代理设置造成的,从而最大程度地减少停机时间并高效恢复访问。