From 8bf9ee446c80c154ecfdf496070f5a24a7f63160 Mon Sep 17 00:00:00 2001 From: spacewander Date: Thu, 10 Jun 2021 19:29:22 +0800 Subject: [PATCH 1/3] feat(stream): accept tls over tcp Signed-off-by: spacewander --- README.md | 2 +- apisix/cli/ngx_tpl.lua | 13 ++- apisix/cli/ops.lua | 35 +++++++ apisix/init.lua | 19 ++++ apisix/router.lua | 6 ++ ci/linux_apisix_current_luarocks_runner.sh | 3 + conf/config-default.yaml | 5 +- docs/ar/README.md | 2 +- docs/en/latest/admin-api.md | 2 +- docs/en/latest/{https.md => certificate.md} | 2 +- docs/en/latest/config.json | 2 +- docs/en/latest/grpc-proxy.md | 2 +- docs/en/latest/stream-proxy.md | 38 ++++++- docs/es/latest/README.md | 2 +- docs/zh/latest/README.md | 2 +- docs/zh/latest/admin-api.md | 2 +- docs/zh/latest/{https.md => certificate.md} | 2 +- docs/zh/latest/config.json | 2 +- docs/zh/latest/grpc-proxy.md | 2 +- docs/zh/latest/stream-proxy.md | 32 ++++++ t/APISIX.pm | 55 ++++++++++ t/cli/test_tls_over_tcp.sh | 56 +++++++++++ t/stream-node/tls.t | 106 ++++++++++++++++++++ utils/create-ssl.py | 41 ++++++++ 24 files changed, 414 insertions(+), 19 deletions(-) rename docs/en/latest/{https.md => certificate.md} (99%) rename docs/zh/latest/{https.md => certificate.md} (99%) create mode 100755 t/cli/test_tls_over_tcp.sh create mode 100644 t/stream-node/tls.t create mode 100755 utils/create-ssl.py diff --git a/README.md b/README.md index 7c752db4bd46..e5e1b27ff188 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ A/B testing, canary release, blue-green deployment, limit rate, defense against - Proxy Protocol - Proxy Dubbo: Dubbo Proxy based on Tengine. - HTTP(S) Forward Proxy - - [SSL](docs/en/latest/https.md): Dynamically load an SSL certificate. + - [SSL](docs/en/latest/certificate.md): Dynamically load an SSL certificate. - **Full Dynamic** diff --git a/apisix/cli/ngx_tpl.lua b/apisix/cli/ngx_tpl.lua index f2376482ae39..40e516d2b7f7 100644 --- a/apisix/cli/ngx_tpl.lua +++ b/apisix/cli/ngx_tpl.lua @@ -99,13 +99,22 @@ stream { } server { - {% for _, addr in ipairs(stream_proxy.tcp or {}) do %} - listen {*addr*} {% if enable_reuseport then %} reuseport {% end %} {% if proxy_protocol and proxy_protocol.enable_tcp_pp then %} proxy_protocol {% end %}; + {% for _, item in ipairs(stream_proxy.tcp or {}) do %} + listen {*item.addr*} {% if item.tls then %} ssl {% end %} {% if enable_reuseport then %} reuseport {% end %} {% if proxy_protocol and proxy_protocol.enable_tcp_pp then %} proxy_protocol {% end %}; {% end %} {% for _, addr in ipairs(stream_proxy.udp or {}) do %} listen {*addr*} udp {% if enable_reuseport then %} reuseport {% end %}; {% end %} + {% if tcp_enable_ssl then %} + ssl_certificate {* ssl.ssl_cert *}; + ssl_certificate_key {* ssl.ssl_cert_key *}; + + ssl_certificate_by_lua_block { + apisix.stream_ssl_phase() + } + {% end %} + {% if proxy_protocol and proxy_protocol.enable_tcp_pp_to_upstream then %} proxy_protocol on; {% end %} diff --git a/apisix/cli/ops.lua b/apisix/cli/ops.lua index 83229b4600f1..5e709ded984f 100644 --- a/apisix/cli/ops.lua +++ b/apisix/cli/ops.lua @@ -192,6 +192,25 @@ local config_schema = { { type = "string", }, + { + type = "object", + properties = { + addr = { + anyOf = { + { + type = "integer", + }, + { + type = "string", + }, + } + }, + tls = { + type = "boolean", + } + }, + required = {"addr"} + }, }, }, uniqueItems = true, @@ -430,6 +449,21 @@ Please modify "admin_key" in conf/config.yaml . yaml_conf.apisix.ssl.ssl_cert = "cert/ssl_PLACE_HOLDER.crt" yaml_conf.apisix.ssl.ssl_cert_key = "cert/ssl_PLACE_HOLDER.key" + local tcp_enable_ssl + -- compatible with the original style which only has the addr + if yaml_conf.apisix.stream_proxy and yaml_conf.apisix.stream_proxy.tcp then + local tcp = yaml_conf.apisix.stream_proxy.tcp + for i, item in ipairs(tcp) do + if type(item) ~= "table" then + tcp[i] = {addr = item} + else + if item.tls then + tcp_enable_ssl = true + end + end + end + end + local dubbo_upstream_multiplex_count = 32 if yaml_conf.plugin_attr and yaml_conf.plugin_attr["dubbo-proxy"] then local dubbo_conf = yaml_conf.plugin_attr["dubbo-proxy"] @@ -454,6 +488,7 @@ Please modify "admin_key" in conf/config.yaml . error_log = {level = "warn"}, enabled_plugins = enabled_plugins, dubbo_upstream_multiplex_count = dubbo_upstream_multiplex_count, + tcp_enable_ssl = tcp_enable_ssl, } if not yaml_conf.apisix then diff --git a/apisix/init.lua b/apisix/init.lua index 92d3451b6326..ee21da1e34a9 100644 --- a/apisix/init.lua +++ b/apisix/init.lua @@ -736,6 +736,25 @@ function _M.http_control() end +function _M.stream_ssl_phase() + local ngx_ctx = ngx.ctx + local api_ctx = ngx_ctx.api_ctx + + if api_ctx == nil then + api_ctx = core.tablepool.fetch("api_ctx", 0, 32) + ngx_ctx.api_ctx = api_ctx + end + + local ok, err = router.router_ssl.match_and_set(api_ctx) + if not ok then + if err then + core.log.error("failed to fetch ssl config: ", err) + end + ngx_exit(-1) + end +end + + function _M.stream_init(args) core.log.info("enter stream_init") diff --git a/apisix/router.lua b/apisix/router.lua index 840f0cd5df0f..9bdafebbdb6e 100644 --- a/apisix/router.lua +++ b/apisix/router.lua @@ -106,9 +106,15 @@ end function _M.stream_init_worker() + local router_ssl_name = "radixtree_sni" + local router_stream = require("apisix.stream.router.ip_port") router_stream.stream_init_worker(filter) _M.router_stream = router_stream + + local router_ssl = require("apisix.ssl.router." .. router_ssl_name) + router_ssl.init_worker() + _M.router_ssl = router_ssl end diff --git a/ci/linux_apisix_current_luarocks_runner.sh b/ci/linux_apisix_current_luarocks_runner.sh index e055c4c0336f..3ca7c0e1f847 100755 --- a/ci/linux_apisix_current_luarocks_runner.sh +++ b/ci/linux_apisix_current_luarocks_runner.sh @@ -58,6 +58,9 @@ script() { # apisix cli test ./utils/set-dns.sh + # install test dependencies + sudo pip install requests + for f in ./t/cli/test_*.sh; do sudo PATH="$PATH" "$f" done diff --git a/conf/config-default.yaml b/conf/config-default.yaml index 3aefd6f051ef..c2c124e74c83 100644 --- a/conf/config-default.yaml +++ b/conf/config-default.yaml @@ -98,8 +98,9 @@ apisix: ssl: 'radixtree_sni' # radixtree_sni: match route by SNI(base on radixtree) #stream_proxy: # TCP/UDP proxy # tcp: # TCP proxy port list - # - 9100 - # - "127.0.0.1:9101" + # - addr: 9100 + # tls: true + # - addr: "127.0.0.1:9101" # udp: # UDP proxy port list # - 9200 # - "127.0.0.1:9201" diff --git a/docs/ar/README.md b/docs/ar/README.md index c2ac6b097bc4..26ef9fe7293d 100644 --- a/docs/ar/README.md +++ b/docs/ar/README.md @@ -79,7 +79,7 @@ - بروتوكول الوكيل - الوكيل Dubbo: Dubbo يعتمد على Tengine. - HTTP(S) وكيل إعادة التوجيه - - [SSL](docs/en/latest/https.md): تحميل شهادة SSL ديناميكيًا. + - [SSL](docs/en/latest/certificate.md): تحميل شهادة SSL ديناميكيًا. - **ديناميكية كاملة** diff --git a/docs/en/latest/admin-api.md b/docs/en/latest/admin-api.md index 2ea7aefaddc8..bf6073989e0e 100644 --- a/docs/en/latest/admin-api.md +++ b/docs/en/latest/admin-api.md @@ -812,7 +812,7 @@ Config Example: } ``` -More examples can be found in [HTTPS](./https.md). +More examples can be found in [Certificate](./certificate.md). ## Global Rule diff --git a/docs/en/latest/https.md b/docs/en/latest/certificate.md similarity index 99% rename from docs/en/latest/https.md rename to docs/en/latest/certificate.md index 30c232580a44..5507e5ee3ba8 100644 --- a/docs/en/latest/https.md +++ b/docs/en/latest/certificate.md @@ -1,5 +1,5 @@ --- -title: HTTPS +title: Certificate ---