Jira (PUP-10154) Detect connection errors when using TLS 1.3 and using post-handshake authentication

0 views
Skip to first unread message

Josh Cooper (JIRA)

unread,
Dec 2, 2019, 5:34:04 PM12/2/19
to puppe...@googlegroups.com
Josh Cooper created an issue
 
Puppet / Bug PUP-10154
Detect connection errors when using TLS 1.3 and using post-handshake authentication
Issue Type: Bug Bug
Assignee: Unassigned
Created: 2019/12/02 2:33 PM
Priority: Normal Normal
Reporter: Josh Cooper

Prior to TLS 1.3, the client always sends it certificate during the TLS handshake. As a result, the OpenSSL::SSL::SSLSocket#connect method only returns success if the server accepted our client cert. This way we can differentiate between connection errors and other types of errors, like HTTP 302, when processing our server list, finding a suitable server using SRV, etc.

When using TLS 1.3, the client cert may be sent after the server completes its side of the TLS handshake. This is referred to as post handshake authentication. This means the client won't know if the server accepted its client cert until after SSLSocket#connect returns and we try to send application data. If the server rejected our cert, then we'll get a ECONNRESET.

It also appears TLS 1.3 can send the client during the handshake, but prefers to send it after, to reduce the number of TLS packages that are needed to connect/resume. It appears ruby hardcodes the use of post_connection_auth. See https://github.com/ruby/openssl/pull/239

If there was a way to set disable that extension via Net::HTTP then we wouldn't need to account for the different protocol behaviors.

Add Comment Add Comment
 
