Skip to content

Couldn't connect to Amazon Keyspaces from EC2-hosted C# app using CassandraCSharpDriver, but CAN from my local machine

0

I'm trying to connect to Amazon Keyspaces from EC2 Windows instance, and couldn't, BUT I can successfully connect to it from my local PC with absolutely same trivial console application:

using System;
using Cassandra;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

namespace cassandraconnectiotest;
internal class Program
{
    static void Main(string[] args)
    {
        try
        {
            var amazoncert = new X509Certificate2("AmazonRootCA1.der");
            // I obtained AmazonRootCA1.der by executing:
            // curl https://www.amazontrust.com/repository/AmazonRootCA1.pem -o AmazonRootCA1.pem
            // openssl x509 -outform der -in AmazonRootCA1.pem -out AmazonRootCA1.der


            var sslOptions = new SSLOptions(System.Security.Authentication.SslProtocols.Tls13, false, null) //it will NOT work with simple new SSLOptions() for some reason
            // and will return Cassandra.NoHostAvailableException: All hosts tried for query failed (tried 3.12.23.190:9142: IOException 'Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host..')
                .SetCertificateCollection(new X509Certificate2Collection { amazoncert })
                .SetRemoteCertValidationCallback((sender, cert, chain, sslPolicyErrors) =>
                {
                    Console.WriteLine(cert.Subject);
                    if (sslPolicyErrors == SslPolicyErrors.None)
                    {
                        Console.WriteLine($"SSL Certificate is valid!");
                        return true; // Certificate is valid
                    }
                    else
                    {
                        // Log the SSL policy errors
                        Console.WriteLine($"SSL Certificate Error: {sslPolicyErrors}");

                        // Optionally, log details about the certificate and chain
                        if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) != 0 && chain != null)
                        {
                            foreach (var chainStatus in chain.ChainStatus)
                            {
                                Console.WriteLine($"Chain Status: {chainStatus.Status} - {chainStatus.StatusInformation}");
                            }
                        }

                        // Return false to reject the certificate
                        return false;
                    }
                });

            var cluster = Cluster.Builder()
                 .AddContactPoints("cassandra.us-east-2.amazonaws.com")
                 .WithPort(9142)
                 .WithAuthProvider(new PlainTextAuthProvider("cassandra_keyspaces+1-at-NNNNhere", @"xLk35password/2ndpartofit="))
                 .WithSSL(sslOptions)
                 .Build();
            var session = cluster.Connect();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
}

When I'm connecting from my local machine, I'm getting number of messages like this:

CN=cassandra.us-east-2.amazonaws.com
SSL Certificate is valid!
CN=cassandra.us-east-2.amazonaws.com
SSL Certificate is valid!

so I'm assuming it's negotiation phase.

But when I'm running same app from EC2 instance, I'm getting:

