From 3f077a080d2adc187d874c2c711c8b7a6cd4177e Mon Sep 17 00:00:00 2001 From: "John.Koepi" Date: Mon, 24 Aug 2015 18:09:28 +0200 Subject: [PATCH 1/2] add ssl support --- README.markdown | 3 + lib/resty/upstream/healthcheck.lua | 89 ++++++++++++++++++------------ 2 files changed, 57 insertions(+), 35 deletions(-) diff --git a/README.markdown b/README.markdown index cf12367..fd47a16 100644 --- a/README.markdown +++ b/README.markdown @@ -58,6 +58,9 @@ http { http_req = "GET /status HTTP/1.0\\r\\nHost: foo.com\\r\\n\\r\\n", -- raw HTTP request for checking + ssl = false, -- use https + ssl_verify = true, -- verify SSL certs, see https://github.com/openresty/lua-nginx-module/pull/290 + interval = 2000, -- run the check cycle every 2 sec timeout = 1000, -- 1 sec is the timeout for network operations fall = 3, -- # of successive failures before turning a peer down diff --git a/lib/resty/upstream/healthcheck.lua b/lib/resty/upstream/healthcheck.lua index 4a6e305..40da2e7 100644 --- a/lib/resty/upstream/healthcheck.lua +++ b/lib/resty/upstream/healthcheck.lua @@ -225,50 +225,65 @@ local function check_peer(ctx, id, peer, is_backup) errlog("failed to connect to ", name, ": ", err) end peer_fail(ctx, is_backup, id, peer) - else - local bytes, err = sock:send(req) - if not bytes then + return + end + + if ctx.ssl then + local session, err = sock:sslhandshake(nil, name, ctx.ssl_verify) + if not session then + errlog("failed to do SSL handshake: ", name, ": ", err) + sock:close() + return + end + end + + local bytes, err = sock:send(req) + if not bytes then + if not peer.down then + errlog("failed to send request to ", name, ": ", err) + end + peer_fail(ctx, is_backup, id, peer) + sock:close() + return + end + + local status_line, err = sock:receive() + if not status_line then + if not peer.down then + errlog("failed to receive status line from ", name, + ": ", err) + end + peer_fail(ctx, is_backup, id, peer) + sock:close() + return + end + + sock:close() + + if statuses then + local from, to, err = re_find(status_line, + [[^HTTP/\d+\.\d+\s+(\d+)]], + "joi", nil, 1) + if not from then if not peer.down then - errlog("failed to send request to ", name, ": ", err) + errlog("bad status line from ", name, ": ", + status_line) end peer_fail(ctx, is_backup, id, peer) else - local status_line, err = sock:receive() - if not status_line then + local status = tonumber(sub(status_line, from, to)) + if not statuses[status] then if not peer.down then - errlog("failed to receive status line from ", name, - ": ", err) + errlog("bad status code from ", + name, ": ", status) end peer_fail(ctx, is_backup, id, peer) else - if statuses then - local from, to, err = re_find(status_line, - [[^HTTP/\d+\.\d+\s+(\d+)]], - "joi", nil, 1) - if not from then - if not peer.down then - errlog("bad status line from ", name, ": ", - status_line) - end - peer_fail(ctx, is_backup, id, peer) - else - local status = tonumber(sub(status_line, from, to)) - if not statuses[status] then - if not peer.down then - errlog("bad status code from ", - name, ": ", status) - end - peer_fail(ctx, is_backup, id, peer) - else - peer_ok(ctx, is_backup, id, peer) - end - end - else - peer_ok(ctx, is_backup, id, peer) - end + peer_ok(ctx, is_backup, id, peer) end - sock:close() end + else + peer_ok(ctx, is_backup, id, peer) end end @@ -519,6 +534,9 @@ function _M.spawn_checker(opts) return nil, "\"http_req\" option required" end + local ssl = opts.ssl and true + local ssl_verify = opts.ssl_verify and true + local timeout = opts.timeout if not timeout then timeout = 1000 @@ -527,7 +545,6 @@ function _M.spawn_checker(opts) local interval = opts.interval if not interval then interval = 1 - else interval = interval / 1000 if interval < 0.002 then -- minimum 2ms @@ -592,6 +609,8 @@ function _M.spawn_checker(opts) primary_peers = preprocess_peers(ppeers), backup_peers = preprocess_peers(bpeers), http_req = http_req, + ssl = ssl, + ssl_verify = ssl_verify, timeout = timeout, interval = interval, dict = dict, From e9a373db2661e2813a1e92a4eab55fbe279dac8d Mon Sep 17 00:00:00 2001 From: "John.Koepi" Date: Tue, 25 Aug 2015 18:25:13 +0200 Subject: [PATCH 2/2] reuse ctx.type to allow https --- README.markdown | 12 +++++------- lib/resty/upstream/healthcheck.lua | 15 +++++++-------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/README.markdown b/README.markdown index fd47a16..0ff1727 100644 --- a/README.markdown +++ b/README.markdown @@ -51,15 +51,13 @@ http { local ok, err = hc.spawn_checker{ shm = "healthcheck", -- defined by "lua_shared_dict" upstream = "foo.com", -- defined by "upstream" - type = "http", - + + type = "https", + ssl_verify = true, -- verify SSL certs, see https://github.com/openresty/lua-nginx-module/pull/290 + -- if you put this Lua snippet in separate .lua file, -- then you should write this instead: http_req = "GET /status HTTP/1.0\r\nHost: foo.com\r\n\r\n", - http_req = "GET /status HTTP/1.0\\r\\nHost: foo.com\\r\\n\\r\\n", - -- raw HTTP request for checking - - ssl = false, -- use https - ssl_verify = true, -- verify SSL certs, see https://github.com/openresty/lua-nginx-module/pull/290 + http_req = "GET /status HTTP/1.0\\r\\nHost: foo.com\\r\\n\\r\\n", -- raw HTTP request for checking interval = 2000, -- run the check cycle every 2 sec timeout = 1000, -- 1 sec is the timeout for network operations diff --git a/lib/resty/upstream/healthcheck.lua b/lib/resty/upstream/healthcheck.lua index 40da2e7..6ca5748 100644 --- a/lib/resty/upstream/healthcheck.lua +++ b/lib/resty/upstream/healthcheck.lua @@ -228,7 +228,7 @@ local function check_peer(ctx, id, peer, is_backup) return end - if ctx.ssl then + if ctx.type == "https" then local session, err = sock:sslhandshake(nil, name, ctx.ssl_verify) if not session then errlog("failed to do SSL handshake: ", name, ": ", err) @@ -525,18 +525,17 @@ function _M.spawn_checker(opts) return nil, "\"type\" option required" end - if typ ~= "http" then - return nil, "only \"http\" type is supported right now" + if typ ~= "http" and typ ~= "https" then + return nil, "no support for this protocol type" end + local ssl_verify = opts.ssl_verify and true + local http_req = opts.http_req if not http_req then return nil, "\"http_req\" option required" end - local ssl = opts.ssl and true - local ssl_verify = opts.ssl_verify and true - local timeout = opts.timeout if not timeout then timeout = 1000 @@ -608,9 +607,9 @@ function _M.spawn_checker(opts) upstream = u, primary_peers = preprocess_peers(ppeers), backup_peers = preprocess_peers(bpeers), - http_req = http_req, - ssl = ssl, + type = typ, ssl_verify = ssl_verify, + http_req = http_req, timeout = timeout, interval = interval, dict = dict,