彻底解决 Nginx 502 错误与跨域困扰:从根源到优化的全流程指导

开发 开发工具
Nexus 是一个强大而灵活的仓库管理工具,广泛应用于 DevOps 和软件开发团队。无论是托管内部构件、代理公共仓库,还是作为 Docker 镜像仓库,Nexus 都能提供高效的解决方案。同时,它与 CI/CD 工具集成良好,是现代软件开发流程中不可或缺的组件。

引言

前几天公司让搭建一个 Nexus 做一个私服。

先简单介绍下为什么要搭建这个服务:

Nexus 是一个强大而灵活的仓库管理工具,广泛应用于 DevOps 和软件开发团队。无论是托管内部构件、代理公共仓库,还是作为 Docker 镜像仓库,Nexus 都能提供高效的解决方案。同时,它与 CI/CD 工具集成良好,是现代软件开发流程中不可或缺的组件。

最主要的是可以将我们开发相关的包放进去。

这边的 Nexus 是使用 Docker-Compose 直接部署了一个。

version: '3'
services:
  nexus3:
    restart: unless-stopped
    image: sonatype/nexus3:latest
    build: .
    container_name: nexus3
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 8081:8081
    volumes:
      - /data/nexus/data:/nexus-data

访问的时候,直接 IP 地址加端口。但是这样的方式在浏览器中不是很友好,于是加上了域名解析,使用域名加端口,哈哈,很有意思吧。但是后面又觉得不安全,决定使用 SSL 证书访问,那就整呗。

开始

决定使用 Yum 在本地安装一个算了,创建一个 /etc/nginx/certs 目录,然后把 SSL 证书放进去。

然后这边主要是说一下 Nginx 的配置:

# /home/user/nginx/conf/nginx.conf

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    keepalive_timeout  65;

    # 启用 Gzip 压缩
    gzip  on;
    gzip_disable "msie6";

    # 定义后端服务的 upstream
    upstream backend {
        server 8.209.247.131:8081;   # 后端服务地址
    }

    # HTTP 服务器 - 处理 ACME Challenge 并重定向到 HTTPS
    server {
        listen 80;
        server_name nexus.test.com;

        # 配置 ACME Challenge 的路径
        location /.well-known/acme-challenge/ {
            root /usr/share/nginx/html;
        }

        # 将所有其他 HTTP 请求重定向到 HTTPS
        location / {
            return 301 https://$host$request_uri;
        }
    }

    # HTTPS 服务器
    server {
        listen 443 ssl;
        server_name nexus.test.com;

        # SSL 证书和私钥路径
        ssl_certificate /etc/nginx/certs/test.com.pem;
        ssl_certificate_key /etc/nginx/certs/test.com.key;

        # SSL 协议和加密套件配置
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';

        # 启用 HSTS
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

        # SSL 会话缓存和超时
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;

        # 日志配置
        access_log /var/log/nginx/access.log main;
        error_log /var/log/nginx/error.log warn;

        # 反向代理设置
        location / {
            proxy_pass http://backend;
            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;

            # 支持 WebSocket
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }

        # 可选:额外的安全头部
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
    }

    # 可选:其他服务器块或配置
}

然后重载上面的配置 :

systemctl reload nginx

访问:

图片图片

看起来是可以访问到,但是没有访问到后端服务 Nexus,这是什么情况呢。

来看下日志吧,看看有什么线索没:

10.23.45.67 - - [31/Dec/2024:10:01:09 +0800] "GET /favicon.ico HTTP/1.1" 502 559 "https://nexus.test.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
12.34.56.78 - - [31/Dec/2024:10:08:38 +0800] "GET /favicon.ico HTTP/1.1" 502 559 "https://nexus.test.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
15.67.89.90 - - [31/Dec/2024:10:13:17 +0800] "GET /favicon.ico HTTP/1.1" 502 559 "https://nexus.test.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"

2024/12/31 10:00:37 [error] 24090#0: *23 connect() failed (110: Connection timed out) while connecting to upstream, client: 10.23.45.67, server: nexus.test.com, request: "GET /favicon.ico HTTP/1.1", upstream: "http://12.45.67.89:8081/favicon.ico", host: "nexus.test.com", referrer: "https://nexus.test.com/"
2024/12/31 10:08:38 [error] 24226#0: *29 connect() failed (110: Connection timed out) while connecting to upstream, client: 12.34.56.78, server: nexus.test.com, request: "GET /favicon.ico HTTP/1.1", upstream: "http://23.56.78.90:8081/favicon.ico", host: "nexus.test.com", referrer: "https://nexus.test.com/"
2024/12/31 10:13:17 [error] 24226#0: *33 connect() failed (110: Connection timed out) while connecting to upstream, client: 15.67.89.90, server: nexus.test.com, request: "GET /favicon.ico HTTP/1.1", upstream: "http://34.67.89.12:8081/favicon.ico", host: "nexus.test.com", referrer: "https://nexus.test.com/"

