[exim-cvs] TLS: on Linux when sockopt TCP_FASTOPEN_CONNECT i…

Page principale
Supprimer ce message
Répondre à ce message
Auteur: Exim Git Commits Mailing List
Date:  
À: exim-cvs
Sujet: [exim-cvs] TLS: on Linux when sockopt TCP_FASTOPEN_CONNECT is available, use TFO for TLS-on-connect client connections
Gitweb: https://git.exim.org/exim.git/commitdiff/81df60f6229e66dc8306e55ea2103e577782d984
Commit:     81df60f6229e66dc8306e55ea2103e577782d984
Parent:     51ffcca6f1f6005c37c25144ed8b30f5e8a094e9
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Thu Jan 21 22:02:18 2021 +0000
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Fri Jan 22 00:20:08 2021 +0000


    TLS: on Linux when sockopt TCP_FASTOPEN_CONNECT is available, use TFO for TLS-on-connect client connections
---
 src/src/smtp_out.c               | 32 +++++++++++++++++++++++++---
 src/src/transports/smtp.c        |  7 +++++-
 test/confs/1160                  |  2 ++
 test/log/1160                    | 46 ++++++++++++++++++++--------------------
 test/scripts/1100-Basic-TLS/1160 | 27 +++++++++++++++++++++--
 5 files changed, 85 insertions(+), 29 deletions(-)


diff --git a/src/src/smtp_out.c b/src/src/smtp_out.c
index 2d2fd21..b1a25f7 100644
--- a/src/src/smtp_out.c
+++ b/src/src/smtp_out.c
@@ -246,9 +246,18 @@ switch (tcp_out_fastopen)
#endif


-/* Arguments as for smtp_connect(), plus
-  early_data    if non-NULL, idenmpotent data to be sent -
+/* Arguments:
+  host        host item containing name and address and port
+  host_af     AF_INET or AF_INET6
+  port          TCP port number
+  interface   outgoing interface address or NULL
+  tb          transport
+  timeout     timeout value or 0
+  early_data    if non-NULL, idempotent data to be sent -
         preferably in the TCP SYN segment
+          Special case: non-NULL but with NULL blob.data - caller is
+          client-data-first (eg. TLS-on-connect) and a lazy-TCP-connect is
+          acceptable.


 Returns:      connected socket number, or -1 with errno set
 */
@@ -318,8 +327,22 @@ early-data but no TFO support, send it after connecting. */
 else
   {
 #ifdef TCP_FASTOPEN
+  /* See if TCP Fast Open usable.  Default is a traditional 3WHS connect */
   if (verify_check_given_host(CUSS &ob->hosts_try_fastopen, host) == OK)
-    fastopen_blob = early_data ? early_data : &tcp_fastopen_nodata;
+    {
+    if (!early_data)
+      fastopen_blob = &tcp_fastopen_nodata;    /* TFO, with no data */
+    else if (early_data->data)
+      fastopen_blob = early_data;        /* TFO, with data */
+# ifdef TCP_FASTOPEN_CONNECT
+    else
+      {                        /* expecting client data */
+      debug_printf(" set up lazy-connect\n");
+      setsockopt(sock, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, US &on, sizeof(on));
+      /* fastopen_blob = NULL;         lazy TFO, triggered by data write */
+      }
+# endif
+    }
 #endif


   if (ip_connect(sock, host_af, host->address, port, timeout, fastopen_blob) < 0)
@@ -409,6 +432,9 @@ host->address will always be an IPv4 address.
 Arguments:
   sc          details for making connection: host, af, interface, transport
   early_data  if non-NULL, data to be sent - preferably in the TCP SYN segment
+          Special case: non-NULL but with NULL blob.data - caller is
+          client-data-first (eg. TLS-on-connect) and a lazy-TCP-connect is
+          acceptable.


 Returns:      connected socket number, or -1 with errno set
 */
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index ee5e49e..eb6b774 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -2098,7 +2098,12 @@ PIPE_CONNECT_RETRY:
   else
 #endif
     {
-    if ((sx->cctx.sock = smtp_connect(&sx->conn_args, NULL)) < 0)
+    blob lazy_conn = {.data = NULL};
+    /* For TLS-connect, a TFO lazy-connect is useful since the Client Hello
+    can go on the TCP SYN. */
+
+    if ((sx->cctx.sock = smtp_connect(&sx->conn_args,
+                sx->smtps ? &lazy_conn : NULL)) < 0)
       {
       set_errno_nohost(sx->addrlist,
     errno == ETIMEDOUT ? ERRNO_CONNECTTIMEOUT : errno,
diff --git a/test/confs/1160 b/test/confs/1160
index c489831..47bb2d5 100644
--- a/test/confs/1160
+++ b/test/confs/1160
@@ -20,6 +20,8 @@ tls_on_connect_ports = PORT_D


tls_certificate = DIR/aux-fixed/cert1

+log_selector = +millisec
+
# ------ ACL ------

begin acl
diff --git a/test/log/1160 b/test/log/1160
index f1c0aa8..f4c1efe 100644
--- a/test/log/1160
+++ b/test/log/1160
@@ -1,25 +1,25 @@
-1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@??? U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@??? U=CALLER P=local S=sss
-1999-03-02 09:44:33 Start queue run: pid=pppp -qf
-1999-03-02 09:44:33 10HmaX-0005vi-00 => CALLER@??? R=client T=send_to_server1 H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes C="250 OK id=10HmaZ-0005vi-00"
-1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
-1999-03-02 09:44:33 10HmaY-0005vi-00 => CALLER@??? R=client T=send_to_server1 H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes C="250 OK id=10HmbA-0005vi-00"
-1999-03-02 09:44:33 10HmaY-0005vi-00 -> xyz@??? R=client T=send_to_server1 H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes C="250 OK id=10HmbA-0005vi-00"
-1999-03-02 09:44:33 10HmaY-0005vi-00 => abcd@??? R=client T=send_to_server2 H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes C="250 OK id=10HmbB-0005vi-00"
-1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
-1999-03-02 09:44:33 End queue run: pid=pppp -qf
+2017-07-30 18:51:05.712 10HmaX-0005vi-00 <= CALLER@??? U=CALLER P=local S=sss
+2017-07-30 18:51:05.712 10HmaY-0005vi-00 <= CALLER@??? U=CALLER P=local S=sss
+2017-07-30 18:51:05.712 Start queue run: pid=pppp -qf
+2017-07-30 18:51:05.712 10HmaX-0005vi-00 => CALLER@??? R=client T=send_to_server1 H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes C="250 OK id=10HmaZ-0005vi-00"
+2017-07-30 18:51:05.712 10HmaX-0005vi-00 Completed
+2017-07-30 18:51:05.712 10HmaY-0005vi-00 => CALLER@??? R=client T=send_to_server1 H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes C="250 OK id=10HmbA-0005vi-00"
+2017-07-30 18:51:05.712 10HmaY-0005vi-00 -> xyz@??? R=client T=send_to_server1 H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes C="250 OK id=10HmbA-0005vi-00"
+2017-07-30 18:51:05.712 10HmaY-0005vi-00 => abcd@??? R=client T=send_to_server2 H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes C="250 OK id=10HmbB-0005vi-00"
+2017-07-30 18:51:05.712 10HmaY-0005vi-00 Completed
+2017-07-30 18:51:05.712 End queue run: pid=pppp -qf

 ******** SERVER ********
-1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTPS on port PORT_D
-1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@???
-1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaY-0005vi-00@???
-1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaY-0005vi-00@???
-1999-03-02 09:44:33 Start queue run: pid=pppp -qf
-1999-03-02 09:44:33 10HmaZ-0005vi-00 => CALLER <CALLER@???> R=server T=local_delivery
-1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbA-0005vi-00 => CALLER <CALLER@???> R=server T=local_delivery
-1999-03-02 09:44:33 10HmbA-0005vi-00 => xyz <xyz@???> R=server T=local_delivery
-1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbB-0005vi-00 => abcd <abcd@???> R=server T=local_delivery
-1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
-1999-03-02 09:44:33 End queue run: pid=pppp -qf
+2017-07-30 18:51:05.712 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTPS on port PORT_D
+2017-07-30 18:51:05.712 10HmaZ-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@???
+2017-07-30 18:51:05.712 10HmbA-0005vi-00 <= CALLER@??? H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaY-0005vi-00@???
+2017-07-30 18:51:05.712 10HmbB-0005vi-00 <= CALLER@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaY-0005vi-00@???
+2017-07-30 18:51:05.712 Start queue run: pid=pppp -qf
+2017-07-30 18:51:05.712 10HmaZ-0005vi-00 => CALLER <CALLER@???> R=server T=local_delivery
+2017-07-30 18:51:05.712 10HmaZ-0005vi-00 Completed
+2017-07-30 18:51:05.712 10HmbA-0005vi-00 => CALLER <CALLER@???> R=server T=local_delivery
+2017-07-30 18:51:05.712 10HmbA-0005vi-00 => xyz <xyz@???> R=server T=local_delivery
+2017-07-30 18:51:05.712 10HmbA-0005vi-00 Completed
+2017-07-30 18:51:05.712 10HmbB-0005vi-00 => abcd <abcd@???> R=server T=local_delivery
+2017-07-30 18:51:05.712 10HmbB-0005vi-00 Completed
+2017-07-30 18:51:05.712 End queue run: pid=pppp -qf
diff --git a/test/scripts/1100-Basic-TLS/1160 b/test/scripts/1100-Basic-TLS/1160
index e57867e..77eef1f 100644
--- a/test/scripts/1100-Basic-TLS/1160
+++ b/test/scripts/1100-Basic-TLS/1160
@@ -25,8 +25,31 @@
 #    Finished        >
 # (otherwise the same).  The extra segments are piplined and do not incur an extra roundtrip time.
 #
-# exim -DSERVER=server -bd -oX PORT_D
-sudo exim -DSERVER=server -d+tls -bd -oX PORT_D
+# To see that pipelining:
+# sudo tc qdisc add dev lo root netem delay 50ms  /  sudo tc qdisc delete dev lo root
+#
+# To test TFO, enable in the transport in the conf/ file
+# With TFO we get the Client Hello on the SYN, and the initial Server segment pipelined with/after the SYN,ACK
+# and before the 3rd-ACK.  We still can't merge the 3rd-ACK with the second Client record set,
+# but it does ack the initial Server data.
+#
+# To see the TFO((R):
+# First clear any previously-obtained cookie:
+#sudo perl
+#open(INFO, "-|", "/usr/bin/uname -s");
+#$_ = <INFO>;
+#if (/^FreeBSD/) {
+#system("sysctl net.inet.tcp.fastopen.client_enable=0"); system("sysctl net.inet.tcp.fastopen.client_enable=1");
+#} else {
+#system ("[ -e /proc/sys/net/ipv4/tcp_fastopen_blackhole_timeout_sec ] && echo 0 > /proc/sys/net/ipv4/tcp_fastopen_blackhole_timeout_sec");
+#system ("ip tcp_metrics delete 127.0.0.1");
+#}
+#
+#****
+#
+#
+# sudo exim -DSERVER=server -d+tls -bd -oX PORT_D
+exim -DSERVER=server -bd -oX PORT_D
 ****
 exim CALLER@???
 Test message. Contains FF: ?