Nginx配置通用反向代理指定域名到指定服务

前言

首先我们先看一下要达到的效果,我们希望访问某一个域名自动指向本地启动的某一个端口的服务(我们就以域名 <number>.localapp.com 为例),效果如下:

8080.localapp.com => 127.0.0.1:8080
8081.localapp.com => 127.0.0.1:8081

接下来大家可能会说为什么要这么做呢,直接访问 http://127.0.0.1:8080 不好吗,非得转一层呢?下面就是好处:

1、解决 cookie 共享的问题

我们直接访问 http://127.0.0.1:8080 是拿不到 localapp.com 下面的 cookie 的,有部分网站的授权是通过 cookie 实现的,当然这个也可以通过 本地配置 host + webpack proxy 实现,但是需要在每个项目中都这样配置。

2、解决跨域的问题

在前后端分离的开发模式中,一般情况前端和服务端一般会使用不同域名。假如 http://localapp-api.com 这个是接口服务器域名,这个服务只允许 *.localapp.com 域名访问时,我们就只能通过 本地配置 host + webpack proxy 中的方式去配置,同样在每个项目都需要修改。如果项目中使用到了 OSS 并且开启了防盗链,OSS 也会去校验域名,导致 OSS 中的资源会加载失败。

3、配置本地 https 证书

如果使用 http://127.0.0.1:8080 访问,是不好配置 https 证书的,访问的时候也就会出现证书错误警告,首先是对开发不友好,如果我们想在手机端有些 app 的 webview 调试页面,那必须要用 https,如果配置了证书,就可以方便的调试。还有一点大家可能发现了,http 服务是拿不到 https 服务下面的 cookie 的。

4、同时启动多个项目

如果我们通过 本地配置 host + webpack proxy 来解决上面的问题,那我们必须要将服务在80或者443上启动,所以无法同时调试多个项目。

实施方案

下面内容主要包含如下:

  • 搭建本地的 DNS 服务器,进行域名解析,将 <number>.localapp.com 指向 127.0.0.1
  • 配置配置 nginx 反向代理实现域名指向指定端口

运行流程如下

pasted-20230905224950

搭建DNS服务器

首先我们要知道为什么要搭建 DNS 服务器呢,而不是直接将域名指向 hosts 呢?是因为 hosts 文件不支持通配符,那么每个端口就需要写一条记录,添加了新的端口就需要添加新的记录,如下:

127.0.0.1 8080.localapp.com
127.0.0.1 8081.localapp.com
127.0.0.1 8082.localapp.com
127.0.0.1 8083.localapp.com

这里我们使用 dnsmasq 来搭建 DNS 服务器,该软件可以运行在 linux/macOS 等操作系统上,以 macOS 为例,我们可以直接使用 brew 进行安装(linux 可以使用内置的 apt 或者 yum 工具进行安装)。

brew install dnsmasq

安装完成修改配置添加 DNS 解析规则,配置文件位置在 $HOMEBREW_PREFIX/etc/dnsmasq.conf ,我们可以使用 VSCode 或者 vim 进行修改。

要添加上面的解析,需要在配置文件中追加下面的内容,这条内容表示 .localapp.com 都解析到 127.0.0.1 ,当然这里也可以指向局域网的其他 IP 实现解析。

# 如果仅仅给自己使用的话,就用 127.0.0.1,否则的话可以加上局域网的IP地址,使用逗号分开
listen-address=127.0.0.1,192.168.1.6
# 注意下面的规则仅匹配 abc.localapp.com 不能匹配,abc.def.localapp.com
address=/.localapp.com/127.0.0.1

修改完成之后,重新启动一下 DNS 服务器即可;

# 这里要使用sudo,否则可能会不生效,不加sudo执行时,控制台也会给出警告
sudo brew services restart dnsmasq

配置DNS解析

DNS 服务器搭建完成之后,我们还需要修改下本地网络 DNS 解析,以 macOS 为例:

pasted-20230905215212

需要将 127.0.0.1 这个 DNS 放到第一位,保存网络后,在本地终端 ping 的时候就会发现下面的域名都指向了 127.0.0.1。

ping 123.localapp.com
ping 456.localapp.com
ping abc.localapp.com

配置反向代理

1、首先我们在 nginx 中创建一个配置文件如 proxy.localapp.conf ,然后将 server_name 设置为正则表达式,具体内容如下所示:

server {
    listen 80;
    server_name ~^(?<port>\d+)\.localapp\.com$;
    location / {
            # 代理到本地的端口上
            # 8000.local.com => 127.0.0.1:8000
            # 9000.local.com => 127.0.0.1:9000
            proxy_pass http://127.0.0.1:$port;
            proxy_set_header Host $host;
            client_max_body_size 50m;
            proxy_redirect off;
            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 Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_pass_header Sec-Websocket-Extensions;
            index index.html index.htm;
    }
}

配置说明:

  • server_name: 该域名匹配 1~n 个数字开头的域名,并且将这段数字提取后存储在变量 port 中,例如 8080.localapp.com 中 port=8080。
  • proxy_pass: 直接转发到本地127.0.0.1监听的某一个端口号上。
  • proxy_set_header: 设置代理请求的头信息,用于真实的目标服务器一些 header。例如设置了 Host 为 $host,在 http://127.0.0.1:8080 这台服务器中得到的 Host 就是 8080.localapp.com 而不是 127.0.0.1:8080。

2、重新加载 Nginx 配置以使更改生效

nginx -s reload

测试

现在在 8080 端口上启动一个 webpack devServer,然后使用 8080.localapp.com 去访问发现就可以正常使用了。

常见问题

1、要是发现配置的 dns 无效,可以检查是否开启了 clash,需要把域名规则在 clash 中排除

留下回复