No suitable servers found (`serverSelectionTryOnce` set): [TLS handshake failed: error:14090086:SSL routines:ssl3_get_server_certificate - mongodb

i`m trying to connect mongodb to php application from compose to local,but get this error.
but i can remote using mongo chef
No suitable servers found (serverSelectionTryOnce set): [TLS handshake failed: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed calling ismaster

I think you have 3 options to solve this problem.
1. Disable SSL on your server
Find mongod.conf, if you're using linux, then normally it should locate at /etc/mongod.conf, use # to comment these lines under net. Finally, you need to restart mongodb for making change works.
net:
ssl:
mode: requireSSL
PEMKeyFile: ./mongodb.pem
...
2. Use the option called weak_cert_validation on your client
This is not a safety solution, but this is definitely one of the simplest one.
For example, if the mongoDB server has enable SSL but without (or did't) offering CA certificate(means self-signed certificate), then set weak_cert_validation as true in the client side, a example for C client:
mongoc_ssl_opt_t ssl_opts = {0};
ssl_opts.weak_cert_validation = true;
mongoc_client_set_ssl_opts(client, &ssl_opts);
3. Follow configure-ssl to create a certificate and get it signed for your program.
Here some provider: https://en.wikipedia.org/wiki/Certificate_authority#Providers

Related

MongoDB SSL Replica setup issues - Unsupported Certificate

Trying to set up a 3 node mongodb server replica on Ubuntu 18.04, mongo version 4.0.18
gl1 192.168.1.30
gl2 192.168.1.31
gl3 192.168.1.33
Using an internal CA on the same network to create certs, I have created 2 certs, one for the server mongo is installed on (GL1, GL2, GL3) for PEMKeyFile and one for the clusterFile (mongo1, mongo2, mongo3). Each CAFile is set listing the respective RSA key, PEMKeyFile and RootCA for each server. I have mongo services running (according to systemctl) fine using the individual certs (PEMKey and clusterFILE).
net:
port: 27017
bindIp: 0.0.0.0
net:
ssl:
mode: requireSSL
PEMKeyFile: /opt/ssl/MongoDB.pem
CAFile: /opt/ssl/ca.pem
clusterFile: /opt/ssl/mongo.pem
allowConnectionsWithoutCertificates: true
#replication
replication:
replSetName: rs0
Getting the following error when I try to rs.add("192.168.1.31:27017") I get the following error
"errmsg" : "Quorum check failed because not enough voting nodes responded; required 2 but only the following 1 voting nodes responded: 192.168.1.30:27017; the following nodes did not respond affirmatively: gl2.domain.com:27017 failed with stream truncated",
"code" : 74,
"codeName" : "NodeNotFound",
In the mongod.log on node 192.168.1.31 the following is logged:
2020-05-22T18:20:48.161+0000 E NETWORK [conn4] SSL peer certificate validation failed: unsupported certificate purpose
2020-05-22T18:20:48.161+0000 I NETWORK [conn4] Error receiving request from client: SSLHandshakeFailed: SSL peer certificate validation failed: unsupported certificate purpose. Ending connection from 192.168.1.30:55002 (connection id: 4)
I have read on an old Google groups post: https://groups.google.com/forum/#!msg/mongodb-user/EmESxx5KK9Q/xH6Ul7fTBQAJ that the clusterFile and PEMKeyFile had to be different. However, I did that and it still is throwing errors. I have done a lot of searching on this and I'm seeing much to support that this how it's done, but it is the only place I've found that has a similar error message and it seems logical that it should work. However, I'm not sure how I can verify that my clusterFile is actually being used. It is indeed a separate certificate with a FQDN for each node. All three nodes have host files updated to find each other (gl1, mongo1, etc). I can ping all nodes between themselves, so networking is up. I've also verified the firewall (ufw and iptables) is not blocking 27017 or anything at this point. Previously I tried the self-signed CA and certs but kept running into errors since those were self signed certs, so that is why I went the internal CA route.
The "purpose" is also known as "extended key usage".
Openssl x509v3 Extended Key Usage gives some example code for setting the purposes.
As pointed out by Joe, the documentation states that the certificates must either have no extended key usage at all, or the one in the PEMKeyFile must have server auth, and the one in the cluster file must have client auth.

How to connect to PostgreSQL from Phoenix Web App via SSL?

When trying to run Elixir (Phoenix) Web Application using PostgreSQL Database hosted 3rd party "Database-as-a-Service" (Azure Database for PostgreSQL).
We attempt to start the app with mix phoenix.server we see the following error:
[info] Running Pxblog.Endpoint with Cowboy using http://localhost:4000
[error] GenServer #PID<0.247.0> terminating
** (FunctionClauseError) no function clause matching in Postgrex.Messages.decode_fields/1
(postgrex) lib/postgrex/messages.ex:339: Postgrex.Messages.decode_fields("")
(postgrex) lib/postgrex/messages.ex:344: Postgrex.Messages.decode_fields/1
(postgrex) lib/postgrex/messages.ex:344: Postgrex.Messages.decode_fields/1
(postgrex) lib/postgrex/messages.ex:131: Postgrex.Messages.parse/3
(postgrex) lib/postgrex/protocol.ex:1842: Postgrex.Protocol.msg_decode/1
(postgrex) lib/postgrex/protocol.ex:1816: Postgrex.Protocol.msg_recv/3
(postgrex) lib/postgrex/protocol.ex:560: Postgrex.Protocol.auth_recv/3
(postgrex) lib/postgrex/protocol.ex:475: Postgrex.Protocol.handshake/2
(db_connection) lib/db_connection/connection.ex:134: DBConnection.Connection.connect/2
(connection) lib/connection.ex:622: Connection.enter_connect/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: nil
State: Postgrex.Protocol
Insight: "Enforce SSL" was Enabled on the Azure DB ...
Through investigation we realised that the error is cause because the Azure PostgreSQL Service had Enforce SSL Connection set to Enabled (by default):
We think having "Enforce SSL" to Enabled is good for Security, but we aren't able to get it working with Phoenix ...
(Temporary) Solution: Disable "Enforce SSL"
So, we have (temporarily) disabled SSL for now:
But we would much prefer a "permanent" solution to this issue.
Preferred Solution: Use SSL when Connecting to PostgreSQL
If anyone can clarify (or point us to) how to connect to PostgreSQL over SSL from Phoenix/Ecto
we would be super grateful! :-)
Does the Application (Phoenix) Server need to have an SSL Certificated configured in order to connect from the App server to the DB Server...?
e.g: http://www.phoenixframework.org/docs/configuration-for-ssl ?
Microsoft has the following help guide:
https://learn.microsoft.com/en-us/azure/postgresql/concepts-ssl-connection-security
It seems to suggest we need OpenSSL on the App Server ... can anyone confirm?
Background
I was experiencing the same problem connecting Phoenix/Ecto/Postgrex to Azure Database for PostgreSQL server. Even after setting ssl: true in my Repo configuration, I was still not able to connect to the database with Postgrex even though connecting using psql "postgresql://...?sslmode=require" -U ... on the same machine succeeded. The error returned with ssl: true was:
[error] Postgrex.Protocol (#PID<0.1853.0>) failed to connect: **(DBConnection.ConnectionError) ssl connect: closed
** (DBConnection.ConnectionError) connection not available because of disconnection
(db_connection) lib/db_connection.ex:926: DBConnection.checkout/2
...
After digging through the source code, I discovered that the failing call was actually the ssl.connect/3 call from the Erlang ssl module:
# deps/postgrex/lib/postgrex/protocol.ex:535
defp ssl_connect(%{sock: {:gen_tcp, sock}, timeout: timeout} = s, status) do
case :ssl.connect(sock, status.opts[:ssl_opts] || [], timeout) do
{:ok, ssl_sock} ->
startup(%{s | sock: {:ssl, ssl_sock}}, status)
{:error, reason} ->
disconnect(s, :ssl, "connect", reason)
end
end
Doing some snooping with Wireshark, I was able to see that when connecting successfully with psql, I could see packets with TLSV1.2 as the protocol, but when postgrex was connecting with ssl: true I was seeing packets with SSL as the protocol before failing to connect.
Looking at the Ecto.Adapters.Postgres options docs, you'll see there's an ssl_opts configuration option which ends up getting passed to :ssl.connect/3 in which you can set versions to override the TLS version(s) used to connect.
Solution
I was able to connect to the database by adding the following to my Repo configuration:
ssl_opts: [
versions: [:"tlsv1.2"]
]
My full configuration ended up looking like this:
config :myapp, Myapp.Repo,
adapter: Ecto.Adapters.Postgres,
username: "myapp#dev-db",
password: "...",
database: "myapp_dev",
port: 5432,
hostname: "dev-db.postgres.database.azure.com",
pool_size: 10,
ssl: true,
ssl_opts: [
versions: [:"tlsv1.2"]
]
I'm not really sure why the TLS version needs to be set explicitly, perhaps someone with more expertise in this area can shed some light on this.
You might also need to add your ip (or ip range) to the postgres firewall in azure. It's right under the SSL settings.
Erlang is usually built with OpenSSL, and does require it for several libraries. You haven't posted the error you get with ssl: true, but if your erlang was built without OpenSSL it might be the cause. From the build/install guide:
OpenSSL -- The opensource toolkit for Secure Socket Layer and
Transport Layer Security. Required for building the application
crypto. Further, ssl and ssh require a working crypto application and
will also be skipped if OpenSSL is missing. The public_key application
is available without crypto, but the functionality will be very
limited.
What output do you get if you run :ssl.versions() in an iex shell?
Here is my Database init() connection code using ssl and certificates. Check your ssl_opts settings, maybe.
def init() do
case Postgrex.start_link(
hostname: App.Endpoint.config(:dbhost),
username: App.Endpoint.config(:username),
database: App.Endpoint.config(:dbname),
port: App.Endpoint.config(:dbport),
ssl: true,
ssl_opts: [
keyfile: "priv/cert.key",
certfile: "priv/cert.crt"
]) do
{:ok, postgrex} ->
postgrex
_ ->
:error
end
end
To add to the above answers, here is my ssl_opts block when using self-signed certificates and auth-options set to clientcert=verify_full in your pg_hba.conf. My connection is using TLSv1.3.
ssl_opts: [
verify: :verify_peer,
versions: [:"tlsv1.3"],
ciphers: :ssl.cipher_suites(:all, {3,4}),
cacertfile: Path.expand("priv/certs/ca-cert.pem"),
certfile: Path.expand("priv/certs/client-cert.pem"),
keyfile: Path.expand("priv/certs/client-key.pem")
],

Net::LDAPS throws unknown error during SSL connect

I am trying to connect to an LDAP server using the Net::LDAPS module. I am passing the right username, password and capath to it. The same code with all the modules in the same version works on one of my other machines. But on this particular machine I see this error.
The sample code I am working with :
my $ad_host = 'XYZ';
my $ad_port = 636;
my $ad_user = 'ABC';
my $ad_pass = '****';
my $ca_path = '<path to ca cert>';
my $ldap = Net::LDAPS->new(
$ad_host,
port => $ad_port,
verify => 'require',
capath => $ca_path
);
Is it a known bug in the LDAPS module? Or am I missing out something apparent.
The debug logs:
DEBUG: .../IO/Socket/SSL.pm:179: set domain to 2
DEBUG: .../IO/Socket/SSL.pm:1427: new ctx 21295632
DEBUG: .../IO/Socket/SSL.pm:309: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:311: socket connected
DEBUG: .../IO/Socket/SSL.pm:324: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:354: set socket to non-blocking to enforce timeout=120
DEBUG: .../IO/Socket/SSL.pm:367: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:377: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:387: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:407: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:367: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:377: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:387: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:407: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:367: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:1175: SSL connect attempt failed with unknown error..error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:373: fatal SSL error: SSL connect attempt failed with unknown error..error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:1462: free ctx 21295632 open=21295632
DEBUG: .../IO/Socket/SSL.pm:1465: OK free ctx 21295632
DEBUG: .../IO/Socket/SSL.pm:1175: IO::Socket::INET6 configuration failederror:00000000:lib(0):func(0):reason(0)
Versions of the modules I am using :
...:~/test_perl$ perlmodver Net::LDAPS
0.05
...:~/test_perl$ perlmodver Net::LDAP
0.39
...:~/test_perl$ perlmodver IO::Socket::SSL
1.18
If you look at the error you can see that certificate verification failed.
SSL connect attempt failed with unknown error..error:14090086:SSL
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
You can either correct the certificate or ignore certificate verification by passing
verify => 'none'
On a sidenote, you can also use Net::LDAP if you pass ldaps:// as a prefix to $ad_host.
$ldaps = Net::LDAP->new('ldaps://myhost.example.com:10000',
verify => 'require',
capath => $ca_path);
Oops just noticed that you said
The same code with all the modules in the same version works on one of
my other machines. But on this particular machine I see this error.
Then this looks like a configuration issue. Can you connect to your server using ldapsearch?
This issue is resolved.
There are 2 ways to solve this :
Bypass the verification (Not recommended)
If you are using the "verify" attribute like the one in my code, you just have to comment it out. It will bypass the cert verification.
Add a soft link to the certificates
Maybe it is a behavior specific to trusty, because on lucid it was working fine. So, you need to create a soft link to all your pem files and place it in the CA Path. You can do this by running
ln -s cacert.pem `openssl x509 -hash -noout < cacert.pem`.0

Need help setting up MongoDB for SSL

I am trying to configure mongodb for ssl. I have the two certs within a directory on Ubuntu, but when I try to restart the service with the mongodb.conf set up correctly, the service will not start. If I comment out the lines in the mongodb.conf file that I added, I can then start mongodb. I think the syntax is wrong, and not the certs them self.
#SSL options
sslMode = requireSSL
#Enable SSL on normal ports
#sslOnNormalPorts = true
# SSL Key file and password
sslPEMKeyFile = /path/to/cert
sslPEMKeyPassword = password
sslCAFile = /path/to/cert
I get this error when I try to start the server with these lines not commented out
stop: Unknown instance:
mongodb start/running, process 7725
If i try to get into mongo shell i get this(assuming this is because I could not restart the service properly)
Thu Jul 21 14:32:07.660 Error: couldn't connect to server 127.0.0.1:27017 at src/mongo/shell/mongo.js:145
exception: connect failed
The mongodb.conf file is a YAML file so you need to format it as such. Meaning you can't use tabs. Also it does look like the syntax you're using isn't correct.
Try this:
net:
#SSL options
ssl:
mode: requireSSL
# SSL Key file and password
PEMKeyFile: /path/to/cert
PEMKeyPassword: password
CAFile: /path/to/cert
Also, I know it's commented out but just wanted to mention, the sslOnNormal ports option is deprecated. See here: https://docs.mongodb.com/manual/reference/configuration-options/#net.ssl.sslOnNormalPorts

PerL SSL connect attempt failed because of handshake problems

I'm hoping someone can help, I'm using the nagios plugin check_ilo2_health, the plugin works fine on our OpenSuSE systems but the new Ubuntu 14.04 system has issues, removing the nagios stuff and running perl, is basically this:
perl -e 'use IO::Socket::SSL qw(debug3);IO::Socket::SSL->new(SSL_hostname => "", PeerAddr=>"10.0.0.1:443", Proto=>"tcp",SSL_verify_mode => SSL_VERIFY_NONE)or die $!'
I'm connecting to an HP ILO2 with a self signed certificate and get a reply:
DEBUG: .../IO/Socket/SSL.pm:2503: new ctx 19182624
DEBUG: .../IO/Socket/SSL.pm:526: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:528: socket connected
DEBUG: .../IO/Socket/SSL.pm:550: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:586: not using SNI because hostname is unknown
DEBUG: .../IO/Socket/SSL.pm:647: Net::SSLeay::connect -> 0
DEBUG: .../IO/Socket/SSL.pm:695: connection failed - connect returned 0
DEBUG: .../IO/Socket/SSL.pm:1757: SSL connect attempt failed because of handshake problems
DEBUG: .../IO/Socket/SSL.pm:2537: free ctx 19182624 open=19182624
DEBUG: .../IO/Socket/SSL.pm:2549: OK free ctx 19182624
IO::Socket::SSL: SSL connect attempt failed because of handshake problems error:140943FC:SSL routines:SSL3_READ_BYTES:sslv3 alert bad record mac ...propagated at -e line 1.
If I run it in curl:
curl "https://10.0.0.1" --insecure
It works returning the page from the ILO.
I want to tell perl or openSSL to ignore any certificate problems as this is a monitoring system and a lot of the servers use self signed certificates.
Any ideas of what can be done?
Versions:
Perl Version: This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-gnu-thread-multi
Crypt::SSLeay 0.72
IO::Socket::SSL 1.997
Net::SSLeay 1.66
Thanks in advance
I want to tell perl or openSSL to ignore any certificate problems as this is a monitoring system and a lot of the servers use self signed certificates.
You are doing it correctly, that is by using SSL_verify_mode of SSL_VERIFY_NONE.
IO::Socket::SSL: SSL connect attempt failed because of handshake problems error:140943FC:SSL routines:SSL3_READ_BYTES:sslv3 alert bad record mac ...propagated at -e line 1.
Strange, but I've seen other reports with "HP ILO2" and bad_record_mac.
Try to reduce the version to SSL 3.0, e.g. SSL_version => "SSLv3".
But because SSL 3.0 would not be a satisfactory solution because of POODLE I would be interested to have a look at the working SSL handshake from curl (upload to cloudshark.org).
The same error happens with Net::LDAP (which also uses IO::Socket::SSL) when connecting to a server that only supports SSLv2.
IO::Socket::SSL "auto-negotiates between SSLv2 and SSLv3" by default according to man page, so omitting SSL_version allows scripts to work with older servers.
Or, more optimistically, the script will still work when the administrator gets around to upgrading the server!