OpenResty实战之WebSocket应用与SSL证书校验

  Seves

本文链接:OpenResty实战之WebSocket应用与SSL证书校验

本文主要介绍如何在OpenResty中使用WebSocket并做SSL证书校验

nginx配置及lua代码如下:

=== TEST 24: SSL with ssl_verify
--- no_check_leak
--- http_config eval: $::HttpConfig
--- config

nginx配置:

    listen 12345 ssl;
    server_name test.com;
    ssl_certificate ../../cert/test.crt;
    ssl_certificate_key ../../cert/test.key;
    server_tokens off;

    resolver 127.0.0.1:1953 ipv6=off;
    resolver_timeout 1s;

    lua_ssl_trusted_certificate ../../cert/test.crt;
    lua_ssl_verify_depth 1;

webSocket客户端代码:

    location = /c {
        content_by_lua '
            local client = require "resty.websocket.client"
            local wb, err = client:new()

            local uri = "wss://test.com:12345/s"
            local ok, err = wb:connect(uri, {ssl_verify = true})
            if not ok then
                ngx.say("failed to connect: " .. err)
                return
            end

            local data = "hello"
            local bytes, err = wb:send_text(data)
            if not bytes then
                ngx.say("failed to send frame: ", err)
                return
            end

            local typ
            data, typ, err = wb:recv_frame()
            if not data then
                ngx.say("failed to receive 2nd frame: ", err)
                return
            end

            ngx.say("received: ", data, " (", typ, ")")

            local ok, err = wb:close()
            if not ok then
                ngx.say("failed to close conn: ", err)
                return
            end
        ';
    }

webSocket服务端代码:

    location = /s {
        content_by_lua '
            local server = require "resty.websocket.server"
            local wb, err = server:new()
            if not wb then
                ngx.log(ngx.ERR, "failed to new websocket: ", err)
                return ngx.exit(444)
            end

            local data, typ, err = wb:recv_frame()
            if not data then
                -- ngx.log(ngx.ERR, "failed to receive a frame: ", err)
                return ngx.exit(444)
            end

            -- send it back!
            local bytes, err = wb:send_text(data)
            if not bytes then
                ngx.log(ngx.ERR, "failed to send the 2nd text: ", err)
                return ngx.exit(444)
            end
        ';
    }


dns解析代码:

--- udp_listen: 1953
--- udp_reply eval
sub {
    # Get DNS request ID from passed UDP datagram
    my $dns_id = unpack("n", shift);
    # Set name and encode it
    my $name = "test.com";
    $name =~ s/([^.]+)\.?/chr(length($1)) . $1/ge;
    $name .= "\0";
    my $s = '';
    $s .= pack("n", $dns_id);
    # DNS response flags, hardcoded
    my $flags = (1 << 15) + (0 << 11) + (0 << 10) + (0 << 9) + (1 << 8) + (1 << 7) + 0;
    $flags = pack("n", $flags);
    $s .= $flags;
    $s .= pack("nnnn", 1, 1, 0, 0);
    $s .= $name;
    $s .= pack("nn", 1, 1);
    # Set response address and pack it
    my @addr = split /\./, "127.0.0.1";
    my $data = pack("CCCC", @addr);
    $s .= $name. pack("nnNn", 1, 1, 1, 4) . $data;
    return $s;
}

输出:

--- request
GET /c
--- response_body
received: hello (text)

--- no_error_log
[error]
[warn]

--- timeout: 10

代码参考 官方测试的代码

注意:

如果client和server端分开部署,两端都要配置证书,如下:

    server_name test.com;
    ssl_certificate ../../cert/test.crt;
    ssl_certificate_key ../../cert/test.key;
	
    resolver 127.0.0.1:1953 ipv6=off;
    resolver_timeout 1s;

    lua_ssl_trusted_certificate ../../cert/test.crt;
    lua_ssl_verify_depth 1;

resolver也可以换成本地/etc/resolv.conf文件里的ip,如下:

resolver 127.0.0.1 202.106.0.20;

如果用本地/etc/resolv.conf文件里的ip,则不需要上面的sub配置。

本文链接:https://www.tech-field.org/openresty-with-ssl-verify-in-websocket.html

fc