Skip to content

Commit 31a5069

Browse files
Jas0n99denji
authored andcommitted
Update patch for NGINX 1.17.7+ (#3)
1 parent fc95cc0 commit 31a5069

File tree

1 file changed

+260
-0
lines changed

1 file changed

+260
-0
lines changed
+260
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
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+
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
29+
index 6a0e8c0..384dd4a 100644
30+
--- a/src/event/ngx_event_openssl.c
31+
+++ b/src/event/ngx_event_openssl.c
32+
@@ -1507,6 +1507,7 @@ ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
33+
34+
sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
35+
sc->buffer_size = ssl->buffer_size;
36+
+ sc->dyn_rec = ssl->dyn_rec;
37+
38+
sc->session_ctx = ssl->ctx;
39+
40+
@@ -2400,6 +2401,41 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
41+
42+
for ( ;; ) {
43+
44+
+ /* Dynamic record resizing:
45+
+ We want the initial records to fit into one TCP segment
46+
+ so we don't get TCP HoL blocking due to TCP Slow Start.
47+
+ A connection always starts with small records, but after
48+
+ a given amount of records sent, we make the records larger
49+
+ to reduce header overhead.
50+
+ After a connection has idled for a given timeout, begin
51+
+ the process from the start. The actual parameters are
52+
+ configurable. If dyn_rec_timeout is 0, we assume dyn_rec is off. */
53+
+
54+
+ if (c->ssl->dyn_rec.timeout > 0 ) {
55+
+
56+
+ if (ngx_current_msec - c->ssl->dyn_rec_last_write >
57+
+ c->ssl->dyn_rec.timeout)
58+
+ {
59+
+ buf->end = buf->start + c->ssl->dyn_rec.size_lo;
60+
+ c->ssl->dyn_rec_records_sent = 0;
61+
+
62+
+ } else {
63+
+ if (c->ssl->dyn_rec_records_sent >
64+
+ c->ssl->dyn_rec.threshold * 2)
65+
+ {
66+
+ buf->end = buf->start + c->ssl->buffer_size;
67+
+
68+
+ } else if (c->ssl->dyn_rec_records_sent >
69+
+ c->ssl->dyn_rec.threshold)
70+
+ {
71+
+ buf->end = buf->start + c->ssl->dyn_rec.size_hi;
72+
+
73+
+ } else {
74+
+ buf->end = buf->start + c->ssl->dyn_rec.size_lo;
75+
+ }
76+
+ }
77+
+ }
78+
+
79+
while (in && buf->last < buf->end && send < limit) {
80+
if (in->buf->last_buf || in->buf->flush) {
81+
flush = 1;
82+
@@ -2507,6 +2543,9 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
83+
84+
if (n > 0) {
85+
86+
+ c->ssl->dyn_rec_records_sent++;
87+
+ c->ssl->dyn_rec_last_write = ngx_current_msec;
88+
+
89+
if (c->ssl->saved_read_handler) {
90+
91+
c->read->handler = c->ssl->saved_read_handler;
92+
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
93+
index 61da0c5..cd2759e 100644
94+
--- a/src/event/ngx_event_openssl.h
95+
+++ b/src/event/ngx_event_openssl.h
96+
@@ -64,10 +64,19 @@
97+
#endif
98+
99+
100+
+typedef struct {
101+
+ ngx_msec_t timeout;
102+
+ ngx_uint_t threshold;
103+
+ size_t size_lo;
104+
+ size_t size_hi;
105+
+} ngx_ssl_dyn_rec_t;
106+
+
107+
+
108+
struct ngx_ssl_s {
109+
SSL_CTX *ctx;
110+
ngx_log_t *log;
111+
size_t buffer_size;
112+
+ ngx_ssl_dyn_rec_t dyn_rec;
113+
};
114+
115+
116+
@@ -99,6 +108,10 @@ struct ngx_ssl_connection_s {
117+
unsigned in_early:1;
118+
unsigned early_preread:1;
119+
unsigned write_blocked:1;
120+
+
121+
+ ngx_ssl_dyn_rec_t dyn_rec;
122+
+ ngx_msec_t dyn_rec_last_write;
123+
+ ngx_uint_t dyn_rec_records_sent;
124+
};
125+
126+
127+
@@ -108,7 +121,7 @@ struct ngx_ssl_connection_s {
128+
#define NGX_SSL_DFLT_BUILTIN_SCACHE -5
129+
130+
131+
-#define NGX_SSL_MAX_SESSION_SIZE 4096
132+
+#define NGX_SSL_MAX_SESSION_SIZE 16384
133+
134+
typedef struct ngx_ssl_sess_id_s ngx_ssl_sess_id_t;
135+
136+
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
137+
index 495e628..9480b73 100644
138+
--- a/src/http/modules/ngx_http_ssl_module.c
139+
+++ b/src/http/modules/ngx_http_ssl_module.c
140+
@@ -249,6 +249,41 @@ static ngx_command_t ngx_http_ssl_commands[] = {
141+
offsetof(ngx_http_ssl_srv_conf_t, early_data),
142+
NULL },
143+
144+
+ { ngx_string("ssl_dyn_rec_enable"),
145+
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
146+
+ ngx_conf_set_flag_slot,
147+
+ NGX_HTTP_SRV_CONF_OFFSET,
148+
+ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_enable),
149+
+ NULL },
150+
+
151+
+ { ngx_string("ssl_dyn_rec_timeout"),
152+
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
153+
+ ngx_conf_set_msec_slot,
154+
+ NGX_HTTP_SRV_CONF_OFFSET,
155+
+ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_timeout),
156+
+ NULL },
157+
+
158+
+ { ngx_string("ssl_dyn_rec_size_lo"),
159+
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
160+
+ ngx_conf_set_size_slot,
161+
+ NGX_HTTP_SRV_CONF_OFFSET,
162+
+ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_size_lo),
163+
+ NULL },
164+
+
165+
+ { ngx_string("ssl_dyn_rec_size_hi"),
166+
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
167+
+ ngx_conf_set_size_slot,
168+
+ NGX_HTTP_SRV_CONF_OFFSET,
169+
+ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_size_hi),
170+
+ NULL },
171+
+
172+
+ { ngx_string("ssl_dyn_rec_threshold"),
173+
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
174+
+ ngx_conf_set_num_slot,
175+
+ NGX_HTTP_SRV_CONF_OFFSET,
176+
+ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_threshold),
177+
+ NULL },
178+
+
179+
ngx_null_command
180+
};
181+
182+
@@ -580,6 +615,11 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
183+
sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
184+
sscf->stapling = NGX_CONF_UNSET;
185+
sscf->stapling_verify = NGX_CONF_UNSET;
186+
+ sscf->dyn_rec_enable = NGX_CONF_UNSET;
187+
+ sscf->dyn_rec_timeout = NGX_CONF_UNSET_MSEC;
188+
+ sscf->dyn_rec_size_lo = NGX_CONF_UNSET_SIZE;
189+
+ sscf->dyn_rec_size_hi = NGX_CONF_UNSET_SIZE;
190+
+ sscf->dyn_rec_threshold = NGX_CONF_UNSET_UINT;
191+
192+
return sscf;
193+
}
194+
@@ -647,6 +687,20 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
195+
ngx_conf_merge_str_value(conf->stapling_responder,
196+
prev->stapling_responder, "");
197+
198+
+ ngx_conf_merge_value(conf->dyn_rec_enable, prev->dyn_rec_enable, 0);
199+
+ ngx_conf_merge_msec_value(conf->dyn_rec_timeout, prev->dyn_rec_timeout,
200+
+ 1000);
201+
+ /* Default sizes for the dynamic record sizes are defined to fit maximal
202+
+ TLS + IPv6 overhead in a single TCP segment for lo and 3 segments for hi:
203+
+ 1369 = 1500 - 40 (IP) - 20 (TCP) - 10 (Time) - 61 (Max TLS overhead) */
204+
+ ngx_conf_merge_size_value(conf->dyn_rec_size_lo, prev->dyn_rec_size_lo,
205+
+ 1369);
206+
+ /* 4229 = (1500 - 40 - 20 - 10) * 3 - 61 */
207+
+ ngx_conf_merge_size_value(conf->dyn_rec_size_hi, prev->dyn_rec_size_hi,
208+
+ 4229);
209+
+ ngx_conf_merge_uint_value(conf->dyn_rec_threshold, prev->dyn_rec_threshold,
210+
+ 40);
211+
+
212+
conf->ssl.log = cf->log;
213+
214+
if (conf->enable) {
215+
@@ -857,6 +911,28 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
216+
return NGX_CONF_ERROR;
217+
}
218+
219+
+ if (conf->dyn_rec_enable) {
220+
+ conf->ssl.dyn_rec.timeout = conf->dyn_rec_timeout;
221+
+ conf->ssl.dyn_rec.threshold = conf->dyn_rec_threshold;
222+
+
223+
+ if (conf->buffer_size > conf->dyn_rec_size_lo) {
224+
+ conf->ssl.dyn_rec.size_lo = conf->dyn_rec_size_lo;
225+
+
226+
+ } else {
227+
+ conf->ssl.dyn_rec.size_lo = conf->buffer_size;
228+
+ }
229+
+
230+
+ if (conf->buffer_size > conf->dyn_rec_size_hi) {
231+
+ conf->ssl.dyn_rec.size_hi = conf->dyn_rec_size_hi;
232+
+
233+
+ } else {
234+
+ conf->ssl.dyn_rec.size_hi = conf->buffer_size;
235+
+ }
236+
+
237+
+ } else {
238+
+ conf->ssl.dyn_rec.timeout = 0;
239+
+ }
240+
+
241+
return NGX_CONF_OK;
242+
}
243+
244+
diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h
245+
index 26fdccf..b14b52a 100644
246+
--- a/src/http/modules/ngx_http_ssl_module.h
247+
+++ b/src/http/modules/ngx_http_ssl_module.h
248+
@@ -61,6 +61,12 @@ typedef struct {
249+
250+
u_char *file;
251+
ngx_uint_t line;
252+
+
253+
+ ngx_flag_t dyn_rec_enable;
254+
+ ngx_msec_t dyn_rec_timeout;
255+
+ size_t dyn_rec_size_lo;
256+
+ size_t dyn_rec_size_hi;
257+
+ ngx_uint_t dyn_rec_threshold;
258+
} ngx_http_ssl_srv_conf_t;
259+
260+

0 commit comments

Comments
 (0)