0

In an effort to test an API via an HTTPS connection locally, I followed the approach described here by Evan Grim where I use stunnel4 as a middleman between my requests and my API server.

Here's a minimalist urls.py that will generate a token provided a valid username and password.

from django.urls import include, path
from django.contrib import admin
from rest_framework_simplejwt import views as jwt_views

urlpatterns = [
    path("admin", admin.site.urls),
    path('api/token/', jwt_views.TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', jwt_views.TokenRefreshView.as_view(), name='token_refresh'),]

I have also modified the stunnel4 config file as below.

pid=

cert = stunnel/stunnel.pem
sslVersion = all
foreground = yes
output = stunnel.log
options = NO_SSLv2

[https]
accept=8443
connect=8001
TIMEOUTclose=1

And here is my runserver script. You'll notice that I'm using pdm for package management.

#!/bin/bash
stunnel4 stunnel/dev_https &
pdm run python3 manage.py runserver &
HTTPS=1 pdm run python3 manage.py runserver 0.0.0.0:8001

When I try any route via postman or curl (at port 8443), I receive the following errors.

I get a tls_setup_handshake:internal error from stunnel4.

2021.12.19 18:51:22 LOG5[16]: Service [https] accepted connection from 127.0.0.1:36502
2021.12.19 18:51:22 LOG3[16]: SSL_accept: ../ssl/statem/statem_lib.c:109: error:141FC044:SSL routines:tls_setup_handshake:internal error
2021.12.19 18:51:22 LOG5[16]: Connection reset: 0 byte(s) sent to TLS, 0 byte(s) sent to socket

Postman gives me the following error in its console when I submit requests through it.

Error: write EPROTO 48081748826312:error:10000438:SSL routines:OPENSSL_internal:TLSV1_ALERT_INTERNAL_ERROR:../../third_party/boringssl/src/ssl/tls_record.cc:594:SSL alert number 80

And when I try curl (curl -v --location --request POST 'https://localhost:8443/api/token/' --form 'username="username_here"' --form 'password="password_here"'), I see the following.

*   Trying 127.0.0.1:8443...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: self signed certificate
* Closing connection 0
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Full stunnel.log

2021.12.20 16:57:48 LOG7[ui]: Clients allowed=500
2021.12.20 16:57:48 LOG5[ui]: stunnel 5.56 on x86_64-pc-linux-gnu platform
2021.12.20 16:57:48 LOG5[ui]: Compiled with OpenSSL 1.1.1c  28 May 2019
2021.12.20 16:57:48 LOG5[ui]: Running  with OpenSSL 1.1.1f  31 Mar 2020
2021.12.20 16:57:48 LOG5[ui]: Threading:PTHREAD Sockets:POLL,IPv6,SYSTEMD TLS:ENGINE,FIPS,OCSP,PSK,SNI Auth:LIBWRAP
2021.12.20 16:57:48 LOG7[ui]: errno: (*__errno_location ())
2021.12.20 16:57:48 LOG5[ui]: Reading configuration from file /home/max/Ledgestone/dev/verdova/verdova-web-core/stunnel/dev_https
2021.12.20 16:57:48 LOG5[ui]: UTF-8 byte order mark not detected
2021.12.20 16:57:48 LOG5[ui]: FIPS mode disabled
2021.12.20 16:57:48 LOG7[ui]: Compression disabled
2021.12.20 16:57:48 LOG7[ui]: No PRNG seeding was required
2021.12.20 16:57:48 LOG6[ui]: Initializing service [https]
2021.12.20 16:57:48 LOG7[ui]: Ciphers: HIGH:!aNULL:!SSLv2:!DH:!kDHEPSK
2021.12.20 16:57:48 LOG7[ui]: TLSv1.3 ciphersuites: TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256
2021.12.20 16:57:48 LOG7[ui]: TLS options: 0x02100004 (+0x00000000, -0x00000000)
2021.12.20 16:57:48 LOG6[ui]: Loading certificate from file: stunnel/stunnel.pem
2021.12.20 16:57:48 LOG6[ui]: Certificate loaded from file: stunnel/stunnel.pem
2021.12.20 16:57:48 LOG6[ui]: Loading private key from file: stunnel/stunnel.pem
2021.12.20 16:57:48 LOG4[ui]: Insecure file permissions on stunnel/stunnel.pem
2021.12.20 16:57:48 LOG6[ui]: Private key loaded from file: stunnel/stunnel.pem
2021.12.20 16:57:48 LOG7[ui]: Private key check succeeded
2021.12.20 16:57:48 LOG6[ui]: DH initialization not needed
2021.12.20 16:57:48 LOG7[ui]: ECDH initialization
2021.12.20 16:57:48 LOG7[ui]: ECDH initialized with curves X25519:P-256:X448:P-521:P-384
2021.12.20 16:57:48 LOG5[ui]: Configuration successful
2021.12.20 16:57:48 LOG7[ui]: Binding service [https]
2021.12.20 16:57:48 LOG7[ui]: Listening file descriptor created (FD=9)
2021.12.20 16:57:48 LOG7[ui]: Setting accept socket options (FD=9)
2021.12.20 16:57:48 LOG7[ui]: Option SO_REUSEADDR set on accept socket
2021.12.20 16:57:48 LOG6[ui]: Service [https] (FD=9) bound to 0.0.0.0:8443
2021.12.20 16:57:48 LOG7[ui]: Listening file descriptor created (FD=10)
2021.12.20 16:57:48 LOG7[ui]: Setting accept socket options (FD=10)
2021.12.20 16:57:48 LOG7[ui]: Option SO_REUSEADDR set on accept socket
2021.12.20 16:57:48 LOG5[ui]: Binding service [https] to :::8443: Address already in use (98)
2021.12.20 16:57:48 LOG7[ui]: No pid file being created
2021.12.20 16:57:48 LOG7[cron]: Cron thread initialized
2021.12.20 16:57:48 LOG6[cron]: Executing cron jobs
2021.12.20 16:57:48 LOG6[cron]: Cron jobs completed in 0 seconds
2021.12.20 16:57:48 LOG7[cron]: Waiting 86400 seconds
2021.12.20 16:58:54 LOG7[ui]: Found 1 ready file descriptor(s)
2021.12.20 16:58:54 LOG7[ui]: FD=4 events=0x2001 revents=0x0
2021.12.20 16:58:54 LOG7[ui]: FD=9 events=0x2001 revents=0x1
2021.12.20 16:58:54 LOG7[ui]: Service [https] accepted (FD=3) from 127.0.0.1:48444
2021.12.20 16:58:54 LOG7[0]: Service [https] started
2021.12.20 16:58:54 LOG7[0]: Setting local socket options (FD=3)
2021.12.20 16:58:54 LOG7[0]: Option TCP_NODELAY set on local socket
2021.12.20 16:58:54 LOG5[0]: Service [https] accepted connection from 127.0.0.1:48444
2021.12.20 16:58:54 LOG6[0]: Peer certificate not required
2021.12.20 16:58:54 LOG7[0]: TLS state (accept): before SSL initialization
2021.12.20 16:58:54 LOG7[0]: TLS state (accept): before SSL initialization
2021.12.20 16:58:54 LOG7[0]: SNI: no virtual services defined
2021.12.20 16:58:54 LOG7[0]: TLS state (accept): SSLv3/TLS read client hello
2021.12.20 16:58:54 LOG7[0]: TLS state (accept): SSLv3/TLS write server hello
2021.12.20 16:58:54 LOG7[0]: TLS state (accept): SSLv3/TLS write change cipher spec
2021.12.20 16:58:54 LOG7[0]: TLS state (accept): TLSv1.3 write encrypted extensions
2021.12.20 16:58:54 LOG7[0]: TLS state (accept): SSLv3/TLS write certificate
2021.12.20 16:58:54 LOG7[0]: TLS state (accept): TLSv1.3 write server certificate verify
2021.12.20 16:58:54 LOG7[0]: TLS state (accept): SSLv3/TLS write finished
2021.12.20 16:58:54 LOG7[0]: TLS state (accept): TLSv1.3 early data
2021.12.20 16:58:54 LOG3[0]: SSL_accept: Peer suddenly disconnected
2021.12.20 16:58:54 LOG5[0]: Connection reset: 0 byte(s) sent to TLS, 0 byte(s) sent to socket
2021.12.20 16:58:54 LOG7[0]: Deallocating application specific data for session connect address
2021.12.20 16:58:54 LOG7[0]: Local descriptor (FD=3) closed
2021.12.20 16:58:54 LOG7[0]: Service [https] finished (0 left)

Any guidance on adjusting my approach to facilitate local testing?

Max Feinberg
  • 810
  • 1
  • 6
  • 21
  • 1
    The problem is between the client and stunnel. Please provide the actual curl command you are using. Also add `-v` and include the full output into your question. – Steffen Ullrich Dec 20 '21 at 06:45
  • @SteffenUllrich, good point, I just provided the verbose output. – Max Feinberg Dec 20 '21 at 15:57
  • Thanks, looks like stunnel is closing the connection immediately after receiving the ClientHello. Can you provide the full output of the stunnel.log? Can you increase debugging for stunnel (i.e. `debug=7`)? – Steffen Ullrich Dec 20 '21 at 16:32
  • @SteffenUllrich, I added the debug parameter and I've included the logs. A message I can also see in postman now is `SSL Error: Self signed certificate` – Max Feinberg Dec 20 '21 at 23:04
  • I updated the error that I see from `curl`. – Max Feinberg Dec 20 '21 at 23:20
  • I have no idea what else changed but this is a different error now than you originally had reported. Before stunnel closed the connection and curl did not even receive the certificate. Now curl closes the connection after receiving the certificate from stunnel because it cannot verify the certificate. This is fully expected - use option `-k` to ignore certificate errors when testing or use option `--cacert` to treat the certificate issuer (the certificate itself when using self-signed) as trusted. – Steffen Ullrich Dec 21 '21 at 05:47

0 Answers0