Skip to content

Commit dd72c5b

Browse files
committed
Adds the StripClientHello option to prevent logging of the initial ClientHello message during a connection upgrade in autossl mode.
- feat(opts): Add `StripClientHello` connection option - feat(autossl): Add function to check if searching for ClientHello - feat(log): Skip logging ClientHello when `StripClientHello` is enabled - test(opts): Add test coverage for `StripClientHello` option - docs: Add `StripClientHello` to documentation and examples - chore: Add new contributor to AUTHORS.md
1 parent ec01fc3 commit dd72c5b

11 files changed

Lines changed: 94 additions & 5 deletions

File tree

‎AUTHORS.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ patches or pull requests, in chronological order of their first contribution:
2727
- Levente Polyak ([anthraxx](https://github.com/anthraxx))
2828
- Nick French ([naf419](https://github.com/naf419))
2929
- Cihan Kömeçoğlu ([cihankom](https://github.com/cihankom))
30+
- Drew Bonasera ([Drewsif](https://github.com/Drewsif))
3031

3132
Many more individuals have contributed by reporting bugs or feature requests.
3233
See [issue tracker on Github][1], `NEWS.md` and `git log` for details.

‎README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ connection options too:
134134

135135
RemoveHTTPAcceptEncoding (yes|no)
136136
RemoveHTTPReferer (yes|no)
137+
StripClientHello (yes|no)
137138
MaxHTTPHeaderSize 8192
138139
ValidateProto (yes|no)
139140

@@ -461,6 +462,7 @@ connection options too:
461462

462463
RemoveHTTPAcceptEncoding (yes|no)
463464
RemoveHTTPReferer (yes|no)
465+
StripClientHello (yes|no)
464466
MaxHTTPHeaderSize 8192
465467
ValidateProto (yes|no)
466468

‎src/opts.c‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ conn_opts_copy(conn_opts_t *conn_opts, const char *argv0, tmp_opts_t *tmp_opts)
613613
cops->validate_proto = conn_opts->validate_proto;
614614
cops->reconnect_ssl = conn_opts->reconnect_ssl;
615615
cops->max_http_header_size = conn_opts->max_http_header_size;
616+
cops->stripclienthello = conn_opts->stripclienthello;
616617

617618
// Pass NULL as tmp_opts param, so we don't reassign the var to itself
618619
// That would be harmless but incorrect
@@ -1129,7 +1130,7 @@ conn_opts_str(conn_opts_t *conn_opts)
11291130
#ifndef WITHOUT_USERAUTH
11301131
"%s|%s|%d"
11311132
#endif /* !WITHOUT_USERAUTH */
1132-
"%s%s|%d",
1133+
"%s%s%s|%d",
11331134
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20702000L)
11341135
#ifdef HAVE_SSLV2
11351136
(conn_opts->sslmethod == SSLv2_method) ? "ssl2" :
@@ -1264,6 +1265,7 @@ conn_opts_str(conn_opts_t *conn_opts)
12641265
#endif /* !WITHOUT_USERAUTH */
12651266
(conn_opts->validate_proto ? "|validate_proto" : ""),
12661267
(conn_opts->reconnect_ssl ? "|reconnect_ssl" : ""),
1268+
(conn_opts->stripclienthello ? "|stripclienthello" : ""),
12671269
conn_opts->max_http_header_size
12681270
) < 0) {
12691271
return oom_return_na_null();
@@ -1605,6 +1607,18 @@ opts_unset_passthrough(conn_opts_t *conn_opts)
16051607
conn_opts->passthrough = 0;
16061608
}
16071609

1610+
void
1611+
opts_set_stripclienthello(conn_opts_t *conn_opts)
1612+
{
1613+
conn_opts->stripclienthello = 1;
1614+
}
1615+
1616+
void
1617+
opts_unset_stripclienthello(conn_opts_t *conn_opts)
1618+
{
1619+
conn_opts->stripclienthello = 0;
1620+
}
1621+
16081622
int
16091623
opts_set_clientcrt(conn_opts_t *conn_opts, const char *argv0, const char *optarg, tmp_opts_t *tmp_opts)
16101624
{
@@ -2784,6 +2798,14 @@ set_conn_opts_option(conn_opts_t *conn_opts, const char *argv0,
27842798
yes ? opts_set_remove_http_referer(conn_opts) : opts_unset_remove_http_referer(conn_opts);
27852799
#ifdef DEBUG_OPTS
27862800
log_dbg_printf("RemoveHTTPReferer: %u\n", conn_opts->remove_http_referer);
2801+
#endif /* DEBUG_OPTS */
2802+
} else if (equal(name, "StripClientHello")) {
2803+
yes = check_value_yesno(value, "StripClientHello", line_num);
2804+
if (yes == -1)
2805+
return -1;
2806+
yes ? opts_set_stripclienthello(conn_opts) : opts_unset_stripclienthello(conn_opts);
2807+
#ifdef DEBUG_OPTS
2808+
log_dbg_printf("StripClientHello: %u\n", conn_opts->stripclienthello);
27872809
#endif /* DEBUG_OPTS */
27882810
}
27892811
else {

‎src/opts.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ typedef struct conn_opts {
146146
// Used with struct filtering rules only
147147
unsigned int reconnect_ssl : 1;
148148
unsigned int max_http_header_size;
149+
unsigned int stripclienthello : 1;
149150
} conn_opts_t;
150151

151152
typedef struct opts {
@@ -313,6 +314,8 @@ int opts_set_chain(conn_opts_t *, const char *, const char *, tmp_opts_t *) NONN
313314
int opts_set_leafcrlurl(conn_opts_t *, const char *, const char *, tmp_opts_t *) NONNULL(1,2,3) WUNRES;
314315
void opts_set_deny_ocsp(conn_opts_t *) NONNULL(1);
315316
void opts_set_passthrough(conn_opts_t *) NONNULL(1);
317+
void opts_set_stripclienthello(conn_opts_t *) NONNULL(1);
318+
void opts_unset_stripclienthello(conn_opts_t *) NONNULL(1);
316319
int opts_set_clientcrt(conn_opts_t *, const char *, const char *, tmp_opts_t *) NONNULL(1,2,3) WUNRES;
317320
int opts_set_clientkey(conn_opts_t *, const char *, const char *, tmp_opts_t *) NONNULL(1,2,3) WUNRES;
318321
#ifndef OPENSSL_NO_DH

‎src/protoautossl.c‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,17 @@ struct protoautossl_ctx {
4242
unsigned int clienthello_found : 1; /* 1 if conn upgrade to SSL */
4343
};
4444

45+
int
46+
protoautossl_is_searching(pxy_conn_ctx_t *ctx)
47+
{
48+
protoautossl_ctx_t *autossl_ctx;
49+
if (!ctx->protoctx) {
50+
return 0;
51+
}
52+
autossl_ctx = ctx->protoctx->arg;
53+
return autossl_ctx && autossl_ctx->clienthello_search;
54+
}
55+
4556
#ifdef DEBUG_PROXY
4657
static void NONNULL(1,2,3)
4758
protoautossl_log_dbg_evbuf_info(pxy_conn_ctx_t *ctx, pxy_conn_desc_t *this, pxy_conn_desc_t *other)

‎src/protoautossl.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,6 @@
3535
protocol_t protoautossl_setup(pxy_conn_ctx_t *) NONNULL(1);
3636
protocol_t protoautossl_setup_child(pxy_conn_child_ctx_t *) NONNULL(1);
3737

38+
int protoautossl_is_searching(pxy_conn_ctx_t *) NONNULL(1);
39+
3840
#endif /* PROTOAUTOSSL_H */

‎src/pxyconn.c‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,20 @@ pxy_bev_readcb_preexec_logging_and_stats(struct bufferevent *bev, pxy_conn_ctx_t
13231323
}
13241324

13251325
if (WANT_CONTENT_LOG(ctx->conn)) {
1326+
if (ctx->conn_opts->stripclienthello && ctx->proto == PROTO_AUTOSSL && bev == ctx->src.bev) {
1327+
if (protoautossl_is_searching(ctx)) {
1328+
size_t inbuf_len = evbuffer_get_length(inbuf);
1329+
size_t pullup_len = inbuf_len > 4096 ? 4096 : inbuf_len;
1330+
unsigned char *data = evbuffer_pullup(inbuf, pullup_len);
1331+
if (data) {
1332+
const unsigned char *chello = NULL;
1333+
int rv = ssl_tls_clienthello_parse(data, pullup_len, 0, &chello, NULL);
1334+
if (rv == 0 || (rv == 1 && chello != NULL)) {
1335+
return 0;
1336+
}
1337+
}
1338+
}
1339+
}
13261340
// HTTP content logging at this point may record certain header lines twice, if we have not seen all headers yet
13271341
return pxy_log_content_inbuf(ctx, inbuf, (bev == ctx->src.bev));
13281342
}
@@ -1371,6 +1385,20 @@ pxy_bev_readcb_preexec_logging_and_stats_child(struct bufferevent *bev, pxy_conn
13711385
}
13721386

13731387
if (WANT_CONTENT_LOG(ctx->conn)) {
1388+
if (ctx->conn->conn_opts->stripclienthello && ctx->conn->proto == PROTO_AUTOSSL && bev == ctx->src.bev) {
1389+
if (protoautossl_is_searching(ctx->conn)) {
1390+
size_t inbuf_len = evbuffer_get_length(inbuf);
1391+
size_t pullup_len = inbuf_len > 4096 ? 4096 : inbuf_len;
1392+
unsigned char *data = evbuffer_pullup(inbuf, pullup_len);
1393+
if (data) {
1394+
const unsigned char *chello = NULL;
1395+
int rv = ssl_tls_clienthello_parse(data, pullup_len, 0, &chello, NULL);
1396+
if (rv == 0 || (rv == 1 && chello != NULL)) {
1397+
return 0;
1398+
}
1399+
}
1400+
}
1401+
}
13741402
return pxy_log_content_inbuf(ctx->conn, inbuf, (bev == ctx->src.bev));
13751403
}
13761404
return 0;

‎src/sslproxy.1‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ ProxySpec {
168168

169169
RemoveHTTPAcceptEncoding (yes|no)
170170
RemoveHTTPReferer (yes|no)
171+
StripClientHello (yes|no)
171172
MaxHTTPHeaderSize 8192
172173
ValidateProto (yes|no)
173174

@@ -475,6 +476,7 @@ FilterRule {
475476

476477
RemoveHTTPAcceptEncoding (yes|no)
477478
RemoveHTTPReferer (yes|no)
479+
StripClientHello (yes|no)
478480
MaxHTTPHeaderSize 8192
479481
ValidateProto (yes|no)
480482

‎src/sslproxy.conf‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ RemoveHTTPAcceptEncoding no
221221
# Remove HTTP header line for Referer
222222
RemoveHTTPReferer yes
223223

224+
# Strip ClientHello messages from content, PCAP, and mirror logs during autossl mode
225+
#StripClientHello no
226+
224227
# Verify peer using default certificates
225228
VerifyPeer yes
226229

@@ -366,6 +369,7 @@ PassUsers admin
366369
# RemoveHTTPReferer (yes|no)
367370
# VerifyPeer (yes|no)
368371
# AllowWrongHost (yes|no)
372+
# StripClientHello (yes|no)
369373
# UserAuth (yes|no)
370374
# UserTimeout 300
371375
# UserAuthURL https://192.168.0.1/userdblogin.php
@@ -435,6 +439,7 @@ ProxySpec {
435439
RemoveHTTPAcceptEncoding no
436440
RemoveHTTPReferer yes
437441
VerifyPeer yes
442+
#StripClientHello no
438443

439444
UserAuth yes
440445
UserTimeout 300

‎src/sslproxy.conf.5‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,14 @@ Remove HTTP header line for Referer.
281281
.br
282282
Default: yes
283283
.TP
284+
\fBStripClientHello BOOL\fR
285+
Strip ClientHello messages from content, PCAP, and mirror logs during autossl mode.
286+
When a connection is upgraded from plain TCP to SSL/TLS in autossl mode,
287+
the initial cleartext ClientHello message sent by the client is stripped
288+
from the logs to prevent polluting them with the SSL handshake.
289+
.br
290+
Default: no
291+
.TP
284292
\fBVerifyPeer BOOL\fR
285293
Verify peer using default certificates.
286294
.br
@@ -485,6 +493,8 @@ RemoveHTTPAcceptEncoding
485493
.br
486494
RemoveHTTPReferer
487495
.br
496+
StripClientHello
497+
.br
488498
MaxHTTPHeaderSize
489499
.br
490500
ValidateProto
@@ -576,6 +586,8 @@ RemoveHTTPAcceptEncoding
576586
.br
577587
RemoveHTTPReferer
578588
.br
589+
StripClientHello
590+
.br
579591
MaxHTTPHeaderSize
580592
.br
581593
ValidateProto

0 commit comments

Comments
 (0)