openresty中upstream侧ssl session reuse功能无法生效分析

最近做项目,以openresty为基础,在upstream侧通过nginx的指令开启SSL连接复用,但实际是不生效的,通过使用原生的程序nginx、openresty进行复现,明白了问题所在,也更加理解openresty与nginx的共性和特性。

自己在服务器中利用未经修改的nginx、openresty测试,编译的时候开启debug,能够在debug中看到upstream侧save、set session的操作。

nginx
简单的配置如下,upstream侧 ssl session reuse默认开启。

upstream web_server {
        server 127.0.0.1:13579;
}
server {
        listen 1234;
        location / {
                proxy_pass https://web_server;
                proxy_http_version 1.1;
        }
}

通过debug观察,upstream侧连接SSL连接建立成功后,会有save session的操作。

[debug] 32028#0: *1 SSL handshake handler: 0
[debug] 32028#0: *1 SSL_do_handshake: 1
[debug] 32028#0: *1 SSL: TLSv1.2, cipher: "ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD"
[debug] 32028#0: *1 http upstream ssl handshake: "/?"
[debug] 32028#0: *1 save session: 000000000217C970
[debug] 32028#0: *1 http upstream send request
[debug] 32028#0: *1 http upstream send request body
[debug] 32028#0: *1 chain writer buf fl:1 s:92
[debug] 32028#0: *1 chain writer in: 0000000002154C78
[debug] 32028#0: *1 malloc: 00000000021EBAE0:80

openresty环境 加入balance.lua脚本 未选peer
balance.lua 只是简单的引入balance_by_lua_file的指令,lua脚本为空,让其运行

upstream webserver {
         server 127.0.0.1:13579;
         balancer_by_lua_file `pwd`/balance.lua;
}

通过调试观察,save session可以得到执行

[debug] 1908#0: *1 SSL handshake handler: 0
[debug] 1908#0: *1 SSL_do_handshake: 1
[debug] 1908#0: *1 SSL: TLSv1.2, cipher: "ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD"
[debug] 1908#0: *1 http upstream ssl handshake: "/?"
[debug] 1908#0: *1 lua balancer save session
[debug] 1908#0: *1 save session: 000000000197D970
[debug] 1908#0: *1 http upstream send request
[debug] 1908#0: *1 http upstream send request body

openresty环境 加入balance.lua脚本 选出peer
在上面的脚本中,强制返回选出的upstream主机

ngx.log(ngx.ERR, ip, "balance session store")
local balancer = require "ngx.balancer"
local backend="127.0.0.1"
local port=13579
local ok, err = balancer.set_current_peer(backend, port)
if not ok then
    ngx.log(ngx.ERR, "failed to set the current peer: ", err)
    return ngx.exit(500)
end

观察debug信息,在ssl握手完成后,没有保存ssl session的操作

[debug] 3122#0: *5 SSL handshake handler: 0
[debug] 3122#0: *5 SSL_do_handshake: 1
[debug] 3122#0: *5 SSL: TLSv1.2, cipher: "ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD"
[debug] 3122#0: *5 http upstream ssl handshake: "/?"
[debug] 3122#0: *5 lua balancer save session
[debug] 3122#0: *5 http upstream send request
[debug] 3122#0: *5 http upstream send request body
[debug] 3122#0: *5 chain writer buf fl:1 s:92

通过深入openresty中balance_by_lua的源码查看

在初始化时,会将upstream侧的session操作替换为自己的。

ngx_http_lua_balancer_init_peer() {
	r->upstream->peer.set_session = ngx_http_lua_balancer_set_session;
	r->upstream->peer.save_session = ngx_http_lua_balancer_save_session;
}

在处理阶段,通过balance的lua脚本,如果正确调用了balancer.set_current_peer则会将bp中的sockaddr与socklen设置上,从而直接返回,如果没有,则走nginx原先的流程。

ngx_http_lua_balancer_get_peer()
{
	rc = lscf->balancer.handler(r, lscf, L);
	if (bp->sockaddr && bp->socklen) { 
		return NGX_OK;
	}
	return ngx_http_upstream_get_round_robin_peer(pc, &bp->rrp);
}

再看看替换的读取与设置ssl session的回调,如果是lua脚本选出的peer,则直接返回,其实可以在这里加入自控session reuse的代码。否则走原先nginx的代码。

ngx_http_lua_balancer_save_session
{
	if (bp->sockaddr && bp->socklen) {                                    
    	/* TODO */                                                        
    	return;                                                           
	}                                                                     
	return ngx_http_upstream_save_round_robin_peer_session(pc, &bp->rrp);  
}

为什么这么处理,算是bug还是未做完的开发?深入想想,这应该是周全的设计。
nginx中的配置都是静态的,upstream侧有多少台主机都可知,session的存储与具体的主机关联即可,但是openresty是动态的,选择出的主机与nginx的配置没有任何关系,信息的存储需要自己编写脚本代码实现。通过代码也可以看出,当balance的lua脚本没有得出主机,则继续执行nginx原有的流程。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值