抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

在使用 Nginx 作为反向代理或 Web 服务器时,通常会配置多个 server 块来监听同一个端口(例如 443),并根据 server_name 区分不同的服务。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server {
listen 443 ssl;
server_name mall.example.com;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private.key;

location / {
proxy_pass http://mall_backend;
}
}

<!--more-->

server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private.key;

location / {
proxy_pass http://api_backend;
}
}

在这种情况下,Nginx 会根据请求的 Host 头将流量路由到对应的 server 块。然而,如果直接通过 IP:443 访问(例如 https://<IP>:443),Nginx 无法通过 server_name 区分请求,因此默认会使用第一个匹配的 server

本文将探讨如何通过 IP:443 访问 Nginx 中的多个服务,并确保请求能够正确路由到对应的 URI。

问题分析

当通过 IP:443 访问时,Nginx 无法获取 Host 头信息(因为请求中没有域名),因此无法根据 server_name 区分请求。此时,Nginx 会使用默认的 server 块(通常是配置文件中第一个定义的 server 块)。

为了确保通过 IP:443 访问时能够正确路由到不同的服务,我们需要采取以下方法之一:

方法 1:为 IP 访问添加默认的 server

在 Nginx 配置中添加一个默认的 server 块,专门处理通过 IP 访问的请求,并根据 URI 路径路由到不同的后端服务。

示例配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 默认处理 IP 访问的 server 块
server {
listen 443 ssl default_server;
server_name _; # _ 表示匹配所有未明确指定的域名
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private.key;

# 根据 URI 路由到不同的 location
location /mall/ {
proxy_pass http://mall_backend; # 指向 mall.example.com 的后端
}

location /api/ {
proxy_pass http://api_backend; # 指向 api.example.com 的后端
}
}

# 处理 mall.example.com 的 server 块
server {
listen 443 ssl;
server_name mall.example.com;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private.key;

location / {
proxy_pass http://mall_backend;
}
}

# 处理 api.example.com 的 server 块
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private.key;

location / {
proxy_pass http://api_backend;
}
}

说明:

  • 第一个 server 块使用 server_name _; 捕获所有未匹配的请求(包括通过 IP 访问的请求)。
  • 通过 location 块根据 URI 路径(如 /mall//api/)将请求路由到不同的后端服务。

客户端访问示例:

1
2
curl https://<IP>:443/mall/
curl https://<IP>:443/api/

方法 2:使用 Host 头手动指定域名

如果无法修改 Nginx 配置,可以通过在客户端请求中手动指定 Host 头来模拟域名访问。

示例:

1
2
curl -H "Host: mall.example.com" https://<IP>:443
curl -H "Host: api.example.com" https://<IP>:443

说明:

  • 客户端在请求中手动添加 Host 头,Nginx 会根据 Host 头的值选择对应的 server 块。
  • 即使通过 IP 访问,也能正确路由请求。

方法 3:修改本地 Hosts 文件

通过修改客户端的 hosts 文件,将域名解析到服务器的 IP 地址。这样,客户端可以通过域名访问,而 Nginx 会根据 server_name 正确路由请求。

步骤:

  1. 打开客户端的 hosts 文件:
    • Windows: C:\Windows\System32\drivers\etc\hosts
    • Linux/Mac: /etc/hosts
  2. 添加以下内容:
    1
    2
    <IP> mall.example.com
    <IP> api.example.com
  3. 保存文件并刷新 DNS 缓存:
    • Windows: 运行 ipconfig /flushdns
    • Linux/Mac: 运行 sudo systemd-resolve --flush-cachessudo dscacheutil -flushcache
  4. 现在可以通过域名访问:
    1
    2
    curl https://mall.example.com
    curl https://api.example.com

方法 4:使用 curl--resolve 参数

如果不想修改 hosts 文件,可以使用 curl--resolve 参数手动指定域名解析的 IP 地址。

示例:

1
2
curl --resolve mall.example.com:443:<IP> https://mall.example.com
curl --resolve api.example.com:443:<IP> https://api.example.com

说明:

  • --resolve 参数会强制将域名解析为指定的 IP 地址。
  • Nginx 会根据 Host 头正确路由请求。

方法 5:使用自定义 DNS 服务器

如果有权限设置自定义 DNS 服务器,可以将域名解析到指定的 IP 地址。这样,所有客户端都可以通过域名访问。

步骤:

  1. 在 DNS 服务器中添加以下记录:
    1
    2
    mall.example.com A <IP>
    api.example.com A <IP>
  2. 将客户端的 DNS 服务器设置为自定义 DNS 服务器。

总结

通过以上方法,可以在 Nginx 中实现通过 IP:443 访问多个服务,并确保请求能够正确路由到对应的 URI。具体方法的选择取决于你的需求和环境:

  • 临时测试:推荐使用 curl --resolveHost 头方法。
  • 长期使用:推荐修改 hosts 文件或设置自定义 DNS 服务器。
  • 无需域名:可以通过 Nginx 的默认 server 块和 URI 路径路由请

评论