Projects
Kolab:Winterfell
roundcubemail-selfcontained
0003-Introduce-optional-support-to-inject-PROXY...
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0003-Introduce-optional-support-to-inject-PROXY-protocol-.patch of Package roundcubemail-selfcontained
From 70e23efafae75b5604fd5206e64571cee59ba71a Mon Sep 17 00:00:00 2001 From: Christian Mollekopf <mollekopf@apheleia-it.ch> Date: Thu, 14 Jul 2022 15:04:16 +0200 Subject: [PATCH 3/6] Introduce optional support to inject PROXY protocol headers after opening IMAP TCP streams. Version 1 (text based) and version 2 (binary) protocol header types are supported. Supports both IPv4 and IPv6 style headers. http://www.haproxy.org/download/1.6/doc/proxy-protocol.txt --- config/defaults.inc.php | 10 +++ program/lib/Roundcube/rcube_imap_generic.php | 8 ++ program/lib/Roundcube/rcube_utils.php | 79 ++++++++++++++++++++ 3 files changed, 97 insertions(+) diff --git a/config/defaults.inc.php b/config/defaults.inc.php index 018ad9af3..a6cd3b9a5 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -157,12 +157,22 @@ $config['imap_auth_type'] = null; // IMAP socket context options // See http://php.net/manual/en/context.ssl.php // The example below enables server certificate validation +// +// proxy_protocol is used to inject HAproxy style headers in the TCP stream +// See http://www.haproxy.org/download/1.6/doc/proxy-protocol.txt //$config['imap_conn_options'] = [ // 'ssl' => [ // 'verify_peer' => true, // 'verify_depth' => 3, // 'cafile' => '/etc/openssl/certs/ca.crt', // ], +// 'proxy_protocol' => 1 | 2 | [ // required (either version number (1|2) or array with 'version' key) +// 'version' => 1 | 2, // required, if array +// 'remote_addr' => $_SERVER['REMOTE_ADDR'], +// 'remote_port' => $_SERVER['REMOTE_PORT'], +// 'local_addr' => $_SERVER['SERVER_ADDR'], +// 'local_port' => $_SERVER['SERVER_PORT'], +// ], // ]; // Note: These can be also specified as an array of options indexed by hostname $config['imap_conn_options'] = null; diff --git a/program/lib/Roundcube/rcube_imap_generic.php b/program/lib/Roundcube/rcube_imap_generic.php index 8f1285368..d2f5cf410 100644 --- a/program/lib/Roundcube/rcube_imap_generic.php +++ b/program/lib/Roundcube/rcube_imap_generic.php @@ -1070,6 +1070,14 @@ class rcube_imap_generic return false; } + // insert proxy protocol header, if enabled + if (!empty($this->prefs['socket_options'])) { + $proxy_protocol_header = rcube_utils::proxy_protocol_header($this->prefs['socket_options'], $this->fp); + if (strlen($proxy_protocol_header) > 0) { + fwrite($this->fp, $proxy_protocol_header); + } + } + if ($this->prefs['timeout'] > 0) { stream_set_timeout($this->fp, $this->prefs['timeout']); } diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php index eb51f98ed..ec31fa11b 100644 --- a/program/lib/Roundcube/rcube_utils.php +++ b/program/lib/Roundcube/rcube_utils.php @@ -1645,4 +1645,83 @@ class rcube_utils return trim($subject); } + + /** + * When proxy_protocol is configured for a connection type, + * generate the HAproxy style PROXY protocol header for injection + * into the TCP stream. + * http://www.haproxy.org/download/1.6/doc/proxy-protocol.txt + * + * PROXY protocol headers must be sent before any other data is sent on the TCP socket. + * + * @param array $conn_options preferences array which may contain proxy_protocol (generally {driver}_conn_options) + * + * @return string proxy protocol header data, if enabled, otherwise empty string + */ + public static function proxy_protocol_header($conn_options = null) + { + if ($conn_options === null) + { + return ""; + } + // verify that proxy_protocol option is present + if (is_array($conn_options) && array_key_exists('proxy_protocol', $conn_options)) { + if (is_array($conn_options['proxy_protocol'])) { + $proxy_protocol_version = $conn_options['proxy_protocol']['version']; + $proxy_protocol_options = $conn_options['proxy_protocol']; + } + else { + $proxy_protocol_version = $conn_options['proxy_protocol']; + $proxy_protocol_options = null; + } + + $proxy_protocol_remote_addr = (array_key_exists('remote_addr', $proxy_protocol_options) ? $proxy_protocol_options['remote_addr'] : $_SERVER['REMOTE_ADDR'] ); + $proxy_protocol_remote_port = (array_key_exists('remote_port', $proxy_protocol_options) ? $proxy_protocol_options['remote_port'] : $_SERVER['REMOTE_PORT'] ); + $proxy_protocol_local_addr = (array_key_exists('local_addr' ,$proxy_protocol_options) ? $proxy_protocol_options['local_addr'] : $_SERVER['SERVER_ADDR'] ); + $proxy_protocol_local_port = (array_key_exists('local_port', $proxy_protocol_options) ? $proxy_protocol_options['local_port'] : $_SERVER['SERVER_PORT'] ); + $proxy_protocol_ip_version = (strpos($proxy_protocol_remote_addr, ":") === false ? 4 : 6); + + if ($proxy_protocol_version === 1) { + // text based PROXY protocol + + // PROXY protocol does not support dual IPv6+IPv4 type addresses, e.g. ::127.0.0.1 + if ($proxy_protocol_ip_version === 6 && strpos($proxy_protocol_remote_addr, ".") !== false) { + $proxy_protocol_remote_addr = inet_ntop(inet_pton($proxy_protocol_remote_addr)); + } + if ($proxy_protocol_ip_version === 6 && strpos($proxy_protocol_local_addr, ".") !== false) { + $proxy_protocol_local_addr = inet_ntop(inet_pton($proxy_protocol_local_addr)); + } + + $proxy_protocol_text = "PROXY " . // protocol header + ($proxy_protocol_ip_version === 6 ? "TCP6 " : "TCP4 ") . // IP version type + $proxy_protocol_remote_addr . + " " . + $proxy_protocol_local_addr . + " " . + $proxy_protocol_remote_port . + " " . + $proxy_protocol_local_port . + "\r\n"; + return $proxy_protocol_text; + } + else if ($proxy_protocol_version === 2) { + // binary PROXY protocol + $proxy_protocol_bin = pack("H*", "0D0A0D0A000D0A515549540A" . // protocol header + "21" . // protocol version and command + ($proxy_protocol_ip_version === 6 ? "2" : "1") . // IP version type + "1"); // TCP + $proxy_protocol_addr = inet_pton($proxy_protocol_remote_addr) . + inet_pton($proxy_protocol_local_addr) . + pack("n", $proxy_protocol_remote_port) . + pack("n", $proxy_protocol_local_port); + $proxy_protocol_bin .= pack("n", strlen($proxy_protocol_addr)) . $proxy_protocol_addr; + return $proxy_protocol_bin; + } + else { + // unknown proxy protocol version + return ""; + } + } + return ""; + } } -- 2.37.1
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.