From af2734088926e87af09bdd87eedf9e8effbc5539 Mon Sep 17 00:00:00 2001 From: Soner Tari Date: Sat, 27 Jun 2020 23:39:41 +0300 Subject: [PATCH] Add -U CipherSuites option --- src/defaults.h | 12 +++++++-- src/main.c | 17 +++++++++++- src/opts.c | 25 ++++++++++++++++-- src/opts.h | 2 ++ src/protossl.c | 3 +++ src/sslproxy.conf | 9 ++++++- src/sslproxy.conf.5 | 36 ++++++++++++++++---------- tests/testproxy/ssl_testset_5.json | 16 ++++++++++-- tests/testproxy/sslproxy.conf | 2 ++ tests/testproxy/sslproxy_no_tls11.conf | 1 + tests/testproxy/sslproxy_no_tls13.conf | 1 + 11 files changed, 102 insertions(+), 22 deletions(-) diff --git a/src/defaults.h b/src/defaults.h index 0bd5228..8522275 100644 --- a/src/defaults.h +++ b/src/defaults.h @@ -58,12 +58,20 @@ #define DFLT_PIDFMODE 0644 /* - * Default cipher suite spec. + * Default ciphers spec. * Use 'openssl ciphers -v spec' to see what ciphers are effectively enabled - * by a cipher suite spec with a given version of OpenSSL. + * by a ciphers spec with a given version of OpenSSL. */ #define DFLT_CIPHERS "ALL:-aNULL" +/* + * Default ciphersuites spec. + * Use 'openssl ciphers -v spec' to see what ciphersuites are effectively enabled + * by a ciphersuites spec with a given version of OpenSSL. + * The ciphersuites spec is for TLS 1.3. + */ +#define DFLT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256" + /* * Default elliptic curve for EC cipher suites. */ diff --git a/src/main.c b/src/main.c index f6ffeff..fed45ab 100644 --- a/src/main.c +++ b/src/main.c @@ -187,7 +187,9 @@ main_usage(void) #endif /* !SSL_OP_NO_COMPRESSION */ " -r proto only support one of " SSL_PROTO_SUPPORT_S "(default: all)\n" " -R proto disable one of " SSL_PROTO_SUPPORT_S "(default: none)\n" -" -s ciphers use the given OpenSSL cipher suite spec (default: " DFLT_CIPHERS ")\n" +" -s ciphers use the given OpenSSL ciphers spec (default: " DFLT_CIPHERS ")\n" +" -U ciphersuites use the given OpenSSL ciphersuites spec (default: " DFLT_CIPHERSUITES ")\n" +" The ciphersuites spec is for TLS 1.3\n" #ifndef OPENSSL_NO_ENGINE " -x engine load OpenSSL engine with the given identifier\n" #define OPT_x "x:" @@ -447,6 +449,9 @@ main(int argc, char *argv[]) case 's': opts_set_ciphers(global->opts, argv0, optarg); break; + case 'U': + opts_set_ciphersuites(global->opts, argv0, optarg); + break; case 'r': opts_force_proto(global->opts, argv0, optarg); break; @@ -662,12 +667,22 @@ main(int argc, char *argv[]) if (!global->opts->ciphers) oom_die(argv0); } + if (!global->opts->ciphersuites) { + global->opts->ciphersuites = strdup(DFLT_CIPHERSUITES); + if (!global->opts->ciphersuites) + oom_die(argv0); + } for (proxyspec_t *spec = global->spec; spec; spec = spec->next) { if (!spec->opts->ciphers) { spec->opts->ciphers = strdup(DFLT_CIPHERS); if (!spec->opts->ciphers) oom_die(argv0); } + if (!spec->opts->ciphersuites) { + spec->opts->ciphersuites = strdup(DFLT_CIPHERSUITES); + if (!spec->opts->ciphersuites) + oom_die(argv0); + } } if (!global->dropuser && !geteuid() && !getuid() && sys_isuser(DFLT_DROPUSER)) { diff --git a/src/opts.c b/src/opts.c index 35d7b5a..825b732 100644 --- a/src/opts.c +++ b/src/opts.c @@ -174,6 +174,9 @@ opts_free(opts_t *opts) if (opts->ciphers) { free(opts->ciphers); } + if (opts->ciphersuites) { + free(opts->ciphersuites); + } if (opts->user_auth_url) { free(opts->user_auth_url); } @@ -618,6 +621,9 @@ clone_global_opts(global_t *global, const char *argv0, global_opts_str_t *global if (global->opts->ciphers) { opts_set_ciphers(opts, argv0, global->opts->ciphers); } + if (global->opts->ciphersuites) { + opts_set_ciphersuites(opts, argv0, global->opts->ciphersuites); + } if (global->opts->user_auth_url) { opts_set_user_auth_url(opts, global->opts->user_auth_url); } @@ -999,8 +1005,7 @@ opts_str(opts_t *opts) #ifdef HAVE_TLSV13 "%s" #endif /* HAVE_TLSV13 */ - "%s%s" - "|%s" + "%s%s|%s|%s" #ifndef OPENSSL_NO_ECDH "|%s" #endif /* !OPENSSL_NO_ECDH */ @@ -1027,6 +1032,7 @@ opts_str(opts_t *opts) (opts->passthrough ? "|passthrough" : ""), (opts->deny_ocsp ? "|deny_ocsp" : ""), (opts->ciphers ? opts->ciphers : "no ciphers"), + (opts->ciphersuites ? opts->ciphersuites : "no ciphersuites"), #ifndef OPENSSL_NO_ECDH (opts->ecdhcurve ? opts->ecdhcurve : "no ecdhcurve"), #endif /* !OPENSSL_NO_ECDH */ @@ -1420,6 +1426,19 @@ opts_set_ciphers(opts_t *opts, const char *argv0, const char *optarg) #endif /* DEBUG_OPTS */ } +void +opts_set_ciphersuites(opts_t *opts, const char *argv0, const char *optarg) +{ + if (opts->ciphersuites) + free(opts->ciphersuites); + opts->ciphersuites = strdup(optarg); + if (!opts->ciphersuites) + oom_die(argv0); +#ifdef DEBUG_OPTS + log_dbg_printf("CipherSuites: %s\n", opts->ciphersuites); +#endif /* DEBUG_OPTS */ +} + /* * Parse SSL proto string in optarg and look up the corresponding SSL method. * Calls exit() on failure. @@ -2363,6 +2382,8 @@ set_option(opts_t *opts, const char *argv0, opts_set_max_proto(opts, argv0, value); } else if (equal(name, "Ciphers")) { opts_set_ciphers(opts, argv0, value); + } else if (equal(name, "CipherSuites")) { + opts_set_ciphersuites(opts, argv0, value); } else if (equal(name, "NATEngine")) { if (*natengine) free(*natengine); diff --git a/src/opts.h b/src/opts.h index ca944e2..304a122 100644 --- a/src/opts.h +++ b/src/opts.h @@ -71,6 +71,7 @@ typedef struct opts { unsigned int passthrough : 1; unsigned int deny_ocsp : 1; char *ciphers; + char *ciphersuites; CONST_SSL_METHOD *(*sslmethod)(void); #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x20702000L) int sslversion; @@ -246,6 +247,7 @@ void opts_unset_sslcomp(opts_t *) NONNULL(1); void opts_force_proto(opts_t *, const char *, const char *) NONNULL(1,2,3); void opts_disable_proto(opts_t *, const char *, const char *) NONNULL(1,2,3); void opts_set_ciphers(opts_t *, const char *, const char *) NONNULL(1,2,3); +void opts_set_ciphersuites(opts_t *, const char *, const char *) NONNULL(1,2,3); void opts_set_pass_site(opts_t *, char *, int); #define OPTS_DEBUG(global) unlikely((global)->debug) diff --git a/src/protossl.c b/src/protossl.c index 2e16bbc..37dd7e4 100644 --- a/src/protossl.c +++ b/src/protossl.c @@ -315,6 +315,9 @@ protossl_sslctx_setoptions(SSL_CTX *sslctx, pxy_conn_ctx_t *ctx) #endif /* SSL_OP_NO_COMPRESSION */ SSL_CTX_set_cipher_list(sslctx, ctx->spec->opts->ciphers); +#ifdef HAVE_TLSV13 + SSL_CTX_set_ciphersuites(sslctx, ctx->spec->opts->ciphersuites); +#endif /* HAVE_TLSV13 */ #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) /* If the security level of OpenSSL is set to 2+ in system configuration, diff --git a/src/sslproxy.conf b/src/sslproxy.conf index 6b4f9d4..fefc2a8 100644 --- a/src/sslproxy.conf +++ b/src/sslproxy.conf @@ -91,11 +91,17 @@ CAKey /etc/sslproxy/ca.key # (default: tls12) #MaxSSLProto tls12 -# Use the given OpenSSL cipher suite spec. +# Use the given OpenSSL ciphers spec. # Equivalent to -s command line option. # (default: ALL:-aNULL) #Ciphers MEDIUM:HIGH +# Use the given OpenSSL ciphersuites spec. +# The ciphersuites spec is for TLS 1.3. +# Equivalent to -U command line option. +# (default: ALL:-aNULL) +#CipherSuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 + # Leaf key RSA keysize in bits, use 1024|2048|3072|4096. # (default: 2048) #LeafKeyRSABits 2048 @@ -292,6 +298,7 @@ ProxySpec { #MinSSLProto tls10 #MaxSSLProto tls12 #Ciphers MEDIUM:HIGH + #CipherSuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 RemoveHTTPAcceptEncoding no RemoveHTTPReferer yes diff --git a/src/sslproxy.conf.5 b/src/sslproxy.conf.5 index 17b7dc6..c9c1aa3 100644 --- a/src/sslproxy.conf.5 +++ b/src/sslproxy.conf.5 @@ -101,7 +101,7 @@ Deny all OCSP requests on all proxyspecs. Equivalent to -O command line option. \fBPassthrough BOOL\fR Passthrough SSL connections if they cannot be split because of client cert auth or no matching cert and no CA. Equivalent to -P command line option. -.br +.br Default: drop .TP \fBPassSite STRING\fR @@ -115,12 +115,12 @@ allowed, one on each line. .TP \fBDHGroupParams STRING\fR Use DH group params from pemfile. Equivalent to -g command line option. -.br +.br Default: keyfiles or auto .TP \fBECDHCurve STRING\fR Use ECDH named curve. Equivalent to -G command line option. -.br +.br Default: prime256v1 .TP \fBSSLCompression BOOL\fR @@ -128,22 +128,28 @@ Enable/disable SSL/TLS compression on all connections. Equivalent to -Z command .TP \fBForceSSLProto STRING\fR Force SSL/TLS protocol version only. Equivalent to -r command line option. -.br +.br Default: all .TP \fBDisableSSLProto STRING\fR Disable SSL/TLS protocol version. Equivalent to -R command line option. -.br +.br Default: none .TP \fBCiphers STRING\fR -Use the given OpenSSL cipher suite spec. Equivalent to -s command line option. -.br +Use the given OpenSSL ciphers spec. Equivalent to -s command line option. +.br Default: ALL:-aNULL .TP +\fBCipherSuites STRING\fR +Use the given OpenSSL ciphersuites spec. The ciphersuites spec is for TLS 1.3. +Equivalent to -U command line option. +.br +Default: TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 +.TP \fBLeafKeyRSABits NUMBER\fR Leaf key RSA keysize in bits, use 1024|2048|3072|4096. -.br +.br Default: 2048 .TP \fBOpenSSLEngine STRING\fR @@ -154,7 +160,7 @@ Specify default NAT engine to use. Equivalent to -e command line option. .TP \fBUser STRING\fR Drop privileges to user. Equivalent to -u command line option. -.br +.br Default: nobody, if run as root .TP \fBGroup STRING\fR @@ -217,7 +223,7 @@ Default: 120 .TP \fBExpiredConnCheckPeriod NUMBER\fR Check for expired connections every this many seconds. -.br +.br Default: 10. .TP \fBLogStats BOOL\fR @@ -227,7 +233,7 @@ Default: yes .TP \fBStatsPeriod NUMBER\fR Log statistics every this many ExpiredConnCheckPeriod periods. -.br +.br Default: 1 .TP \fBRemoveHTTPAcceptEncoding BOOL\fR @@ -262,7 +268,7 @@ Path to user db file. .TP \fBUserTimeout NUMBER\fR Time users out after this many seconds of idle time. -.br +.br Default: 300. .TP \fBUserAuthURL STRING\fR @@ -275,12 +281,12 @@ Default: no .TP \fBMaxHTTPHeaderSize NUMBER\fR Max HTTP header size in bytes for protocol validation. -.br +.br Default: 8192. .TP \fBOpenFilesLimit NUMBER\fR Set open files limit, use 50-10000. -.br +.br Default: System-wide limit. .TP \fBProxySpec STRING\fR @@ -336,6 +342,8 @@ DisableSSLProto .br Ciphers .br +CipherSuites +.br RemoveHTTPAcceptEncoding .br RemoveHTTPReferer diff --git a/tests/testproxy/ssl_testset_5.json b/tests/testproxy/ssl_testset_5.json index 57a9556..2c90df0 100644 --- a/tests/testproxy/ssl_testset_5.json +++ b/tests/testproxy/ssl_testset_5.json @@ -9,7 +9,8 @@ "no_tls10": "yes", "no_tls11": "yes", "no_tls12": "yes", - "no_tls13": "no" + "no_tls13": "no", + "ciphersuites": "TLS_CHACHA20_POLY1305_SHA256" }, "client": { "ip": "127.0.0.1", @@ -32,7 +33,8 @@ "no_tls10": "no", "no_tls11": "no", "no_tls12": "no", - "no_tls13": "no" + "no_tls13": "no", + "ciphersuites": "TLS_CHACHA20_POLY1305_SHA256" }, "client": { "ip": "127.0.0.1", @@ -57,6 +59,11 @@ "cmd": "send", "payload": "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n", "assert": { + "current_cipher_name": { + "==": [ + "TLS_CHACHA20_POLY1305_SHA256" + ] + }, "current_cipher_version": { "==": [ "TLSv1.3" @@ -89,6 +96,11 @@ "cmd": "recv", "payload": "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n", "assert": { + "current_cipher_name": { + "==": [ + "TLS_CHACHA20_POLY1305_SHA256" + ] + }, "current_cipher_version": { "==": [ "TLSv1.3" diff --git a/tests/testproxy/sslproxy.conf b/tests/testproxy/sslproxy.conf index e896a2f..f8ae1fe 100644 --- a/tests/testproxy/sslproxy.conf +++ b/tests/testproxy/sslproxy.conf @@ -50,6 +50,7 @@ CAKey ca.key #MinSSLProto tls10 #MaxSSLProto tls12 #Ciphers MEDIUM:HIGH +#CipherSuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 #NATEngine netfilter #RemoveHTTPAcceptEncoding no #RemoveHTTPReferer yes @@ -169,6 +170,7 @@ ProxySpec { TargetAddr 127.0.0.1 TargetPort 9462 ForceSSLProto tls13 + CipherSuites TLS_CHACHA20_POLY1305_SHA256 } # Tests for SSL configuration: Rejects unsupported SSL/TLS proto ProxySpec { diff --git a/tests/testproxy/sslproxy_no_tls11.conf b/tests/testproxy/sslproxy_no_tls11.conf index daf1ea1..9d43755 100644 --- a/tests/testproxy/sslproxy_no_tls11.conf +++ b/tests/testproxy/sslproxy_no_tls11.conf @@ -50,6 +50,7 @@ CAKey ca.key #MinSSLProto tls10 #MaxSSLProto tls12 #Ciphers MEDIUM:HIGH +#CipherSuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 #NATEngine netfilter #RemoveHTTPAcceptEncoding no #RemoveHTTPReferer yes diff --git a/tests/testproxy/sslproxy_no_tls13.conf b/tests/testproxy/sslproxy_no_tls13.conf index 83789df..4302261 100644 --- a/tests/testproxy/sslproxy_no_tls13.conf +++ b/tests/testproxy/sslproxy_no_tls13.conf @@ -50,6 +50,7 @@ CAKey ca.key #MinSSLProto tls10 #MaxSSLProto tls12 #Ciphers MEDIUM:HIGH +#CipherSuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 #NATEngine netfilter #RemoveHTTPAcceptEncoding no #RemoveHTTPReferer yes