Klaus Demo nginx / d5a2700
SSL: save sessions for upstream peers using a callback function. In TLSv1.3, NewSessionTicket messages arrive after the handshake and can come at any time. Therefore we use a callback to save the session when we know about it. This approach works for < TLSv1.3 as well. The callback function is set once per location on merge phase. Since SSL_get_session() in BoringSSL returns an unresumable session for TLSv1.3, peer save_session() methods have been updated as well to use a session supplied within the callback. To preserve API, the session is cached in c->ssl->session. It is preferably accessed in save_session() methods by ngx_ssl_get_session() and ngx_ssl_get0_session() wrappers. Sergey Kandaurov 3 years ago
9 changed file(s) with 139 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
2323 static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
2424 int ret);
2525 static void ngx_ssl_passwords_cleanup(void *data);
26 static int ngx_ssl_new_client_session(ngx_ssl_conn_t *ssl_conn,
27 ngx_ssl_session_t *sess);
2628 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
2729 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
2830 static void ngx_ssl_write_handler(ngx_event_t *wev);
11611163
11621164
11631165 ngx_int_t
1166 ngx_ssl_client_session_cache(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t enable)
1167 {
1168 if (!enable) {
1169 return NGX_OK;
1170 }
1171
1172 SSL_CTX_set_session_cache_mode(ssl->ctx,
1173 SSL_SESS_CACHE_CLIENT
1174 |SSL_SESS_CACHE_NO_INTERNAL);
1175
1176 SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_client_session);
1177
1178 return NGX_OK;
1179 }
1180
1181
1182 static int
1183 ngx_ssl_new_client_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
1184 {
1185 ngx_connection_t *c;
1186
1187 c = ngx_ssl_get_connection(ssl_conn);
1188
1189 if (c->ssl->save_session) {
1190 c->ssl->session = sess;
1191
1192 c->ssl->save_session(c);
1193
1194 c->ssl->session = NULL;
1195 }
1196
1197 return 0;
1198 }
1199
1200
1201 ngx_int_t
11641202 ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
11651203 {
11661204 ngx_ssl_connection_t *sc;
12061244 c->ssl = sc;
12071245
12081246 return NGX_OK;
1247 }
1248
1249
1250 ngx_ssl_session_t *
1251 ngx_ssl_get_session(ngx_connection_t *c)
1252 {
1253 #ifdef TLS1_3_VERSION
1254 if (c->ssl->session) {
1255 SSL_SESSION_up_ref(c->ssl->session);
1256 return c->ssl->session;
1257 }
1258 #endif
1259
1260 return SSL_get1_session(c->ssl->connection);
1261 }
1262
1263
1264 ngx_ssl_session_t *
1265 ngx_ssl_get0_session(ngx_connection_t *c)
1266 {
1267 if (c->ssl->session) {
1268 return c->ssl->session;
1269 }
1270
1271 return SSL_get0_session(c->ssl->connection);
12091272 }
12101273
12111274
7575 size_t buffer_size;
7676
7777 ngx_connection_handler_pt handler;
78
79 ngx_ssl_session_t *session;
80 ngx_connection_handler_pt save_session;
7881
7982 ngx_event_handler_pt saved_read_handler;
8083 ngx_event_handler_pt saved_write_handler;
167170 ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file);
168171 ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file);
169172 ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name);
173 ngx_int_t ngx_ssl_client_session_cache(ngx_conf_t *cf, ngx_ssl_t *ssl,
174 ngx_uint_t enable);
170175 ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
171176 ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout);
172177 ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl,
177182
178183 void ngx_ssl_remove_cached_session(SSL_CTX *ssl, ngx_ssl_session_t *sess);
179184 ngx_int_t ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session);
180 #define ngx_ssl_get_session(c) SSL_get1_session(c->ssl->connection)
185 ngx_ssl_session_t *ngx_ssl_get_session(ngx_connection_t *c);
186 ngx_ssl_session_t *ngx_ssl_get0_session(ngx_connection_t *c);
181187 #define ngx_ssl_free_session SSL_SESSION_free
182188 #define ngx_ssl_get_connection(ssl_conn) \
183189 SSL_get_ex_data(ssl_conn, ngx_ssl_connection_index)
46264626 }
46274627 }
46284628
4629 if (ngx_ssl_client_session_cache(cf, glcf->upstream.ssl,
4630 glcf->upstream.ssl_session_reuse)
4631 != NGX_OK)
4632 {
4633 return NGX_ERROR;
4634 }
4635
46294636 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
46304637
46314638 if (SSL_CTX_set_alpn_protos(glcf->upstream.ssl->ctx,
43074307 }
43084308 }
43094309
4310 if (ngx_ssl_client_session_cache(cf, plcf->upstream.ssl,
4311 plcf->upstream.ssl_session_reuse)
4312 != NGX_OK)
4313 {
4314 return NGX_ERROR;
4315 }
4316
43104317 return NGX_OK;
43114318 }
43124319
23902390 }
23912391 }
23922392
2393 if (ngx_ssl_client_session_cache(cf, uwcf->upstream.ssl,
2394 uwcf->upstream.ssl_session_reuse)
2395 != NGX_OK)
2396 {
2397 return NGX_ERROR;
2398 }
2399
23932400 return NGX_OK;
23942401 }
23952402
186186 static void ngx_http_upstream_ssl_handshake_handler(ngx_connection_t *c);
187187 static void ngx_http_upstream_ssl_handshake(ngx_http_request_t *,
188188 ngx_http_upstream_t *u, ngx_connection_t *c);
189 static void ngx_http_upstream_ssl_save_session(ngx_connection_t *c);
189190 static ngx_int_t ngx_http_upstream_ssl_name(ngx_http_request_t *r,
190191 ngx_http_upstream_t *u, ngx_connection_t *c);
191192 #endif
16741675 }
16751676
16761677 if (u->conf->ssl_session_reuse) {
1678 c->ssl->save_session = ngx_http_upstream_ssl_save_session;
1679
16771680 if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) {
16781681 ngx_http_upstream_finalize_request(r, u,
16791682 NGX_HTTP_INTERNAL_SERVER_ERROR);
17581761 }
17591762 }
17601763
1761 if (u->conf->ssl_session_reuse) {
1762 u->peer.save_session(&u->peer, u->peer.data);
1763 }
1764
17651764 c->write->handler = ngx_http_upstream_handler;
17661765 c->read->handler = ngx_http_upstream_handler;
17671766
17781777 failed:
17791778
17801779 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
1780 }
1781
1782
1783 static void
1784 ngx_http_upstream_ssl_save_session(ngx_connection_t *c)
1785 {
1786 ngx_http_request_t *r;
1787 ngx_http_upstream_t *u;
1788
1789 if (c->idle) {
1790 return;
1791 }
1792
1793 r = c->data;
1794
1795 u = r->upstream;
1796 c = r->connection;
1797
1798 ngx_http_set_log_request(c->log, r);
1799
1800 u->peer.save_session(&u->peer, u->peer.data);
17811801 }
17821802
17831803
743743
744744 if (peers->shpool) {
745745
746 ssl_session = SSL_get0_session(pc->connection->ssl->connection);
746 ssl_session = ngx_ssl_get0_session(pc->connection);
747747
748748 if (ssl_session == NULL) {
749749 return;
9191 ngx_command_t *cmd, void *conf);
9292 static void ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s);
9393 static void ngx_stream_proxy_ssl_handshake(ngx_connection_t *pc);
94 static void ngx_stream_proxy_ssl_save_session(ngx_connection_t *c);
9495 static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s);
9596 static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf,
9697 ngx_stream_proxy_srv_conf_t *pscf);
10071008 }
10081009
10091010 if (pscf->ssl_session_reuse) {
1011 pc->ssl->save_session = ngx_stream_proxy_ssl_save_session;
1012
10101013 if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) {
10111014 ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
10121015 return;
10651068 }
10661069 }
10671070
1068 if (pscf->ssl_session_reuse) {
1069 u = s->upstream;
1070 u->peer.save_session(&u->peer, u->peer.data);
1071 }
1072
10731071 if (pc->write->timer_set) {
10741072 ngx_del_timer(pc->write);
10751073 }
10821080 failed:
10831081
10841082 ngx_stream_proxy_next_upstream(s);
1083 }
1084
1085
1086 static void
1087 ngx_stream_proxy_ssl_save_session(ngx_connection_t *c)
1088 {
1089 ngx_stream_session_t *s;
1090 ngx_stream_upstream_t *u;
1091
1092 s = c->data;
1093 u = s->upstream;
1094
1095 u->peer.save_session(&u->peer, u->peer.data);
10851096 }
10861097
10871098
20502061 }
20512062 }
20522063
2064 if (ngx_ssl_client_session_cache(cf, pscf->ssl, pscf->ssl_session_reuse)
2065 != NGX_OK)
2066 {
2067 return NGX_ERROR;
2068 }
2069
20532070 return NGX_OK;
20542071 }
20552072
775775
776776 if (peers->shpool) {
777777
778 ssl_session = SSL_get0_session(pc->connection->ssl->connection);
778 ssl_session = ngx_ssl_get0_session(pc->connection);
779779
780780 if (ssl_session == NULL) {
781781 return;