From 650f89fc2b5fe9d594a3c34349988283983c7362 Mon Sep 17 00:00:00 2001 From: Jared Hillier Date: Sat, 19 Jan 2019 19:34:17 +0800 Subject: [PATCH 01/12] TCP Fast Open support --- src/connection.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/connection.h b/src/connection.h index 013f046f..aa6bb557 100644 --- a/src/connection.h +++ b/src/connection.h @@ -47,6 +47,7 @@ struct Connection { struct { struct sockaddr_storage addr, local_addr; + struct sockaddr_in * addr_once; socklen_t addr_len, local_addr_len; struct ev_io watcher; struct Buffer *buffer; From a9eb97f90e0c1670486cb32f7468ba9626169627 Mon Sep 17 00:00:00 2001 From: Jared Hillier Date: Sat, 19 Jan 2019 19:41:31 +0800 Subject: [PATCH 02/12] TCP Fast Open support --- src/connection.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/connection.h b/src/connection.h index aa6bb557..3135ac4c 100644 --- a/src/connection.h +++ b/src/connection.h @@ -58,6 +58,7 @@ struct Connection { size_t header_len; struct ResolvQuery *query_handle; ev_tstamp established_timestamp; + int fast_open; int use_proxy_header; TAILQ_ENTRY(Connection) entries; From ecc3ec9f41332bdbaf5f02dc0dac91854a365849 Mon Sep 17 00:00:00 2001 From: Jared Hillier Date: Sat, 19 Jan 2019 19:57:01 +0800 Subject: [PATCH 03/12] TCP Fast Open support --- src/connection.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/connection.c b/src/connection.c index c10a1090..7e42e047 100644 --- a/src/connection.c +++ b/src/connection.c @@ -268,7 +268,17 @@ connection_cb(struct ev_loop *loop, struct ev_io *w, int revents) { /* Transmit */ if (revents & EV_WRITE && buffer_len(output_buffer)) { - ssize_t bytes_transmitted = buffer_send(output_buffer, w->fd, 0, loop); + ssize_t bytes_transmitted = -1; + if ((!is_client) && con->server.addr_once) { + bytes_transmitted = + buffer_sendto(output_buffer, w->fd, + MSG_FASTOPEN, con->server.addr_once, + con->server.addr_len, loop); + con->server.addr_once = NULL; + } else { + buffer_send(output_buffer, w->fd, 0, loop); + } + if (bytes_transmitted < 0 && !IS_TEMPORARY_SOCKERR(errno)) { warn("send(%s): %s, closing connection", socket_name, @@ -680,6 +690,10 @@ initiate_server_connect(struct Connection *con, struct ev_loop *loop) { } } + /* TODO TCP Fast Open killswitch */ + con->fast_open = 1; + +#ifndef MSG_FASTOPEN int result = connect(sockfd, (struct sockaddr *)&con->server.addr, con->server.addr_len); @@ -693,6 +707,9 @@ initiate_server_connect(struct Connection *con, struct ev_loop *loop) { abort_connection(con); return; } +#else + con->server.addr_once = (struct sockaddr *)&con->server.addr; +#endif if (getsockname(sockfd, (struct sockaddr *)&con->server.local_addr, &con->server.local_addr_len) != 0) { From 25cf9cf33cb88eb3822df7df3677e5439a8519d6 Mon Sep 17 00:00:00 2001 From: PantherJohn Date: Sat, 19 Jan 2019 20:19:50 +0800 Subject: [PATCH 04/12] TCP Fast Open support --- src/buffer.c | 22 ++++++++++++++++++++++ src/buffer.h | 1 + src/connection.c | 9 ++++++++- src/listener.c | 15 +++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/buffer.c b/src/buffer.c index 23a609ca..92c011cc 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -147,6 +147,28 @@ buffer_send(struct Buffer *buffer, int sockfd, int flags, struct ev_loop *loop) return bytes; } +ssize_t +buffer_sendto(struct Buffer *buffer, int sockfd, int flags, + const struct sockaddr *dest_addr, socklen_t dest_addr_len, + struct ev_loop *loop) { + struct iovec iov[2]; + struct msghdr msg = { + .msg_name = (struct sockaddr *)dest_addr, + .msg_namelen = dest_addr_len, + .msg_iov = iov, + .msg_iovlen = setup_read_iov(buffer, iov, 0) + }; + + ssize_t bytes = sendmsg(sockfd, &msg, flags); + + buffer->last_send = ev_now(loop); + + if (bytes > 0) + advance_read_position(buffer, (size_t)bytes); + + return bytes; +} + /* * Read data from file into buffer */ diff --git a/src/buffer.h b/src/buffer.h index 1b0a4671..a8955bbc 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -47,6 +47,7 @@ void free_buffer(struct Buffer *); ssize_t buffer_recv(struct Buffer *, int, int, struct ev_loop *); ssize_t buffer_send(struct Buffer *, int, int, struct ev_loop *); +ssize_t buffer_sendto(struct Buffer *, int, int, const struct sockaddr *, socklen_t, struct ev_loop *); ssize_t buffer_read(struct Buffer *, int); ssize_t buffer_write(struct Buffer *, int); ssize_t buffer_resize(struct Buffer *, size_t); diff --git a/src/connection.c b/src/connection.c index 7e42e047..e8c98af8 100644 --- a/src/connection.c +++ b/src/connection.c @@ -33,6 +33,7 @@ #include #include #include +#include #include /* getaddrinfo */ #include /* close */ #include @@ -48,6 +49,7 @@ #define IS_TEMPORARY_SOCKERR(_errno) (_errno == EAGAIN || \ _errno == EWOULDBLOCK || \ + _errno == EINPROGRESS || \ _errno == EINTR) #define MAX(a, b) ((a) > (b) ? (a) : (b)) @@ -638,10 +640,15 @@ initiate_server_connect(struct Connection *con, struct ev_loop *loop) { fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); #endif + int on = 1; +#ifdef TCP_NODELAY + result = setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)); +#endif + result = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); + if (con->listener->transparent_proxy && con->client.addr.ss_family == con->server.addr.ss_family) { #ifdef IP_TRANSPARENT - int on = 1; int result = setsockopt(sockfd, SOL_IP, IP_TRANSPARENT, &on, sizeof(on)); #else int result = -EPERM; diff --git a/src/listener.c b/src/listener.c index ce5956da..bb89e9a3 100644 --- a/src/listener.c +++ b/src/listener.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include "address.h" @@ -536,6 +537,10 @@ init_listener(struct Listener *listener, const struct Table_head *tables, return result; } +#ifdef TCP_NODELAY + result = setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)); +#endif + if (listener->reuseport == 1) { #ifdef SO_REUSEPORT /* set SO_REUSEPORT on server socket to allow binding of multiple @@ -567,6 +572,16 @@ init_listener(struct Listener *listener, const struct Table_head *tables, } } +#ifdef TCP_FASTOPEN + int qlen = SOMAXCONN; + result = setsockopt(sockfd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen)); + if (result < 0) { + err("setsockopt TCP_FASTOPEN failed: %s", strerror(errno)); + close(sockfd); + return result; + } +#endif + result = bind(sockfd, address_sa(listener->address), address_sa_len(listener->address)); if (result < 0 && errno == EACCES) { From 1a8a4457da7520609ff7b13d77bc8dc9a5dde8c9 Mon Sep 17 00:00:00 2001 From: PantherJohn Date: Sun, 20 Jan 2019 10:54:48 +0800 Subject: [PATCH 05/12] TCP Fast Open support --- configure.ac | 2 +- redhat/sniproxy.spec | 2 +- src/connection.c | 22 +++++++++++----------- src/connection.h | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/configure.ac b/configure.ac index 1d0805b7..ffa68be9 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.60]) -AC_INIT([sniproxy], [0.6.0]) +AC_INIT([sniproxy], [0.6.0+git.10.g6fd682d]) AC_CONFIG_SRCDIR([src/sniproxy.c]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([subdir-objects]) diff --git a/redhat/sniproxy.spec b/redhat/sniproxy.spec index 3633a1db..d94253de 100644 --- a/redhat/sniproxy.spec +++ b/redhat/sniproxy.spec @@ -1,5 +1,5 @@ Name: sniproxy -Version: 0.6.0 +Version: 0.6.0+git.10.g6fd682d Release: 1%{?dist} Summary: Transparent TLS and HTTP layer 4 proxy with SNI support diff --git a/src/connection.c b/src/connection.c index e8c98af8..53378593 100644 --- a/src/connection.c +++ b/src/connection.c @@ -642,25 +642,25 @@ initiate_server_connect(struct Connection *con, struct ev_loop *loop) { int on = 1; #ifdef TCP_NODELAY - result = setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)); + int result = setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)); +#else + /* XXX error: not implemented would be better, but this shouldn't be + * reached since it is prohibited in the configuration parser. */ + int result = -EPERM; #endif result = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); if (con->listener->transparent_proxy && con->client.addr.ss_family == con->server.addr.ss_family) { #ifdef IP_TRANSPARENT - int result = setsockopt(sockfd, SOL_IP, IP_TRANSPARENT, &on, sizeof(on)); -#else - int result = -EPERM; - /* XXX error: not implemented would be better, but this shouldn't be - * reached since it is prohibited in the configuration parser. */ -#endif + result = setsockopt(sockfd, SOL_IP, IP_TRANSPARENT, &on, sizeof(on)); if (result < 0) { err("setsockopt IP_TRANSPARENT failed: %s", strerror(errno)); close(sockfd); abort_connection(con); return; } +#endif result = bind(sockfd, (struct sockaddr *)&con->client.addr, con->client.addr_len); @@ -700,8 +700,10 @@ initiate_server_connect(struct Connection *con, struct ev_loop *loop) { /* TODO TCP Fast Open killswitch */ con->fast_open = 1; -#ifndef MSG_FASTOPEN - int result = connect(sockfd, +#ifdef MSG_FASTOPEN + con->server.addr_once = (struct sockaddr *)&con->server.addr; +#else + result = connect(sockfd, (struct sockaddr *)&con->server.addr, con->server.addr_len); /* TODO retry connect in EADDRNOTAVAIL case */ @@ -714,8 +716,6 @@ initiate_server_connect(struct Connection *con, struct ev_loop *loop) { abort_connection(con); return; } -#else - con->server.addr_once = (struct sockaddr *)&con->server.addr; #endif if (getsockname(sockfd, (struct sockaddr *)&con->server.local_addr, diff --git a/src/connection.h b/src/connection.h index 3135ac4c..9b26302a 100644 --- a/src/connection.h +++ b/src/connection.h @@ -47,7 +47,7 @@ struct Connection { struct { struct sockaddr_storage addr, local_addr; - struct sockaddr_in * addr_once; + struct sockaddr *addr_once; socklen_t addr_len, local_addr_len; struct ev_io watcher; struct Buffer *buffer; From 054fd40a9db8cd4fcb3b9ee01b9eb828c3e5384d Mon Sep 17 00:00:00 2001 From: PantherJohn Date: Sun, 20 Jan 2019 18:17:20 +0800 Subject: [PATCH 06/12] TCP Fast Open support --- configure.ac | 2 +- redhat/sniproxy.spec | 2 +- src/connection.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index ffa68be9..fc822b2c 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.60]) -AC_INIT([sniproxy], [0.6.0+git.10.g6fd682d]) +AC_INIT([sniproxy], [0.6.0+git.11.g1a8a445]) AC_CONFIG_SRCDIR([src/sniproxy.c]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([subdir-objects]) diff --git a/redhat/sniproxy.spec b/redhat/sniproxy.spec index d94253de..6ca77835 100644 --- a/redhat/sniproxy.spec +++ b/redhat/sniproxy.spec @@ -1,5 +1,5 @@ Name: sniproxy -Version: 0.6.0+git.10.g6fd682d +Version: 0.6.0+git.11.g1a8a445 Release: 1%{?dist} Summary: Transparent TLS and HTTP layer 4 proxy with SNI support diff --git a/src/connection.c b/src/connection.c index 53378593..4f70df9a 100644 --- a/src/connection.c +++ b/src/connection.c @@ -255,7 +255,7 @@ connection_cb(struct ev_loop *loop, struct ev_io *w, int revents) { /* Receive first in case the socket was closed */ if (revents & EV_READ && buffer_room(input_buffer)) { ssize_t bytes_received = buffer_recv(input_buffer, w->fd, 0, loop); - if (bytes_received < 0 && !IS_TEMPORARY_SOCKERR(errno)) { + if (!con->fast_open && bytes_received < 0 && !IS_TEMPORARY_SOCKERR(errno)) { warn("recv(%s): %s, closing connection", socket_name, strerror(errno)); @@ -271,7 +271,7 @@ connection_cb(struct ev_loop *loop, struct ev_io *w, int revents) { /* Transmit */ if (revents & EV_WRITE && buffer_len(output_buffer)) { ssize_t bytes_transmitted = -1; - if ((!is_client) && con->server.addr_once) { + if (!is_client && con->server.addr_once) { bytes_transmitted = buffer_sendto(output_buffer, w->fd, MSG_FASTOPEN, con->server.addr_once, @@ -644,9 +644,9 @@ initiate_server_connect(struct Connection *con, struct ev_loop *loop) { #ifdef TCP_NODELAY int result = setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)); #else - /* XXX error: not implemented would be better, but this shouldn't be - * reached since it is prohibited in the configuration parser. */ int result = -EPERM; + /* XXX error: not implemented would be better, but this shouldn't be + * reached since it is prohibited in the configuration parser. */ #endif result = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); From a01050ef413d0f4aefd07bd1eaf87a9af7a8dc48 Mon Sep 17 00:00:00 2001 From: PantherJohn Date: Sun, 20 Jan 2019 20:00:58 +0800 Subject: [PATCH 07/12] TCP Fast Open support --- configure.ac | 2 +- redhat/sniproxy.spec | 2 +- src/connection.c | 39 ++++++++++++++++++++++----------------- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/configure.ac b/configure.ac index fc822b2c..bbee3f99 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.60]) -AC_INIT([sniproxy], [0.6.0+git.11.g1a8a445]) +AC_INIT([sniproxy], [0.6.0+git.12.g054fd40]) AC_CONFIG_SRCDIR([src/sniproxy.c]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([subdir-objects]) diff --git a/redhat/sniproxy.spec b/redhat/sniproxy.spec index 6ca77835..c3723bf4 100644 --- a/redhat/sniproxy.spec +++ b/redhat/sniproxy.spec @@ -1,5 +1,5 @@ Name: sniproxy -Version: 0.6.0+git.11.g1a8a445 +Version: 0.6.0+git.12.g054fd40 Release: 1%{?dist} Summary: Transparent TLS and HTTP layer 4 proxy with SNI support diff --git a/src/connection.c b/src/connection.c index 4f70df9a..defe8947 100644 --- a/src/connection.c +++ b/src/connection.c @@ -49,7 +49,6 @@ #define IS_TEMPORARY_SOCKERR(_errno) (_errno == EAGAIN || \ _errno == EWOULDBLOCK || \ - _errno == EINPROGRESS || \ _errno == EINTR) #define MAX(a, b) ((a) > (b) ? (a) : (b)) @@ -255,7 +254,8 @@ connection_cb(struct ev_loop *loop, struct ev_io *w, int revents) { /* Receive first in case the socket was closed */ if (revents & EV_READ && buffer_room(input_buffer)) { ssize_t bytes_received = buffer_recv(input_buffer, w->fd, 0, loop); - if (!con->fast_open && bytes_received < 0 && !IS_TEMPORARY_SOCKERR(errno)) { + if (bytes_received < 0 && + !IS_TEMPORARY_SOCKERR(errno) && !con->server.addr_once) { warn("recv(%s): %s, closing connection", socket_name, strerror(errno)); @@ -281,7 +281,8 @@ connection_cb(struct ev_loop *loop, struct ev_io *w, int revents) { buffer_send(output_buffer, w->fd, 0, loop); } - if (bytes_transmitted < 0 && !IS_TEMPORARY_SOCKERR(errno)) { + if (bytes_transmitted < 0 && + errno != EINPROGRESS && !IS_TEMPORARY_SOCKERR(errno)) { warn("send(%s): %s, closing connection", socket_name, strerror(errno)); @@ -700,23 +701,27 @@ initiate_server_connect(struct Connection *con, struct ev_loop *loop) { /* TODO TCP Fast Open killswitch */ con->fast_open = 1; + if (con->fast_open) { #ifdef MSG_FASTOPEN - con->server.addr_once = (struct sockaddr *)&con->server.addr; + con->server.addr_once = (struct sockaddr *)&con->server.addr; #else - result = connect(sockfd, - (struct sockaddr *)&con->server.addr, - con->server.addr_len); - /* TODO retry connect in EADDRNOTAVAIL case */ - if (result < 0 && errno != EINPROGRESS) { - close(sockfd); - char server[INET6_ADDRSTRLEN + 8]; - warn("Failed to open connection to %s: %s", - display_sockaddr(&con->server.addr, server, sizeof(server)), - strerror(errno)); - abort_connection(con); - return; - } + warn("TCP Fast Open not supported"); #endif + } else { + result = connect(sockfd, + (struct sockaddr *)&con->server.addr, + con->server.addr_len); + /* TODO retry connect in EADDRNOTAVAIL case */ + if (result < 0 && errno != EINPROGRESS) { + close(sockfd); + char server[INET6_ADDRSTRLEN + 8]; + warn("Failed to open connection to %s: %s", + display_sockaddr(&con->server.addr, server, sizeof(server)), + strerror(errno)); + abort_connection(con); + return; + } + } if (getsockname(sockfd, (struct sockaddr *)&con->server.local_addr, &con->server.local_addr_len) != 0) { From 136934fee0b2a3319719d7c76ac232f370d22ecf Mon Sep 17 00:00:00 2001 From: PantherJohn Date: Mon, 21 Jan 2019 00:00:37 +0800 Subject: [PATCH 08/12] TCP Fast Open support --- configure.ac | 2 +- redhat/sniproxy.spec | 2 +- src/connection.c | 14 ++++++++------ src/connection.h | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index bbee3f99..4666bf8d 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.60]) -AC_INIT([sniproxy], [0.6.0+git.12.g054fd40]) +AC_INIT([sniproxy], [0.6.0+git.13.ga01050e]) AC_CONFIG_SRCDIR([src/sniproxy.c]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([subdir-objects]) diff --git a/redhat/sniproxy.spec b/redhat/sniproxy.spec index c3723bf4..191cf54c 100644 --- a/redhat/sniproxy.spec +++ b/redhat/sniproxy.spec @@ -1,5 +1,5 @@ Name: sniproxy -Version: 0.6.0+git.12.g054fd40 +Version: 0.6.0+git.13.ga01050e Release: 1%{?dist} Summary: Transparent TLS and HTTP layer 4 proxy with SNI support diff --git a/src/connection.c b/src/connection.c index defe8947..44cb7a69 100644 --- a/src/connection.c +++ b/src/connection.c @@ -699,14 +699,16 @@ initiate_server_connect(struct Connection *con, struct ev_loop *loop) { } /* TODO TCP Fast Open killswitch */ - con->fast_open = 1; + con->server.fast_open = 1; - if (con->fast_open) { -#ifdef MSG_FASTOPEN - con->server.addr_once = (struct sockaddr *)&con->server.addr; -#else - warn("TCP Fast Open not supported"); +#ifndef MSG_FASTOPEN + con->server.fast_open = 0; + con->server.addr_once = NULL; + warn("TCP Fast Open not supported"); #endif + + if (con->server.fast_open) { + con->server.addr_once = (struct sockaddr *)&con->server.addr; } else { result = connect(sockfd, (struct sockaddr *)&con->server.addr, diff --git a/src/connection.h b/src/connection.h index 9b26302a..e2c96b74 100644 --- a/src/connection.h +++ b/src/connection.h @@ -46,6 +46,7 @@ struct Connection { } state; struct { + int fast_open; struct sockaddr_storage addr, local_addr; struct sockaddr *addr_once; socklen_t addr_len, local_addr_len; @@ -58,7 +59,6 @@ struct Connection { size_t header_len; struct ResolvQuery *query_handle; ev_tstamp established_timestamp; - int fast_open; int use_proxy_header; TAILQ_ENTRY(Connection) entries; From 078fad880f46fadcd31b5f0790b7213e0fbab33c Mon Sep 17 00:00:00 2001 From: PantherJohn Date: Mon, 21 Jan 2019 08:35:33 +0800 Subject: [PATCH 09/12] TCP Fast Open support --- configure.ac | 2 +- redhat/sniproxy.spec | 2 +- src/connection.c | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 4666bf8d..c4b70ce8 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.60]) -AC_INIT([sniproxy], [0.6.0+git.13.ga01050e]) +AC_INIT([sniproxy], [0.6.0+git.14.g136934f]) AC_CONFIG_SRCDIR([src/sniproxy.c]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([subdir-objects]) diff --git a/redhat/sniproxy.spec b/redhat/sniproxy.spec index 191cf54c..685d0b82 100644 --- a/redhat/sniproxy.spec +++ b/redhat/sniproxy.spec @@ -1,5 +1,5 @@ Name: sniproxy -Version: 0.6.0+git.13.ga01050e +Version: 0.6.0+git.14.g136934f Release: 1%{?dist} Summary: Transparent TLS and HTTP layer 4 proxy with SNI support diff --git a/src/connection.c b/src/connection.c index 44cb7a69..933e67d2 100644 --- a/src/connection.c +++ b/src/connection.c @@ -255,7 +255,8 @@ connection_cb(struct ev_loop *loop, struct ev_io *w, int revents) { if (revents & EV_READ && buffer_room(input_buffer)) { ssize_t bytes_received = buffer_recv(input_buffer, w->fd, 0, loop); if (bytes_received < 0 && - !IS_TEMPORARY_SOCKERR(errno) && !con->server.addr_once) { + !IS_TEMPORARY_SOCKERR(errno) && + !con->server.addr_once) { warn("recv(%s): %s, closing connection", socket_name, strerror(errno)); @@ -278,7 +279,7 @@ connection_cb(struct ev_loop *loop, struct ev_io *w, int revents) { con->server.addr_len, loop); con->server.addr_once = NULL; } else { - buffer_send(output_buffer, w->fd, 0, loop); + bytes_transmitted = buffer_send(output_buffer, w->fd, 0, loop); } if (bytes_transmitted < 0 && From e1219da5703341c50106ba1612f694eb91cb1ba9 Mon Sep 17 00:00:00 2001 From: PantherJohn Date: Mon, 21 Jan 2019 16:53:06 +0800 Subject: [PATCH 10/12] Refine TCP Fast Open option parsing --- configure.ac | 2 +- redhat/sniproxy.spec | 2 +- src/config.c | 4 ++++ src/connection.c | 10 ++++------ src/connection.h | 1 - src/listener.c | 37 +++++++++++++++++++++++++++++++------ src/listener.h | 3 ++- 7 files changed, 43 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index c4b70ce8..5e4df47a 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.60]) -AC_INIT([sniproxy], [0.6.0+git.14.g136934f]) +AC_INIT([sniproxy], [0.6.0+git.15.g078fad8]) AC_CONFIG_SRCDIR([src/sniproxy.c]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([subdir-objects]) diff --git a/redhat/sniproxy.spec b/redhat/sniproxy.spec index 685d0b82..747233be 100644 --- a/redhat/sniproxy.spec +++ b/redhat/sniproxy.spec @@ -1,5 +1,5 @@ Name: sniproxy -Version: 0.6.0+git.14.g136934f +Version: 0.6.0+git.15.g078fad8 Release: 1%{?dist} Summary: Transparent TLS and HTTP layer 4 proxy with SNI support diff --git a/src/config.c b/src/config.c index 017d7eb5..99acbcc0 100644 --- a/src/config.c +++ b/src/config.c @@ -105,6 +105,10 @@ static const struct Keyword listener_stanza_grammar[] = { .keyword="reuseport", .parse_arg=(int(*)(void *, const char *))accept_listener_reuseport, }, + { + .keyword="fastopen", + .parse_arg=(int(*)(void *, const char *))accept_listener_fastopen, + }, { .keyword="ipv6_v6only", .parse_arg=(int(*)(void *, const char *))accept_listener_ipv6_v6only, diff --git a/src/connection.c b/src/connection.c index 933e67d2..7b8132e6 100644 --- a/src/connection.c +++ b/src/connection.c @@ -699,16 +699,14 @@ initiate_server_connect(struct Connection *con, struct ev_loop *loop) { } } - /* TODO TCP Fast Open killswitch */ - con->server.fast_open = 1; - #ifndef MSG_FASTOPEN - con->server.fast_open = 0; + con->listener->fastopen = 0; con->server.addr_once = NULL; - warn("TCP Fast Open not supported"); + warn("TCP Fast Open for client sockets not supported in this build"); #endif - if (con->server.fast_open) { + if (con->listener->fastopen == 1 || + con->listener->fastopen == 3) { con->server.addr_once = (struct sockaddr *)&con->server.addr; } else { result = connect(sockfd, diff --git a/src/connection.h b/src/connection.h index e2c96b74..796743c9 100644 --- a/src/connection.h +++ b/src/connection.h @@ -46,7 +46,6 @@ struct Connection { } state; struct { - int fast_open; struct sockaddr_storage addr, local_addr; struct sockaddr *addr_once; socklen_t addr_len, local_addr_len; diff --git a/src/listener.c b/src/listener.c index bb89e9a3..8cc5a136 100644 --- a/src/listener.c +++ b/src/listener.c @@ -217,6 +217,7 @@ new_listener() { listener->table_name = NULL; listener->access_log = NULL; listener->log_bad_requests = 0; + listener->fastopen = 0; listener->reuseport = 0; listener->ipv6_v6only = 0; listener->transparent_proxy = 0; @@ -293,6 +294,27 @@ accept_listener_protocol(struct Listener *listener, const char *protocol) { return 1; } +int +accept_listener_fastopen(struct Listener *listener, const char *fastopen) { + if (listener->fastopen = parse_boolean(fastopen)) + listener->fastopen = 3; + else if (strcasecmp(fastopen, "frontend") == 0) + listener->fastopen = 2; + else if (strcasecmp(fastopen, "backend") == 0) + listener->fastopen = 1; + else + return 0; + +#ifndef TCP_FASTOPEN + if (listener->fastopen != -1) { + err("TCP Fast Open not supported in this build"); + return 0; + } +#endif + + return 1; +} + int accept_listener_reuseport(struct Listener *listener, const char *reuseport) { listener->reuseport = parse_boolean(reuseport); @@ -573,12 +595,15 @@ init_listener(struct Listener *listener, const struct Table_head *tables, } #ifdef TCP_FASTOPEN - int qlen = SOMAXCONN; - result = setsockopt(sockfd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen)); - if (result < 0) { - err("setsockopt TCP_FASTOPEN failed: %s", strerror(errno)); - close(sockfd); - return result; + if (listener->fastopen == 2 || + listener->fastopen == 3) { + int qlen = SOMAXCONN; + result = setsockopt(sockfd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen)); + if (result < 0) { + err("setsockopt TCP_FASTOPEN failed: %s", strerror(errno)); + close(sockfd); + return result; + } } #endif diff --git a/src/listener.h b/src/listener.h index c6fb5514..4a36787d 100644 --- a/src/listener.h +++ b/src/listener.h @@ -39,7 +39,7 @@ struct Listener { const struct Protocol *protocol; char *table_name; struct Logger *access_log; - int log_bad_requests, reuseport, transparent_proxy, ipv6_v6only; + int log_bad_requests, fastopen, reuseport, transparent_proxy, ipv6_v6only; int fallback_use_proxy_header; /* Runtime fields */ @@ -58,6 +58,7 @@ int accept_listener_table_name(struct Listener *, const char *); int accept_listener_fallback_address(struct Listener *, const char *); int accept_listener_source_address(struct Listener *, const char *); int accept_listener_protocol(struct Listener *, const char *); +int accept_listener_fastopen(struct Listener *, const char *); int accept_listener_reuseport(struct Listener *, const char *); int accept_listener_ipv6_v6only(struct Listener *, const char *); int accept_listener_bad_request_action(struct Listener *, const char *); From 686756998c5d1ce3e998bb21f72cac5063d869d3 Mon Sep 17 00:00:00 2001 From: PantherJohn Date: Mon, 21 Jan 2019 17:09:03 +0800 Subject: [PATCH 11/12] Refine TCP Fast Open option parsing --- src/listener.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/listener.c b/src/listener.c index 8cc5a136..eea3e545 100644 --- a/src/listener.c +++ b/src/listener.c @@ -296,7 +296,8 @@ accept_listener_protocol(struct Listener *listener, const char *protocol) { int accept_listener_fastopen(struct Listener *listener, const char *fastopen) { - if (listener->fastopen = parse_boolean(fastopen)) + listener->fastopen = parse_boolean(fastopen); + if (listener->fastopen) listener->fastopen = 3; else if (strcasecmp(fastopen, "frontend") == 0) listener->fastopen = 2; From 5c2d515473dde394f21dcfc0f494f257d928f34e Mon Sep 17 00:00:00 2001 From: PantherJohn Date: Mon, 21 Jan 2019 18:42:06 +0800 Subject: [PATCH 12/12] Add missing headers --- configure.ac | 2 +- redhat/sniproxy.spec | 2 +- src/buffer.c | 1 - src/buffer.h | 1 + 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 5e4df47a..6293f569 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.60]) -AC_INIT([sniproxy], [0.6.0+git.15.g078fad8]) +AC_INIT([sniproxy], [0.6.0+git.17.g6867569]) AC_CONFIG_SRCDIR([src/sniproxy.c]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([subdir-objects]) diff --git a/redhat/sniproxy.spec b/redhat/sniproxy.spec index 747233be..393d0683 100644 --- a/redhat/sniproxy.spec +++ b/redhat/sniproxy.spec @@ -1,5 +1,5 @@ Name: sniproxy -Version: 0.6.0+git.15.g078fad8 +Version: 0.6.0+git.17.g6867569 Release: 1%{?dist} Summary: Transparent TLS and HTTP layer 4 proxy with SNI support diff --git a/src/buffer.c b/src/buffer.c index 92c011cc..89b8935c 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -27,7 +27,6 @@ #include /* malloc */ #include /* memcpy */ #include -#include #include #include #include diff --git a/src/buffer.h b/src/buffer.h index a8955bbc..87ebccd1 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -28,6 +28,7 @@ #include #include +#include #include