Add proxy_protocol_timeout main config option.
authorHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Sun, 4 Oct 2020 10:22:01 +0000 (12:22 +0200)
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Mon, 5 Oct 2020 08:46:49 +0000 (10:46 +0200)
14 files changed:
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
src/src/globals.c
src/src/globals.h
src/src/macros.h
src/src/readconf.c
src/src/smtp_in.c
test/confs/4030
test/scripts/4030-proxy-protocol/4030
test/scripts/4030-proxy-protocol/4031
test/stderr/4030 [new file with mode: 0644]
test/stderr/4031
test/stdout/4030
test/stdout/4031

index d0c3e7846041e458b09c08dc7e77d578105299d6..31c8c5653a573fdc9dc2cd82cd317bd6696955be 100644 (file)
@@ -14680,6 +14680,7 @@ listed in more than one group.
 .row &%local_scan_timeout%&          "timeout for &[local_scan()]&"
 .row &%message_size_limit%&          "for all messages"
 .row &%percent_hack_domains%&        "recognize %-hack for these domains"
 .row &%local_scan_timeout%&          "timeout for &[local_scan()]&"
 .row &%message_size_limit%&          "for all messages"
 .row &%percent_hack_domains%&        "recognize %-hack for these domains"
+.row &%proxy_protocol_timeout%&      "timeout for proxy protocol negotiation"
 .row &%spamd_address%&               "set interface to SpamAssassin"
 .row &%strict_acl_vars%&             "object to unset ACL variables"
 .row &%spf_smtp_comment_template%&   "template for &$spf_smtp_comment$&"
 .row &%spamd_address%&               "set interface to SpamAssassin"
 .row &%strict_acl_vars%&             "object to unset ACL variables"
 .row &%spf_smtp_comment_template%&   "template for &$spf_smtp_comment$&"
@@ -17017,6 +17018,14 @@ admin user unless &%prod_requires_admin%& is set false. See also
 &%queue_list_requires_admin%& and &%commandline_checks_require_admin%&.
 
 
 &%queue_list_requires_admin%& and &%commandline_checks_require_admin%&.
 
 
+.new
+.option proxy_protocol_timeout main time 3s
+.cindex proxy "proxy protocol"
+This option sets the timeout for proxy protocol negotiation.
+For details see section &<<SECTproxyInbound>>&.
+.wen
+
+
 .option qualify_domain main string "see below"
 .cindex "domain" "for qualifying addresses"
 .cindex "address" "qualification"
 .option qualify_domain main string "see below"
 .cindex "domain" "for qualifying addresses"
 .cindex "address" "qualification"
@@ -41929,7 +41938,8 @@ automatically determines which version is in use.
 The Proxy Protocol header is the first data received on a TCP connection
 and is inserted before any TLS-on-connect handshake from the client; Exim
 negotiates TLS between Exim-as-server and the remote client, not between
 The Proxy Protocol header is the first data received on a TCP connection
 and is inserted before any TLS-on-connect handshake from the client; Exim
 negotiates TLS between Exim-as-server and the remote client, not between
