SSL / TLS

Multipath Certification Desired

Open issue is that we have private keys for both ends of the connection, and although it is possible and rather desirable to generate multiple certificate requests for each of our private keys, perhaps two to verify our identity, and another to certify our competency, the description of a server certificate currently assumes there will only be one such thing. “it chooses one”.

This may be like saying to a bank that ask for 2 forms of identity, I am only allowed to give you one.

Also, where we establish the principle of a “generally trusted” person, commonly described as a well-known trusted root certificate authority we could end up requiring that person’s permission, be that in the form of a certificate, to do anything. 😼

Both these effects we might mitigate by allowing multipath wherever certification of public keys are used.

Tunnelling with SSL

This is access through a proxy followed by a patched Apache2 with "AllowCONNECT" and "SSLVerifyClient require" options set.

The server requires "-cert" to be signed by "SSLCACertificateFile" and the client requires "SSLCertificateFile" to be signed by "-CAfile".

The tunnel gateway can share port 443 with other websites with a different configuration, via Server Name Indication. These other sites may choose to require or not a client certificate depending on their application. We can also enable TLS upgrade on port 80, in that situation it is activated via SSLEngine optional.

Also, some adversary networks will even check the SNI indicator as it is also sent in the clear and unencrypted, and may thus even need to be set specifically to please it. It may be possible to patch apache2 further to remove the requirement that the SNI and tunnelled service be the same.

HTTPS intercepting proxy

When you trust the proxy, and your client, but perhaps not the whole network between them, it would be very useful for it to be able to cache responses.

The common CONNECT remote.example.home.arpa:443 HTTP/1.1 pattern did not allow for that.

So instead, train the clients to issue GET https://remote.example.home.arpa:443 HTTP/1.1style requests inside https, then clients can trust a legitimate certificate obtained for your proxy instead of fake rapid generated certs inside connect.

The way found to do this is to add the SSLProxyEngine directive to the forward proxy, despite the apache2 manual saying otherwise.

This moves the issue of checking origin server certificates to apache2.

SSL testcase

Setup openssl as remote.server

  1. openssl s_server -accept 8443 -www -cert server.crt -key server.key

Connect to the apache2 proxy and tell it to connect to the "server"

  1. printf 'GET https://remote.server.away.from.home.arpa:8443/ HTTP/1.1\r\nHost: remote.server.away.from.home.arpa\r\n\r\n' | \
  2. openssl s_client -quiet -connect proxy.at.home.arpa:443 -cert laptop.crt -key laptop.key

A successful connection and no fake TLS/SSL certificates, and apache2 has the chance to do some caching.

There is support for getting browsers to connect to proxies over https but maybe not as of 2022, "GET https" style requests.

Sample Apache2 configuration

<VirtualHost *:443>
 SSLEngine on
 # remove SSLv2 SSLv3, let TLSv1 onwards for now
 # SSLv2 has been cracked and so even has SSLv3
 SSLProtocol all -SSLv2 -SSLv3

 # use only the best cipher! - check string with "openssl ciphers -v $'AES256-SHA'"
 SSLCipherSuite AES256-SHA
 #SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

 # we are this certificate
 SSLCertificateFile /usr/local/lib/ssl/certs/apache.crt
 SSLCertificateKeyFile /usr/local/lib/ssl/private/apache.key

 # our cert was from our root
 SSLCertificateChainFile /usr/local/lib/ssl/cacert.pem

 # we expect clients to have a cert signed with our root's private key
 SSLCACertificateFile /usr/local/lib/ssl/cacert.pem
 SSLCARevocationPath /usr/local/lib/ssl/crl/
 SSLCADNRequestFile /usr/local/lib/ssl/cacert.pem
 SSLOptions +StdEnvVars +ExportCertData +FakeBasicAuth +StrictRequire
 SSLVerifyClient require

 # SSL functions as a forward proxy to interesting places
 ProxyRequests On
 ProxyVia On

 # allow connection to interesting ports, 
 # AllowCONNECT 443 22 5222 5223 119 143 993 587 80 8080

        <Proxy *>
                Order deny,allow
                Deny from all
                Allow from  127.0.0.0/255.0.0.0 ::1/128
                Allow from  192.0.2.0/24 2001:db8::/32

		# Be ready to evaluate the security of apache2 with local tests before enabling something such as the following: 
		# Allow from all
		# The proxy is expected to be protected by the SSLVerifyClient require line,
		# this does depend on adversaries not guessing or having been issued a key signed by SSLCertificateChainFile
		# 
		# Allow from all would not likely be used with plaintext http,
		# that can be served similarly although then security relies strongly upon IP and the lower layers
		# like ipsec, macsec, and the integrity of the network.
        </Proxy>

 # This is for the support of "GET https://" requests, that do not use CONNECT
 SSLProxyEngine on
 # For testing purposes, accept any certificate, although more checks would need adding.
 #SSLProxyCheckPeerName off
 #SSLProxyCheckPeerExpire off
</VirtualHost>

Sample Client end script

This should also check verify the server certificate, and abandon the connection if it is not right.

#!/bin/bash

CERT=/usr/local/lib/ssl/certs/cert.pem
KEY=/usr/local/lib/ssl/private/private.key
TRUSTED=/usr/local/lib/ssl/certs/trusted.crt
SNI=$1

# first connect to the webserver on its SSL port via the local proxy
nc6 -l -s 127.0.0.1 -p 0 --exec "nc.openbsd -X connect -x $1 $2 443" &

C=($(jobs -l|tail -1))
PID=${C[1]}
D=($(netstat -lnp 2>&-|grep ${PID}/nc6))
PORT=${D[3]}

# user is to see if the server certificate is not as expected
exec 4>&2

# open a SSL session on the webserver
nc6 -l -s 127.0.0.1 -p 0 --exec "2>&4 /usr/bin/openssl s_client -nbio -verify -1 \
-servername ${SNI} -quiet -connect ${PORT} -cert ${CERT} \
-key ${KEY} -CAfile ${TRUSTED}" &

C=($(jobs -l|tail -1))
PID=${C[1]}
D=($(netstat -lnp 2>&-|grep ${PID}/nc6))
PORT=${D[3]}

# treat this webserver as a proxy to connect to the destination within the SSL tunnel
# note that if apache2 is to be used as the forward proxy it seems necessary to have it connect to itself at this point,
# such as on port 80.
exec nc.openbsd -X connect -x ${PORT} ${SNI} 22

To use, add something like this to ~/.ssh/config

Host tunnel
ProxyCommand ssltunnel wpad:8080 remote.example.net

Then you may connect to the remote SSH server inside SSL with ssh tunnel