21

I am trying to connect to a closed-off server - an air-conditioner - using a simple PERL script

#!/usr/bin/perl

use 5.10.1;
use warnings;
use strict;
use IO::Socket::SSL;
use IO::Socket::SSL qw/debug3/;
my $sock = IO::Socket::SSL->new(
        PeerHost => '192.168.1.4',
        PeerPort => 2878,
        verify_hostname => 0,   
        SSL_verify_mode => SSL_VERIFY_NONE,
        SSL_verifycn_scheme => undef
) or die "failed connect or ssl handshake: $!,$SSL_ERROR";
print "$sock\n";

Now, this was all working well and good, then I updated OpenSSL (libssl1.0.0) to be exact, and all hell broke loose:

DEBUG: .../IO/Socket/SSL.pm:220: set domain to 2
DEBUG: .../IO/Socket/SSL.pm:1653: new ctx 1984680
DEBUG: .../IO/Socket/SSL.pm:363: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:365: socket connected
DEBUG: .../IO/Socket/SSL.pm:383: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:446: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:1328: SSL connect attempt failed with unknown error error:14082174:SSL routines:SSL3_CHECK_CERT_AND_ALGORITHM:dh key too small

DEBUG: .../IO/Socket/SSL.pm:452: fatal SSL error: SSL connect attempt failed with unknown error error:14082174:SSL routines:SSL3_CHECK_CERT_AND_ALGORITHM:dh key too small
DEBUG: .../IO/Socket/SSL.pm:1328: IO::Socket::INET6 configuration failed error:00000000:lib(0):func(0):reason(0)

DEBUG: .../IO/Socket/SSL.pm:1690: free ctx 1984680 open=1984680
DEBUG: .../IO/Socket/SSL.pm:1698: OK free ctx 1984680
failed connect or ssl handshake: ,IO::Socket::INET6 configuration failed error:00000000:lib(0):func(0):reason(0) at ./spare line 9.

I am happy to use any alternative packages to get around this, but I do need to get around it, as I can't update the certificate on the air-conditioner...

I have looked in to using LWP and raw Net:SSLeay, but the problem seems to be in the underlying OpenSSL libs.

jsnfwlr
  • 3,638
  • 2
  • 23
  • 25
  • 1
    How long is the key of the certificate used for SSL/TLS? The recommended value is 4096 or at least 2048. – Oleg Apr 05 '16 at 05:23
  • echo | openssl s_client -connect 192.168.1.4:2878 2>/dev/null | openssl x509 -text -noout | grep "Public-Key" Public-Key: (1024 bit) – jsnfwlr Apr 05 '16 at 05:26

4 Answers4

18
... SSL3_CHECK_CERT_AND_ALGORITHM:dh key too small

I have looked in to using LWP and raw Net:SSLeay, but the problem seems to be in the underlying OpenSSL libs.

While it is caused by changes to OpenSSL the problem is actually at the server side. The server is using a weak DH key within the key exchange and recent versions of OpenSSL enforce a non-weak DH key because of the Logjam attack.

If the server supports ciphers which don't use DH key exchange you can work around the problem by restricting the ciphers offered by the client so that they don't include any DH ciphers.

my $sock = IO::Socket::SSL->new(..., SSL_cipher_list => 'DEFAULT:!DH' ...);

Apart from that simply disabling any validation like you do is bad:

    ...
    verify_hostname => 0,   
    SSL_verify_mode => SSL_VERIFY_NONE,
    SSL_verifycn_scheme => undef

For one, verify_hostname is not a valid parameter at all (this is for LWP only). Also, you don't need to set a SSL_verifycn_scheme if you disable validation with SSL_verify_mode since no validation also means no validation of the certificates subject.

But much better than disabling validation would be to use SSL_fingerprint to specify which certificate you expect and thus have a proper check even for self-signed or expired certificates. See common usage errors in the IO::Socket::SSL documentation for more information.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • I understand that ignoring SSL errors is terrible, the saving grace is it is just for an aircon - the cert doesn't even really need to be there too, as this is only done over a private in-house network. Thanks for the pointers though, I will look in to them ASAP. – jsnfwlr Apr 05 '16 at 05:39
  • adding SSL_cipher_list => 'DEFAULT:!DH' to the options worked perfectly. – jsnfwlr Apr 05 '16 at 05:44
  • 1
    For wider context, if (unlike the OP) you _do_ have access to / control over the server, then you should instead make changes on the server so that dhparams uses more bits, e.g. see https://stackoverflow.com/a/64581683/ – sparrowt May 16 '22 at 08:26
12

In my case only solution was to set CipherString in /etc/ssl/openssl.cnf from

CipherString = DEFAULT@SECLEVEL=2

to

CipherString = DEFAULT@SECLEVEL=1
GetoX
  • 4,225
  • 2
  • 33
  • 30
  • 6
    While that works, it'd be better to make that change in a separate file, `openssl-weak.cnf`, and then set then OPENSSL_CONF environment variable just for the programs that are running into this problem. – hackerb9 Sep 30 '20 at 21:48
  • 6
    My openssl.cnf does not have a CipherString option – Cheetaiean Jan 07 '22 at 21:44
2

The proper solution for dh key too small is to generate a new DH 2048 key for the server using:

openssl dhparam -out /etc/openvpn/dh2048.pem 2048

and then change dh dh1024.pem to dh dh2048.pem in /etc/openvpn/server.conf and restart openvpn server.

(in my case no change was required in the client configs after this)

source:

https://kudzia.eu/b/2019/08/openvpn-openssl-error1408518assl-routinesssl3_ctx_ctrldh-key-too-small-after-upgrade-to-debina-buster/

If (after changing the above) you also face the error TLS error: Unsupported protocol this means that the client has old openssl version and the way to overcome this is to add:

tls-version-min 1.0

in /etc/openvpn/server.conf and restart openvpn server.

(also no change was required in the client configs after this)

source:

https://community.openvpn.net/openvpn/ticket/1211

  • Did you read the original post? "I am trying to connect to a closed-off server - an air-conditioner" 1) This doesn't have anything to do with OpenVPN. 2) I can't install a new DH key on a device I don't have root access to. – jsnfwlr Jul 20 '22 at 08:46
  • You are absolutely right. I came across your question while googling the error "dh key too small" after an OpenVPN server update. I saw other answer here related to OpenVPN that was helpful. Finally I found a way to fix this and I just wanted to share my findings in the same place that I came across while googling this error. I just wanted to help anyone else facing the same issue in OpenVPN. Sorry for "hijacking" and adding an answer. I did it on good intentions to help the community in general, not the specific question here (which already had an accepted answer, so it was already solved) – Triantafyllos Jul 21 '22 at 19:39
  • While this doesn't actually answer the original question, I did end up here with my "ssl3_ctx_ctrl:dh key too small" OpenVPN error, And re-generating a new one as shown here was the simple solution. And as stated, that's all, and there is nothing else to do on th clients side. – mivk Jan 01 '23 at 16:37
  • It's heavy [according to the docs](https://docs.netscaler.com/en-us/citrix-adc/current-release/ssl/ciphers-available-on-the-citrix-ADC-appliances/diffie-hellman-key-generation-and-achieving-pfs-with-dhe.html), but it's right. – Jesse Aug 29 '23 at 05:33
1

For OpenVPN files, add below entry to your .ovpn file:

tls-cipher "DEFAULT:@SECLEVEL=0"

Refer here: https://forums.openvpn.net/viewtopic.php?t=23979#p71603

Gilbert
  • 2,699
  • 28
  • 29