Self-signed certificate with stunnel on linux

0

I'm trying to connect to an application over stunnel 5.44 on ubuntu 18.04. I'm using a config from a setup that is working on Windows and MacOS. It seems like the client is rejecting the authorisation due to using a self-signed certificate.

Here is the redacted config:


[myapp]

client = yes

accept = 10076

connect = myserver.mydomain.com:10073

verify = 4

CAfile = /etc/stunnel/stunnel.pem

cert = /etc/stunnel/stunnel.pem


This is the log when starting stunnel:


May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: Clients allowed=500

May 3 08:53:54 kerzanoserv stunnel: LOG5[ui]: stunnel 5.44 on x86_64-pc-linux-gnu platform

May 3 08:53:54 kerzanoserv stunnel: LOG5[ui]: Compiled/running with OpenSSL 1.1.0g 2 Nov 2017

May 3 08:53:54 kerzanoserv stunnel: LOG5[ui]: Threading:PTHREAD Sockets:POLL,IPv6,SYSTEMD TLS:ENGINE,FIPS,OCSP,PSK,SNI Auth:LIBWRAP

May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: errno: (*__errno_location ())

May 3 08:53:54 kerzanoserv stunnel: LOG5[ui]: Reading configuration from file /etc/stunnel/stunnel.conf

May 3 08:53:54 kerzanoserv stunnel: LOG5[ui]: UTF-8 byte order mark not detected

May 3 08:53:54 kerzanoserv stunnel: LOG5[ui]: FIPS mode disabled

May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: Compression disabled

May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: Snagged 64 random bytes from /home/eoin/.rnd

May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: Wrote 1024 new random bytes to /home/eoin/.rnd

May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: PRNG seeded successfully

May 3 08:53:54 kerzanoserv stunnel: LOG6[ui]: Initializing service [ledbestDO]

May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: Ciphers: HIGH:!DH:!aNULL:!SSLv2

May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: TLS options: 0x02020004 (+0x02000000, -0x00000000)

May 3 08:53:54 kerzanoserv stunnel: LOG6[ui]: Loading certificate from file: /etc/stunnel/stunnel.pem

May 3 08:53:54 kerzanoserv stunnel: LOG6[ui]: Certificate loaded from file: /etc/stunnel/stunnel.pem

May 3 08:53:54 kerzanoserv stunnel: LOG6[ui]: Loading private key from file: /etc/stunnel/stunnel.pem

May 3 08:53:54 kerzanoserv stunnel: LOG6[ui]: Private key loaded from file: /etc/stunnel/stunnel.pem

May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: Private key check succeeded

May 3 08:53:54 kerzanoserv stunnel: LOG5[ui]: Configuration successful

May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: Binding service [myapp]

May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: Listening file descriptor created (FD=7)

May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: Option SO_REUSEADDR set on accept socket

May 3 08:53:54 kerzanoserv stunnel: LOG7[ui]: Service [myapp] (FD=7) bound to 0.0.0.0:10076

May 3 08:53:54 kerzanoserv stunnel: LOG7[main]: Created pid file /var/run/stunnel4.pid

May 3 08:53:54 kerzanoserv stunnel: LOG7[cron]: Cron thread initialized


When I try to establish a websocket connection via python through this tunnel, in a way that works on windows, I get the following stunnel log:


May 3 09:29:56 kerzanoserv stunnel: LOG7[main]: Found 1 ready file descriptor(s)

May 3 09:29:56 kerzanoserv stunnel: LOG7[main]: FD=4 events=0x2001 revents=0x0

May 3 09:29:56 kerzanoserv stunnel: LOG7[main]: FD=7 events=0x2001 revents=0x1

May 3 09:29:56 kerzanoserv stunnel: LOG7[main]: Service [myapp] accepted (FD=3) from 127.0.0.1:41880

May 3 09:29:56 kerzanoserv stunnel: LOG7[0]: Service [myapp] started

May 3 09:29:56 kerzanoserv stunnel: LOG7[0]: Option TCP_NODELAY set on local socket

May 3 09:29:56 kerzanoserv stunnel: LOG5[0]: Service [myapp] accepted connection from 127.0.0.1:41880

May 3 09:29:56 kerzanoserv stunnel: LOG6[0]: s_connect: connecting ...:10073

May 3 09:29:56 kerzanoserv stunnel: LOG7[0]: s_connect: s_poll_wait ...:10073: waiting 10 seconds

May 3 09:29:56 kerzanoserv stunnel: LOG5[0]: s_connect: connected ...:10073

May 3 09:29:56 kerzanoserv stunnel: LOG5[0]: Service [myapp] connected remote server from 192.168.1.26:36406

May 3 09:29:56 kerzanoserv stunnel: LOG7[0]: Option TCP_NODELAY set on remote socket

May 3 09:29:56 kerzanoserv stunnel: LOG7[0]: Remote descriptor (FD=8) initialized

May 3 09:29:56 kerzanoserv stunnel: LOG6[0]: SNI: sending servername: myserver.mydomain.com

May 3 09:29:56 kerzanoserv stunnel: LOG6[0]: Peer certificate required

May 3 09:29:56 kerzanoserv stunnel: LOG7[0]: TLS state (connect): before SSL initialization

May 3 09:29:56 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS write client hello

May 3 09:29:56 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS write client hello

May 3 09:29:56 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS read server hello

May 3 09:29:56 kerzanoserv stunnel: LOG7[0]: Verification started at depth=0: C=PL, ST=Mazovia Province, L=Warsaw, O=Stunnel Developers, OU=Provisional CA, CN=localhost

May 3 09:29:56 kerzanoserv stunnel: LOG4[0]: CERT: Pre-verification error: self signed certificate

May 3 09:29:56 kerzanoserv stunnel: LOG4[0]: Rejected by CERT at depth=0: C=PL, ST=Mazovia Province, L=Warsaw, O=Stunnel Developers, OU=Provisional CA, CN=localhost

May 3 09:29:56 kerzanoserv stunnel: LOG7[0]: Remove session callback

May 3 09:29:57 kerzanoserv stunnel: LOG7[0]: TLS alert (write): fatal: unknown CA

May 3 09:29:57 kerzanoserv stunnel: LOG3[0]: SSL_connect: 1416F086: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed

May 3 09:29:57 kerzanoserv stunnel: LOG5[0]: Connection reset: 0 byte(s) sent to TLS, 0 byte(s) sent to socket

May 3 09:29:57 kerzanoserv stunnel: LOG7[0]: Deallocating application specific data for session connect address

May 3 09:29:57 kerzanoserv stunnel: LOG7[0]: Remote descriptor (FD=8) closed

May 3 09:29:57 kerzanoserv stunnel: LOG7[0]: Local descriptor (FD=3) closed

May 3 09:29:57 kerzanoserv stunnel: LOG7[0]: Service [myapp] finished (0 left)


I'm no expert in stunnel or certificates, so unsure what's going on. I tried to add my .pem file as a trusted certificate in /etc/ssl/certs/ but it didn't solve the problem.

This is pretty irritating and difficult to understand, could anyone help?

Many thanks, kerzane.


Here is the log output when I set verify = 0:


May 3 16:19:09 kerzanoserv stunnel: LOG7[main]: Found 1 ready file descriptor(s)

May 3 16:19:09 kerzanoserv stunnel: LOG7[main]: FD=4 events=0x2001 revents=0x0

May 3 16:19:09 kerzanoserv stunnel: LOG7[main]: FD=7 events=0x2001 revents=0x1

May 3 16:19:09 kerzanoserv stunnel: LOG7[main]: Service [myapp] accepted (FD=3) from 127.0.0.1:48238

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: Service [myapp] started

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: Option TCP_NODELAY set on local socket

May 3 16:19:09 kerzanoserv stunnel: LOG5[0]: Service [myapp] accepted connection from 127.0.0.1:48238

May 3 16:19:09 kerzanoserv stunnel: LOG6[0]: s_connect: connecting *:10073

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: s_connect: s_poll_wait *:10073: waiting 10 seconds

May 3 16:19:09 kerzanoserv stunnel: LOG5[0]: s_connect: connected *:10073

May 3 16:19:09 kerzanoserv stunnel: LOG5[0]: Service [myapp] connected remote server from 192.168.1.26:42764

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: Option TCP_NODELAY set on remote socket

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: Remote descriptor (FD=8) initialized

May 3 16:19:09 kerzanoserv stunnel: LOG6[0]: SNI: sending servername: myserver.mydomain.com

May 3 16:19:09 kerzanoserv stunnel: LOG6[0]: Peer certificate not required

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): before SSL initialization

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS write client hello

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS write client hello

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS read server hello

May 3 16:19:09 kerzanoserv stunnel: LOG6[0]: Certificate verification disabled

May 3 16:19:09 kerzanoserv stunnel: message repeated 2 times: [ LOG6[0]: Certificate verification disabled]

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS read server certificate

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS read server key exchange

