From 18da1b8df5069ada5dede40a4e90f9b0f7d38d81 Mon Sep 17 00:00:00 2001
From: Dirk Wetter <dirk@testssl.sh>
Date: Tue, 25 Mar 2025 19:13:30 +0100
Subject: [PATCH 1/6] Fix some IPv6 proxy issues

As a quick hack this PR enables *basically* the IPv6 proxy which results that testssl.sh
will use an IPv6 proxy when

* the binary supports that
* the binary is used an not tls_sockets()
* there's no A record but an AAAA record of the proxy or an IPv6 address as proxy address was specified.

The latter should guarantee that it doesn't break anything.

However tls_sockets() still uses IPv4 for the connection to the proxy.

See #1105
---
 testssl.sh | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/testssl.sh b/testssl.sh
index 6c61a38..0ca9a5b 100755
--- a/testssl.sh
+++ b/testssl.sh
@@ -21962,17 +21962,23 @@ check_proxy() {
           # strip off http/https part if supplied:
           PROXY="${PROXY/http\:\/\//}"
           PROXY="${PROXY/https\:\/\//}"      # this shouldn't be needed
+          PROXYPORT="${PROXY##*:}"
           PROXYNODE="${PROXY%:*}"
-          PROXYPORT="${PROXY#*:}"
           is_number "$PROXYPORT" || fatal "Proxy port cannot be determined from \"$PROXY\"" $ERR_CMDLINE
 
-          #if is_ipv4addr "$PROXYNODE" || is_ipv6addr "$PROXYNODE" ; then
-          # IPv6 via openssl -proxy: that doesn't work. Sockets does
-#FIXME: finish this with LibreSSL which supports an IPv6 proxy
+          #FIXME: finish this with IPv6 proxy support, see #1105.
           if is_ipv4addr "$PROXYNODE"; then
                PROXYIP="$PROXYNODE"
+          elif is_ipv6addr "$PROXYNODE"; then
+               # Maybe an option like --proxy6 is better for purists
+               PROXYIP="[$PROXYNODE]"
           else
+               # We check now preferred whether there was an IPv4 proxy via DNS specified
+               # If it fails it could be an IPv6 only proxy via DNS or we just can't reach the proxy
                PROXYIP="$(get_a_record "$PROXYNODE" 2>/dev/null | grep -v alias | sed 's/^.*address //')"
+               if [[ -z "$PROXYIP" ]]; then
+                    PROXYIP="$(get_aaaa_record "$PROXYNODE" 2>/dev/null | grep -v alias | sed 's/^.*address //')"
+               fi
                [[ -z "$PROXYIP" ]] && fatal "Proxy IP cannot be determined from \"$PROXYNODE\"" $ERR_CMDLINE
           fi
           PROXY="-proxy $PROXYIP:$PROXYPORT"

From e81b09176dcd2164f858bbce7d3bed922d7edc3f Mon Sep 17 00:00:00 2001
From: Dirk Wetter <dirk@testssl.sh>
Date: Tue, 25 Mar 2025 19:42:54 +0100
Subject: [PATCH 2/6] Distunguish between LibreSSL and OpenSSL IPv6 proxy

Somehow the proxy now shows only IPv6 source addresses when specifying
--proxy=IPV6ADDRESS:PORT
---
 testssl.sh | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/testssl.sh b/testssl.sh
index 0ca9a5b..7603a9a 100755
--- a/testssl.sh
+++ b/testssl.sh
@@ -21966,12 +21966,16 @@ check_proxy() {
           PROXYNODE="${PROXY%:*}"
           is_number "$PROXYPORT" || fatal "Proxy port cannot be determined from \"$PROXY\"" $ERR_CMDLINE
 
-          #FIXME: finish this with IPv6 proxy support, see #1105.
+          #FIXME: finish IPv6 proxy support, see #1105.
           if is_ipv4addr "$PROXYNODE"; then
                PROXYIP="$PROXYNODE"
           elif is_ipv6addr "$PROXYNODE"; then
                # Maybe an option like --proxy6 is better for purists
-               PROXYIP="[$PROXYNODE]"
+               if [[ "$OSSL_NAME" =~ LibreSSL ]]; then
+                    PROXYIP="$PROXYNODE"
+               else
+                    PROXYIP="[$PROXYNODE]"
+               fi
           else
                # We check now preferred whether there was an IPv4 proxy via DNS specified
                # If it fails it could be an IPv6 only proxy via DNS or we just can't reach the proxy

From 36a58e2b3edb46b7c14f87e613addf42a179e9d5 Mon Sep 17 00:00:00 2001
From: Dirk Wetter <dirk@testssl.sh>
Date: Thu, 27 Mar 2025 18:26:17 +0100
Subject: [PATCH 3/6] Allow square bracket notation for IPv6 proxy

---
 testssl.sh | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/testssl.sh b/testssl.sh
index 7603a9a..9889ff8 100755
--- a/testssl.sh
+++ b/testssl.sh
@@ -21959,11 +21959,14 @@ check_proxy() {
                [[ -z "$PROXY" ]] && PROXY="${http_proxy#*\/\/}"
                [[ -z "$PROXY" ]] && fatal "you specified \"--proxy=auto\" but \"\$http(s)_proxy\" is empty" $ERR_CMDLINE
           fi
-          # strip off http/https part if supplied:
+          # strip http/https part if supplied:
           PROXY="${PROXY/http\:\/\//}"
           PROXY="${PROXY/https\:\/\//}"      # this shouldn't be needed
           PROXYPORT="${PROXY##*:}"
           PROXYNODE="${PROXY%:*}"
+          # strip square brackets in IPv6 notation, but we may enter them later
+          PROXYNODE="${PROXYNODE/\[/}"
+          PROXYNODE="${PROXYNODE/\]/}"
           is_number "$PROXYPORT" || fatal "Proxy port cannot be determined from \"$PROXY\"" $ERR_CMDLINE
 
           #FIXME: finish IPv6 proxy support, see #1105.

From 87edb78b3e787fccd4dc15ee01b6f7f1105d7f53 Mon Sep 17 00:00:00 2001
From: Dirk Wetter <dirk@testssl.sh>
Date: Thu, 27 Mar 2025 18:27:00 +0100
Subject: [PATCH 4/6] Add docu for IPv6 proxy

---
 doc/testssl.1      | 2 +-
 doc/testssl.1.html | 2 +-
 doc/testssl.1.md   | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/doc/testssl.1 b/doc/testssl.1
index 810d54a..55bb900 100644
--- a/doc/testssl.1
+++ b/doc/testssl.1
@@ -90,7 +90,7 @@ A typical internal conversion to testssl\.sh file format from nmap's grep(p)able
 .P
 \fB\-\-ip <ip>\fR tests either the supplied IPv4 or IPv6 address instead of resolving host(s) in \fB<URI>\fR\. IPv6 addresses need to be supplied in square brackets\. \fB\-\-ip=one\fR means: just test the first A record DNS returns (useful for multiple IPs)\. If \fB\-6\fR and \fB\-\-ip=one\fR was supplied an AAAA record will be picked if available\. The \fB\-\-ip\fR option might be also useful if you want to resolve the supplied hostname to a different IP, similar as if you would edit \fB/etc/hosts\fR or \fB/c/Windows/System32/drivers/etc/hosts\fR\. \fB\-\-ip=proxy\fR tries a DNS resolution via proxy\. \fB\-\-ip=proxy\fR plus \fB\-\-nodns=min\fR is useful for situations with no local DNS as there'll be no DNS timeouts when trying to resolve CAA, TXT and MX records\.
 .P
-\fB\-\-proxy <host>:<port>\fR does ANY check via the specified proxy\. \fB\-\-proxy=auto\fR inherits the proxy setting from the environment\. The hostname supplied will be resolved to the first A record\. In addition if you want lookups via proxy you can specify \fBDNS_VIA_PROXY=true\fR\. OCSP revocation checking (\fB\-S \-\-phone\-out\fR) is not supported by OpenSSL via proxy\. As supplying a proxy is an indicator for port 80 and 443 outgoing being blocked in your network an OCSP revocation check won't be performed\. However if \fBIGN_OCSP_PROXY=true\fR has been supplied it will be tried directly\. Authentication to the proxy is not supported\. Proxying via IPv6 addresses is not possible, no HTTPS or SOCKS proxy is supported\.
+\fB\-\-proxy <host>:<port>\fR does ANY check via the specified proxy\. \fB\-\-proxy=auto\fR inherits the proxy setting from the environment\. Any hostname supplied will be resolved to the first A record, if it does not exist the AAAA record is used\. IPv4 and IPv6 addresses can be passed too, the latter \fIalso\fR with square bracket notation\. Please note that you need a newer OpenSSL or LibreSSL version for IPv6 proxy functionality\. In addition if you want lookups via proxy you can specify \fBDNS_VIA_PROXY=true\fR\. OCSP revocation checking (\fB\-S \-\-phone\-out\fR) is not supported by OpenSSL via proxy\. As supplying a proxy is an indicator for port 80 and 443 outgoing being blocked in your network an OCSP revocation check won't be performed\. However if \fBIGN_OCSP_PROXY=true\fR has been supplied it will be tried directly\. Authentication to the proxy is not supported\. Proxying via IPv6 addresses is not supported, also no HTTPS or SOCKS proxy\.
 .P
 \fB\-6\fR does (also) IPv6 checks\. Please note that testssl\.sh doesn't perform checks on an IPv6 address automatically, because of two reasons: testssl\.sh does no connectivity checks for IPv6 and it cannot determine reliably whether the OpenSSL binary you're using has IPv6 s_client support\. \fB\-6\fR assumes both is the case\. If both conditions are met and you in general prefer to test for IPv6 branches as well you can add \fBHAS_IPv6\fR to your shell environment\. Besides the OpenSSL binary supplied IPv6 is known to work with vanilla OpenSSL >= 1\.1\.0 and older versions >=1\.0\.2 in RHEL/CentOS/FC and Gentoo\.
 .P
diff --git a/doc/testssl.1.html b/doc/testssl.1.html
index 0336c4b..b323e8d 100644
--- a/doc/testssl.1.html
+++ b/doc/testssl.1.html
@@ -204,7 +204,7 @@ The same can be achieved by setting the environment variable <code>WARNINGS</cod
 
 <p><code>--ip &lt;ip&gt;</code> tests either the supplied IPv4 or IPv6 address instead of resolving host(s) in <code>&lt;URI&gt;</code>. IPv6 addresses need to be supplied in square brackets. <code>--ip=one</code> means: just test the first A record DNS returns (useful for multiple IPs). If <code>-6</code> and  <code>--ip=one</code> was supplied an AAAA record will be picked if available. The <code>--ip</code> option might be also useful if you want to resolve the supplied hostname to a different IP, similar as if you would edit <code>/etc/hosts</code> or <code>/c/Windows/System32/drivers/etc/hosts</code>. <code>--ip=proxy</code> tries a DNS resolution via proxy. <code>--ip=proxy</code> tries a DNS resolution via proxy. </code>--ip=proxy</code> plus <code>--nodns=min</code> is useful for situations with no local DNS as there'll be no DNS timeouts when trying to resolve CAA, TXT and MX records.</p>
 
-<p><code>--proxy &lt;host&gt;:&lt;port&gt;</code>  does ANY check via the specified proxy. <code>--proxy=auto</code> inherits the proxy setting from the environment. The hostname supplied will be resolved to the first A record. In addition if you want lookups via proxy you can specify <code>DNS_VIA_PROXY=true</code>. OCSP revocation checking (<code>-S --phone-out</code>) is not supported by OpenSSL via proxy. As supplying a proxy is an indicator for port 80 and 443 outgoing being blocked in your network an OCSP revocation check won't be performed. However if <code>IGN_OCSP_PROXY=true</code> has been supplied it will be tried directly. Authentication to the proxy is not supported. Proxying via IPv6 addresses is not possible, no HTTPS or SOCKS proxy is supported.</p>
+<p><code>--proxy &lt;host&gt;:&lt;port&gt;</code> does ANY check via the specified proxy. <code>--proxy=auto</code> inherits the proxy setting from the environment. Any hostname supplied will be resolved to the first A record, if it does not exist the AAAA record is used. IPv4 and IPv6 addresses can be passed too, the latter <em>also</em> with square bracket notation. Please note that you need a newer OpenSSL or LibreSSL version for IPv6 proxy functionality. In addition if you want lookups via proxy you can specify <code>DNS_VIA_PROXY=true</code>. OCSP revocation checking (<code>-S --phone-out</code>) is not supported by OpenSSL via proxy. As supplying a proxy is an indicator for port 80 and 443 outgoing being blocked in your network an OCSP revocation check won't be performed. However if <code>IGN_OCSP_PROXY=true</code> has been supplied it will be tried directly. Authentication to the proxy is not supported, also no HTTPS or SOCKS proxy.</p>
 
 <p><code>-6</code> does (also) IPv6 checks. Please note that testssl.sh doesn't perform checks on an IPv6 address automatically, because of two reasons: testssl.sh does no connectivity checks for IPv6 and it cannot determine reliably whether the OpenSSL binary you're using has IPv6 s_client support. <code>-6</code> assumes both is the case. If both conditions are met and you in general prefer to test for IPv6 branches as well you can add <code>HAS_IPv6</code> to your shell environment. Besides the OpenSSL binary supplied IPv6 is known to work with vanilla OpenSSL &gt;= 1.1.0 and older versions &gt;=1.0.2 in RHEL/CentOS/FC and Gentoo.</p>
 
diff --git a/doc/testssl.1.md b/doc/testssl.1.md
index edbc304..0f78672 100644
--- a/doc/testssl.1.md
+++ b/doc/testssl.1.md
@@ -126,7 +126,7 @@ The same can be achieved by setting the environment variable `WARNINGS`.
 
 `--ip <ip>` tests either the supplied IPv4 or IPv6 address instead of resolving host(s) in `<URI>`. IPv6 addresses need to be supplied in square brackets. `--ip=one` means: just test the first A record DNS returns (useful for multiple IPs). If `-6` and  `--ip=one` was supplied an AAAA record will be picked if available. The ``--ip`` option might be also useful if you want to resolve the supplied hostname to a different IP, similar as if you would edit `/etc/hosts` or `/c/Windows/System32/drivers/etc/hosts`. `--ip=proxy` tries a DNS resolution via proxy. `--ip=proxy` plus `--nodns=min` is useful for situations with no local DNS as there'll be no DNS timeouts when trying to resolve CAA, TXT and MX records.
 
-`--proxy <host>:<port>`  does ANY check via the specified proxy. `--proxy=auto` inherits the proxy setting from the environment. The hostname supplied will be resolved to the first A record. In addition if you want lookups via proxy you can specify `DNS_VIA_PROXY=true`. OCSP revocation checking (`-S --phone-out`) is not supported by OpenSSL via proxy. As supplying a proxy is an indicator for port 80 and 443 outgoing being blocked in your network an OCSP revocation check won't be performed. However if `IGN_OCSP_PROXY=true` has been supplied it will be tried directly. Authentication to the proxy is not supported. Proxying via IPv6 addresses is not possible, no HTTPS or SOCKS proxy is supported.
+`--proxy <host>:<port>`  does ANY check via the specified proxy. `--proxy=auto` inherits the proxy setting from the environment. Any hostname supplied will be resolved to the first A record, if it does not exist the AAAA record is used. IPv4 and IPv6 addresses can be passed too, the latter *also* with square bracket notation. Please note that you need a newer OpenSSL or LibreSSL version for IPv6 proxy functionality. In addition if you want lookups via proxy you can specify `DNS_VIA_PROXY=true`. OCSP revocation checking (`-S --phone-out`) is not supported by OpenSSL via proxy. As supplying a proxy is an indicator for port 80 and 443 outgoing being blocked in your network an OCSP revocation check won't be performed. However if `IGN_OCSP_PROXY=true` has been supplied it will be tried directly. Authentication to the proxy is not supported, also no HTTPS or SOCKS proxy.
 
 `-6` does (also) IPv6 checks. Please note that testssl.sh doesn't perform checks on an IPv6 address automatically, because of two reasons: testssl.sh does no connectivity checks for IPv6 and it cannot determine reliably whether the OpenSSL binary you're using has IPv6 s_client support. `-6` assumes both is the case. If both conditions are met and you in general prefer to test for IPv6 branches as well you can add `HAS_IPv6` to your shell environment. Besides the OpenSSL binary supplied IPv6 is known to work with vanilla OpenSSL >= 1.1.0 and older versions >=1.0.2 in RHEL/CentOS/FC and Gentoo.
 

From 44d9f520fb1cc87739479775865a238c77023cb8 Mon Sep 17 00:00:00 2001
From: Dirk Wetter <dirk@testssl.sh>
Date: Tue, 1 Apr 2025 23:37:54 +0200
Subject: [PATCH 5/6] Add check for proxy IPv6 support

... of the binary. Testing needs to be done.
---
 testssl.sh | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/testssl.sh b/testssl.sh
index 9889ff8..bbc879b 100755
--- a/testssl.sh
+++ b/testssl.sh
@@ -21977,7 +21977,12 @@ check_proxy() {
                if [[ "$OSSL_NAME" =~ LibreSSL ]]; then
                     PROXYIP="$PROXYNODE"
                else
-                    PROXYIP="[$PROXYNODE]"
+                    # This was tested with vanilla OpenSSL versions
+                    if [[ ${OSSL_VER_MAJOR$}${OSSL_VER_MINOR} -ge 11 ]]; then
+                         PROXYIP="[$PROXYNODE]"
+                    else
+                         fatal_cmd_line "OpenSSL version >= 1.1.0 required for IPv6 proxy support" $ERR_OSSLBIN
+                    fi
                fi
           else
                # We check now preferred whether there was an IPv4 proxy via DNS specified
@@ -21985,6 +21990,11 @@ check_proxy() {
                PROXYIP="$(get_a_record "$PROXYNODE" 2>/dev/null | grep -v alias | sed 's/^.*address //')"
                if [[ -z "$PROXYIP" ]]; then
                     PROXYIP="$(get_aaaa_record "$PROXYNODE" 2>/dev/null | grep -v alias | sed 's/^.*address //')"
+                    if [[ -n "$PROXYIP" ]]; then
+                         if [[ ${OSSL_VER_MAJOR$}${OSSL_VER_MINOR} -lt 11 ]]; then
+                              fatal_cmd_line "OpenSSL version >= 1.1.0 required for IPv6 proxy support" $ERR_OSSLBIN
+                         fi
+                    fi
                fi
                [[ -z "$PROXYIP" ]] && fatal "Proxy IP cannot be determined from \"$PROXYNODE\"" $ERR_CMDLINE
           fi

From ffe5dea84401027fbbe058017fc8ba76627d4815 Mon Sep 17 00:00:00 2001
From: Dirk <dirk@testssl.sh>
Date: Tue, 22 Apr 2025 12:55:42 +0200
Subject: [PATCH 6/6] remove misleading command

---
 testssl.sh | 1 -
 1 file changed, 1 deletion(-)

diff --git a/testssl.sh b/testssl.sh
index bbc879b..b1d86e7 100755
--- a/testssl.sh
+++ b/testssl.sh
@@ -21969,7 +21969,6 @@ check_proxy() {
           PROXYNODE="${PROXYNODE/\]/}"
           is_number "$PROXYPORT" || fatal "Proxy port cannot be determined from \"$PROXY\"" $ERR_CMDLINE
 
-          #FIXME: finish IPv6 proxy support, see #1105.
           if is_ipv4addr "$PROXYNODE"; then
                PROXYIP="$PROXYNODE"
           elif is_ipv6addr "$PROXYNODE"; then