This message was sent by Atlassian JIRA (v7.7.1#77002-sha1:e75ca93)
Atlassian logo

Josh Cooper (JIRA)

unread,
Dec 2, 2019, 5:42:04 PM12/2/19
to puppe...@googlegroups.com
Josh Cooper updated an issue
Change By: Josh Cooper
Prior to TLS 1.3, the client always sends it certificate during the TLS handshake. As a result, the {{OpenSSL::SSL::SSLSocket#connect}} method only returns success if the server accepted our client cert. This way we can differentiate between connection errors and other types of errors, like HTTP 302, when processing our server list, finding a suitable server using SRV, etc.

When using TLS 1.3, the client cert *may* be sent after the server completes its side of the TLS handshake. This is referred to as post handshake authentication. This means the client won't know if the server accepted its client cert until after {{SSLSocket#connect}} returns and we try to send application data. If the server rejected our cert, then we'll get a {{ECONNRESET}}.

It also appears TLS 1.3 can send the client during the handshake
(it was on by default in openssl 1.1.0 , but prefers [changed to send it after, opt-in in 1.1.1|https://github.com/openssl/openssl/pull/6938]) to reduce the number of TLS packages that are needed to connect/resume. It appears ruby hardcodes the use of {{post_connection_auth}}. See [ https://github.com/ruby/openssl/pull/239 ]

If there was a way to set disable that extension via {{Net::HTTP}} then we wouldn't need to account for the different protocol behaviors.

Josh Cooper (JIRA)

unread,
Dec 2, 2019, 6:26:04 PM12/2/19
to puppe...@googlegroups.com
Josh Cooper updated an issue
Prior to TLS 1.3, the client always sends it certificate during the TLS handshake. As a result, the {{OpenSSL::SSL::SSLSocket#connect}} method only returns success if the server accepted our client cert. This way we can differentiate between connection errors and other types of errors, like HTTP 302, when processing our server list, finding a suitable server using SRV, etc.

When using TLS 1.3, the client cert *may* be sent after the server completes its side of the TLS handshake. This is referred to as post handshake authentication. This means the client won't know if the server accepted its client cert until after {{SSLSocket#connect}} returns and we try to send application data. If the server rejected our cert, then we'll get a {{ECONNRESET}}.

It also appears TLS 1.3 can send the client during the handshake (it was on by default in openssl 1.1.0, but [changed to opt-in in 1.1.1|https://github.com/openssl/openssl/pull/6938]) to reduce the number of TLS packages that are needed to connect/resume. It appears ruby hardcodes the use of {{post_connection_auth}}. See [https://github.com/ruby/openssl/pull/239]  However that version of ruby-openssl hasn't been promoted into any branch of ruby yet.

If there was a way to set disable that extension via {{Net::HTTP}} then we wouldn't need to account for the different protocol behaviors.

Josh Cooper (JIRA)

unread,
Dec 4, 2019, 11:40:03 AM12/4/19
to puppe...@googlegroups.com

Josh Cooper (JIRA)

unread,
Dec 4, 2019, 11:40:04 AM12/4/19
to puppe...@googlegroups.com

Josh Cooper (JIRA)

unread,
Jan 6, 2020, 5:50:04 PM1/6/20
to puppe...@googlegroups.com
Josh Cooper updated an issue
Prior to TLS 1.3, the client always sends it its certificate (if it has one) during the TLS handshake. As a result, the {{OpenSSL::SSL::SSLSocket#connect}} method only returns success if the server accepted our client cert (or we didn't have one) . This way we can differentiate between connection errors and other types of errors, like HTTP 302, when processing our server list, finding a suitable server using SRV, etc.


When using TLS 1.3, the client cert *may* be sent after the server completes its side of the TLS handshake. This is referred to as post handshake authentication. This means the client won't know if the server accepted its client cert until after {{SSLSocket#connect}} returns and we try to send application data. If the server rejected our cert, then we'll get a {{ECONNRESET}}.

It also appears TLS 1.3 can send the client during the handshake (it was on by default in openssl 1.1.0, but [changed to opt-in in 1.1.1|https://github.com/openssl/openssl/pull/6938]) to reduce the number of TLS packages that are needed to connect/resume. It appears ruby hardcodes the use of {{post_connection_auth}}. See [https://github.com/ruby/openssl/pull/239] However that version of ruby-openssl hasn't been promoted into any branch of ruby yet.

If there was a way to set disable that extension via {{Net::HTTP}} then we wouldn't need to account for the different protocol behaviors.

Jorie Tappa (JIRA)

unread,
Jan 27, 2020, 1:18:04 PM1/27/20
to puppe...@googlegroups.com
Jorie Tappa commented on Bug PUP-10154
 
Re: Detect connection errors when using TLS 1.3 and using post-handshake authentication

We need to ask Server what TLS protocols Puppet Server supports in a fresh install, and determine from there how to proceed with this.

Josh Cooper (Jira)

unread,
Mar 4, 2020, 2:55:03 PM3/4/20
to puppe...@googlegroups.com
Josh Cooper commented on Bug PUP-10154

Puppetserver doesn't support TLSv1.3:

$ openssl s_client -connect red-overhead.delivery.puppetlabs.net:8140 -tls1_3
CONNECTED(00000005)
4754687424:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:ssl/record/rec_layer_s3.c:1544:SSL alert number 40
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 260 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)

This message was sent by Atlassian Jira (v8.5.2#805002-sha1:a66f935)
Atlassian logo

Josh Cooper (Jira)

unread,
Mar 30, 2020, 7:45:03 PM3/30/20
to puppe...@googlegroups.com

Josh Cooper (Jira)

unread,
Jun 22, 2021, 7:29:02 PM6/22/21
to puppe...@googlegroups.com
Josh Cooper commented on Bug PUP-10154
 
Re: Detect connection errors when using TLS 1.3 and using post-handshake authentication

It's now possible to configure puppetserver to use TLS 1.3:

[root@prim-skepticism ~]# yum install java-11-openjdk
[root@prim-skepticism ~]# yum install java-11-openjdk-devel
[root@prim-skepticism ~]# grep JAVA_BIN /etc/sysconfig/puppetserver 
JAVA_BIN="/usr/lib/jvm/java-11/bin/java"
[root@prim-skepticism ~]# cat /etc/puppetlabs/puppetserver/conf.d/webserver.conf 
webserver: {
    access-log-config: /etc/puppetlabs/puppetserver/request-logging.xml
    client-auth: want
    ssl-host: 0.0.0.0
    ssl-port: 8140
    ssl-protocols: [TLSv1.3]
    cipher-suites: [TLS_AES_128_GCM_SHA256]
}
[root@prim-skepticism ~]# systemctl restart puppetserver
[root@prim-skepticism ~]# openssl s_client -connect $(facter fqdn):8140 -CAfile /etc/puppetlabs/puppet/ssl/certs/ca.pem -cert /etc/puppetlabs/puppet/ssl/certs/prim-skepticism.delivery.puppetlabs.net.pem -key /etc/puppetlabs/puppet/ssl/private_keys/prim-skepticism.delivery.puppetlabs.net.pem -tls1_3
CONNECTED(00000004)
depth=1 CN = Puppet CA: prim-skepticism.delivery.puppetlabs.net
verify return:1
depth=0 CN = prim-skepticism.delivery.puppetlabs.net
verify return:1
...
---
SSL handshake has read 2381 bytes and written 3979 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Server public key is 4096 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
    Protocol  : TLSv1.3
    Cipher    : TLS_AES_128_GCM_SHA256
...
    Start Time: 1624404239
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: no
    Max Early Data: 0
---
read R BLOCK
^C
[root@prim-skepticism ~]# puppet agent -t
Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for prim-skepticism.delivery.puppetlabs.net
Info: Applying configuration version '1624404247'
Notice: 4
Notice: /Stage[main]/Timeout/Notify[4]/message: defined 'message' as '4'
Notice: Applied catalog in 0.01 seconds
[root@prim-skepticism ~]# puppet agent -t --h^C
[root@prim-skepticism ~]# puppet agent -t --debug 2>&1 | grep TLS
Debug: Using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256

This message was sent by Atlassian Jira (v8.13.2#813002-sha1:c495a97)
Atlassian logo
Reply all
Reply to author
Forward
0 new messages