This is an automated email from the ASF dual-hosted git repository. spacewander pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push: new f914807 feat: patch tcp.sock.connect to use our DNS resolver (#4114) f914807 is described below commit f9148073aa5edc774b87cae7cb3eee5d634e3f61 Author: 罗泽轩 <spacewander...@gmail.com> AuthorDate: Tue May 4 13:07:48 2021 +0800 feat: patch tcp.sock.connect to use our DNS resolver (#4114) Co-authored-by: Alex Zhang <tok...@apache.org> --- apisix/core.lua | 1 + apisix/core/resolver.lua | 51 ++++++++++++++++++++++++++++++++++++ apisix/core/utils.lua | 3 ++- apisix/init.lua | 30 ++------------------- apisix/patch.lua | 42 ++++++++++++++++++++++++++++- apisix/plugins/traffic-split.lua | 3 +-- t/misc/patch.t | 25 ++++++++++++++++++ t/node/route-domain-with-local-dns.t | 4 +-- 8 files changed, 125 insertions(+), 34 deletions(-) diff --git a/apisix/core.lua b/apisix/core.lua index b0c3da6..0ef6ae9 100644 --- a/apisix/core.lua +++ b/apisix/core.lua @@ -48,5 +48,6 @@ return { dns_client = require("apisix.core.dns.client"), etcd = require("apisix.core.etcd"), tablepool = require("tablepool"), + resolver = require("apisix.core.resolver"), empty_tab = {}, } diff --git a/apisix/core/resolver.lua b/apisix/core/resolver.lua new file mode 100644 index 0000000..d6b76cd --- /dev/null +++ b/apisix/core/resolver.lua @@ -0,0 +1,51 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +local json = require("apisix.core.json") +local log = require("apisix.core.log") +local utils = require("apisix.core.utils") + + +local _M = {} + + +function _M.init_resolver(args) + local dns_resolver = args and args["dns_resolver"] + utils.set_resolver(dns_resolver) + log.info("dns resolver ", json.delay_encode(dns_resolver, true)) +end + + +function _M.parse_domain(host) + local ip_info, err = utils.dns_parse(host) + if not ip_info then + log.error("failed to parse domain: ", host, ", error: ",err) + return nil, err + end + + log.info("parse addr: ", json.delay_encode(ip_info)) + log.info("resolver: ", json.delay_encode(utils.get_resolver())) + log.info("host: ", host) + if ip_info.address then + log.info("dns resolver domain: ", host, " to ", ip_info.address) + return ip_info.address + end + + return nil, "failed to parse domain" +end + + +return _M diff --git a/apisix/core/utils.lua b/apisix/core/utils.lua index 921df6a..1b304f7 100644 --- a/apisix/core/utils.lua +++ b/apisix/core/utils.lua @@ -114,9 +114,10 @@ end _M.dns_parse = dns_parse -function _M.set_resolver(resolvers) +local function set_resolver(resolvers) dns_resolvers = resolvers end +_M.set_resolver = set_resolver function _M.get_resolver(resolvers) diff --git a/apisix/init.lua b/apisix/init.lua index 4a30b77..e090377 100644 --- a/apisix/init.lua +++ b/apisix/init.lua @@ -47,17 +47,9 @@ if ngx.config.subsystem == "http" then end local load_balancer local local_conf -local dns_resolver local ver_header = "APISIX/" .. core.version.VERSION -local function parse_args(args) - dns_resolver = args and args["dns_resolver"] - core.utils.set_resolver(dns_resolver) - core.log.info("dns resolver", core.json.delay_encode(dns_resolver, true)) -end - - local _M = {version = 0.4} @@ -72,7 +64,7 @@ function _M.http_init(args) "maxrecord=8000", "sizemcode=64", "maxmcode=4000", "maxirconst=1000") - parse_args(args) + core.resolver.init_resolver(args) core.id.init() local process = require("ngx.process") @@ -156,24 +148,6 @@ function _M.http_ssl_phase() end -local function parse_domain(host) - local ip_info, err = core.utils.dns_parse(host) - if not ip_info then - core.log.error("failed to parse domain: ", host, ", error: ",err) - return nil, err - end - - core.log.info("parse addr: ", core.json.delay_encode(ip_info)) - core.log.info("resolver: ", core.json.delay_encode(dns_resolver)) - core.log.info("host: ", host) - if ip_info.address then - core.log.info("dns resolver domain: ", host, " to ", ip_info.address) - return ip_info.address - else - return nil, "failed to parse domain" - end -end -_M.parse_domain = parse_domain local function parse_domain_for_nodes(nodes) @@ -182,7 +156,7 @@ local function parse_domain_for_nodes(nodes) local host = node.host if not ipmatcher.parse_ipv4(host) and not ipmatcher.parse_ipv6(host) then - local ip, err = parse_domain(host) + local ip, err = core.resolver.parse_domain(host) if ip then local new_node = core.table.clone(node) new_node.host = ip diff --git a/apisix/patch.lua b/apisix/patch.lua index 6bea363..66bf17d 100644 --- a/apisix/patch.lua +++ b/apisix/patch.lua @@ -15,6 +15,7 @@ -- limitations under the License. -- local require = require +local ipmatcher = require("resty.ipmatcher") local socket = require("socket") local unix_socket = require("socket.unix") local ssl = require("ssl") @@ -45,6 +46,45 @@ local function get_local_conf() end +local patch_tcp_socket +do + local old_tcp_sock_connect + + local function new_tcp_sock_connect(sock, host, port, opts) + local core_str = require("apisix.core.string") + local resolver = require("apisix.core.resolver") + + if host then + if core_str.has_prefix(host, "unix:") then + if not opts then + -- workaround for https://github.com/openresty/lua-nginx-module/issues/860 + return old_tcp_sock_connect(sock, host) + end + + elseif not ipmatcher.parse_ipv4(host) and not ipmatcher.parse_ipv6(host) then + local err + host, err = resolver.parse_domain(host) + if not host then + return nil, "failed to parse domain: " .. err + end + end + end + + return old_tcp_sock_connect(sock, host, port, opts) + end + + + function patch_tcp_socket(sock) + if not old_tcp_sock_connect then + old_tcp_sock_connect = sock.connect + end + + sock.connect = new_tcp_sock_connect + return sock + end +end + + local function flatten(args) local buf = new_tab(#args, 0) for i, v in ipairs(args) do @@ -255,7 +295,7 @@ function _M.patch() ngx_socket.tcp = function () local phase = get_phase() if phase ~= "init" and phase ~= "init_worker" then - return original_tcp() + return patch_tcp_socket(original_tcp()) end return luasocket_tcp() diff --git a/apisix/plugins/traffic-split.lua b/apisix/plugins/traffic-split.lua index f7e75af..6b3ee5d 100644 --- a/apisix/plugins/traffic-split.lua +++ b/apisix/plugins/traffic-split.lua @@ -17,7 +17,6 @@ local core = require("apisix.core") local upstream = require("apisix.upstream") local schema_def = require("apisix.schema_def") -local init = require("apisix.init") local roundrobin = require("resty.roundrobin") local ipmatcher = require("resty.ipmatcher") local expr = require("resty.expr.v1") @@ -130,7 +129,7 @@ local function parse_domain_for_node(node) if not ipmatcher.parse_ipv4(node) and not ipmatcher.parse_ipv6(node) then - local ip, err = init.parse_domain(node) + local ip, err = core.resolver.parse_domain(node) if ip then return ip end diff --git a/t/misc/patch.t b/t/misc/patch.t index b94d5f5..1635715 100644 --- a/t/misc/patch.t +++ b/t/misc/patch.t @@ -126,3 +126,28 @@ end } --- error_log failed to read: timeout + + + +=== TEST 4: resolve host by ourselves +--- yaml_config +apisix: + node_listen: 1984 + enable_resolv_search_opt: true +--- config + location /t { + content_by_lua_block { + local http = require("resty.http") + local httpc = http.new() + local res, err = httpc:request_uri("http://apisix") + if not res then + ngx.log(ngx.ERR, err) + return + end + ngx.say(res.status) + } + } +--- request +GET /t +--- response_body +301 diff --git a/t/node/route-domain-with-local-dns.t b/t/node/route-domain-with-local-dns.t index d79dc2e..0ab68ef 100644 --- a/t/node/route-domain-with-local-dns.t +++ b/t/node/route-domain-with-local-dns.t @@ -62,7 +62,7 @@ GET /t --- response_body passed --- error_log eval -qr/.*parse_args\(\): dns resolver\[.+\]/ +qr/.*init_resolver\(\): dns resolver \[.+\]/ --- no_error_log [error] @@ -75,7 +75,7 @@ GET /not_found --- response_body {"error_msg":"404 Route Not Found"} --- error_log eval -qr/.*parse_args\(\): dns resolver\[.+\]/ +qr/.*init_resolver\(\): dns resolver \[.+\]/ --- no_error_log [error]