解决AMH面板lngx(NGINX)与FRP反代80/443端口限制下的域名访问问题?

提一个及其特殊的情况下,amh面板的lngx+FRP反代80、443端口的问题
注:amh面板的lngx就是Linux+Nginx+X,其中X为未限定

前提描述:

  1. A机器部署frps, http和https监听80 443端口,nginx配置不可修改,且仅能新建两条隧道(80 443)
  2. 通配符域名*.a.cn指向A机器的CNAME
  3. B机器无法直接访问80 443端口,部署了AMH面板的lngx,然后lngx部署通配符域名站点*.a.cn和业务站点b.cn(本地ip 127.0.0.1:1000),然后通过FRPC监听本地的127.0.0.1:80 和127.0.0.1:443
  4. 域名b.cn指向B机器的IP
  5. frp隧道已通,其他任意的xxx.a.cn可以访问到frp的页面

问题需求:
如何通过直接访问域名:b.a.cn,实现直接访问B机器上b.cn的效果?
同理,实现直接访问c.a.cn的效果

尝试

目前可行的方法一:
直接新建一个frp隧道b.a.cn,直接代理B机器的1000端口,但是这个方法肯定要多一条隧道,不满足第一点仅能80 443两条隧道的方法

方法二:修改B机器的nginx
首先B机器lngx站点*.a.cn直接监听80端口
其次直接修改站点*.a.cn的nginx配置文件:

server {
    listen 80;
    server_name *.a.cn;

    # 处理 b.a.cn 请求
    if ($host = "b.a.cn") {
        proxy_pass http://127.0.0.1:1000;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }

    # 处理 c.a.cn 请求
    if ($host = "c.a.cn") {
        proxy_pass http://127.0.0.1:1001;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }

    # 处理其他请求
    location / {
        proxy_pass http://127.0.0.1:80;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }

    access_log /home/wwwroot/Lngx01/logs/*.z.taor.site-access.log;
    error_log /home/wwwroot/Lngx01/logs/*.z.taor.site-error.log crit;
}

但没有成功,虽然frp页面可以
请教各位大佬,此时我应该如何调整实现需求?

阅读 1.1k
avatarAI BotBETA

在您的场景中,由于FRP服务器(A机器)的端口限制(仅能使用80和443端口),并且B机器上的Nginx(lngx)需要处理多个基于域名的反向代理,但又不希望增加额外的FRP隧道,我们可以考虑以下解决方案:

解决方案

  1. 修改B机器上的Nginx配置
    由于您已经尝试使用if语句在Nginx中根据$host变量进行代理,但这种方法通常不推荐用于性能原因,并且可能不总是按预期工作。更好的方法是使用server_name来区分不同的服务器块(server blocks)。

    修改Nginx配置如下:

    server {
        listen 80;
        server_name b.a.cn;
    
        location / {
            proxy_pass http://127.0.0.1:1000;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
        }
    
        access_log /home/wwwroot/Lngx01/logs/b.a.cn-access.log;
        error_log /home/wwwroot/Lngx01/logs/b.a.cn-error.log crit;
    }
    
    server {
        listen 80;
        server_name c.a.cn;
    
        location / {
            proxy_pass http://127.0.0.1:1001;  # 假设c.a.cn对应的是1001端口
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
        }
    
        access_log /home/wwwroot/Lngx01/logs/c.a.cn-access.log;
        error_log /home/wwwroot/Lngx01/logs/c.a.cn-error.log crit;
    }
    
    # 处理其他所有*.a.cn的请求
    server {
        listen 80;
        server_name *.a.cn;
    
        location / {
            # 这里可以配置一个默认的处理方式,比如重定向到某个页面或另一个服务
            proxy_pass http://127.0.0.1:8080;  # 假设有一个默认服务在8080端口
            # 或者直接返回404
            # return 404;
    
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
        }
    
        access_log /home/wwwroot/Lngx01/logs/default-*.a.cn-access.log;
        error_log /home/wwwroot/Lngx01/logs/default-*.a.cn-error.log crit;
    }
  2. 确保FRP隧道配置正确
    在A机器上,FRP服务器应该已经配置好监听80和443端口,并将这些请求转发到B机器的80端口(因为B机器的Nginx监听在80端口上)。
  3. DNS配置
    确保b.a.cnc.a.cn的DNS解析正确指向A机器的IP地址,这样所有请求都会先到达A机器,然后通过FRP转发到B机器。
  4. 重启Nginx和FRP服务
    在B机器上重启Nginx服务,确保新的配置生效。同时,在A机器上重启FRP服务(如果更改了FRP配置)。
  5. 测试
    使用浏览器或curl命令测试b.a.cnc.a.cn的访问情况,确保它们分别被正确代理到B机器的1000和1001端口。

通过以上步骤,您应该能够实现在不增加额外FRP隧道的情况下,通过直接访问b.a.cnc.a.cn来访问B机器上对应的服务。

1 个回答

proxy_pass是需要写在 location / { ... } 之内,
不能直接写在 if ($host = "c.a.cn") { ... }中,nginx会出错。

或是location / { if ($host = "c.a.cn") { proxy_pass ... } } 这样。

通常请求不同的源站,还是建议直接添加多个lngx主机,
绑定明确的域名与请求不同的源站地址。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