-Exim and the proxy server.
+Exim and the proxy server. The Proxy Protocol header must be received
+within &%proxy_protocol_timeout%&, which defaults to 3s.
 
 The following expansion variables are usable
 (&"internal"& and &"external"& here refer to the interfaces
 
 The following expansion variables are usable
 (&"internal"& and &"external"& here refer to the interfaces
index acbbc15fd8a0d551c4d5e23085b64fd81c8a5093..cd1699dc6f11cde7c55083b149707da1f686b50d 100644 (file)
@@ -43,6 +43,9 @@ Version 4.95
     than the provious behaviour of always loading at startup time for every
     connection.  This helps particularly for the CA bundle.
 
     than the provious behaviour of always loading at startup time for every
     connection.  This helps particularly for the CA bundle.
 
+12. Proxy Protocol Timeout is configurable via "proxy_protocol_timeout"
+    main config option.
+
 Version 4.94
 ------------
 
 Version 4.94
 ------------
 
index 240c2eb80a6d2dbfc559f969f587094ffab7a213..d029f7540b4923b629f4ab410137d9869d23a333 100644 (file)
@@ -1204,6 +1204,7 @@ uschar *proxy_external_address = NULL;
 int     proxy_external_port    = 0;
 uschar *proxy_local_address    = NULL;
 int     proxy_local_port       = 0;
 int     proxy_external_port    = 0;
 uschar *proxy_local_address    = NULL;
 int     proxy_local_port       = 0;
+int     proxy_protocol_timeout = 3;
 #endif
 
 uschar *prvscheck_address      = NULL;
 #endif
 
 uschar *prvscheck_address      = NULL;
index 8fbb141367223764ba267ca9622d9f9451a2959f..41705fb4bb7254d8e2c02da581681ea8ab2aee0b 100644 (file)
@@ -788,6 +788,7 @@ extern uschar *proxy_external_address; /* IP of remote interface of proxy */
 extern int     proxy_external_port;    /* Port on remote interface of proxy */
 extern uschar *proxy_local_address;    /* IP of local interface of proxy */
 extern int     proxy_local_port;       /* Port on local interface of proxy */
 extern int     proxy_external_port;    /* Port on remote interface of proxy */
 extern uschar *proxy_local_address;    /* IP of local interface of proxy */
 extern int     proxy_local_port;       /* Port on local interface of proxy */
+extern int     proxy_protocol_timeout; /* Timeout for proxy negotiation */
 extern BOOL    proxy_session;          /* TRUE if receiving mail from valid proxy  */
 #endif
 
 extern BOOL    proxy_session;          /* TRUE if receiving mail from valid proxy  */
 #endif
 
index c3f1c5d43a6d87178b1ccafae053d48926ffdb92..62b6290eb7b06cc5d93d8433b696c7d91fca69c3 100644 (file)
@@ -196,13 +196,6 @@ record. */
 
 #define WAIT_NAME_MAX 50
 
 
 #define WAIT_NAME_MAX 50
 
-/* Wait this long before determining that a Proxy Protocol configured
-host isn't speaking the protocol, and so is disallowed. Can be moved to
-runtime configuration if per site settings become needed. */
-#ifdef SUPPORT_PROXY
-#define PROXY_NEGOTIATION_TIMEOUT_SEC 3
-#endif
-
 /* Fixed option values for all PCRE functions */
 
 #define PCRE_COPT 0   /* compile */
 /* Fixed option values for all PCRE functions */
 
 #define PCRE_COPT 0   /* compile */
@@ -887,7 +880,7 @@ enum {
 
 /* Options for smtp_write_command */
 
 
 /* Options for smtp_write_command */
 
-enum { 
+enum {
   SCMD_FLUSH = 0,      /* write to kernel */
   SCMD_MORE,           /* write to kernel, but likely more soon */
   SCMD_BUFFER          /* stash in application cmd output buffer */
   SCMD_FLUSH = 0,      /* write to kernel */
   SCMD_MORE,           /* write to kernel, but likely more soon */
   SCMD_BUFFER          /* stash in application cmd output buffer */
index dabe86348b1b0037e7ff6b112d963f15f1c9b72b..0b78a88b9179b6f51eae0f560c3400c71e20b414 100644 (file)
@@ -259,6 +259,9 @@ static optionlist optionlist_config[] = {
   { "print_topbitchars",        opt_bool,        {&print_topbitchars} },
   { "process_log_path",         opt_stringptr,   {&process_log_path} },
   { "prod_requires_admin",      opt_bool,        {&prod_requires_admin} },
   { "print_topbitchars",        opt_bool,        {&print_topbitchars} },
   { "process_log_path",         opt_stringptr,   {&process_log_path} },
   { "prod_requires_admin",      opt_bool,        {&prod_requires_admin} },
+#ifdef SUPPORT_PROXY
+  { "proxy_protocol_timeout",   opt_time,        {&proxy_protocol_timeout} },
+#endif
   { "qualify_domain",           opt_stringptr,   {&qualify_domain_sender} },
   { "qualify_recipient",        opt_stringptr,   {&qualify_domain_recipient} },
   { "queue_domains",            opt_stringptr,   {&queue_domains} },
   { "qualify_domain",           opt_stringptr,   {&qualify_domain_sender} },
   { "qualify_recipient",        opt_stringptr,   {&qualify_domain_recipient} },
   { "queue_domains",            opt_stringptr,   {&queue_domains} },
index 69eae3cb4bd1016307f9fa577d5f469a0e2bebcf..da6d23602c02b864c713095bb953449d0304554f 100644 (file)
@@ -1219,7 +1219,7 @@ socklen_t vslen = sizeof(struct timeval);
 BOOL yield = FALSE;
 
 os_non_restarting_signal(SIGALRM, command_timeout_handler);
 BOOL yield = FALSE;
 
 os_non_restarting_signal(SIGALRM, command_timeout_handler);
-ALARM(PROXY_NEGOTIATION_TIMEOUT_SEC);
+ALARM(proxy_protocol_timeout);
 
 do
   {
 
 do
   {
index e648597694846143d638c60826697da209d0612f..86bf6b31c59ad4c6c049c93ac761d0b442720b06 100644 (file)
@@ -5,6 +5,8 @@
 
 primary_hostname = myhost.test.ex
 hosts_proxy = HOSTIPV4
 
 primary_hostname = myhost.test.ex
 hosts_proxy = HOSTIPV4
+# default timeout is 3s, speed up the timeout test here
+proxy_protocol_timeout = 1s
 queue_only
 
 # ----- Main settings -----
 queue_only
 
 # ----- Main settings -----
index 1eece11120925b250c592b79650cfe3d841721f5..868a2581c008995eeb729115775da98e3d8323a7 100644 (file)
@@ -5,7 +5,7 @@ munge loopback
 exim -bd -DSERVER=server -oX PORT_D
 ****
 #
 exim -bd -DSERVER=server -oX PORT_D
 ****
 #
-# non-prox plain receive
+### non-prox plain receive
 client 127.0.0.1 PORT_D
 ??? 220
 HELO clientname
 client 127.0.0.1 PORT_D
 ??? 220
 HELO clientname
@@ -25,7 +25,7 @@ QUIT
 ??? 221
 ****
 #
 ??? 221
 ****
 #
-# protocol v1 plain receive
+### protocol v1 plain receive
 client HOSTIPV4 PORT_D
 PROXY TCP4 127.0.0.2 127.42.42.42 64000 25
 ??? 220
 client HOSTIPV4 PORT_D
 PROXY TCP4 127.0.0.2 127.42.42.42 64000 25
 ??? 220
@@ -48,7 +48,7 @@ QUIT
 #
 #
 #
 #
 #
 #
-# protocol v2 plain receive
+### protocol v2 plain receive
 client HOSTIPV4 PORT_D
 >>> \x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21\x11\x00\x0c\x7f\x00\x00\x02\x7f\x2a\x2a\x2a\xc2\x95\x04\x01
 ??? 220
 client HOSTIPV4 PORT_D
 >>> \x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21\x11\x00\x0c\x7f\x00\x00\x02\x7f\x2a\x2a\x2a\xc2\x95\x04\x01
 ??? 220
@@ -71,5 +71,13 @@ QUIT
 #
 #
 #
 #
 #
 #
+### proxy timeout
+client HOSTIPV4 PORT_D
+??? 220
+PROXY TCP4 127.0.0.2 127.42.42.42 64000 25
+??? 503
+QUIT
+??? 221
+****
 killdaemon
 no_msglog_check
 killdaemon
 no_msglog_check
index f3d2456ecd78ee7fe33191a4427c76d859229f8e..55e8ba806645f35bd68b84bb6ef036e3e920dd49 100644 (file)
@@ -38,3 +38,9 @@ body v2
 .
 QUIT
 ****
 .
 QUIT
 ****
+### proxy timeout
+exim -bh HOSTIPV4
+:sleep:3
+PROXY TCP4 127.0.0.2 127.42.42.42 64000 25
+QUIT
+****
diff --git a/test/stderr/4030 b/test/stderr/4030
new file mode 100644 (file)
index 0000000..00cf8ea
--- /dev/null
@@ -0,0 +1,10 @@
+### non-prox plain receive
+### protocol v1 plain receive
+### protocol v2 plain receive
+### proxy timeout
+
+******** SERVER ********
+### non-prox plain receive
+### protocol v1 plain receive
+### protocol v2 plain receive
+### proxy timeout
index c5336cb2547fdcb6a2a0b65092b665475bd3b2a8..b0d6a4aaf5003cf9ce8e4ff2ea2226a950e239bc 100644 (file)
@@ -9,7 +9,7 @@
 >>> host in helo_accept_junk_hosts? no (option unset)
 >>> clientname in helo_lookup_domains? no (end of list)
 >>> using ACL "r_acl"
 >>> host in helo_accept_junk_hosts? no (option unset)
 >>> clientname in helo_lookup_domains? no (end of list)
 >>> using ACL "r_acl"
->>> processing "accept" (TESTSUITE/test-config 20)
+>>> processing "accept" (TESTSUITE/test-config 22)
 >>> check logwrite = proxy session: $proxy_session
 >>>                = proxy session: no
 LOG: proxy session: no
 >>> check logwrite = proxy session: $proxy_session
 >>>                = proxy session: no
 LOG: proxy session: no
@@ -42,7 +42,7 @@ LOG: 10HmaX-0005vi-00 <= a@test.ex H=(clientname) [127.0.0.2] P=smtp S=sss
 LOG: no host name found for IP address 127.0.0.2
 >>> clientname in helo_lookup_domains? no (end of list)
 >>> using ACL "r_acl"
 LOG: no host name found for IP address 127.0.0.2
 >>> clientname in helo_lookup_domains? no (end of list)
 >>> using ACL "r_acl"
->>> processing "accept" (TESTSUITE/test-config 20)
+>>> processing "accept" (TESTSUITE/test-config 22)
 >>> check logwrite = proxy session: $proxy_session
 >>>                = proxy session: yes
 LOG: proxy session: yes
 >>> check logwrite = proxy session: $proxy_session
 >>>                = proxy session: yes
 LOG: proxy session: yes
@@ -75,7 +75,7 @@ LOG: 10HmaY-0005vi-00 <= a@test.ex H=(clientname) [127.0.0.2]:1113 P=smtp PRX=ip
 LOG: no host name found for IP address 127.0.0.2
 >>> clientname in helo_lookup_domains? no (end of list)
 >>> using ACL "r_acl"
 LOG: no host name found for IP address 127.0.0.2
 >>> clientname in helo_lookup_domains? no (end of list)
 >>> using ACL "r_acl"
->>> processing "accept" (TESTSUITE/test-config 20)
+>>> processing "accept" (TESTSUITE/test-config 22)
 >>> check logwrite = proxy session: $proxy_session
 >>>                = proxy session: yes
 LOG: proxy session: yes
 >>> check logwrite = proxy session: $proxy_session
 >>>                = proxy session: yes
 LOG: proxy session: yes
@@ -95,8 +95,18 @@ LOG: remote         [127.0.0.2]:1115
 >>> end of ACL "r_acl": ACCEPT
 >>> host in ignore_fromline_hosts? no (option unset)
 LOG: 10HmaZ-0005vi-00 <= a@test.ex H=(clientname) [127.0.0.2]:1115 P=smtp PRX=ip4.ip4.ip4.ip4 S=sss
 >>> end of ACL "r_acl": ACCEPT
 >>> host in ignore_fromline_hosts? no (option unset)
 LOG: 10HmaZ-0005vi-00 <= a@test.ex H=(clientname) [127.0.0.2]:1115 P=smtp PRX=ip4.ip4.ip4.ip4 S=sss
+### proxy timeout
+>>> host in hosts_connection_nolog? no (option unset)
+>>> host in host_lookup? no (option unset)
+>>> host in host_reject_connection? no (option unset)
+>>> host in sender_unqualified_hosts? no (option unset)
+>>> host in recipient_unqualified_hosts? no (option unset)
+>>> host in helo_verify_hosts? no (option unset)
+>>> host in helo_try_verify_hosts? no (option unset)
+>>> host in helo_accept_junk_hosts? no (option unset)
 
 ******** SERVER ********
 ### non-prox plain receive
 ### protocol v1 receive
 ### protocol v2 receive
 
 ******** SERVER ********
 ### non-prox plain receive
 ### protocol v1 receive
 ### protocol v2 receive
+### proxy timeout
index c37aaa963a534b2c3f7cf17354e5cc94bf1afe8b..d6dcda7182146b74f57938a82bac616460713b57 100644 (file)
@@ -1,3 +1,4 @@
+### non-prox plain receive
 Connecting to 127.0.0.1 port 1225 ... connected
 ??? 220
 <<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
 Connecting to 127.0.0.1 port 1225 ... connected
 ??? 220
 <<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
@@ -23,6 +24,7 @@ Connecting to 127.0.0.1 port 1225 ... connected
 ??? 221
 <<< 221 myhost.test.ex closing connection
 End of script
 ??? 221
 <<< 221 myhost.test.ex closing connection
 End of script
+### protocol v1 plain receive
 Connecting to ip4.ip4.ip4.ip4 port 1225 ... connected
 >>> PROXY TCP4 127.0.0.2 127.42.42.42 64000 25
 ??? 220
 Connecting to ip4.ip4.ip4.ip4 port 1225 ... connected
 >>> PROXY TCP4 127.0.0.2 127.42.42.42 64000 25
 ??? 220
@@ -49,6 +51,7 @@ Connecting to ip4.ip4.ip4.ip4 port 1225 ... connected
 ??? 221
 <<< 221 myhost.test.ex closing connection
 End of script
 ??? 221
 <<< 221 myhost.test.ex closing connection
 End of script
+### protocol v2 plain receive
 Connecting to ip4.ip4.ip4.ip4 port 1225 ... connected
 >>> \x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21\x11\x00\x0c\x7f\x00\x00\x02\x7f\x2a\x2a\x2a\xc2\x95\x04\x01
 ??? 220
 Connecting to ip4.ip4.ip4.ip4 port 1225 ... connected
 >>> \x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21\x11\x00\x0c\x7f\x00\x00\x02\x7f\x2a\x2a\x2a\xc2\x95\x04\x01
 ??? 220
@@ -75,3 +78,20 @@ Connecting to ip4.ip4.ip4.ip4 port 1225 ... connected
 ??? 221
 <<< 221 myhost.test.ex closing connection
 End of script
 ??? 221
 <<< 221 myhost.test.ex closing connection
 End of script
+### proxy timeout
+Connecting to ip4.ip4.ip4.ip4 port 1225 ... connected
+??? 220
+<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> PROXY TCP4 127.0.0.2 127.42.42.42 64000 25
+??? 503
+<<< 503 Command refused, required Proxy negotiation failed
+>>> QUIT
+??? 221
+<<< 221 myhost.test.ex closing connection
+End of script
+
+******** SERVER ********
+### non-prox plain receive
+### protocol v1 plain receive
+### protocol v2 plain receive
+### proxy timeout
index a0cddc62ddc98e4866fa42aa616ff2136662c77f..d53009cc1a54b91dc7f8f8cace407da308facce1 100644 (file)
 
 **** SMTP testing: that is not a real message id!
 
 
 **** SMTP testing: that is not a real message id!
 
+221 myhost.test.ex closing connection\r
+### proxy timeout
+
+**** SMTP testing session as if from host ip4.ip4.ip4.ip4
+**** but without any ident (RFC 1413) callback.
+**** This is not for real!
+
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+503 Command refused, required Proxy negotiation failed\r
 221 myhost.test.ex closing connection\r
 
 ******** SERVER ********
 ### non-prox plain receive
 ### protocol v1 receive
 ### protocol v2 receive
 221 myhost.test.ex closing connection\r
 
 ******** SERVER ********
 ### non-prox plain receive
 ### protocol v1 receive
 ### protocol v2 receive
+### proxy timeout