May 3 16:19:09 kerzanoserv stunnel: LOG6[0]: Client CA: C=PL, ST=Mazovia Province, L=Warsaw, O=Stunnel Developers, OU=Provisional CA, CN=localhost

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS read server certificate request

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS read server done

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS write client certificate

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS write client key exchange

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS write certificate verify

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS write change cipher spec

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS state (connect): SSLv3/TLS write finished

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS alert (read): fatal: unknown CA

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: Remove session callback

May 3 16:19:09 kerzanoserv stunnel: LOG3[0]: SSL_connect: 14094418: error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca

May 3 16:19:09 kerzanoserv stunnel: LOG5[0]: Connection reset: 0 byte(s) sent to TLS, 0 byte(s) sent to socket

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: Deallocating application specific data for session connect address

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: Remote descriptor (FD=8) closed

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: Local descriptor (FD=3) closed

May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: Service [myapp] finished (0 left)

kerzane

Posted 2019-05-03T10:25:23.463

Reputation: 1

Answers

1

Your configuration currently points to /etc/stunnel/stunnel.pem as CA and local certificate. Is it intentionnal (same cert/CA on both sides?). I assume it isn't...

You should either:

  • set verify = 0 to ignore certificate verification (not recommended in production environment of course).

  • or change CAfile option, making it point to a file where you copy/paste the peer CA-certificates (all in one file).

  • or use CApath option instead of CAfile and copy there the peer CA-certificates file (one file per CA)

tonioc

Posted 2019-05-03T10:25:23.463

Reputation: 787

Hi Tonioc, thanks for your reply. stunnel.pem is a cert file provided by the server admin, so it should be same on both sides. In this case, what file should be pointed to by CAfile? – kerzane – 2019-05-03T13:17:09.350

Really appreciate your help, would be delighted if we could figure this out. – kerzane – 2019-05-03T13:19:51.153

Something I don't understand, if the certificate is self signed, what relevance does a CA have? Is it failing because of mismatching CA, or because it is rejecting self-signed altogether? My understanding here is obviously far from perfect :) – kerzane – 2019-05-03T13:21:50.233

Hi Kerzane, the cert file may refer to a different CA (Certificate Authority), or to itself if a self-signed cert is used. In such a case, the CAfile may actually have the same contents, and verify=2 should be OK. What do you see when typing the command: openssl x509 -text -noout -in /etc/stunnel/stunnel.pem | grep -E 'Subject:|Issuer:' – tonioc – 2019-05-03T14:08:35.617

Anyway, in a first step, verify=0 will allow you to start working with the tunnel if you trust the remote server. – tonioc – 2019-05-03T14:10:10.707

Hi again. Result of command you posted shows the Issuer and Subject were both the admin of the server I'm trying to connect to (i.e. the metadata is stuff he entered.) – kerzane – 2019-05-03T14:14:00.023

I edited my question and added the log when verify = 0. Key lines are I guess: May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: TLS alert (read): fatal: unknown CA May 3 16:19:09 kerzanoserv stunnel: LOG7[0]: Remove session callback May 3 16:19:09 kerzanoserv stunnel: LOG3[0]: SSL_connect: 14094418: error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca – kerzane – 2019-05-03T14:24:34.283

So, I think it should work with verify=2. Note I use the CApath mode (directory where I put several CA-cert files using the <hash>.0 naming as explained in man stunnel, but this should be ok in your case with CAfile... – tonioc – 2019-05-03T14:26:48.230

Let us continue this discussion in chat.

– kerzane – 2019-05-03T14:29:37.263

I'm afraid with verify = 2 it still fails. The key lines in log I think are: – kerzane – 2019-05-03T14:39:53.437

May 3 16:28:57 kerzanoserv stunnel: LOG4[0]: CERT: Pre-verification error: self signed certificate May 3 16:28:57 kerzanoserv stunnel: LOG4[0]: Rejected by CERT at depth=0: C=PL, ST=Mazovia Province, L=Warsaw, O=Stunnel Developers, OU=Provisional CA, CN=localhost May 3 16:28:57 kerzanoserv stunnel: LOG7[0]: Remove session callback May 3 16:28:57 kerzanoserv stunnel: LOG7[0]: TLS alert (write): fatal: unknown CA May 3 16:28:57 kerzanoserv stunnel: LOG3[0]: SSL_connect: 1416F086: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed – kerzane – 2019-05-03T14:39:57.290