Cassandra.NoHostAvailableException: All hosts tried for query failed (tried 3.12.23.188:9142: AuthenticationException 'Authentication failed, see inner exception.')
   at Cassandra.Connections.Control.ControlConnection.Connect(Boolean isInitializing)
   at Cassandra.Connections.Control.ControlConnection.InitAsync()
   at Cassandra.Tasks.TaskHelper.WaitToCompleteAsync(Task task, Int32 timeout)
   at Cassandra.Cluster.Init()
   at Cassandra.Cluster.ConnectAsync(String keyspace)
   at Cassandra.Tasks.TaskHelper.WaitToComplete(Task task, Int32 timeout)
   at Cassandra.Tasks.TaskHelper.WaitToComplete[T](Task`1 task, Int32 timeout)
   at Cassandra.Cluster.Connect(String keyspace)
   at Cassandra.Cluster.Connect()
   at cassandraconnectiotest.Program.Main(String[] args) in D:\git\beholdtech\trivialcassandraconnectiontest\cassandraconnectiotest\Program.cs:line 56

At the same time on EC2 instance:

tracert cassandra.us-east-2.amazonaws.com

gives:

Tracing route to cassandra.us-east-2.amazonaws.com [3.12.23.165]... 

(seems to be working)

C:\>nslookup cassandra.us-east-2.amazonaws.com
Server:  ip-172-31-0-2.us-east-2.compute.internal
Address:  172.31.0.2

Non-authoritative answer:
Name:    cassandra.us-east-2.amazonaws.com
Address:  3.12.23.190



telnet cassandra.us-east-2.amazonaws.com 9142

gives black screen with some effect when I type.

c:\> openssl s_client -connect cassandra.us-east-2.amazonaws.com:9142 -msg -debug

gives

Connecting to 3.12.23.184
CONNECTED(00000140)
... dumps... 
subject=CN=cassandra.us-east-2.amazonaws.com
issuer=C=US, O=Amazon, CN=Amazon RSA 2048 M01
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 5565 bytes and written 408 bytes
Verification error: unable to get local issuer certificate
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Protocol: TLSv1.3
Server public key is 2048 bit
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 20 (unable to get local issuer certificate)

openssl s_client -connect cassandra.us-east-2.amazonaws.com:9142 -CAfile "C:\AmazonRootCA1.der" returns:

E4130000:error:05800088:x509 certificate routines:X509_load_cert_crl_file_ex:no certificate or crl found:crypto\x509\by_file.c:264:

If I use another certificate, sf-class2-root.crt, or sf-class2-root.cer obtained via:

$client = new-object System.Net.WebClient
$client.DownloadFile("https://certs.secureserver.net/repository/sf-class2-root.crt","d:\sf-class2-root.crt")                                                                                                            
Export-Certificate -Cert $cert -FilePath "c:\sf-class2-root.cer"

c:>openssl s_client -connect cassandra.us-east-2.amazonaws.com:9142 -CAfile "C:\NEWTEST\sf-class2-root.crt"

will give me:

Connecting to 3.12.23.176
CONNECTED(00000140)
depth=4 C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification Authority
verify return:1
depth=3 C=US, ST=Arizonа, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Services Root Certificate Authority - G2
verify return:1
depth=2 C=US, O=Amazon, CN=Amazon Root CA 1
verify return:1
depth=1 C=US, O=Amazon, CN=Amazon RSA 2048 M01
verify return:1
depth=0 CN=cassandra.us-east-2.amazonaws.com
verify return:1
---
Certificate chain
 0 s:CN=cassandra.us-east-2.amazonaws.com
   i:C=US, O=Amazon, CN=Amazon RSA 2048 M01
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Nov  8 00:00:00 2024 GMT; NotAfter: Oct 26 23:59:59 2025 GMT
 1 s:C=US, O=Amazon, CN=Amazon RSA 2048 M01
   i:C=US, O=Amazon, CN=Amazon Root CA 1
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Aug 23 22:21:28 2022 GMT; NotAfter: Aug 23 22:21:28 2030 GMT
 2 s:C=US, O=Amazon, CN=Amazon Root CA 1
   i:C=US, ST=Arizonа, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Services Root Certificate Authority - G2
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: May 25 12:00:00 2015 GMT; NotAfter: Dec 31 01:00:00 2037 GMT
 3 s:C=US, ST=Arizonа, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Services Root Certificate Authority - G2
   i:C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification Authority
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Sep  2 00:00:00 2009 GMT; NotAfter: Jun 28 17:39:16 2034 GMT

...
-----END CERTIFICATE-----
subject=CN=cassandra.us-east-2.amazonaws.com
issuer=C=US, O=Amazon, CN=Amazon RSA 2048 M01
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 5565 bytes and written 408 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Protocol: TLSv1.3
Server public key is 2048 bit
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---

DONE

but starting application with this sf-class2-root.crt will lead to the same result: everything works from localhost and error on EC2 instance.

Can you please advice, what to do? How to add any logging? what could be the reason? My EC2 instance has static IP and all outbound connections allowed.

3 Answers
1

Based on the information provided, it appears that the issue is likely related to network configuration or security settings on your EC2 instance rather than the C# application itself. Here are some steps you can take to troubleshoot and potentially resolve the issue:

  1. Check your EC2 security group settings: Ensure that your EC2 instance's security group allows outbound traffic on port 9142 to the Amazon Keyspaces endpoint. Even though you mentioned all outbound connections are allowed, it's worth double-checking this specific port.

  2. Verify VPC settings: If your EC2 instance is in a VPC, make sure the VPC has the necessary route table entries to reach the internet or the Amazon Keyspaces endpoint.

  3. Check Network ACLs: If you're using Network ACLs in your VPC, ensure they allow outbound traffic to the Keyspaces endpoint on port 9142.

  4. DNS resolution: Confirm that your EC2 instance can resolve the Amazon Keyspaces endpoint. Your nslookup test suggests this is working, but double-check DNS settings in your VPC.

  5. TLS/SSL configuration: Your OpenSSL test with the Starfield root certificate shows a successful connection. Ensure your C# application is using the correct certificate (sf-class2-root.crt) instead of AmazonRootCA1.der.

  6. Add more logging to your C# application: Implement more detailed exception handling and logging in your C# code. Capture and log the inner exception details, which might provide more insight into the authentication failure.

  7. Check IAM permissions: Ensure that the IAM role associated with your EC2 instance (if any) has the necessary permissions to access Amazon Keyspaces.

  8. Try using the AWS CLI: As a test, try connecting to Amazon Keyspaces using the AWS CLI from your EC2 instance. This can help determine if the issue is specific to your C# application or more general.

  9. Check for any proxy settings: Ensure there are no proxy settings on your EC2 instance that might interfere with the connection.

  10. Verify service-specific credentials: Double-check that the service-specific credentials you're using are correct and have not expired.

If none of these steps resolve the issue, you may need to contact AWS support for further assistance, as there could be account-specific or region-specific issues at play.
Sources
Troubleshooting connection errors in Amazon Keyspaces - Amazon Keyspaces (for Apache Cassandra)
Using a Cassandra .NET Core client driver to access Amazon Keyspaces programmatically - Amazon Keyspaces (for Apache Cassandra)

answered a year ago

EXPERT

reviewed a year ago

0
Accepted Answer

OK, I figured it out.

Issue was with System.Security.Authentication.SslProtocols.Tls13 version of protocol, and on the server machine with older windows version there were not enough ciphers to establish 1.3 connection. I specified Tls13, because simple default creation of options via new SSLOptions() didn't work for me locally for some reason.

My mistake was that I haven't enabled extensive logging for the driver, which is described in FAQ: https://docs.datastax.com/en/developer/csharp-driver/3.4/faq/index.html and could be done via:

// Specify the minimum trace level you want to see
Diagnostics.CassandraTraceSwitch.Level = TraceLevel.Verbose;
// Add a standard .NET trace listener
Trace.Listeners.Add(new ConsoleTraceListener());

This immediately gives me:

AssemblyHelpers: 02/24/2025 0:21:53.481 +00:00 Attempting to get entry assembly.
Cluster: 02/24/2025 0:21:53.566 +00:00 : Connecting to cluster using DataStax C# Driver for Apache Cassandra v3.22.0
ControlConnection: 02/24/2025 0:21:53.569 +00:00 : Trying to connect the ControlConnection
ControlConnection: 02/24/2025 0:21:53.573 +00:00 Control Connection 27717712 connecting.
ControlConnection: 02/24/2025 0:21:53.577 +00:00 Attempting to connect to 3.12.23.176:9142.
Connection: 02/24/2025 0:21:53.588 +00:00 Attempting to open Connection #48132822 to 3.12.23.176:9142
TcpSocket: 02/24/2025 0:21:53.600 +00:00 Socket connected, starting SSL client authentication
TcpSocket: 02/24/2025 0:21:53.601 +00:00 Starting SSL authentication
Connection: 02/24/2025 0:21:53.622 +00:00 : Cancelling in Connection #48132822 to 3.12.23.176:9142, 0 pending operations and write queue 0
Connection: 02/24/2025 0:21:53.625 +00:00 Disposing Connection #48132822 to 3.12.23.176:9142.
ControlConnection: 02/24/2025 0:21:53.641 +00:00 : Failed to connect to 3.12.23.176:9142. Exception: System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
 ---> System.ComponentModel.Win32Exception (0x80090331): **The client and server cannot communicate, because they do not possess a common algorithm.**
   at System.Net.SSPIWrapper.AcquireCredentialsHandle(ISSPIInterface secModule, String package, CredentialUse intent, SCHANNEL_CRED* scc)
   at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(CredentialUse credUsage, SCHANNEL_CRED* secureCredential)
   at System.Net.Security.SslStreamPal.AcquireCredentialsHandleSchannelCred(SslAuthenticationOptions authOptions)
   at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(SslAuthenticationOptions sslAuthenticationOptions, Boolean newCredentialsRequested)
   --- End of inner exception stack trace ---
   at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(SslAuthenticationOptions sslAuthenticationOptions, Boolean newCredentialsRequested)
   at System.Net.Security.SslStream.AcquireCredentialsHandle(SslAuthenticationOptions sslAuthenticationOptions, Boolean newCredentialsRequested)
   at System.Net.Security.SslStream.AcquireClientCredentials(Byte[]& thumbPrint, Boolean newCredentialsRequested)
   at System.Net.Security.SslStream.GenerateToken(ReadOnlySpan`1 inputBuffer, Byte[]& output)
   at System.Net.Security.SslStream.NextMessage(ReadOnlySpan`1 incomingBuffer, ProtocolToken& token)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
   at Cassandra.Connections.TcpSocket.ConnectSsl() in D:\git\beholdtech\cassandranonuget\csharp-driver\src\Cassandra\Connections\TcpSocket.cs:line 221
   at Cassandra.Connections.TcpSocket.Connect() in D:\git\beholdtech\cassandranonuget\csharp-driver\src\Cassandra\Connections\TcpSocket.cs:line 162
   at Cassandra.Connections.Connection.DoOpen() in D:\git\beholdtech\cassandranonuget\csharp-driver\src\Cassandra\Connections\Connection.cs:line 486
   at Cassandra.Connections.Connection.Open() in D:\git\beholdtech\cassandranonuget\csharp-driver\src\Cassandra\Connections\Connection.cs:line 460
   at Cassandra.Connections.Control.ControlConnection.Connect(Boolean isInitializing) in D:\git\beholdtech\cassandranonuget\csharp-driver\src\Cassandra\Connections\Control\ControlConnection.cs:line 344
Cassandra.NoHostAvailableException: All hosts tried for query failed (tried 3.12.23.176:9142: AuthenticationException 'Authentication failed, see inner exception.')

here is the ChatGPT response about it:

This error message indicates that during the SSL/TLS handshake the client (your application) and the server (Amazon Keyspaces) couldn’t agree on a common cryptographic algorithm (typically a cipher suite) to secure the connection. Here are some common causes and troubleshooting steps:

Possible Causes

TLS Version/Cipher Suite Mismatch: Amazon Keyspaces requires connections to use TLS 1.2 (or TLS 1.3) with specific cipher suites. If your EC2 instance’s Schannel configuration (the Windows SSL/TLS provider) isn’t set up to support one of the cipher suites required by Amazon Keyspaces, you’ll see this error.

Windows Schannel Settings or Updates: The underlying Windows OS might not have the necessary cipher suites enabled or might be missing recent updates that add support for newer TLS protocols or ciphers. Make sure your EC2 instance is fully updated.

Explicit TLS Settings in Your Application: If your application is not explicitly forcing TLS 1.2 (or 1.3) and is instead trying to use an older protocol (or a default that doesn’t include the required ciphers), the negotiation may fail.

Policy or Group Policy Restrictions: There could be local security policies on the EC2 instance that disable certain cipher suites or TLS versions.

Troubleshooting Steps Force TLS 1.2: At the beginning of your application’s startup code, explicitly set the security protocol to TLS 1.2: System.Net.ServicePointManager.SecurityProtocol = System.Net.Security.SecurityProtocolType.Tls12;

Update Your EC2 Instance: Ensure that your EC2 Windows instance is fully updated. Windows updates often include improvements and additional support for modern TLS protocols and cipher suites.

Check Schannel Settings: Review the Schannel settings in the Windows registry to confirm that the necessary TLS protocols and cipher suites are enabled. You might need to adjust settings in: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols (Modifications here should be done carefully and typically by an administrator.)

Review AWS Keyspaces Requirements: Double-check Amazon Keyspaces documentation for any specific cipher suites or TLS settings it requires. Ensure your client (EC2 instance) supports those.

Driver Logging: Enable verbose logging (e.g., via log4net or system diagnostics) to capture more details during the handshake. This can help pinpoint whether the failure is due to a missing cipher or protocol mismatch.

Summary The error "The client and server cannot communicate, because they do not possess a common algorithm" means that during the TLS handshake no cipher suite was found that is supported by both sides. This is likely due to the EC2 instance’s TLS/Schannel configuration (or outdated Windows settings) not supporting the cipher suites required by Amazon Keyspaces. Ensure you’re forcing TLS 1.2, update your OS, and verify Schannel settings to resolve the issue.

answered a year ago

EXPERT

reviewed a year ago

0

Thanks for the answer, here is the results of item-by-item check:

1. Check your EC2 security group settings: Ensure that your EC2 instance's security group allows outbound traffic on port 9142 to the Amazon Keyspaces endpoint. Even though you mentioned all outbound connections are allowed, it's worth double-checking this specific port.

I have single security group with following Outbound rules:

IPv4  Type: All traffic, Protocol: All, Port range: All, Destination: 0.0.0.0/0

Check passed - outbound connections are allowed

also, I've tried telnet cassandra.us-east-2.amazonaws.com 9142 it shows black screen, but they say it's OK and it actually means connection could be obtained using this port

2. Verify VPC settings: If your EC2 instance is in a VPC, make sure the VPC has the necessary route table entries to reach the internet or the Amazon Keyspaces endpoint. 3. Check Network ACLs: If you're using Network ACLs in your VPC, ensure they allow outbound traffic to the Keyspaces endpoint on port 9142. 4. DNS resolution: Confirm that your EC2 instance can resolve the Amazon Keyspaces endpoint. Your nslookup test suggests this is working, but double-check DNS settings in your VPC. 5. TLS/SSL configuration: Your OpenSSL test with the Starfield root certificate shows a successful connection. Ensure your C# application is using the correct certificate (sf-class2-root.crt) instead of AmazonRootCA1.der.

Again, openssl s_client -connect cassandra.us-east-2.amazonaws.com:9142 -CAfile "C:\NEWTEST\sf-class2-root.crt" gives

Connecting to 3.12.23.182
CONNECTED(00000140)

which means all of the above checks are passed, I'm 100% sure I'm using same certificate in C# app because it's just connects locally!

at the same time now I think issue is somewhere with network access... and it drives me crazy, since it seems openssl s_client -connect + nslookup + telnet + tracert gives good results??

6. Add more logging to your C# application: Implement more detailed exception handling and logging in your C# code. Capture and log the inner exception details, which might provide more insight into the authentication failure.

I couldn't get any more information, inner exception is null, I use global try/catch with exception.ToString()... and it seems there are no way I can go deeper with verbose tracing of CassandraCSharpDriver operations...

7. Check IAM permissions: Ensure that the IAM role associated with your EC2 instance (if any) has the necessary permissions to access Amazon Keyspaces.

IAM user has AmazonKeyspacesFullAccess policy assigned. And again, everything fails just on cluster.Connect(); step and works locally... , so this is not the case I think.

I've tried Sigv4 approach with access-key-id and secret-access-key pair. Same result - it works locally, but does NOT from EC2 windows instance.

8. Try using the AWS CLI: As a test, try connecting to Amazon Keyspaces using the AWS CLI from your EC2 instance. This can help determine if the issue is specific to your C# application or more general.

I've installed AWS CLI, configured it using "aws configure" with credentials I used for Sigv4 (access-key-id/secret-access-key pair) and executed the following commands:

aws keyspaces list-keyspaces --region us-east-2

gives me a list of my keyspaces I created!!!, no problems - everything works just great

9. Check for any proxy settings: Ensure there are no proxy settings on your EC2 instance that might interfere with the connection.

not sure how to do this...

10. Verify service-specific credentials: Double-check that the service-specific credentials you're using are correct and have not expired.

Since they work locally and with AWS CLI I don't think it's an issue...

So, as of now, I think it may be something very tricky with network connection, since CassandraCSharpDriver uses TLS and 9142 port, while AWS CLI uses HTTPS and 443 port... Porbably I have to try CQLSH which uses same 9142/TLS ( https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.endpoints.html ), will do tomorrow, it requires python installation...

answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.