4

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)

2 Answers 2

3

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)

11
  • 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
    Commented May 3, 2019 at 13:17
  • Really appreciate your help, would be delighted if we could figure this out.
    – kerzane
    Commented May 3, 2019 at 13:19
  • 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
    Commented May 3, 2019 at 13:21
  • 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
    Commented May 3, 2019 at 14:08
  • Anyway, in a first step, verify=0 will allow you to start working with the tunnel if you trust the remote server.
    – tonioc
    Commented May 3, 2019 at 14:10
1

I had the same issue recently, after a client's client-certificate expired and they provided a new one to replace it.

I should have realized the source of the problem because the error changed from certificate has expired to CERT: Pre-verification error: self signed certificate and then changed back when I put their old certificate back into the CAFile.

Only after using tcpdump to capture and review the certificate the client was sending did I actually realize that ... the client was still sending the old certificate during the handshake.

So in my case, the stunnel error is misleading: sure, the cert was self-signed, but the real problem that it just wasn't in the list of trusted certificates. The Pre-verification error: self signed certificate was a red herring.

4
  • tcpdump -X -i eth0 'port 4242' it's just printing garbage, how did you know that the client was sending an old certificate from the garbage?
    – pwned
    Commented Aug 4, 2022 at 12:38
  • @pwned It's been a while, but I'm fairly sure I captured the pcap file and then read it using Wireshark, which is one of the most amazing tools ever created by humankind. Commented Feb 22 at 14:38
  • Well since we are on a tangent, it used to be called Ethereal before the name change. I used it to reverse engineer one of the old yahoo messenger protocols a couple of decades ago. Great software. Also shows garbage when used with encrypted packges if it doesn't know the certificate.
    – pwned
    Commented Feb 24 at 18:35
  • @pwned Yes, it was Ethereal and I still call it that every time before remembering "oh, yeah, Wireshark". You don't need the certificate to view TLS. You need the ephemeral key which many products are willing to drop to a log file for this kind of debugging. Commented Feb 26 at 15:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .