基於radixtree_sni路由插件,使用port字段而非sni進行路由選擇。express
radixtree_port依賴的SSL屬性以下:apache
名字json |
可選項api |
類型數組 |
說明app |
示例less |
certfetch |
必需ui |
證書this |
https 證書 |
|
key |
必需 |
私鑰 |
https 證書私鑰 |
|
port |
必需 |
匹配規則 |
須要匹配的端口 |
|
certs |
可選 |
證書字符串數組 |
當你想給同一個域名配置多個證書時,除了第一個證書須要經過 cert 傳遞外,剩下的證書能夠經過該參數傳遞上來 |
|
keys |
可選 |
私鑰字符串數組 |
certs 對應的證書私鑰,注意要跟 certs 一一對應 |
|
client.ca |
可選 |
證書 |
設置將用於客戶端證書校驗的 CA 證書。該特性須要 OpenResty 1.19+ |
|
client.depth |
可選 |
輔助 |
設置客戶端證書校驗的深度,默認爲 1。該特性須要 OpenResty 1.19+ |
|
labels |
可選 |
匹配規則 |
標識附加屬性的鍵值對 |
{"version":"v2","build":"16","env":"production"} |
cd /usr/local/apisix/apisix/ssl/router vi ./radixtree_port.lua #鍵入插件代碼
cd /usr/local/apisix vi ./schema_def.lua #修改_M.SSL配置
_M.ssl = { type = "object", properties = { id = id_schema, cert = certificate_scheme, key = private_key_schema, certs = { type = "array", items = certificate_scheme, }, keys = { type = "array", items = private_key_schema, }, port = { type = "integer" }, --changed client = { type = "object", properties = { ca = certificate_scheme, depth = { type = "integer", minimum = 0, default = 1, }, }, required = {"ca"}, }, exptime = { type = "integer", minimum = 1588262400, -- 2020/5/1 0:0:0 }, labels = labels_def, status = { description = "ssl status, 1 to enable, 0 to disable", type = "integer", enum = {1, 0}, default = 1 }, validity_end = timestamp_def, validity_start = timestamp_def, create_time = timestamp_def, update_time = timestamp_def }, required = {"port", "key", "cert"}, additionalProperties = false, }
cd /usr/local/apisix/conf vi ./config-default.yaml #修改路由配置
刪除或註釋ssl: 'radixtree_sni'字段,新增ssl: 'radixtree_port'以選擇路由插件
…… …… router: http: 'radixtree_uri' # ssl: 'radixtree_sni' ssl: 'radixtree_port' …… ……
-- -- 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 get_request = require("resty.core.base").get_request local router_new = require("apisix.utils.router").new local core = require("apisix.core") local apisix_ssl = require("apisix.ssl") local ngx_ssl = require("ngx.ssl") local config_util = require("apisix.core.config_util") local ipairs = ipairs local type = type local error = error local str_find = core.string.find local str_gsub = string.gsub local ssl_certificates local radixtree_router local radixtree_router_ver local _M = { version = 0.1, server_name = ngx_ssl.server_name, } local function create_router(ssl_items) --changed local ssl_items = ssl_items or {} local route_items = core.table.new(#ssl_items, 0) local idx = 0 for _, ssl in config_util.iterate_values(ssl_items) do if ssl.value ~= nil and (ssl.value.status == nil or ssl.value.status == 1) then -- compatible with old version local labels_port = tostring(ssl.value.port) idx = idx + 1 route_items[idx] = { paths = labels_port, handler = function (api_ctx) if not api_ctx then return end api_ctx.matched_ssl = ssl end } end end core.log.info("route items: ", core.json.delay_encode(route_items, true)) -- for testing if #route_items > 1 then core.log.info("we have more than 1 ssl certs now") end local router, err = router_new(route_items) if not router then return nil, err end return router end local function set_pem_ssl_key(port, cert, pkey) --changed local r = get_request() if r == nil then return false, "no request found" end local parsed_cert, err = apisix_ssl.fetch_cert(port, cert) if not parsed_cert then return false, "failed to parse PEM cert: " .. err end local ok, err = ngx_ssl.set_cert(parsed_cert) if not ok then return false, "failed to set PEM cert: " .. err end local parsed_pkey, err = apisix_ssl.fetch_pkey(port, pkey) if not parsed_cert then return false, "failed to parse PEM priv key: " .. err end ok, err = ngx_ssl.set_priv_key(parsed_pkey) if not ok then return false, "failed to set PEM priv key: " .. err end return true end function _M.match_and_set(api_ctx) local err if not radixtree_router or radixtree_router_ver ~= ssl_certificates.conf_version then radixtree_router, err = create_router(ssl_certificates.values) if not radixtree_router then return false, "failed to create radixtree router: " .. err end radixtree_router_ver = ssl_certificates.conf_version end local port = tostring(ngx_ssl.server_port()) --changed local ok = radixtree_router:dispatch(port, nil, api_ctx) if not ok then core.log.error("failed to find any SSL certificate by Port: ", port) --changed return false end local matched_ssl = api_ctx.matched_ssl core.log.info("debug - matched: ", core.json.delay_encode(matched_ssl, true)) ngx_ssl.clear_certs() ok, err = set_pem_ssl_key(port, matched_ssl.value.cert, matched_ssl.value.key) --changed if not ok then return false, err end -- multiple certificates support. if matched_ssl.value.certs then for i = 1, #matched_ssl.value.certs do local cert = matched_ssl.value.certs[i] local key = matched_ssl.value.keys[i] ok, err = set_pem_ssl_key(port, cert, key) --changed if not ok then return false, err end end end if matched_ssl.value.client then local ca_cert = matched_ssl.value.client.ca local depth = matched_ssl.value.client.depth if apisix_ssl.support_client_verification() then local parsed_cert, err = apisix_ssl.fetch_cert(port, ca_cert) --changed if not parsed_cert then return false, "failed to parse client cert: " .. err end local ok, err = ngx_ssl.verify_client(parsed_cert, depth) if not ok then return false, err end api_ctx.ssl_client_verified = true end end return true end function _M.ssls() if not ssl_certificates then return nil, nil end return ssl_certificates.values, ssl_certificates.conf_version end function _M.init_worker() local err ssl_certificates, err = core.config.new("/ssl", { automatic = true, item_schema = core.schema.ssl, checker = function (item, schema_type) return apisix_ssl.check_ssl_conf(true, item) end, }) if not ssl_certificates then error("failed to create etcd instance for fetching ssl certificates: " .. err) end end return _M