如何用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
相关产品推荐
相关产品推荐