还是看不出来具体的错误,大佬们有经验的可以先思考下。


经过一番排查,误以为是和 VPN 有关系,于是,想了半天,要不然试试 127.0.0.1。

试下,我这里选择更改我的 upstream 的地址:

# /home/user/nginx/conf/nginx.conf

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    keepalive_timeout  65;

    # 启用 Gzip 压缩
    gzip  on;
    gzip_disable "msie6";

    # 定义后端服务的 upstream
    upstream backend {
        server 127.0.0.1:8081;   # 后端服务地址
    }

    # HTTP 服务器 - 处理 ACME Challenge 并重定向到 HTTPS
    server {
        listen 80;
        server_name nexus.test.com;

        # 配置 ACME Challenge 的路径
        location /.well-known/acme-challenge/ {
            root /usr/share/nginx/html;
        }

        # 将所有其他 HTTP 请求重定向到 HTTPS
        location / {
            return 301 https://$host$request_uri;
        }
    }

    # HTTPS 服务器
    server {
        listen 443 ssl;
        server_name nexus.test.com;

        # SSL 证书和私钥路径
        ssl_certificate /etc/nginx/certs/test.com.pem;
        ssl_certificate_key /etc/nginx/certs/test.com.key;

        # SSL 协议和加密套件配置
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';

        # 启用 HSTS
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

        # SSL 会话缓存和超时
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;

        # 日志配置
        access_log /var/log/nginx/access.log main;
        error_log /var/log/nginx/error.log warn;

        # 反向代理设置
        location / {
            proxy_pass http://backend;
            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;

            # 支持 WebSocket
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }

        # 可选:额外的安全头部
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
    }

    # 可选:其他服务器块或配置
}

搞笑了,这波操作,属实是给我弄的不想说什么了,哈哈,但是又有新的问题了,我们接着看

又有新的错误了:

图片图片


排查了会儿,新的问题是 跨域问题(CORS)。

1. "Uncaught SecurityError" 表明浏览器阻止了对 nexus.test.com 的跨域访问。

2. Blocked a frame with origin 表示 Nexus 的前端代码试图访问另一个域或协议(可能是 HTTP 而非 HTTPS,或子域不匹配)。

原因分析

1.协议或域名不一致:

• Nexus 的资源(如静态文件或 API 请求)可能仍指向 HTTP,而您使用的是 HTTPS。

• Nexus 的前端代码试图访问外部的资源,但浏览器将其视为跨域。

2.Nginx 配置问题:

• Nginx 的反向代理可能没有正确设置 CORS 相关头部,导致资源加载失败。

解决方法

更新 Nginx 配置以支持 CORS

为 Nginx 添加 CORS 支持,允许 Nexus 的前端和 API 资源在同一个域下工作。

在 Nginx 的 location / 配置中,添加以下内容:

location / {
·····
    # 添加 CORS 头部
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
    add_header Access-Control-Allow-Headers "Origin, Authorization, Accept, Content-Type";
·····
}

重新加载 Nginx:

systemctl reload nginx

再次访问:

图片图片

可以看到,没有问题了。

结语

经过这一次的故障排查,又加深了我对 Nginx 的学习。

因为啥呢,工作这边很少会有去部署一个 Nginx,然后去配置相应的参数,真的很少。但是当有这种情况,你又不能说不会,或者不干。在这个排查的过程中,当时排查的真的有点泄气,但是总归还是过来了。

责任编辑:武晓燕 来源: 云原生运维圈
相关推荐

2010-03-29 17:46:39

Nginx asp

2012-12-17 11:07:22

虚拟机快照虚拟服务器备份

2010-11-17 09:48:07

Nginx 502错误

2010-03-24 18:19:42

Nginx php

2019-04-10 10:32:16

CORSNginx反向代理

2018-08-14 11:44:23

数据库MySQLMySQL 8.0

2010-03-26 18:41:51

Nginx 502错误

2021-04-27 15:20:41

人工智能机器学习技术

2021-03-13 21:00:30

电脑PC电脑弹窗广告

2009-11-27 10:31:02

GPRS路由

2022-10-08 23:55:58

iOS苹果开发

2021-12-03 12:15:01

QT中文乱码Windows

2024-02-27 08:14:51

Nginx跨域服务

2010-01-04 15:05:53

2009-02-11 09:35:00

DHCP服务器故障

2021-05-18 09:06:19

零信任邮件安全安全威胁

2021-02-18 08:22:26

KubernetesDocker镜像

2009-12-21 14:12:30

路由器配置故障

2018-09-18 11:28:01

2023-02-27 08:08:54

Pulsar源码重复消费
点赞
收藏

51CTO技术栈公众号