diff --git a/changes/21359 b/changes/21359
new file mode 100644
index 0000000000000000000000000000000000000000..3b54c9154927263b20afc6896619b9826c0e2756
--- /dev/null
+++ b/changes/21359
@@ -0,0 +1,8 @@
+  o Testing
+    - tortls tests now use an autoconf check to determine if OpenSSL
+      structures are opaque, instead of an explicit version check.
+      See ticket 21359.
+
+  o Minor bugfixes (compilation)
+    - Support building with recent LibreSSL code that uses opaque
+      structures. Closes ticket 21359.
diff --git a/configure.ac b/configure.ac
index 2134a41d3f4a61358b5b691c0d3d8c9abfa5c401..f7bdd97e130a4d34f364d141feff02956d74fbf6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -677,6 +677,11 @@ AC_CHECK_FUNCS([ \
 dnl Check if OpenSSL has scrypt implementation.
 AC_CHECK_FUNCS([ EVP_PBE_scrypt ])
 
+dnl Check if OpenSSL structures are opaque
+AC_CHECK_MEMBERS([SSL.state], , ,
+[#include <openssl/ssl.h>
+])
+
 LIBS="$save_LIBS"
 LDFLAGS="$save_LDFLAGS"
 CPPFLAGS="$save_CPPFLAGS"
diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c
index 1cba617a34e64cdb5db7c6df7e215da8f2e4db4c..47455cff838d4afbfbbfd453cc081428e342d85e 100644
--- a/src/test/test_tortls.c
+++ b/src/test/test_tortls.c
@@ -38,9 +38,11 @@ ENABLE_GCC_WARNING(redundant-decls)
 #include "log_test_helpers.h"
 #define NS_MODULE tortls
 
-#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) \
-    && !defined(LIBRESSL_VERSION_NUMBER)
+#ifndef HAVE_SSL_STATE
 #define OPENSSL_OPAQUE
+#endif
+
+#if defined(OPENSSL_OPAQUE) && !defined(LIBRESSL_VERSION_NUMBER)
 #define SSL_STATE_STR "before SSL initialization"
 #else
 #define SSL_STATE_STR "before/accept initialization"
@@ -723,6 +725,26 @@ test_tortls_get_my_certs(void *ignored)
   (void)1;
 }
 
+#ifndef HAVE_SSL_GET_CLIENT_CIPHERS
+static SSL_CIPHER *
+get_cipher_by_name(const char *name)
+{
+  int i;
+  const SSL_METHOD *method = SSLv23_method();
+  int num = method->num_ciphers();
+
+  for (i = 0; i < num; ++i) {
+    const SSL_CIPHER *cipher = method->get_cipher(i);
+    const char *ciphername = SSL_CIPHER_get_name(cipher);
+    if (!strcmp(ciphername, name)) {
+      return (SSL_CIPHER *)cipher;
+    }
+  }
+
+  return NULL;
+}
+#endif
+
 #ifndef OPENSSL_OPAQUE
 static void
 test_tortls_get_ciphersuite_name(void *ignored)
@@ -741,23 +763,6 @@ test_tortls_get_ciphersuite_name(void *ignored)
   tor_free(ctx);
 }
 
-static SSL_CIPHER *
-get_cipher_by_name(const char *name)
-{
-  int i;
-  const SSL_METHOD *method = SSLv23_method();
-  int num = method->num_ciphers();
-  for (i = 0; i < num; ++i) {
-    const SSL_CIPHER *cipher = method->get_cipher(i);
-    const char *ciphername = SSL_CIPHER_get_name(cipher);
-    if (!strcmp(ciphername, name)) {
-      return (SSL_CIPHER *)cipher;
-    }
-  }
-
-  return NULL;
-}
-
 static SSL_CIPHER *
 get_cipher_by_id(uint16_t id)
 {