Fix autossl without STARTTLS in divert mode

In the previous implementation, the use case for autossl was assumed to
be STARTTLS with POP3 or SMTP. But there are users who use autossl with
HTTP too. The split mode was fine, but the divert mode was broken. This
change makes autossl a generic upgrade mechanism.
Also fix sslproxy line in autossl, change p to s if upgraded.
Add e2e tests for autossl in divert and split mode.
This commit is contained in:
Soner Tari 2022-04-11 01:11:04 +03:00
parent 45abd2e85c
commit 63a48308cd
11 changed files with 437 additions and 67 deletions

View File

@ -136,6 +136,46 @@ protoautossl_setup_dst_new_bev_ssl_connecting(pxy_conn_ctx_t *ctx)
return 0;
}
static void NONNULL(1)
protoautossl_upgrade_dst(pxy_conn_ctx_t *ctx)
{
if (protossl_setup_dst_ssl(ctx) == -1) {
return;
}
if (protoautossl_setup_dst_new_bev_ssl_connecting(ctx) == -1) {
return;
}
bufferevent_setcb(ctx->dst.bev, pxy_bev_readcb, pxy_bev_writecb, pxy_bev_eventcb, ctx);
}
static int NONNULL(1) WUNRES
protoautossl_setup_srvdst_new_bev_ssl_connecting(pxy_conn_ctx_t *ctx)
{
ctx->srvdst.bev = bufferevent_openssl_filter_new(ctx->thr->evbase, ctx->srvdst.bev, ctx->srvdst.ssl,
BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS);
if (!ctx->srvdst.bev) {
log_err_level_printf(LOG_CRIT, "Error creating srvdst bufferevent\n");
SSL_free(ctx->srvdst.ssl);
ctx->srvdst.ssl = NULL;
pxy_conn_term(ctx, 1);
return -1;
}
ctx->srvdst.free = protoautossl_bufferevent_free_and_close_fd;
return 0;
}
static void NONNULL(1)
protoautossl_upgrade_srvdst(pxy_conn_ctx_t *ctx)
{
if (protossl_setup_srvdst_ssl(ctx) == -1) {
return;
}
if (protoautossl_setup_srvdst_new_bev_ssl_connecting(ctx) == -1) {
return;
}
bufferevent_setcb(ctx->srvdst.bev, pxy_bev_readcb, pxy_bev_writecb, pxy_bev_eventcb, ctx);
}
static int NONNULL(1) WUNRES
protoautossl_setup_dst_new_bev_ssl_connecting_child(pxy_conn_child_ctx_t *ctx)
{
@ -152,18 +192,6 @@ protoautossl_setup_dst_new_bev_ssl_connecting_child(pxy_conn_child_ctx_t *ctx)
return 0;
}
static void NONNULL(1)
protoautossl_upgrade_dst(pxy_conn_ctx_t *ctx)
{
if (protossl_setup_dst_ssl(ctx) == -1) {
return;
}
if (protoautossl_setup_dst_new_bev_ssl_connecting(ctx) == -1) {
return;
}
bufferevent_setcb(ctx->dst.bev, pxy_bev_readcb, pxy_bev_writecb, pxy_bev_eventcb, ctx);
}
static void NONNULL(1)
protoautossl_upgrade_dst_child(pxy_conn_child_ctx_t *ctx)
{
@ -216,13 +244,26 @@ protoautossl_peek_and_upgrade(pxy_conn_ctx_t *ctx)
if (ctx->divert) {
if (!ctx->children) {
// This means that there was no autossl handshake prior to ClientHello, e.g. no STARTTLS message
// This is perhaps the SSL handshake of a direct SSL connection, i.e. invalid protocol
log_err_level(LOG_CRIT, "No children setup yet, autossl protocol error");
return -1;
// This is perhaps the SSL handshake of a direct SSL connection
log_err_level(LOG_CRIT, "No children setup yet, upgrading srvdst");
protoautossl_upgrade_srvdst(ctx);
bufferevent_enable(ctx->srvdst.bev, EV_READ|EV_WRITE);
}
else {
// @attention Autossl protocol should never have multiple children.
log_err_level(LOG_CRIT, "Upgrading child dst");
protoautossl_upgrade_dst_child(ctx->children);
}
// @attention Autossl protocol should never have multiple children.
protoautossl_upgrade_dst_child(ctx->children);
// Change p in sslproxy_header to s
if (ctx->sslproxy_header) {
free(ctx->sslproxy_header);
ctx->sslproxy_header = NULL;
ctx->sslproxy_header_len = 0;
if (pxy_set_sslproxy_header(ctx, 1) == -1) {
return -1;
}
}
} else {
// srvdst == dst in split mode
protoautossl_upgrade_dst(ctx);
@ -241,6 +282,19 @@ protoautossl_peek_and_upgrade(pxy_conn_ctx_t *ctx)
return 0;
}
static void NONNULL(1)
protoautossl_disable_srvdst(pxy_conn_ctx_t *ctx)
{
log_finest("ENTER");
// Do not disable underlying bevs in autossl
bufferevent_setcb(ctx->srvdst.bev, NULL, NULL, NULL, NULL);
bufferevent_disable(ctx->srvdst.bev, EV_READ|EV_WRITE);
// Do not access srvdst.bev from this point on
ctx->srvdst.bev = NULL;
}
static int NONNULL(1) WUNRES
protoautossl_conn_connect(pxy_conn_ctx_t *ctx)
{
@ -415,11 +469,14 @@ protoautossl_enable_conn_src(pxy_conn_ctx_t *ctx)
bufferevent_setcb(ctx->src.bev, pxy_bev_readcb, pxy_bev_writecb, pxy_bev_eventcb, ctx);
// Save the ssl info for logging, srvdst == dst in split mode
ctx->sslctx->srvdst_ssl_version = strdup(SSL_get_version(ctx->dst.ssl));
ctx->sslctx->srvdst_ssl_cipher = strdup(SSL_get_cipher(ctx->dst.ssl));
ctx->sslctx->srvdst_ssl_version = strdup(SSL_get_version(ctx->srvdst.ssl ? ctx->srvdst.ssl : ctx->dst.ssl));
ctx->sslctx->srvdst_ssl_cipher = strdup(SSL_get_cipher(ctx->srvdst.ssl ? ctx->srvdst.ssl : ctx->dst.ssl));
// Now open the gates for a second time after autossl upgrade
bufferevent_enable(ctx->src.bev, EV_READ|EV_WRITE);
protoautossl_ctx_t *autossl_ctx = ctx->protoctx->arg;
autossl_ctx->clienthello_found = 0;
return 0;
}
@ -501,13 +558,16 @@ protoautossl_enable_conn_src_child(pxy_conn_child_ctx_t *ctx)
bufferevent_setcb(ctx->conn->src.bev, pxy_bev_readcb, pxy_bev_writecb, pxy_bev_eventcb, ctx->conn);
// srvdst is xferred to the first child conn, so save the ssl info for logging
ctx->conn->sslctx->srvdst_ssl_version = strdup(SSL_get_version(ctx->dst.ssl));
ctx->conn->sslctx->srvdst_ssl_cipher = strdup(SSL_get_cipher(ctx->dst.ssl));
ctx->conn->sslctx->srvdst_ssl_version = strdup(SSL_get_version(ctx->conn->srvdst.ssl ? ctx->conn->srvdst.ssl : ctx->dst.ssl));
ctx->conn->sslctx->srvdst_ssl_cipher = strdup(SSL_get_cipher(ctx->conn->srvdst.ssl ? ctx->conn->srvdst.ssl : ctx->dst.ssl));
log_finer_va("Enabling ssl src, %s", ctx->conn->sslproxy_header);
// Now open the gates for a second time after autossl upgrade
bufferevent_enable(ctx->conn->src.bev, EV_READ|EV_WRITE);
protoautossl_ctx_t *autossl_ctx = ctx->protoctx->arg;
autossl_ctx->clienthello_found = 0;
return 0;
}
@ -657,6 +717,8 @@ protoautossl_setup(pxy_conn_ctx_t *ctx)
ctx->protoctx->set_watermarkcb = protoautossl_try_set_watermark;
ctx->protoctx->unset_watermarkcb = protoautossl_try_unset_watermark;
ctx->protoctx->disable_srvdstcb = protoautossl_disable_srvdst;
ctx->protoctx->arg = malloc(sizeof(protoautossl_ctx_t));
if (!ctx->protoctx->arg) {
return PROTO_ERROR;

View File

@ -1449,7 +1449,7 @@ protossl_setup_dst_ssl(pxy_conn_ctx_t *ctx)
return 0;
}
static int NONNULL(1)
int
protossl_setup_srvdst_ssl(pxy_conn_ctx_t *ctx)
{
ctx->srvdst.ssl = protossl_dstssl_create(ctx);
@ -1520,7 +1520,7 @@ protossl_connect_child(pxy_conn_child_ctx_t *ctx)
ctx->dst = ctx->conn->srvdst;
// See the comments in prototcp_setup_dst()
prototcp_disable_srvdst(ctx->conn);
ctx->conn->protoctx->disable_srvdstcb(ctx->conn);
bufferevent_setcb(ctx->dst.bev, pxy_bev_readcb_child, pxy_bev_writecb_child, pxy_bev_eventcb_child, ctx);
ctx->protoctx->bev_eventcb(ctx->dst.bev, BEV_EVENT_CONNECTED, ctx);
@ -1574,7 +1574,9 @@ protossl_setup_src_ssl_from_dst(pxy_conn_ctx_t *ctx)
{
// @attention We cannot engage passthrough mode upon ssl errors on already enabled src
// This function is used by protoautossl only
if (ctx->src.ssl || (ctx->src.ssl = protossl_srcssl_create(ctx, ctx->dst.ssl))) {
// srvdst may or may not have been xfered to child, or it may be divert or split mode
// so make sure dst.ssl is not NULL
if (ctx->src.ssl || (ctx->src.ssl = protossl_srcssl_create(ctx, ctx->srvdst.ssl ? ctx->srvdst.ssl : ctx->dst.ssl))) {
return 0;
}
else if (ctx->term) {

View File

@ -52,7 +52,8 @@ int protossl_setup_src_ssl_from_child_dst(pxy_conn_child_ctx_t *) NONNULL(1);
int protossl_setup_dst_ssl(pxy_conn_ctx_t *) NONNULL(1);
int protossl_setup_dst_ssl_child(pxy_conn_child_ctx_t *) NONNULL(1);
int protossl_setup_srvdst(pxy_conn_ctx_t *ctx) NONNULL(1);
int protossl_setup_srvdst_ssl(pxy_conn_ctx_t *) NONNULL(1);
int protossl_setup_srvdst(pxy_conn_ctx_t *) NONNULL(1);
void protossl_bev_eventcb_srvdst(struct bufferevent *, short, pxy_conn_ctx_t *) NONNULL(1);

View File

@ -111,9 +111,11 @@ prototcp_setup_src(pxy_conn_ctx_t *ctx)
return 0;
}
void
static void NONNULL(1)
prototcp_disable_srvdst(pxy_conn_ctx_t *ctx)
{
log_finest("ENTER");
bufferevent_setcb(ctx->srvdst.bev, NULL, NULL, NULL, NULL);
bufferevent_disable(ctx->srvdst.bev, EV_READ|EV_WRITE);
@ -151,7 +153,7 @@ prototcp_setup_dst(pxy_conn_ctx_t *ctx)
// This seems to be an issue with libevent.
// @todo Why does libevent raise the same event again for an already disabled and freed conn end?
// Note again that srvdst == dst or child_dst here.
prototcp_disable_srvdst(ctx);
ctx->protoctx->disable_srvdstcb(ctx);
bufferevent_setcb(ctx->dst.bev, pxy_bev_readcb, pxy_bev_writecb, pxy_bev_eventcb, ctx);
ctx->protoctx->bev_eventcb(ctx->dst.bev, BEV_EVENT_CONNECTED, ctx);
@ -213,7 +215,7 @@ prototcp_connect_child(pxy_conn_child_ctx_t *ctx)
ctx->dst = ctx->conn->srvdst;
// See the comments in prototcp_setup_dst()
prototcp_disable_srvdst(ctx->conn);
ctx->conn->protoctx->disable_srvdstcb(ctx->conn);
bufferevent_setcb(ctx->dst.bev, pxy_bev_readcb_child, pxy_bev_writecb_child, pxy_bev_eventcb_child, ctx);
ctx->protoctx->bev_eventcb(ctx->dst.bev, BEV_EVENT_CONNECTED, ctx);
@ -988,6 +990,7 @@ prototcp_setup(pxy_conn_ctx_t *ctx)
ctx->protoctx->set_watermarkcb = prototcp_try_set_watermark;
ctx->protoctx->unset_watermarkcb = prototcp_try_unset_watermark;
ctx->protoctx->disable_srvdstcb = prototcp_disable_srvdst;
return PROTO_TCP;
}

View File

@ -82,7 +82,6 @@ int prototcp_enable_src(pxy_conn_ctx_t *) NONNULL(1);
void prototcp_bev_eventcb_srvdst(struct bufferevent *, short, pxy_conn_ctx_t *) NONNULL(1);
int prototcp_setup_src(pxy_conn_ctx_t *) NONNULL(1);
void prototcp_disable_srvdst(pxy_conn_ctx_t *) NONNULL(1);
int prototcp_setup_dst(pxy_conn_ctx_t *) NONNULL(1);
int prototcp_setup_srvdst(pxy_conn_ctx_t *) NONNULL(1);

View File

@ -1153,44 +1153,8 @@ pxy_opensock_child(pxy_conn_ctx_t *ctx)
}
int
pxy_setup_child_listener(pxy_conn_ctx_t *ctx)
pxy_set_sslproxy_header(pxy_conn_ctx_t *ctx, int upgraded)
{
if (!ctx->divert) {
// split mode
return 0;
}
// @attention Defer child setup and evcl creation until after parent init is complete, otherwise (1) causes multithreading issues (proxy_listener_acceptcb is
// running on a different thread from the conn, and we only have thrmgr mutex), and (2) we need to clean up less upon errors.
// Child evcls use the evbase of the parent thread, otherwise we would get multithreading issues.
// We don't need a privsep call to open a socket for child listener,
// because listener port of child conns are assigned by the system, hence are from non-privileged range above 1024
ctx->child_fd = pxy_opensock_child(ctx);
if (ctx->child_fd < 0) {
log_err_level_printf(LOG_CRIT, "Error opening child socket: %s (%i)\n", strerror(errno), errno);
log_fine_va("Error opening child socket: %s (%i)", strerror(errno), errno);
pxy_conn_term(ctx, 1);
return -1;
}
ctx->thr->max_fd = max(ctx->thr->max_fd, ctx->child_fd);
// @attention Do not pass NULL as user-supplied pointer
struct evconnlistener *child_evcl = evconnlistener_new(ctx->thr->evbase, pxy_listener_acceptcb_child, ctx, LEV_OPT_CLOSE_ON_FREE, 1024, ctx->child_fd);
if (!child_evcl) {
log_err_level_printf(LOG_CRIT, "Error creating child evconnlistener: %s\n", strerror(errno));
log_fine_va("Error creating child evconnlistener: %s", strerror(errno));
// @attention Close child fd separately, because child evcl does not exist yet, hence fd would not be closed by calling pxy_conn_free()
evutil_closesocket(ctx->child_fd);
pxy_conn_term(ctx, 1);
return -1;
}
ctx->child_evcl = child_evcl;
evconnlistener_set_error_cb(child_evcl, proxy_listener_errorcb);
log_finer_va("Finished setting up child listener, child_fd=%d", ctx->child_fd);
struct sockaddr_in child_listener_addr;
socklen_t child_listener_len = sizeof(child_listener_addr);
@ -1244,7 +1208,7 @@ pxy_setup_child_listener(pxy_conn_ctx_t *ctx)
#endif /* !WITHOUT_USERAUTH */
,
SSLPROXY_KEY, addr, port, STRORNONE(ctx->srchost_str), STRORNONE(ctx->srcport_str),
STRORNONE(ctx->dsthost_str), STRORNONE(ctx->dstport_str), ctx->spec->ssl ? "s":"p"
STRORNONE(ctx->dsthost_str), STRORNONE(ctx->dstport_str), ctx->spec->ssl || upgraded ? "s":"p"
#ifndef WITHOUT_USERAUTH
, user_len ? "," : "", user_len ? ctx->user : ""
#endif /* !WITHOUT_USERAUTH */
@ -1254,9 +1218,52 @@ pxy_setup_child_listener(pxy_conn_ctx_t *ctx)
return -1;
}
log_finer_va("sslproxy_header= %s", ctx->sslproxy_header);
return 0;
}
int
pxy_setup_child_listener(pxy_conn_ctx_t *ctx)
{
if (!ctx->divert) {
// split mode
return 0;
}
// @attention Defer child setup and evcl creation until after parent init is complete, otherwise (1) causes multithreading issues (proxy_listener_acceptcb is
// running on a different thread from the conn, and we only have thrmgr mutex), and (2) we need to clean up less upon errors.
// Child evcls use the evbase of the parent thread, otherwise we would get multithreading issues.
// We don't need a privsep call to open a socket for child listener,
// because listener port of child conns are assigned by the system, hence are from non-privileged range above 1024
ctx->child_fd = pxy_opensock_child(ctx);
if (ctx->child_fd < 0) {
log_err_level_printf(LOG_CRIT, "Error opening child socket: %s (%i)\n", strerror(errno), errno);
log_fine_va("Error opening child socket: %s (%i)", strerror(errno), errno);
pxy_conn_term(ctx, 1);
return -1;
}
ctx->thr->max_fd = max(ctx->thr->max_fd, ctx->child_fd);
// @attention Do not pass NULL as user-supplied pointer
struct evconnlistener *child_evcl = evconnlistener_new(ctx->thr->evbase, pxy_listener_acceptcb_child, ctx, LEV_OPT_CLOSE_ON_FREE, 1024, ctx->child_fd);
if (!child_evcl) {
log_err_level_printf(LOG_CRIT, "Error creating child evconnlistener: %s\n", strerror(errno));
log_fine_va("Error creating child evconnlistener: %s", strerror(errno));
// @attention Close child fd separately, because child evcl does not exist yet, hence fd would not be closed by calling pxy_conn_free()
evutil_closesocket(ctx->child_fd);
pxy_conn_term(ctx, 1);
return -1;
}
ctx->child_evcl = child_evcl;
evconnlistener_set_error_cb(child_evcl, proxy_listener_errorcb);
log_finer_va("Finished setting up child listener, child_fd=%d", ctx->child_fd);
return pxy_set_sslproxy_header(ctx, 0);
}
int
pxy_try_close_conn_end(pxy_conn_desc_t *conn_end, pxy_conn_ctx_t *ctx)
{

View File

@ -87,6 +87,8 @@ typedef void (*child_proto_free_func_t)(pxy_conn_child_ctx_t *);
typedef void (*set_watermark_func_t)(struct bufferevent *, pxy_conn_ctx_t *, struct bufferevent *);
typedef void (*unset_watermark_func_t)(struct bufferevent *, pxy_conn_ctx_t *, pxy_conn_desc_t *);
typedef void (*disable_srvdstcb)(pxy_conn_ctx_t *);
typedef filter_action_t * (*proto_filter_func_t)(pxy_conn_ctx_t *, filter_list_t *) NONNULL(1,2) WUNRES;
/*
@ -174,6 +176,8 @@ struct proto_ctx {
set_watermark_func_t set_watermarkcb;
unset_watermark_func_t unset_watermarkcb;
disable_srvdstcb disable_srvdstcb;
// For protocol specific fields, if any
void *arg;
};
@ -434,6 +438,7 @@ void pxy_conn_term(pxy_conn_ctx_t *, int) NONNULL(1);
void pxy_conn_term_child(pxy_conn_child_ctx_t *) NONNULL(1);
void pxy_conn_free_children(pxy_conn_ctx_t *) NONNULL(1);
int pxy_set_sslproxy_header(pxy_conn_ctx_t *, int) NONNULL(1);
int pxy_setup_child_listener(pxy_conn_ctx_t *) NONNULL(1);
int pxy_bev_readcb_preexec_logging_and_stats(struct bufferevent *, pxy_conn_ctx_t *) NONNULL(1,2);

View File

@ -0,0 +1,140 @@
{
"comment": "Autossl tests for HTTP request headers: SSLproxy, Connection, Upgrade, Keep-Alive, Accept-Encoding, Via, X-Forwarded-For, and Referer",
"configs": {
"1": {
"proto": {
"proto": "tcp"
},
"client": {
"ip": "127.0.0.1",
"port": "8214"
},
"server": {
"ip": "127.0.0.1",
"port": "9214"
}
},
"2": {
"proto": {
"proto": "ssl",
"crt": "server.crt",
"key": "server.key"
},
"client": {
"ip": "127.0.0.1",
"port": "8214"
},
"server": {
"ip": "127.0.0.1",
"port": "9214"
}
}
},
"tests": {
"1": {
"comment": "Does not remove any extra SSLproxy line, nor appends Connection: close",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nSSLproxy: sslproxy\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nSSLproxy: sslproxy\r\n\r\n"
}
}
},
"2": {
"comment": "Does not change Connection header to close",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: Keep-Alive\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: Keep-Alive\r\n\r\n"
}
}
},
"3": {
"comment": "Does not suppress upgrading to SSL/TLS, WebSockets or HTTP/2",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nUpgrade: websocket\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nUpgrade: websocket\r\n\r\n"
}
}
},
"4": {
"comment": "Does not remove Accept-Encoding",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nAccept-Encoding: encoding\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nAccept-Encoding: encoding\r\n\r\n"
}
}
},
"5": {
"comment": "Does not remove Via",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nVia: via\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nVia: via\r\n\r\n"
}
}
},
"6": {
"comment": "Does not remove X-Forwarded-For",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nX-Forwarded-For: x-forwarded-for\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nX-Forwarded-For: x-forwarded-for\r\n\r\n"
}
}
},
"7": {
"comment": "Does not remove Referer",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nReferer: referer\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nReferer: referer\r\n\r\n"
}
}
}
}
}

View File

@ -0,0 +1,140 @@
{
"comment": "Autossl split mode tests for HTTP request headers: SSLproxy, Connection, Upgrade, Keep-Alive, Accept-Encoding, Via, X-Forwarded-For, and Referer",
"configs": {
"1": {
"proto": {
"proto": "tcp"
},
"client": {
"ip": "127.0.0.1",
"port": "8215"
},
"server": {
"ip": "127.0.0.1",
"port": "9215"
}
},
"2": {
"proto": {
"proto": "ssl",
"crt": "server.crt",
"key": "server.key"
},
"client": {
"ip": "127.0.0.1",
"port": "8215"
},
"server": {
"ip": "127.0.0.1",
"port": "9215"
}
}
},
"tests": {
"1": {
"comment": "Does not remove any extra SSLproxy line, nor appends Connection: close",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nSSLproxy: sslproxy\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nSSLproxy: sslproxy\r\n\r\n"
}
}
},
"2": {
"comment": "Does not change Connection header to close",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: Keep-Alive\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: Keep-Alive\r\n\r\n"
}
}
},
"3": {
"comment": "Does not suppress upgrading to SSL/TLS, WebSockets or HTTP/2",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nUpgrade: websocket\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nUpgrade: websocket\r\n\r\n"
}
}
},
"4": {
"comment": "Does not remove Accept-Encoding",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nAccept-Encoding: encoding\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nAccept-Encoding: encoding\r\n\r\n"
}
}
},
"5": {
"comment": "Does not remove Via",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nVia: via\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nVia: via\r\n\r\n"
}
}
},
"6": {
"comment": "Does not remove X-Forwarded-For",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nX-Forwarded-For: x-forwarded-for\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nX-Forwarded-For: x-forwarded-for\r\n\r\n"
}
}
},
"7": {
"comment": "Does not remove Referer",
"states": {
"1": {
"testend": "client",
"cmd": "send",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nReferer: referer\r\n\r\n"
},
"2": {
"testend": "server",
"cmd": "recv",
"payload": "GET / HTTP/1.1\r\nHost: example.com\r\nReferer: referer\r\n\r\n"
}
}
}
}
}

View File

@ -1751,3 +1751,7 @@ ProxySpec {
MaxHTTPHeaderSize 8192
}
}
# Autossl tests for HTTP request headers: SSLproxy, Connection, Upgrade, Keep-Alive, Accept-Encoding, Via, X-Forwarded-For, and Referer
ProxySpec autossl 127.0.0.1 8214 up:8080 127.0.0.1 9214
ProxySpec autossl 127.0.0.1 8215 127.0.0.1 9215

View File

@ -61,6 +61,13 @@
"13": "filter_struct_testset_1.json",
"14": "filter_struct_reconnect_testset_1.json"
}
},
"6": {
"comment": "Autossl tests",
"testsets": {
"1": "autossl_testset_1.json",
"2": "autossl_testset_2.json"
}
}
}
}