从openresty lua发出https tls请求

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从openresty lua发出https tls请求相关的知识,希望对你有一定的参考价值。

我试图找到一种方法从我的nginx / lua模块中向服务器发出安全的GET请求,以检查入口调用的身份验证。关于如何做到这一点似乎很少。我目前的尝试主要围绕使用resty.http和以下内容。

-- Create http client
local httpc = http.new();
httpc:set_timeout(500)

ngx.log(ngx.DEBUG, '**** Connect with TLS ****');
ok, err = httpc:connect(my_server, port);

然而my_server在输入时需要cert,ca和key,但是再次,不知道如何使用[“ca”] = myca.pem;等...不起作用。如果我订

lua_ssl_trusted_certificate=myca.pem

请求失败,并显示以下内容:

2018/02/23 19:22:17 [crit] 19#0: *4 SSL_shutdown() failed (SSL: error:140E0197:SSL routines:SSL_shutdown:shutdown while in init), client: 127.0.0.1, server: my_server

我看过https://github.com/brunoos/luasec/archive/luasec-0.6,但坦率地说无法在我的alpine linux容器上编译干净。不知道在这一点上使用什么模块或如何进行,任何想法?

更新根据我收到的评论和答案提供的其他信息。尝试使用openresty pintsized lua-resty-http和https失败,目前没有办法让cert / key / ca相互TLS流程起作用。使用下面的答案,我能够配置对我的后端应用程序微服务的上游代理调用,以正确地为请求提供服务。我的proxy.conf文件片段使其工作看起来像跟随。注意:上游服务器必须匹配证书中的CN,否则它将无法工作,或者至少我没有得到证明失败的信息。

http {
    # Upstream backend for services
    upstream apimy {
        server apimy:3003;
    }
...
        location /api/analytics/token-info {
            internal; # Specifies that a given location can only be used for internal requests

            set $bearerToken $arg_token;
            set $args "";

            proxy_pass_request_headers on;

            proxy_ssl_protocols            TLSv1 TLSv1.1 TLSv1.2;
            proxy_ssl_ciphers              HIGH:!aNULL:!MD5;
            proxy_ssl_certificate          /etc/certs/analytics_proxy_client_public.cert.pem;
            proxy_ssl_certificate_key      /etc/certs/analytics_proxy_client_private.key.pem;
            proxy_ssl_trusted_certificate  /etc/certs/analytics_proxy_client_ca.cert.pem;

            proxy_ssl_verify         on;
            proxy_ssl_verify_depth    2;
            proxy_ssl_session_reuse off;

            proxy_set_header Host apimy;
            proxy_set_header Content-Type "application/json";
            proxy_set_header Accept "application/json";
            proxy_set_header Authorization "Bearer $bearerToken";

            proxy_pass    https://apimy/api/analytics/token-info; # trailing slash
        }

另一个注意事项,无论我怎么都不能让bearerToken工作从lua那边传递出来,我必须把它作为一个arg传递,然后在那之后清除args,所以任何其他人都没有进入呼叫。我的lua代码调用路径。

-- Connect --
ngx.log(ngx.DEBUG, '**** Connect with TLS ****');

res = ngx.location.capture('/api/analytics/token-info',
{
    method = ngx.HTTP_POST,
    body = json.encode(query),
    args = {
        token = accessToken;
    }
})
答案

忘记luasec,你的最后一个代码片段没有意义。

LuaSec与LuaSocket兼容,并且与nginx cosocket API完全不兼容。

使用通用的resty-http request_uri()接口:

  local http = require "resty.http"
  local httpc = http.new()
  local res, err = httpc:request_uri("https://example.com:443/helloworld", {
    method = "POST",
    body = "a=1&b=2",
    headers = {
      ["Content-Type"] = "application/x-www-form-urlencoded",
    },
    ssl_verify = true
  })

顺便说一下,request_uri() source是如何使用通用resty-http API(connect / ssl_handshake / request)的完美示例

更新:

如果您确实需要通过证书对客户端进行身份验证,则可以使用下一种方法:

创建上游,配置客户端证书:

  location /my_upstream/ {
      internal; # Specifies that a given location can only be used for internal requests
      proxy_pass_request_headers off;
      proxy_set_header Host backend.example.com;
      proxy_set_header Content-Type "application/json";
      proxy_set_header Accept "application/json";
      proxy_set_header Authorization "Bearer $bearerToken"
      proxy_pass                https://backend.example.com/; # trailing slash
      proxy_ssl_certificate     /etc/nginx/client.pem;
      proxy_ssl_certificate_key /etc/nginx/client.key
      proxy_ssl_verify on;
      proxy_ssl_verify_depth 2; #just example
      proxy_ssl_trusted_certificate /etc/nginx/ca.pem;
  }

使用ngx.location.capture API发出同步但仍然无阻塞的Nginx子请求:

local res = ngx.location.capture('/my_upstream/login',
    {
        method = ngx.HTTP_POST,
        body = "some text",
        vars = {
                    bearerToken = "12345"
               }
    })

请不要淹没RTFM关于ngx.location.capture API和proxy_pass的所有细节

PS:期待你的最新更新 - 不能相信有人会同时要求客户证书和令牌授权。通常,没有客户端证书的HTTPS用于安全传输,而授权标头用于身份验证。

以上是关于从openresty lua发出https tls请求的主要内容,如果未能解决你的问题,请参考以下文章

openresty + lua+项目环境搭建

openresty + lua+项目环境搭建

Nginx视频教程 反向代理/https/openresty/lua实战

Openresty 安装 cjson

验证 Openresty+Lua+GraphicsMagick

高并发 Nginx+Lua OpenResty系列——Lua模版渲染