Skip to content

Commit 5e3b560

Browse files
authored
Update patch for NGINX 1.15.3+
1 parent 556ed42 commit 5e3b560

File tree

1 file changed

+252
-0
lines changed

1 file changed

+252
-0
lines changed
+252
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
What we do now:
2+
We use a static record size of 4K. This gives a good balance of latency and
3+
throughput.
4+
5+
Optimize latency:
6+
By initialy sending small (1 TCP segment) sized records, we are able to avoid
7+
HoL blocking of the first byte. This means TTFB is sometime lower by a whole
8+
RTT.
9+
10+
Optimizing throughput:
11+
By sending increasingly larger records later in the connection, when HoL is not
12+
a problem, we reduce the overhead of TLS record (29 bytes per record with
13+
GCM/CHACHA-POLY).
14+
15+
Logic:
16+
Start each connection with small records (1369 byte default, change with
17+
ssl_dyn_rec_size_lo). After a given number of records (40, change with
18+
ssl_dyn_rec_threshold) start sending larger records (4229, ssl_dyn_rec_size_hi).
19+
Eventually after the same number of records, start sending the largest records
20+
(ssl_buffer_size).
21+
In case the connection idles for a given amount of time (1s,
22+
ssl_dyn_rec_timeout), the process repeats itself (i.e. begin sending small
23+
records again).
24+
25+
Upstream source:
26+
https://github.com/cloudflare/sslconfig/blob/master/patches/nginx__dynamic_tls_records.patch
27+
28+
--- a/src/event/ngx_event_openssl.c
29+
+++ b/src/event/ngx_event_openssl.c
30+
@@ -1131,6 +1131,7 @@
31+
32+
sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
33+
sc->buffer_size = ssl->buffer_size;
34+
+ sc->dyn_rec = ssl->dyn_rec;
35+
36+
sc->session_ctx = ssl->ctx;
37+
38+
@@ -1669,6 +1670,41 @@
39+
40+
for ( ;; ) {
41+
42+
+ /* Dynamic record resizing:
43+
+ We want the initial records to fit into one TCP segment
44+
+ so we don't get TCP HoL blocking due to TCP Slow Start.
45+
+ A connection always starts with small records, but after
46+
+ a given amount of records sent, we make the records larger
47+
+ to reduce header overhead.
48+
+ After a connection has idled for a given timeout, begin
49+
+ the process from the start. The actual parameters are
50+
+ configurable. If dyn_rec_timeout is 0, we assume dyn_rec is off. */
51+
+
52+
+ if (c->ssl->dyn_rec.timeout > 0 ) {
53+
+
54+
+ if (ngx_current_msec - c->ssl->dyn_rec_last_write >
55+
+ c->ssl->dyn_rec.timeout)
56+
+ {
57+
+ buf->end = buf->start + c->ssl->dyn_rec.size_lo;
58+
+ c->ssl->dyn_rec_records_sent = 0;
59+
+
60+
+ } else {
61+
+ if (c->ssl->dyn_rec_records_sent >
62+
+ c->ssl->dyn_rec.threshold * 2)
63+
+ {
64+
+ buf->end = buf->start + c->ssl->buffer_size;
65+
+
66+
+ } else if (c->ssl->dyn_rec_records_sent >
67+
+ c->ssl->dyn_rec.threshold)
68+
+ {
69+
+ buf->end = buf->start + c->ssl->dyn_rec.size_hi;
70+
+
71+
+ } else {
72+
+ buf->end = buf->start + c->ssl->dyn_rec.size_lo;
73+
+ }
74+
+ }
75+
+ }
76+
+
77+
while (in && buf->last < buf->end && send < limit) {
78+
if (in->buf->last_buf || in->buf->flush) {
79+
flush = 1;
80+
@@ -1770,6 +1806,9 @@
81+
82+
if (n > 0) {
83+
84+
+ c->ssl->dyn_rec_records_sent++;
85+
+ c->ssl->dyn_rec_last_write = ngx_current_msec;
86+
+
87+
if (c->ssl->saved_read_handler) {
88+
89+
c->read->handler = c->ssl->saved_read_handler;
90+
--- a/src/event/ngx_event_openssl.h
91+
+++ b/src/event/ngx_event_openssl.h
92+
@@ -64,10 +64,19 @@
93+
#endif
94+
95+
96+
+typedef struct {
97+
+ ngx_msec_t timeout;
98+
+ ngx_uint_t threshold;
99+
+ size_t size_lo;
100+
+ size_t size_hi;
101+
+} ngx_ssl_dyn_rec_t;
102+
+
103+
+
104+
struct ngx_ssl_s {
105+
SSL_CTX *ctx;
106+
ngx_log_t *log;
107+
size_t buffer_size;
108+
+ ngx_ssl_dyn_rec_t dyn_rec;
109+
};
110+
111+
112+
@@ -95,6 +104,11 @@
113+
unsigned no_wait_shutdown:1;
114+
unsigned no_send_shutdown:1;
115+
unsigned handshake_buffer_set:1;
116+
+
117+
+ ngx_ssl_dyn_rec_t dyn_rec;
118+
+ ngx_msec_t dyn_rec_last_write;
119+
+ ngx_uint_t dyn_rec_records_sent;
120+
+
121+
unsigned try_early_data:1;
122+
unsigned in_early:1;
123+
unsigned early_preread:1;
124+
@@ -107,7 +121,7 @@
125+
#define NGX_SSL_DFLT_BUILTIN_SCACHE -5
126+
127+
128+
-#define NGX_SSL_MAX_SESSION_SIZE 4096
129+
+#define NGX_SSL_MAX_SESSION_SIZE 16384
130+
131+
typedef struct ngx_ssl_sess_id_s ngx_ssl_sess_id_t;
132+
133+
--- a/src/http/modules/ngx_http_ssl_module.c
134+
+++ b/src/http/modules/ngx_http_ssl_module.c
135+
@@ -233,6 +233,41 @@
136+
offsetof(ngx_http_ssl_srv_conf_t, stapling_verify),
137+
NULL },
138+
139+
+ { ngx_string("ssl_dyn_rec_enable"),
140+
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
141+
+ ngx_conf_set_flag_slot,
142+
+ NGX_HTTP_SRV_CONF_OFFSET,
143+
+ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_enable),
144+
+ NULL },
145+
+
146+
+ { ngx_string("ssl_dyn_rec_timeout"),
147+
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
148+
+ ngx_conf_set_msec_slot,
149+
+ NGX_HTTP_SRV_CONF_OFFSET,
150+
+ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_timeout),
151+
+ NULL },
152+
+
153+
+ { ngx_string("ssl_dyn_rec_size_lo"),
154+
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
155+
+ ngx_conf_set_size_slot,
156+
+ NGX_HTTP_SRV_CONF_OFFSET,
157+
+ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_size_lo),
158+
+ NULL },
159+
+
160+
+ { ngx_string("ssl_dyn_rec_size_hi"),
161+
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
162+
+ ngx_conf_set_size_slot,
163+
+ NGX_HTTP_SRV_CONF_OFFSET,
164+
+ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_size_hi),
165+
+ NULL },
166+
+
167+
+ { ngx_string("ssl_dyn_rec_threshold"),
168+
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
169+
+ ngx_conf_set_num_slot,
170+
+ NGX_HTTP_SRV_CONF_OFFSET,
171+
+ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_threshold),
172+
+ NULL },
173+
+
174+
ngx_null_command
175+
};
176+
177+
@@ -533,6 +568,11 @@
178+
sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
179+
sscf->stapling = NGX_CONF_UNSET;
180+
sscf->stapling_verify = NGX_CONF_UNSET;
181+
+ sscf->dyn_rec_enable = NGX_CONF_UNSET;
182+
+ sscf->dyn_rec_timeout = NGX_CONF_UNSET_MSEC;
183+
+ sscf->dyn_rec_size_lo = NGX_CONF_UNSET_SIZE;
184+
+ sscf->dyn_rec_size_hi = NGX_CONF_UNSET_SIZE;
185+
+ sscf->dyn_rec_threshold = NGX_CONF_UNSET_UINT;
186+
187+
return sscf;
188+
}
189+
@@ -598,6 +638,20 @@
190+
ngx_conf_merge_str_value(conf->stapling_responder,
191+
prev->stapling_responder, "");
192+
193+
+ ngx_conf_merge_value(conf->dyn_rec_enable, prev->dyn_rec_enable, 0);
194+
+ ngx_conf_merge_msec_value(conf->dyn_rec_timeout, prev->dyn_rec_timeout,
195+
+ 1000);
196+
+ /* Default sizes for the dynamic record sizes are defined to fit maximal
197+
+ TLS + IPv6 overhead in a single TCP segment for lo and 3 segments for hi:
198+
+ 1369 = 1500 - 40 (IP) - 20 (TCP) - 10 (Time) - 61 (Max TLS overhead) */
199+
+ ngx_conf_merge_size_value(conf->dyn_rec_size_lo, prev->dyn_rec_size_lo,
200+
+ 1369);
201+
+ /* 4229 = (1500 - 40 - 20 - 10) * 3 - 61 */
202+
+ ngx_conf_merge_size_value(conf->dyn_rec_size_hi, prev->dyn_rec_size_hi,
203+
+ 4229);
204+
+ ngx_conf_merge_uint_value(conf->dyn_rec_threshold, prev->dyn_rec_threshold,
205+
+ 40);
206+
+
207+
conf->ssl.log = cf->log;
208+
209+
if (conf->enable) {
210+
@@ -778,6 +832,28 @@
211+
212+
}
213+
214+
+ if (conf->dyn_rec_enable) {
215+
+ conf->ssl.dyn_rec.timeout = conf->dyn_rec_timeout;
216+
+ conf->ssl.dyn_rec.threshold = conf->dyn_rec_threshold;
217+
+
218+
+ if (conf->buffer_size > conf->dyn_rec_size_lo) {
219+
+ conf->ssl.dyn_rec.size_lo = conf->dyn_rec_size_lo;
220+
+
221+
+ } else {
222+
+ conf->ssl.dyn_rec.size_lo = conf->buffer_size;
223+
+ }
224+
+
225+
+ if (conf->buffer_size > conf->dyn_rec_size_hi) {
226+
+ conf->ssl.dyn_rec.size_hi = conf->dyn_rec_size_hi;
227+
+
228+
+ } else {
229+
+ conf->ssl.dyn_rec.size_hi = conf->buffer_size;
230+
+ }
231+
+
232+
+ } else {
233+
+ conf->ssl.dyn_rec.timeout = 0;
234+
+ }
235+
+
236+
return NGX_CONF_OK;
237+
}
238+
239+
--- a/src/http/modules/ngx_http_ssl_module.h
240+
+++ b/src/http/modules/ngx_http_ssl_module.h
241+
@@ -57,6 +57,12 @@
242+
243+
u_char *file;
244+
ngx_uint_t line;
245+
+
246+
+ ngx_flag_t dyn_rec_enable;
247+
+ ngx_msec_t dyn_rec_timeout;
248+
+ size_t dyn_rec_size_lo;
249+
+ size_t dyn_rec_size_hi;
250+
+ ngx_uint_t dyn_rec_threshold;
251+
} ngx_http_ssl_srv_conf_t;
252+

0 commit comments

Comments
 (0)