You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2021/05/04 05:07:58 UTC

[apisix] branch master updated: feat: patch tcp.sock.connect to use our DNS resolver (#4114)

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: 罗泽轩 <sp...@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 <to...@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]