[ 
https://issues.apache.org/jira/browse/CASSANDRA-21750?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Arad Yaron updated CASSANDRA-21750:
-----------------------------------
    Description: 
cqlsh never sets {{server_hostname}} in the SSL options it passes to the Python 
driver. The driver adds SNI only when {{check_hostname}} is enabled, and cqlsh 
never enables it, so the TLS ClientHello carries no {{server_name}} extension. 
TLS-aware middleboxes (WAFs, SNI-routing proxies, load balancers) may reset or 
misroute such connections, even though the host was given on the command line.

cqlsh also exposes only {{validate = true|false}}, with no way to request a 
host name check.

*Proposed change* (PR: https://github.com/apache/cassandra/pull/5237, commit 
81f2ca9f99, against trunk)
* Send SNI with the target host whenever TLS is on, at every validation level, 
except for IP literals (RFC 6066).
* Add {{ssl_mode}} ({{disable | require | verify-ca | verify-identity}}) via 
{{--ssl-mode}}, the {{SSL_MODE}} environment variable, or {{[ssl] ssl_mode}} in 
cqlshrc, in that order of precedence.
* {{verify-identity}} turns on host name checking.
* When {{ssl_mode}} is unset, {{validate}} keeps today's mapping: true or unset 
-> verify-ca, false -> require.
* {{disable}} while SSL is enabled is an error, and an invalid value is 
rejected.
* Settings stay an {{ssl_options}} dict rather than an {{SSLContext}}, so the 
connection reused via {{self.conn.ssl_options}} keeps working.

*Testing*
* 12 new tests in {{pylib/cqlshlib/test/test_sslhandling.py}} pass. They cover 
each mode, the {{validate}} fallback, precedence, IPv4/IPv6 hosts and the error 
cases.
* {{pycodestyle --ignore E501,E402,E731,W503}} (per {{pylib/README.asc}}) is 
clean.
* Real {{bin/cqlsh}} against a local TLS server that records the SNI of each 
handshake:
** trunk, host {{localhost}}: SNI {{None}}
** this patch, {{validate = false}}, host {{localhost}}: SNI {{'localhost'}}
* Docs ({{cqlsh.adoc}}) and {{conf/cqlshrc.sample}} are updated.

*How to reproduce the missing SNI*
Run {{cqlsh --ssl <host> <port>}} against any TLS endpoint that logs the SNI it 
receives (or capture the ClientHello). On trunk, no {{server_name}} is sent.

  was:
cqlsh never sets {{server_hostname}} in the SSL options it passes to the Python 
driver. The driver adds SNI only when {{check_hostname}} is enabled, and cqlsh 
never enables it, so the TLS ClientHello carries no {{server_name}} extension. 
TLS-aware middleboxes (WAFs, SNI-routing proxies, load balancers) may reset or 
misroute such connections, even though the host was given on the command line.

cqlsh also exposes only {{validate = true|false}}, with no way to request a 
host name check.

*Proposed change* (PR: https://github.com/apache/cassandra/pull/5237)
* Send SNI with the target host at every validation level, except for IP 
literals (RFC 6066).
* Add {{ssl_mode}} ({{disable | require | verify-ca | verify-identity}}) via 
{{--ssl-mode}}, the {{SSL_MODE}} environment variable, or {{[ssl] ssl_mode}} in 
cqlshrc, in that order of precedence.
* When {{ssl_mode}} is unset, {{validate}} keeps today's mapping: true or unset 
-> verify-ca, false -> require.
* {{disable}} while SSL is enabled is an error.
* Settings stay an {{ssl_options}} dict rather than an {{SSLContext}}, so the 
connection reused via {{self.conn.ssl_options}} keeps working.

*Testing*
12 new tests in {{pylib/cqlshlib/test/test_sslhandling.py}}. Docs 
({{cqlsh.adoc}}) and {{conf/cqlshrc.sample}} are updated.

*How to reproduce the missing SNI*
{noformat}
cqlsh --ssl <host> 9142
# capture the handshake in parallel:
tshark -i any -Y 'tls.handshake.type == 1' -T fields -e 
tls.handshake.extensions_server_name
{noformat}
Stock cqlsh prints an empty server name. With the patch it prints {{<host>}}.


> cqlsh: send TLS SNI and add ssl_mode
> ------------------------------------
>
>                 Key: CASSANDRA-21750
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-21750
>             Project: Apache Cassandra
>          Issue Type: Improvement
>          Components: Tool/cqlsh
>            Reporter: Arad Yaron
>            Priority: Normal
>
> cqlsh never sets {{server_hostname}} in the SSL options it passes to the 
> Python driver. The driver adds SNI only when {{check_hostname}} is enabled, 
> and cqlsh never enables it, so the TLS ClientHello carries no {{server_name}} 
> extension. TLS-aware middleboxes (WAFs, SNI-routing proxies, load balancers) 
> may reset or misroute such connections, even though the host was given on the 
> command line.
> cqlsh also exposes only {{validate = true|false}}, with no way to request a 
> host name check.
> *Proposed change* (PR: https://github.com/apache/cassandra/pull/5237, commit 
> 81f2ca9f99, against trunk)
> * Send SNI with the target host whenever TLS is on, at every validation 
> level, except for IP literals (RFC 6066).
> * Add {{ssl_mode}} ({{disable | require | verify-ca | verify-identity}}) via 
> {{--ssl-mode}}, the {{SSL_MODE}} environment variable, or {{[ssl] ssl_mode}} 
> in cqlshrc, in that order of precedence.
> * {{verify-identity}} turns on host name checking.
> * When {{ssl_mode}} is unset, {{validate}} keeps today's mapping: true or 
> unset -> verify-ca, false -> require.
> * {{disable}} while SSL is enabled is an error, and an invalid value is 
> rejected.
> * Settings stay an {{ssl_options}} dict rather than an {{SSLContext}}, so the 
> connection reused via {{self.conn.ssl_options}} keeps working.
> *Testing*
> * 12 new tests in {{pylib/cqlshlib/test/test_sslhandling.py}} pass. They 
> cover each mode, the {{validate}} fallback, precedence, IPv4/IPv6 hosts and 
> the error cases.
> * {{pycodestyle --ignore E501,E402,E731,W503}} (per {{pylib/README.asc}}) is 
> clean.
> * Real {{bin/cqlsh}} against a local TLS server that records the SNI of each 
> handshake:
> ** trunk, host {{localhost}}: SNI {{None}}
> ** this patch, {{validate = false}}, host {{localhost}}: SNI {{'localhost'}}
> * Docs ({{cqlsh.adoc}}) and {{conf/cqlshrc.sample}} are updated.
> *How to reproduce the missing SNI*
> Run {{cqlsh --ssl <host> <port>}} against any TLS endpoint that logs the SNI 
> it receives (or capture the ClientHello). On trunk, no {{server_name}} is 
> sent.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to