You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Nginx服务器替换/etc/hosts文件中指定映射条目?

我来帮你搞定这个用Nginx替换/etc/hosts里b.com映射的需求,结合你提到的从数据库动态获取IP和端口的场景,整理了一套可落地的方案:

解决方案:Nginx动态转发b.com请求至数据库获取的IP:Port

1. 先调整本地hosts文件

首先得让访问b.com的请求先走到你的Nginx服务器,所以修改/etc/hosts,把原来的映射替换成指向本地Nginx的地址:

# 注释掉旧的条目,添加新映射
# 192.x.x.x b.com
127.0.0.1 b.com

2. 完善Nginx配置,实现动态转发

基于你给出的nginx.conf片段,我们新增一个专门处理b.com的server块,同时补充从数据库获取IP/端口的Lua逻辑:

server {
    listen 80;
    # 把server_name设置为b.com,精准匹配这个域名的请求
    server_name b.com;

    location / {
        # 初始化变量存储目标IP和端口
        set $target_ip '';
        set $target_port '';

        rewrite_by_lua_block {
            # 调用内部的/getIp接口获取数据库中的IP和端口
            local res = ngx.location.capture("/getIp", { method = ngx.HTTP_GET })
            
            if res.status == 200 and res.body then
                # 解析JSON响应,需要确保Nginx安装了lua-resty-json模块
                local json = require("cjson")
                local data = json.decode(res.body)
                ngx.var.target_ip = data.ip or ''
                ngx.var.target_port = data.port or '80' -- 端口默认用80
            end
        }

        # 如果没拿到有效IP,返回500错误
        if ($target_ip = '') {
            return 500 "Failed to retrieve target IP from database";
        }

        # 转发请求到目标服务
        proxy_pass http://$target_ip:$target_port;
        # 传递必要的请求头,保证后端服务能正确识别请求
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # 内部接口:从数据库查询b.com对应的IP和端口
    location /getIp {
        internal; # 只允许Nginx内部调用,不对外暴露
        default_type application/json;
        content_by_lua_block {
            # 用lua-resty-mysql连接数据库(需要先安装这个模块)
            local mysql = require("resty.mysql")
            local db, err = mysql:new()
            if not db then
                ngx.say('{"error":"Failed to init MySQL client: '..err..'"}')
                return
            end

            db:set_timeout(1000) -- 设置1秒超时

            # 连接数据库,替换成你的实际数据库信息
            local ok, err = db:connect{
                host = "你的数据库地址",
                port = 3306,
                database = "你的数据库名",
                user = "数据库用户名",
                password = "数据库密码",
                charset = "utf8"
            }

            if not ok then
                ngx.say('{"error":"Failed to connect to DB: '..err..'"}')
                return
            end

            # 查询b.com对应的映射记录,根据你的表结构调整SQL
            local res, err = db:query("SELECT target_ip, target_port FROM domain_mappings WHERE domain='b.com' LIMIT 1")
            if not res then
                ngx.say('{"error":"DB query failed: '..err..'"}')
                return
            end

            if #res == 0 then
                ngx.say('{"error":"No mapping found for b.com"}')
                return
            end

            # 返回JSON格式的IP和端口
            local json = require("cjson")
            ngx.say(json.encode({ip=res[1].target_ip, port=res[1].target_port}))

            # 把连接放回池,复用节省资源
            local ok, err = db:set_keepalive(10000, 100)
            if not ok then
                ngx.log(ngx.ERR, "Failed to set MySQL keepalive: ", err)
            end
        }
    }
}

3. 关键注意事项

  • 安装依赖Lua模块:确保你的Nginx已经安装了lua-nginx-module、lua-resty-mysql和lua-resty-json,可以通过系统包管理器(比如apt install lua-nginx-module lua-resty-mysql)或者源码编译添加。
  • 测试内部接口:可以临时去掉internal;指令,用curl http://localhost/getIp验证是否返回正确的IP和端口数据。
  • 重载Nginx配置:修改完配置后,执行sudo nginx -s reload让新配置生效。
  • 验证转发效果:访问http://b.com,检查是否成功转发到数据库指定的目标IP和端口。

4. 可选:不修改hosts的替代方案

如果不想改动/etc/hosts,可以让Nginx充当本地DNS服务器拦截b.com的解析,但这种配置相对复杂。修改hosts是最直接可靠的方式,能确保本地请求优先路由到你的Nginx。

内容的提问来源于stack exchange,提问作者Floriane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:04:57