Merge pull request #8769 from zmstone/0820-refactor-simplify-ssl-opts-handling
0820 refactor simplify ssl opts handling
This commit is contained in:
commit
2b29b1b2cd
|
@ -6,6 +6,10 @@
|
||||||
* Fix `$queue` topic name error in management API return. [#8728](https://github.com/emqx/emqx/pull/8728)
|
* Fix `$queue` topic name error in management API return. [#8728](https://github.com/emqx/emqx/pull/8728)
|
||||||
* Fix sometimes `client.connected` and `client.disconnected` could be in wrong order. [#8625](https://github.com/emqx/emqx/pull/8625)
|
* Fix sometimes `client.connected` and `client.disconnected` could be in wrong order. [#8625](https://github.com/emqx/emqx/pull/8625)
|
||||||
|
|
||||||
|
## Enhancements
|
||||||
|
|
||||||
|
* Do not auto-populate default SSL cipher suites, so that the configs are less bloated. [#8769](https://github.com/emqx/emqx/pull/8769)
|
||||||
|
|
||||||
# 5.0.5
|
# 5.0.5
|
||||||
|
|
||||||
## Bug fixes
|
## Bug fixes
|
||||||
|
|
|
@ -583,11 +583,7 @@ enable_authn(Opts) ->
|
||||||
maps:get(enable_authn, Opts, true).
|
maps:get(enable_authn, Opts, true).
|
||||||
|
|
||||||
ssl_opts(Opts) ->
|
ssl_opts(Opts) ->
|
||||||
maps:to_list(
|
emqx_tls_lib:to_server_opts(tls, maps:get(ssl_options, Opts, #{})).
|
||||||
emqx_tls_lib:drop_tls13_for_old_otp(
|
|
||||||
maps:get(ssl_options, Opts, #{})
|
|
||||||
)
|
|
||||||
).
|
|
||||||
|
|
||||||
tcp_opts(Opts) ->
|
tcp_opts(Opts) ->
|
||||||
maps:to_list(
|
maps:to_list(
|
||||||
|
|
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
-export([namespace/0, roots/0, roots/1, fields/1, desc/1]).
|
-export([namespace/0, roots/0, roots/1, fields/1, desc/1]).
|
||||||
-export([conf_get/2, conf_get/3, keys/2, filter/1]).
|
-export([conf_get/2, conf_get/3, keys/2, filter/1]).
|
||||||
-export([server_ssl_opts_schema/2, client_ssl_opts_schema/1, ciphers_schema/1, default_ciphers/1]).
|
-export([server_ssl_opts_schema/2, client_ssl_opts_schema/1, ciphers_schema/1]).
|
||||||
-export([sc/2, map/2]).
|
-export([sc/2, map/2]).
|
||||||
|
|
||||||
-elvis([{elvis_style, god_modules, disable}]).
|
-elvis([{elvis_style, god_modules, disable}]).
|
||||||
|
@ -1843,6 +1843,8 @@ filter(Opts) ->
|
||||||
common_ssl_opts_schema(Defaults) ->
|
common_ssl_opts_schema(Defaults) ->
|
||||||
D = fun(Field) -> maps:get(to_atom(Field), Defaults, undefined) end,
|
D = fun(Field) -> maps:get(to_atom(Field), Defaults, undefined) end,
|
||||||
Df = fun(Field, Default) -> maps:get(to_atom(Field), Defaults, Default) end,
|
Df = fun(Field, Default) -> maps:get(to_atom(Field), Defaults, Default) end,
|
||||||
|
Collection = maps:get(versions, Defaults, tls_all_available),
|
||||||
|
AvailableVersions = default_tls_vsns(Collection),
|
||||||
[
|
[
|
||||||
{"cacertfile",
|
{"cacertfile",
|
||||||
sc(
|
sc(
|
||||||
|
@ -1909,9 +1911,9 @@ common_ssl_opts_schema(Defaults) ->
|
||||||
sc(
|
sc(
|
||||||
hoconsc:array(typerefl:atom()),
|
hoconsc:array(typerefl:atom()),
|
||||||
#{
|
#{
|
||||||
default => default_tls_vsns(maps:get(versions, Defaults, tls_all_available)),
|
default => AvailableVersions,
|
||||||
desc => ?DESC(common_ssl_opts_schema_versions),
|
desc => ?DESC(common_ssl_opts_schema_versions),
|
||||||
validator => fun validate_tls_versions/1
|
validator => fun(Inputs) -> validate_tls_versions(AvailableVersions, Inputs) end
|
||||||
}
|
}
|
||||||
)},
|
)},
|
||||||
{"ciphers", ciphers_schema(D("ciphers"))},
|
{"ciphers", ciphers_schema(D("ciphers"))},
|
||||||
|
@ -2022,9 +2024,9 @@ client_ssl_opts_schema(Defaults) ->
|
||||||
].
|
].
|
||||||
|
|
||||||
default_tls_vsns(dtls_all_available) ->
|
default_tls_vsns(dtls_all_available) ->
|
||||||
proplists:get_value(available_dtls, ssl:versions());
|
emqx_tls_lib:available_versions(dtls);
|
||||||
default_tls_vsns(tls_all_available) ->
|
default_tls_vsns(tls_all_available) ->
|
||||||
emqx_tls_lib:default_versions().
|
emqx_tls_lib:available_versions(tls).
|
||||||
|
|
||||||
-spec ciphers_schema(quic | dtls_all_available | tls_all_available | undefined) ->
|
-spec ciphers_schema(quic | dtls_all_available | tls_all_available | undefined) ->
|
||||||
hocon_schema:field_schema().
|
hocon_schema:field_schema().
|
||||||
|
@ -2039,6 +2041,10 @@ ciphers_schema(Default) ->
|
||||||
#{
|
#{
|
||||||
default => default_ciphers(Default),
|
default => default_ciphers(Default),
|
||||||
converter => fun
|
converter => fun
|
||||||
|
(<<>>) ->
|
||||||
|
[];
|
||||||
|
("") ->
|
||||||
|
[];
|
||||||
(Ciphers) when is_binary(Ciphers) ->
|
(Ciphers) when is_binary(Ciphers) ->
|
||||||
binary:split(Ciphers, <<",">>, [global]);
|
binary:split(Ciphers, <<",">>, [global]);
|
||||||
(Ciphers) when is_list(Ciphers) ->
|
(Ciphers) when is_list(Ciphers) ->
|
||||||
|
@ -2060,19 +2066,15 @@ default_ciphers(Which) ->
|
||||||
do_default_ciphers(Which)
|
do_default_ciphers(Which)
|
||||||
).
|
).
|
||||||
|
|
||||||
do_default_ciphers(undefined) ->
|
|
||||||
do_default_ciphers(tls_all_available);
|
|
||||||
do_default_ciphers(quic) ->
|
do_default_ciphers(quic) ->
|
||||||
[
|
[
|
||||||
"TLS_AES_256_GCM_SHA384",
|
"TLS_AES_256_GCM_SHA384",
|
||||||
"TLS_AES_128_GCM_SHA256",
|
"TLS_AES_128_GCM_SHA256",
|
||||||
"TLS_CHACHA20_POLY1305_SHA256"
|
"TLS_CHACHA20_POLY1305_SHA256"
|
||||||
];
|
];
|
||||||
do_default_ciphers(dtls_all_available) ->
|
do_default_ciphers(_) ->
|
||||||
%% as of now, dtls does not support tlsv1.3 ciphers
|
%% otherwise resolve default ciphers list at runtime
|
||||||
emqx_tls_lib:selected_ciphers(['dtlsv1.2', 'dtlsv1']);
|
[].
|
||||||
do_default_ciphers(tls_all_available) ->
|
|
||||||
emqx_tls_lib:default_ciphers().
|
|
||||||
|
|
||||||
%% @private return a list of keys in a parent field
|
%% @private return a list of keys in a parent field
|
||||||
-spec keys(string(), hocon:config()) -> [string()].
|
-spec keys(string(), hocon:config()) -> [string()].
|
||||||
|
@ -2246,19 +2248,16 @@ parse_user_lookup_fun(StrConf) ->
|
||||||
{fun Mod:Fun/3, undefined}.
|
{fun Mod:Fun/3, undefined}.
|
||||||
|
|
||||||
validate_ciphers(Ciphers) ->
|
validate_ciphers(Ciphers) ->
|
||||||
All = emqx_tls_lib:all_ciphers(),
|
Set = emqx_tls_lib:all_ciphers_set_cached(),
|
||||||
case lists:filter(fun(Cipher) -> not lists:member(Cipher, All) end, Ciphers) of
|
case lists:filter(fun(Cipher) -> not sets:is_element(Cipher, Set) end, Ciphers) of
|
||||||
[] -> ok;
|
[] -> ok;
|
||||||
Bad -> {error, {bad_ciphers, Bad}}
|
Bad -> {error, {bad_ciphers, Bad}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
validate_tls_versions(Versions) ->
|
validate_tls_versions(AvailableVersions, Versions) ->
|
||||||
AvailableVersions =
|
|
||||||
proplists:get_value(available, ssl:versions()) ++
|
|
||||||
proplists:get_value(available_dtls, ssl:versions()),
|
|
||||||
case lists:filter(fun(V) -> not lists:member(V, AvailableVersions) end, Versions) of
|
case lists:filter(fun(V) -> not lists:member(V, AvailableVersions) end, Versions) of
|
||||||
[] -> ok;
|
[] -> ok;
|
||||||
Vs -> {error, {unsupported_ssl_versions, Vs}}
|
Vs -> {error, {unsupported_tls_versions, Vs}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
validations() ->
|
validations() ->
|
||||||
|
|
|
@ -18,13 +18,12 @@
|
||||||
|
|
||||||
%% version & cipher suites
|
%% version & cipher suites
|
||||||
-export([
|
-export([
|
||||||
default_versions/0,
|
available_versions/1,
|
||||||
integral_versions/1,
|
integral_versions/2,
|
||||||
default_ciphers/0,
|
default_ciphers/0,
|
||||||
selected_ciphers/1,
|
selected_ciphers/1,
|
||||||
integral_ciphers/2,
|
integral_ciphers/2,
|
||||||
drop_tls13_for_old_otp/1,
|
all_ciphers_set_cached/0
|
||||||
all_ciphers/0
|
|
||||||
]).
|
]).
|
||||||
|
|
||||||
%% SSL files
|
%% SSL files
|
||||||
|
@ -38,7 +37,9 @@
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
to_client_opts/1
|
to_server_opts/2,
|
||||||
|
to_client_opts/1,
|
||||||
|
to_client_opts/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
@ -54,27 +55,80 @@
|
||||||
%% non-empty list of strings
|
%% non-empty list of strings
|
||||||
-define(IS_STRING_LIST(L), (is_list(L) andalso L =/= [] andalso ?IS_STRING(hd(L)))).
|
-define(IS_STRING_LIST(L), (is_list(L) andalso L =/= [] andalso ?IS_STRING(hd(L)))).
|
||||||
|
|
||||||
%% @doc Returns the default supported tls versions.
|
%% The ciphers that ssl:cipher_suites(exclusive, 'tlsv1.3', openssl)
|
||||||
-spec default_versions() -> [atom()].
|
%% should return when running on otp 23.
|
||||||
default_versions() -> available_versions().
|
%% But we still have to hard-code them because tlsv1.3 on otp 22 is
|
||||||
|
%% not trustworthy.
|
||||||
|
-define(TLSV13_EXCLUSIVE_CIPHERS, [
|
||||||
|
"TLS_AES_256_GCM_SHA384",
|
||||||
|
"TLS_AES_128_GCM_SHA256",
|
||||||
|
"TLS_CHACHA20_POLY1305_SHA256",
|
||||||
|
"TLS_AES_128_CCM_SHA256",
|
||||||
|
"TLS_AES_128_CCM_8_SHA256"
|
||||||
|
]).
|
||||||
|
|
||||||
|
-define(SELECTED_CIPHERS, [
|
||||||
|
"ECDHE-ECDSA-AES256-GCM-SHA384",
|
||||||
|
"ECDHE-RSA-AES256-GCM-SHA384",
|
||||||
|
"ECDHE-ECDSA-AES256-SHA384",
|
||||||
|
"ECDHE-RSA-AES256-SHA384",
|
||||||
|
"ECDH-ECDSA-AES256-GCM-SHA384",
|
||||||
|
"ECDH-RSA-AES256-GCM-SHA384",
|
||||||
|
"ECDH-ECDSA-AES256-SHA384",
|
||||||
|
"ECDH-RSA-AES256-SHA384",
|
||||||
|
"DHE-DSS-AES256-GCM-SHA384",
|
||||||
|
"DHE-DSS-AES256-SHA256",
|
||||||
|
"AES256-GCM-SHA384",
|
||||||
|
"AES256-SHA256",
|
||||||
|
"ECDHE-ECDSA-AES128-GCM-SHA256",
|
||||||
|
"ECDHE-RSA-AES128-GCM-SHA256",
|
||||||
|
"ECDHE-ECDSA-AES128-SHA256",
|
||||||
|
"ECDHE-RSA-AES128-SHA256",
|
||||||
|
"ECDH-ECDSA-AES128-GCM-SHA256",
|
||||||
|
"ECDH-RSA-AES128-GCM-SHA256",
|
||||||
|
"ECDH-ECDSA-AES128-SHA256",
|
||||||
|
"ECDH-RSA-AES128-SHA256",
|
||||||
|
"DHE-DSS-AES128-GCM-SHA256",
|
||||||
|
"DHE-DSS-AES128-SHA256",
|
||||||
|
"AES128-GCM-SHA256",
|
||||||
|
"AES128-SHA256",
|
||||||
|
"ECDHE-ECDSA-AES256-SHA",
|
||||||
|
"ECDHE-RSA-AES256-SHA",
|
||||||
|
"DHE-DSS-AES256-SHA",
|
||||||
|
"ECDH-ECDSA-AES256-SHA",
|
||||||
|
"ECDH-RSA-AES256-SHA",
|
||||||
|
"ECDHE-ECDSA-AES128-SHA",
|
||||||
|
"ECDHE-RSA-AES128-SHA",
|
||||||
|
"DHE-DSS-AES128-SHA",
|
||||||
|
"ECDH-ECDSA-AES128-SHA",
|
||||||
|
"ECDH-RSA-AES128-SHA",
|
||||||
|
|
||||||
|
%% psk
|
||||||
|
"RSA-PSK-AES256-GCM-SHA384",
|
||||||
|
"RSA-PSK-AES256-CBC-SHA384",
|
||||||
|
"RSA-PSK-AES128-GCM-SHA256",
|
||||||
|
"RSA-PSK-AES128-CBC-SHA256",
|
||||||
|
"RSA-PSK-AES256-CBC-SHA",
|
||||||
|
"RSA-PSK-AES128-CBC-SHA"
|
||||||
|
]).
|
||||||
|
|
||||||
%% @doc Validate a given list of desired tls versions.
|
%% @doc Validate a given list of desired tls versions.
|
||||||
%% raise an error exception if non of them are available.
|
%% raise an error exception if non of them are available.
|
||||||
%% The input list can be a string/binary of comma separated versions.
|
%% The input list can be a string/binary of comma separated versions.
|
||||||
-spec integral_versions(undefined | string() | binary() | [ssl:tls_version()]) ->
|
-spec integral_versions(tls | dtls, undefined | string() | binary() | [ssl:tls_version()]) ->
|
||||||
[ssl:tls_version()].
|
[ssl:tls_version()].
|
||||||
integral_versions(undefined) ->
|
integral_versions(Type, undefined) ->
|
||||||
integral_versions(default_versions());
|
available_versions(Type);
|
||||||
integral_versions([]) ->
|
integral_versions(Type, []) ->
|
||||||
integral_versions(default_versions());
|
available_versions(Type);
|
||||||
integral_versions(<<>>) ->
|
integral_versions(Type, <<>>) ->
|
||||||
integral_versions(default_versions());
|
available_versions(Type);
|
||||||
integral_versions(Desired) when ?IS_STRING(Desired) ->
|
integral_versions(Type, Desired) when ?IS_STRING(Desired) ->
|
||||||
integral_versions(iolist_to_binary(Desired));
|
integral_versions(Type, iolist_to_binary(Desired));
|
||||||
integral_versions(Desired) when is_binary(Desired) ->
|
integral_versions(Type, Desired) when is_binary(Desired) ->
|
||||||
integral_versions(parse_versions(Desired));
|
integral_versions(Type, parse_versions(Desired));
|
||||||
integral_versions(Desired) ->
|
integral_versions(Type, Desired) ->
|
||||||
Available = available_versions(),
|
Available = available_versions(Type),
|
||||||
case lists:filter(fun(V) -> lists:member(V, Available) end, Desired) of
|
case lists:filter(fun(V) -> lists:member(V, Available) end, Desired) of
|
||||||
[] ->
|
[] ->
|
||||||
erlang:error(#{
|
erlang:error(#{
|
||||||
|
@ -86,33 +140,36 @@ integral_versions(Desired) ->
|
||||||
Filtered
|
Filtered
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc Return a list of all supported ciphers.
|
%% @doc Return a set of all ciphers
|
||||||
all_ciphers() -> all_ciphers(default_versions()).
|
all_ciphers_set_cached() ->
|
||||||
|
case persistent_term:get(?FUNCTION_NAME, false) of
|
||||||
|
false ->
|
||||||
|
S = sets:from_list(all_ciphers()),
|
||||||
|
persistent_term:put(?FUNCTION_NAME, S);
|
||||||
|
Set ->
|
||||||
|
Set
|
||||||
|
end.
|
||||||
|
|
||||||
%% @doc Return a list of (openssl string format) cipher suites.
|
%% @hidden Return a list of all supported ciphers.
|
||||||
|
all_ciphers() ->
|
||||||
|
all_ciphers(available_versions(all)).
|
||||||
|
|
||||||
|
%% @hidden Return a list of (openssl string format) cipher suites.
|
||||||
-spec all_ciphers([ssl:tls_version()]) -> [string()].
|
-spec all_ciphers([ssl:tls_version()]) -> [string()].
|
||||||
all_ciphers(['tlsv1.3']) ->
|
all_ciphers(['tlsv1.3']) ->
|
||||||
%% When it's only tlsv1.3 wanted, use 'exclusive' here
|
%% When it's only tlsv1.3 wanted, use 'exclusive' here
|
||||||
%% because 'all' returns legacy cipher suites too,
|
%% because 'all' returns legacy cipher suites too,
|
||||||
%% which does not make sense since tlsv1.3 can not use
|
%% which does not make sense since tlsv1.3 can not use
|
||||||
%% legacy cipher suites.
|
%% legacy cipher suites.
|
||||||
ssl:cipher_suites(exclusive, 'tlsv1.3', openssl);
|
?TLSV13_EXCLUSIVE_CIPHERS;
|
||||||
all_ciphers(Versions) ->
|
all_ciphers(Versions) ->
|
||||||
%% assert non-empty
|
%% assert non-empty
|
||||||
List = lists:append([ssl:cipher_suites(all, V, openssl) || V <- Versions]),
|
List = lists:append([ssl:cipher_suites(all, V, openssl) || V <- Versions]),
|
||||||
[_ | _] = dedup(List).
|
[_ | _] = dedup(List).
|
||||||
|
|
||||||
%% @doc All Pre-selected TLS ciphers.
|
%% @doc All Pre-selected TLS ciphers.
|
||||||
%% ssl:cipher_suites(all, V, openssl) is too slow. so we cache default ciphers.
|
|
||||||
default_ciphers() ->
|
default_ciphers() ->
|
||||||
case persistent_term:get(default_ciphers, undefined) of
|
selected_ciphers(available_versions(all)).
|
||||||
undefined ->
|
|
||||||
Default = selected_ciphers(available_versions()),
|
|
||||||
persistent_term:put(default_ciphers, Default),
|
|
||||||
Default;
|
|
||||||
Default ->
|
|
||||||
Default
|
|
||||||
end.
|
|
||||||
|
|
||||||
%% @doc Pre-selected TLS ciphers for given versions..
|
%% @doc Pre-selected TLS ciphers for given versions..
|
||||||
selected_ciphers(Vsns) ->
|
selected_ciphers(Vsns) ->
|
||||||
|
@ -126,54 +183,11 @@ selected_ciphers(Vsns) ->
|
||||||
|
|
||||||
do_selected_ciphers('tlsv1.3') ->
|
do_selected_ciphers('tlsv1.3') ->
|
||||||
case lists:member('tlsv1.3', proplists:get_value(available, ssl:versions())) of
|
case lists:member('tlsv1.3', proplists:get_value(available, ssl:versions())) of
|
||||||
true -> ssl:cipher_suites(exclusive, 'tlsv1.3', openssl);
|
true -> ?TLSV13_EXCLUSIVE_CIPHERS;
|
||||||
false -> []
|
false -> []
|
||||||
end ++ do_selected_ciphers('tlsv1.2');
|
end ++ do_selected_ciphers('tlsv1.2');
|
||||||
do_selected_ciphers(_) ->
|
do_selected_ciphers(_) ->
|
||||||
[
|
?SELECTED_CIPHERS.
|
||||||
"ECDHE-ECDSA-AES256-GCM-SHA384",
|
|
||||||
"ECDHE-RSA-AES256-GCM-SHA384",
|
|
||||||
"ECDHE-ECDSA-AES256-SHA384",
|
|
||||||
"ECDHE-RSA-AES256-SHA384",
|
|
||||||
"ECDH-ECDSA-AES256-GCM-SHA384",
|
|
||||||
"ECDH-RSA-AES256-GCM-SHA384",
|
|
||||||
"ECDH-ECDSA-AES256-SHA384",
|
|
||||||
"ECDH-RSA-AES256-SHA384",
|
|
||||||
"DHE-DSS-AES256-GCM-SHA384",
|
|
||||||
"DHE-DSS-AES256-SHA256",
|
|
||||||
"AES256-GCM-SHA384",
|
|
||||||
"AES256-SHA256",
|
|
||||||
"ECDHE-ECDSA-AES128-GCM-SHA256",
|
|
||||||
"ECDHE-RSA-AES128-GCM-SHA256",
|
|
||||||
"ECDHE-ECDSA-AES128-SHA256",
|
|
||||||
"ECDHE-RSA-AES128-SHA256",
|
|
||||||
"ECDH-ECDSA-AES128-GCM-SHA256",
|
|
||||||
"ECDH-RSA-AES128-GCM-SHA256",
|
|
||||||
"ECDH-ECDSA-AES128-SHA256",
|
|
||||||
"ECDH-RSA-AES128-SHA256",
|
|
||||||
"DHE-DSS-AES128-GCM-SHA256",
|
|
||||||
"DHE-DSS-AES128-SHA256",
|
|
||||||
"AES128-GCM-SHA256",
|
|
||||||
"AES128-SHA256",
|
|
||||||
"ECDHE-ECDSA-AES256-SHA",
|
|
||||||
"ECDHE-RSA-AES256-SHA",
|
|
||||||
"DHE-DSS-AES256-SHA",
|
|
||||||
"ECDH-ECDSA-AES256-SHA",
|
|
||||||
"ECDH-RSA-AES256-SHA",
|
|
||||||
"ECDHE-ECDSA-AES128-SHA",
|
|
||||||
"ECDHE-RSA-AES128-SHA",
|
|
||||||
"DHE-DSS-AES128-SHA",
|
|
||||||
"ECDH-ECDSA-AES128-SHA",
|
|
||||||
"ECDH-RSA-AES128-SHA",
|
|
||||||
|
|
||||||
%% psk
|
|
||||||
"RSA-PSK-AES256-GCM-SHA384",
|
|
||||||
"RSA-PSK-AES256-CBC-SHA384",
|
|
||||||
"RSA-PSK-AES128-GCM-SHA256",
|
|
||||||
"RSA-PSK-AES128-CBC-SHA256",
|
|
||||||
"RSA-PSK-AES256-CBC-SHA",
|
|
||||||
"RSA-PSK-AES128-CBC-SHA"
|
|
||||||
].
|
|
||||||
|
|
||||||
%% @doc Ensure version & cipher-suites integrity.
|
%% @doc Ensure version & cipher-suites integrity.
|
||||||
-spec integral_ciphers([ssl:tls_version()], binary() | string() | [string()]) -> [string()].
|
-spec integral_ciphers([ssl:tls_version()], binary() | string() | [string()]) -> [string()].
|
||||||
|
@ -201,17 +215,17 @@ ensure_tls13_cipher(true, Ciphers) ->
|
||||||
ensure_tls13_cipher(false, Ciphers) ->
|
ensure_tls13_cipher(false, Ciphers) ->
|
||||||
Ciphers.
|
Ciphers.
|
||||||
|
|
||||||
%% default ssl versions based on available versions.
|
%% @doc Returns the default available tls/dtls versions.
|
||||||
-spec available_versions() -> [atom()].
|
available_versions(Type) ->
|
||||||
available_versions() ->
|
All = ssl:versions(),
|
||||||
OtpRelease = list_to_integer(erlang:system_info(otp_release)),
|
available_versions(Type, All).
|
||||||
default_versions(OtpRelease).
|
|
||||||
|
|
||||||
%% tlsv1.3 is available from OTP-22 but we do not want to use until 23.
|
available_versions(tls, All) ->
|
||||||
default_versions(OtpRelease) when OtpRelease >= 23 ->
|
proplists:get_value(available, All);
|
||||||
proplists:get_value(available, ssl:versions());
|
available_versions(dtls, All) ->
|
||||||
default_versions(_) ->
|
proplists:get_value(available_dtls, All);
|
||||||
lists:delete('tlsv1.3', proplists:get_value(available, ssl:versions())).
|
available_versions(all, All) ->
|
||||||
|
available_versions(tls, All) ++ available_versions(dtls, All).
|
||||||
|
|
||||||
%% Deduplicate a list without re-ordering the elements.
|
%% Deduplicate a list without re-ordering the elements.
|
||||||
dedup([]) ->
|
dedup([]) ->
|
||||||
|
@ -244,6 +258,8 @@ do_parse_versions([V | More], Acc) ->
|
||||||
do_parse_versions(More, [Parsed | Acc])
|
do_parse_versions(More, [Parsed | Acc])
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
parse_version(<<"dtlsv1.2">>) -> 'dtlsv1.2';
|
||||||
|
parse_version(<<"dtlsv1">>) -> dtlsv1;
|
||||||
parse_version(<<"tlsv", Vsn/binary>>) -> parse_version(Vsn);
|
parse_version(<<"tlsv", Vsn/binary>>) -> parse_version(Vsn);
|
||||||
parse_version(<<"v", Vsn/binary>>) -> parse_version(Vsn);
|
parse_version(<<"v", Vsn/binary>>) -> parse_version(Vsn);
|
||||||
parse_version(<<"1.3">>) -> 'tlsv1.3';
|
parse_version(<<"1.3">>) -> 'tlsv1.3';
|
||||||
|
@ -259,36 +275,6 @@ split_by_comma(Bin) ->
|
||||||
trim_space(Bin) ->
|
trim_space(Bin) ->
|
||||||
hd([I || I <- binary:split(Bin, <<" ">>), I =/= <<>>]).
|
hd([I || I <- binary:split(Bin, <<" ">>), I =/= <<>>]).
|
||||||
|
|
||||||
%% @doc Drop tlsv1.3 version and ciphers from ssl options
|
|
||||||
%% if running on otp 22 or earlier.
|
|
||||||
drop_tls13_for_old_otp(SslOpts) ->
|
|
||||||
case list_to_integer(erlang:system_info(otp_release)) < 23 of
|
|
||||||
true -> drop_tls13(SslOpts);
|
|
||||||
false -> SslOpts
|
|
||||||
end.
|
|
||||||
|
|
||||||
%% The ciphers that ssl:cipher_suites(exclusive, 'tlsv1.3', openssl)
|
|
||||||
%% should return when running on otp 23.
|
|
||||||
%% But we still have to hard-code them because tlsv1.3 on otp 22 is
|
|
||||||
%% not trustworthy.
|
|
||||||
-define(TLSV13_EXCLUSIVE_CIPHERS, [
|
|
||||||
"TLS_AES_256_GCM_SHA384",
|
|
||||||
"TLS_AES_128_GCM_SHA256",
|
|
||||||
"TLS_CHACHA20_POLY1305_SHA256",
|
|
||||||
"TLS_AES_128_CCM_SHA256",
|
|
||||||
"TLS_AES_128_CCM_8_SHA256"
|
|
||||||
]).
|
|
||||||
drop_tls13(SslOpts0) ->
|
|
||||||
SslOpts1 =
|
|
||||||
case maps:find(versions, SslOpts0) of
|
|
||||||
error -> SslOpts0;
|
|
||||||
{ok, Vsns} -> SslOpts0#{versions => (Vsns -- ['tlsv1.3'])}
|
|
||||||
end,
|
|
||||||
case maps:find(ciphers, SslOpts1) of
|
|
||||||
error -> SslOpts1;
|
|
||||||
{ok, Ciphers} -> SslOpts1#{ciphers => Ciphers -- ?TLSV13_EXCLUSIVE_CIPHERS}
|
|
||||||
end.
|
|
||||||
|
|
||||||
%% @doc The input map is a HOCON decoded result of a struct defined as
|
%% @doc The input map is a HOCON decoded result of a struct defined as
|
||||||
%% emqx_schema:server_ssl_opts_schema. (NOTE: before schema-checked).
|
%% emqx_schema:server_ssl_opts_schema. (NOTE: before schema-checked).
|
||||||
%% `keyfile', `certfile' and `cacertfile' can be either pem format key or certificates,
|
%% `keyfile', `certfile' and `cacertfile' can be either pem format key or certificates,
|
||||||
|
@ -498,27 +484,54 @@ do_drop_invalid_certs([Key | Keys], SSL) ->
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc Convert hocon-checked ssl client options (map()) to
|
%% @doc Convert hocon-checked ssl server options (map()) to
|
||||||
%% proplist accepted by ssl library.
|
%% proplist accepted by ssl library.
|
||||||
|
-spec to_server_opts(tls | dtls, map()) -> [{atom(), term()}].
|
||||||
|
to_server_opts(Type, Opts) ->
|
||||||
|
Versions = integral_versions(Type, maps:get(versions, Opts, undefined)),
|
||||||
|
Ciphers = integral_ciphers(Versions, maps:get(ciphers, Opts, undefined)),
|
||||||
|
maps:to_list(Opts#{
|
||||||
|
ciphers => Ciphers,
|
||||||
|
versions => Versions
|
||||||
|
}).
|
||||||
|
|
||||||
|
%% @doc Convert hocon-checked tls client options (map()) to
|
||||||
|
%% proplist accepted by ssl library.
|
||||||
|
-spec to_client_opts(map()) -> [{atom(), term()}].
|
||||||
to_client_opts(Opts) ->
|
to_client_opts(Opts) ->
|
||||||
|
to_client_opts(tls, Opts).
|
||||||
|
|
||||||
|
%% @doc Convert hocon-checked tls or dtls client options (map()) to
|
||||||
|
%% proplist accepted by ssl library.
|
||||||
|
-spec to_client_opts(tls | dtls, map()) -> [{atom(), term()}].
|
||||||
|
to_client_opts(Type, Opts) ->
|
||||||
GetD = fun(Key, Default) -> fuzzy_map_get(Key, Opts, Default) end,
|
GetD = fun(Key, Default) -> fuzzy_map_get(Key, Opts, Default) end,
|
||||||
Get = fun(Key) -> GetD(Key, undefined) end,
|
Get = fun(Key) -> GetD(Key, undefined) end,
|
||||||
KeyFile = ensure_str(Get(keyfile)),
|
case GetD(enable, false) of
|
||||||
CertFile = ensure_str(Get(certfile)),
|
true ->
|
||||||
CAFile = ensure_str(Get(cacertfile)),
|
KeyFile = ensure_str(Get(keyfile)),
|
||||||
Verify = GetD(verify, verify_none),
|
CertFile = ensure_str(Get(certfile)),
|
||||||
SNI = ensure_sni(Get(server_name_indication)),
|
CAFile = ensure_str(Get(cacertfile)),
|
||||||
Versions = integral_versions(Get(versions)),
|
Verify = GetD(verify, verify_none),
|
||||||
Ciphers = integral_ciphers(Versions, Get(ciphers)),
|
SNI = ensure_sni(Get(server_name_indication)),
|
||||||
filter([
|
Versions = integral_versions(Type, Get(versions)),
|
||||||
{keyfile, KeyFile},
|
Ciphers = integral_ciphers(Versions, Get(ciphers)),
|
||||||
{certfile, CertFile},
|
filter([
|
||||||
{cacertfile, CAFile},
|
{keyfile, KeyFile},
|
||||||
{verify, Verify},
|
{certfile, CertFile},
|
||||||
{server_name_indication, SNI},
|
{cacertfile, CAFile},
|
||||||
{versions, Versions},
|
{verify, Verify},
|
||||||
{ciphers, Ciphers}
|
{server_name_indication, SNI},
|
||||||
]).
|
{versions, Versions},
|
||||||
|
{ciphers, Ciphers},
|
||||||
|
{reuse_sessions, Get(reuse_sessions)},
|
||||||
|
{depth, Get(depth)},
|
||||||
|
{password, ensure_str(Get(password))},
|
||||||
|
{secure_renegotiate, Get(secure_renegotiate)}
|
||||||
|
]);
|
||||||
|
false ->
|
||||||
|
[]
|
||||||
|
end.
|
||||||
|
|
||||||
filter([]) -> [];
|
filter([]) -> [];
|
||||||
filter([{_, undefined} | T]) -> filter(T);
|
filter([{_, undefined} | T]) -> filter(T);
|
||||||
|
@ -556,28 +569,3 @@ ensure_ssl_file_key(SSL, RequiredKeys) ->
|
||||||
[] -> ok;
|
[] -> ok;
|
||||||
Miss -> {error, #{reason => ssl_file_option_not_found, which_options => Miss}}
|
Miss -> {error, #{reason => ssl_file_option_not_found, which_options => Miss}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-if(?OTP_RELEASE > 22).
|
|
||||||
-ifdef(TEST).
|
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
|
||||||
|
|
||||||
drop_tls13_test() ->
|
|
||||||
Versions = default_versions(),
|
|
||||||
?assert(lists:member('tlsv1.3', Versions)),
|
|
||||||
Ciphers = all_ciphers(),
|
|
||||||
?assert(has_tlsv13_cipher(Ciphers)),
|
|
||||||
Opts0 = #{versions => Versions, ciphers => Ciphers, other => true},
|
|
||||||
Opts = drop_tls13(Opts0),
|
|
||||||
?assertNot(lists:member('tlsv1.3', maps:get(versions, Opts, undefined))),
|
|
||||||
?assertNot(has_tlsv13_cipher(maps:get(ciphers, Opts, undefined))).
|
|
||||||
|
|
||||||
drop_tls13_no_versions_cipers_test() ->
|
|
||||||
Opts0 = #{other => 0, bool => true},
|
|
||||||
Opts = drop_tls13(Opts0),
|
|
||||||
?_assertEqual(Opts0, Opts).
|
|
||||||
|
|
||||||
has_tlsv13_cipher(Ciphers) ->
|
|
||||||
lists:any(fun(C) -> lists:member(C, Ciphers) end, ?TLSV13_EXCLUSIVE_CIPHERS).
|
|
||||||
|
|
||||||
-endif.
|
|
||||||
-endif.
|
|
||||||
|
|
|
@ -21,8 +21,7 @@
|
||||||
ssl_opts_dtls_test() ->
|
ssl_opts_dtls_test() ->
|
||||||
Sc = emqx_schema:server_ssl_opts_schema(
|
Sc = emqx_schema:server_ssl_opts_schema(
|
||||||
#{
|
#{
|
||||||
versions => dtls_all_available,
|
versions => dtls_all_available
|
||||||
ciphers => dtls_all_available
|
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
),
|
),
|
||||||
|
@ -30,7 +29,7 @@ ssl_opts_dtls_test() ->
|
||||||
?assertMatch(
|
?assertMatch(
|
||||||
#{
|
#{
|
||||||
versions := ['dtlsv1.2', 'dtlsv1'],
|
versions := ['dtlsv1.2', 'dtlsv1'],
|
||||||
ciphers := ["ECDHE-ECDSA-AES256-GCM-SHA384" | _]
|
ciphers := []
|
||||||
},
|
},
|
||||||
Checked
|
Checked
|
||||||
).
|
).
|
||||||
|
@ -42,7 +41,7 @@ ssl_opts_tls_1_3_test() ->
|
||||||
?assertMatch(
|
?assertMatch(
|
||||||
#{
|
#{
|
||||||
versions := ['tlsv1.3'],
|
versions := ['tlsv1.3'],
|
||||||
ciphers := [_ | _]
|
ciphers := []
|
||||||
},
|
},
|
||||||
Checked
|
Checked
|
||||||
).
|
).
|
||||||
|
@ -53,7 +52,7 @@ ssl_opts_tls_for_ranch_test() ->
|
||||||
?assertMatch(
|
?assertMatch(
|
||||||
#{
|
#{
|
||||||
versions := ['tlsv1.3'],
|
versions := ['tlsv1.3'],
|
||||||
ciphers := [_ | _],
|
ciphers := [],
|
||||||
handshake_timeout := _
|
handshake_timeout := _
|
||||||
},
|
},
|
||||||
Checked
|
Checked
|
||||||
|
@ -125,7 +124,7 @@ validate(Schema, Data0) ->
|
||||||
),
|
),
|
||||||
Checked.
|
Checked.
|
||||||
|
|
||||||
ciperhs_schema_test() ->
|
ciphers_schema_test() ->
|
||||||
Sc = emqx_schema:ciphers_schema(undefined),
|
Sc = emqx_schema:ciphers_schema(undefined),
|
||||||
WSc = #{roots => [{ciphers, Sc}]},
|
WSc = #{roots => [{ciphers, Sc}]},
|
||||||
?assertThrow(
|
?assertThrow(
|
||||||
|
@ -135,7 +134,7 @@ ciperhs_schema_test() ->
|
||||||
|
|
||||||
bad_tls_version_test() ->
|
bad_tls_version_test() ->
|
||||||
Sc = emqx_schema:server_ssl_opts_schema(#{}, false),
|
Sc = emqx_schema:server_ssl_opts_schema(#{}, false),
|
||||||
Reason = {unsupported_ssl_versions, [foo]},
|
Reason = {unsupported_tls_versions, [foo]},
|
||||||
?assertThrow(
|
?assertThrow(
|
||||||
{_Sc, [#{kind := validation_error, reason := Reason}]},
|
{_Sc, [#{kind := validation_error, reason := Reason}]},
|
||||||
validate(Sc, #{<<"versions">> => [<<"foo">>]})
|
validate(Sc, #{<<"versions">> => [<<"foo">>]})
|
||||||
|
|
|
@ -51,24 +51,34 @@ test_cipher_format(Input) ->
|
||||||
?assertEqual([?TLS_13_CIPHER, ?TLS_12_CIPHER], Ciphers).
|
?assertEqual([?TLS_13_CIPHER, ?TLS_12_CIPHER], Ciphers).
|
||||||
|
|
||||||
tls_versions_test() ->
|
tls_versions_test() ->
|
||||||
?assert(lists:member('tlsv1.3', emqx_tls_lib:default_versions())).
|
?assert(lists:member('tlsv1.3', emqx_tls_lib:available_versions(tls))).
|
||||||
|
|
||||||
tls_version_unknown_test() ->
|
tls_version_unknown_test_() ->
|
||||||
?assertEqual(
|
lists:flatmap(
|
||||||
emqx_tls_lib:default_versions(),
|
fun(Type) ->
|
||||||
emqx_tls_lib:integral_versions([])
|
[
|
||||||
),
|
?_assertEqual(
|
||||||
?assertEqual(
|
emqx_tls_lib:available_versions(Type),
|
||||||
emqx_tls_lib:default_versions(),
|
emqx_tls_lib:integral_versions(Type, [])
|
||||||
emqx_tls_lib:integral_versions(<<>>)
|
),
|
||||||
),
|
?_assertEqual(
|
||||||
?assertEqual(
|
emqx_tls_lib:available_versions(Type),
|
||||||
emqx_tls_lib:default_versions(),
|
emqx_tls_lib:integral_versions(Type, <<>>)
|
||||||
emqx_tls_lib:integral_versions("foo")
|
),
|
||||||
),
|
?_assertEqual(
|
||||||
?assertError(
|
emqx_tls_lib:available_versions(Type),
|
||||||
#{reason := no_available_tls_version},
|
%% unknown version dropped
|
||||||
emqx_tls_lib:integral_versions([foo])
|
emqx_tls_lib:integral_versions(Type, "foo")
|
||||||
|
),
|
||||||
|
fun() ->
|
||||||
|
?assertError(
|
||||||
|
#{reason := no_available_tls_version},
|
||||||
|
emqx_tls_lib:integral_versions(Type, [foo])
|
||||||
|
)
|
||||||
|
end
|
||||||
|
]
|
||||||
|
end,
|
||||||
|
[tls, dtls]
|
||||||
).
|
).
|
||||||
|
|
||||||
cipher_suites_no_duplication_test() ->
|
cipher_suites_no_duplication_test() ->
|
||||||
|
|
|
@ -365,8 +365,7 @@ fields(ssl_server_opts) ->
|
||||||
#{
|
#{
|
||||||
depth => 10,
|
depth => 10,
|
||||||
reuse_sessions => true,
|
reuse_sessions => true,
|
||||||
versions => tls_all_available,
|
versions => tls_all_available
|
||||||
ciphers => tls_all_available
|
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
@ -502,8 +501,7 @@ fields(dtls_opts) ->
|
||||||
#{
|
#{
|
||||||
depth => 10,
|
depth => 10,
|
||||||
reuse_sessions => true,
|
reuse_sessions => true,
|
||||||
versions => dtls_all_available,
|
versions => dtls_all_available
|
||||||
ciphers => dtls_all_available
|
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
).
|
).
|
||||||
|
|
|
@ -455,14 +455,12 @@ esockd_access_rules(StrRules) ->
|
||||||
[Access(R) || R <- StrRules].
|
[Access(R) || R <- StrRules].
|
||||||
|
|
||||||
ssl_opts(Name, Opts) ->
|
ssl_opts(Name, Opts) ->
|
||||||
maps:to_list(
|
Type =
|
||||||
emqx_tls_lib:drop_tls13_for_old_otp(
|
case Name of
|
||||||
maps:without(
|
ssl -> tls;
|
||||||
[enable],
|
dtls -> dtls
|
||||||
maps:get(Name, Opts, #{})
|
end,
|
||||||
)
|
emqx_tls_lib:to_server_opts(Type, maps:get(Name, Opts, #{})).
|
||||||
)
|
|
||||||
).
|
|
||||||
|
|
||||||
sock_opts(Name, Opts) ->
|
sock_opts(Name, Opts) ->
|
||||||
maps:to_list(
|
maps:to_list(
|
||||||
|
|
|
@ -483,8 +483,8 @@ ssl_opts() ->
|
||||||
maps:merge(
|
maps:merge(
|
||||||
Certs,
|
Certs,
|
||||||
#{
|
#{
|
||||||
versions => emqx_tls_lib:default_versions(),
|
versions => emqx_tls_lib:available_versions(tls),
|
||||||
ciphers => emqx_tls_lib:default_ciphers(),
|
ciphers => [],
|
||||||
verify => verify_peer,
|
verify => verify_peer,
|
||||||
fail_if_no_peer_cert => true,
|
fail_if_no_peer_cert => true,
|
||||||
secure_renegotiate => false,
|
secure_renegotiate => false,
|
||||||
|
|
|
@ -233,3 +233,76 @@ authentication=[{enable=true, backend="built_in_database", mechanism="password_b
|
||||||
authentication=[{enable=true}]
|
authentication=[{enable=true}]
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
#### TLS/SSL ciphers
|
||||||
|
|
||||||
|
Starting from v5.0.6, EMQX no longer pre-populate the ciphers list with a default
|
||||||
|
set of cipher suite names.
|
||||||
|
Instead, the default ciphers are applyed at runtime when starting the listener
|
||||||
|
for servers, or when establishing a TLS connection as a client.
|
||||||
|
|
||||||
|
Below are the default ciphers selected by EMQX.
|
||||||
|
|
||||||
|
For tlsv1.3:
|
||||||
|
```
|
||||||
|
ciphers =
|
||||||
|
[ "TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256",
|
||||||
|
"TLS_CHACHA20_POLY1305_SHA256", "TLS_AES_128_CCM_SHA256",
|
||||||
|
"TLS_AES_128_CCM_8_SHA256"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
For tlsv1.2 or earlier
|
||||||
|
|
||||||
|
```
|
||||||
|
ciphers =
|
||||||
|
[ "ECDHE-ECDSA-AES256-GCM-SHA384",
|
||||||
|
"ECDHE-RSA-AES256-GCM-SHA384",
|
||||||
|
"ECDHE-ECDSA-AES256-SHA384",
|
||||||
|
"ECDHE-RSA-AES256-SHA384",
|
||||||
|
"ECDH-ECDSA-AES256-GCM-SHA384",
|
||||||
|
"ECDH-RSA-AES256-GCM-SHA384",
|
||||||
|
"ECDH-ECDSA-AES256-SHA384",
|
||||||
|
"ECDH-RSA-AES256-SHA384",
|
||||||
|
"DHE-DSS-AES256-GCM-SHA384",
|
||||||
|
"DHE-DSS-AES256-SHA256",
|
||||||
|
"AES256-GCM-SHA384",
|
||||||
|
"AES256-SHA256",
|
||||||
|
"ECDHE-ECDSA-AES128-GCM-SHA256",
|
||||||
|
"ECDHE-RSA-AES128-GCM-SHA256",
|
||||||
|
"ECDHE-ECDSA-AES128-SHA256",
|
||||||
|
"ECDHE-RSA-AES128-SHA256",
|
||||||
|
"ECDH-ECDSA-AES128-GCM-SHA256",
|
||||||
|
"ECDH-RSA-AES128-GCM-SHA256",
|
||||||
|
"ECDH-ECDSA-AES128-SHA256",
|
||||||
|
"ECDH-RSA-AES128-SHA256",
|
||||||
|
"DHE-DSS-AES128-GCM-SHA256",
|
||||||
|
"DHE-DSS-AES128-SHA256",
|
||||||
|
"AES128-GCM-SHA256",
|
||||||
|
"AES128-SHA256",
|
||||||
|
"ECDHE-ECDSA-AES256-SHA",
|
||||||
|
"ECDHE-RSA-AES256-SHA",
|
||||||
|
"DHE-DSS-AES256-SHA",
|
||||||
|
"ECDH-ECDSA-AES256-SHA",
|
||||||
|
"ECDH-RSA-AES256-SHA",
|
||||||
|
"ECDHE-ECDSA-AES128-SHA",
|
||||||
|
"ECDHE-RSA-AES128-SHA",
|
||||||
|
"DHE-DSS-AES128-SHA",
|
||||||
|
"ECDH-ECDSA-AES128-SHA",
|
||||||
|
"ECDH-RSA-AES128-SHA"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
For PSK enabled listeners
|
||||||
|
|
||||||
|
```
|
||||||
|
ciphers =
|
||||||
|
[ "RSA-PSK-AES256-GCM-SHA384",
|
||||||
|
"RSA-PSK-AES256-CBC-SHA384",
|
||||||
|
"RSA-PSK-AES128-GCM-SHA256",
|
||||||
|
"RSA-PSK-AES128-CBC-SHA256",
|
||||||
|
"RSA-PSK-AES256-CBC-SHA",
|
||||||
|
"RSA-PSK-AES128-CBC-SHA"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
|
@ -216,3 +216,73 @@ authentication=[{enable=true, backend="built_in_database", mechanism="password_b
|
||||||
authentication=[{enable=true}]
|
authentication=[{enable=true}]
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
#### TLS/SSL ciphers
|
||||||
|
|
||||||
|
从 v5.0.6 开始 EMQX 不在配置文件中详细列出所有默认的密码套件名称。
|
||||||
|
而是在配置文件中使用一个空列表,然后在运行时替换成默认的密码套件。
|
||||||
|
|
||||||
|
下面这些密码套件是 EMQX 默认支持的:
|
||||||
|
|
||||||
|
tlsv1.3:
|
||||||
|
```
|
||||||
|
ciphers =
|
||||||
|
[ "TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256",
|
||||||
|
"TLS_CHACHA20_POLY1305_SHA256", "TLS_AES_128_CCM_SHA256",
|
||||||
|
"TLS_AES_128_CCM_8_SHA256"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
tlsv1.2 或更早
|
||||||
|
|
||||||
|
```
|
||||||
|
ciphers =
|
||||||
|
[ "ECDHE-ECDSA-AES256-GCM-SHA384",
|
||||||
|
"ECDHE-RSA-AES256-GCM-SHA384",
|
||||||
|
"ECDHE-ECDSA-AES256-SHA384",
|
||||||
|
"ECDHE-RSA-AES256-SHA384",
|
||||||
|
"ECDH-ECDSA-AES256-GCM-SHA384",
|
||||||
|
"ECDH-RSA-AES256-GCM-SHA384",
|
||||||
|
"ECDH-ECDSA-AES256-SHA384",
|
||||||
|
"ECDH-RSA-AES256-SHA384",
|
||||||
|
"DHE-DSS-AES256-GCM-SHA384",
|
||||||
|
"DHE-DSS-AES256-SHA256",
|
||||||
|
"AES256-GCM-SHA384",
|
||||||
|
"AES256-SHA256",
|
||||||
|
"ECDHE-ECDSA-AES128-GCM-SHA256",
|
||||||
|
"ECDHE-RSA-AES128-GCM-SHA256",
|
||||||
|
"ECDHE-ECDSA-AES128-SHA256",
|
||||||
|
"ECDHE-RSA-AES128-SHA256",
|
||||||
|
"ECDH-ECDSA-AES128-GCM-SHA256",
|
||||||
|
"ECDH-RSA-AES128-GCM-SHA256",
|
||||||
|
"ECDH-ECDSA-AES128-SHA256",
|
||||||
|
"ECDH-RSA-AES128-SHA256",
|
||||||
|
"DHE-DSS-AES128-GCM-SHA256",
|
||||||
|
"DHE-DSS-AES128-SHA256",
|
||||||
|
"AES128-GCM-SHA256",
|
||||||
|
"AES128-SHA256",
|
||||||
|
"ECDHE-ECDSA-AES256-SHA",
|
||||||
|
"ECDHE-RSA-AES256-SHA",
|
||||||
|
"DHE-DSS-AES256-SHA",
|
||||||
|
"ECDH-ECDSA-AES256-SHA",
|
||||||
|
"ECDH-RSA-AES256-SHA",
|
||||||
|
"ECDHE-ECDSA-AES128-SHA",
|
||||||
|
"ECDHE-RSA-AES128-SHA",
|
||||||
|
"DHE-DSS-AES128-SHA",
|
||||||
|
"ECDH-ECDSA-AES128-SHA",
|
||||||
|
"ECDH-RSA-AES128-SHA"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
配置 PSK 认证的监听器
|
||||||
|
|
||||||
|
```
|
||||||
|
ciphers = [
|
||||||
|
[ "RSA-PSK-AES256-GCM-SHA384",
|
||||||
|
"RSA-PSK-AES256-CBC-SHA384",
|
||||||
|
"RSA-PSK-AES128-GCM-SHA256",
|
||||||
|
"RSA-PSK-AES128-CBC-SHA256",
|
||||||
|
"RSA-PSK-AES256-CBC-SHA",
|
||||||
|
"RSA-PSK-AES128-CBC-SHA"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
Loading…
Reference in New Issue