============
Make self-signed cert:
$ openssl req -x509 -newkey ec:<(openssl ecparam -name secp384r1) -keyout key.pem -out cert.pem -nodes -sha256 -days 3650 -subj '/CN=server'
Record our fingerprint in an environment variable for the client to use later:
$ server_fingerprint="$(openssl x509 -in cert.pem -noout -sha256 -fingerprint | sed 's/.*=//;s/\(.*\)/\L\1/')"
Start openvpn with tls verify script:
$ sudo openvpn --server 10.66.0.0 255.255.255.0 --dev tun --dh none --ca none --cert cert.pem --key key.pem --tls-verify $(readlink -f tls-verify.sh) --script-security 2
TLS Verify Script:
==================
#!/bin/sh
[ -n "$tls_digest_sha256_0" -a -e "/tmp/allowed-openvpn-fingerprints/$tls_digest_sha256_0" ]
Client side:
============
Make self-signed cert:
$ openssl req -x509 -newkey ec:<(openssl ecparam -name secp384r1) -keyout key.pem -out cert.pem -nodes -sha256 -days 3650 -subj '/CN=client'
"Tell" the server about our fingerprint:
$ mkdir -p /tmp/allowed-openvpn-fingerprints; touch "/tmp/allowed-openvpn-fingerprints/$(openssl x509 -in cert.pem -noout -sha256 -fingerprint | sed 's/.*=//;s/\(.*\)/\L\1/')"
Start openvpn with server fingerprint verification:
$ sudo openvpn --client --remote 127.0.0.1 --dev tun --ca none --cert cert.pem --key key.pem --verify-hash "$server_fingerprint" SHA256 --nobind
Crufty patch:
=============
@@ -2749,6 +2749,7 @@
to.remote_cert_eku = options->remote_cert_eku;
to.verify_hash = options->verify_hash;
to.verify_hash_algo = options->verify_hash_algo;
+ to.ca_file_none = options->ca_file_none;
#ifdef ENABLE_X509ALTUSERNAME
to.x509_username_field = (char *) options->x509_username_field;
#else
@@ -3290,7 +3290,10 @@
#ifdef ENABLE_CRYPTO
/* ** SSL/TLS/crypto related files ** */
errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE, options->dh_file, R_OK, "--dh");
- errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE, options->ca_file, R_OK, "--ca");
+ if (!options->ca_file_none)
+ {
+ errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE, options->ca_file, R_OK, "--ca");
+ }
errs |= check_file_access_chroot(options->chroot_dir, CHKACC_FILE, options->ca_path, R_OK, "--capath");
errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE, options->cert_file, R_OK, "--cert");
errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE, options->extra_certs_file, R_OK,
@@ -7700,6 +7703,10 @@
{
options->ca_file_inline = p[2];
}
+ else if (streq(p[1], "none"))
+ {
+ options->ca_file_none = true;
+ }
}
#ifndef ENABLE_CRYPTO_MBEDTLS
else if (streq(p[0], "capath") && p[1] && !p[2])
@@ -495,6 +495,7 @@
/* TLS (control channel) parms */
bool tls_server;
bool tls_client;
+ bool ca_file_none;
const char *ca_file;
const char *ca_path;
const char *dh_file;
@@ -695,7 +695,7 @@
}
}
- if (options->ca_file || options->ca_path)
+ if ((!options->ca_file_none && options->ca_file) || options->ca_path)
{
tls_ctx_load_ca(new_ctx, options->ca_file, options->ca_file_inline,
options->ca_path, options->tls_server);
@@ -272,6 +272,7 @@
uint8_t *verify_hash;
hash_algo_type verify_hash_algo;
char *x509_username_field;
+ bool ca_file_none;
/* allow openvpn config info to be
* passed over control channel */
@@ -719,7 +719,7 @@
}
/* verify level 1 cert, i.e. the CA that signed our leaf cert */
- if (cert_depth == 1 && opt->verify_hash)
+ if ((opt->ca_file_none || cert_depth == 1) && opt->verify_hash)
{
struct buffer ca_hash = {0};
@@ -66,7 +66,7 @@
cert_hash_remember(session, X509_STORE_CTX_get_error_depth(ctx), &cert_hash);
/* did peer present cert which was signed by our root cert? */
- if (!preverify_ok)
+ if (!preverify_ok && !session->opt->ca_file_none)
{
/* get the X509 name */
char *subject = x509_get_subject(current_cert, &gc);