I using Erlang Mochiweb as Http server with SSL. Mochiweb use pure Erlang SSL library.
How to configure erlang ssl to support Forward Secrecy? For more info about SSL Forward Secrecy: https://en.wikipedia.org/wiki/Forward_secrecy
I using Erlang Mochiweb as Http server with SSL. Mochiweb use pure Erlang SSL library.
How to configure erlang ssl to support Forward Secrecy? For more info about SSL Forward Secrecy: https://en.wikipedia.org/wiki/Forward_secrecy
I'm using Erlang/OTP 17 with openssl 1.0.2a (erlang needs openssl for ciphers but not handshake or protocol, so theoretically it should supports all openssl-supported ciphers) , so its SSL module does support perfect forward secrecy by default. But it also supports some insecure protocol or ciphers like sslv3 or des, or weak ciphers like rc4 by default. SSLlabs ssltest will give you rank C for default options. You might want to disable the insecure protocol and ciphers.
And, the erlang ssl module does honor client's ciphersuite preference by default. Which will make some IEs using RSA key exchange because those versions prefers RSA key-exchange rather than ECDHE (see: https://www.ssllabs.com/ssltest/viewClient.html?name=IE&version=8-10&platform=Win%207). You will need {honor_cipher_order, true}
to use server's preference. And you'll need to manually adjust the preference order of cipher-suites to fit what you need. The default order is not ranking completely by PFS.
If your have control on the client (like your own apps rather than browsers), and you really want PFS only, you can disable rsa key exchange.
A sample escript and options for erlang is: I didn't reorder the ciphersuite orders.
For mochiweb, you can add these options to your ssl_opts.
#!/usr/bin/env escript
% these ciphers will got A- on ssllabs's ssltest.
% Because as mentioned above, some version's IE prefers non-PFS key exchange.
% And got A if {honor_cipher_order, true} is set.
% No manual adjusting needed to get A, because the first ciphersuite is PFS-enabled and supported by IEs.
% So you need to adjust orders to fit whatever you needed.
secure_ciphers() -> secure_ciphers(ssl:cipher_suites()).
% It includes insecure and weak ciphers, so it should get low rank on ssltest
pfs_ciphers() -> pfs_ciphers(ssl:cipher_suites()).
% Rank A on ssllabs' ssltest, all modern client is using perfect forward secrecy key-exchange
% but some client without PFS support will fail to handshake.
pfs_secure_ciphers() ->
sets:to_list(sets:intersection(sets:from_list(secure_ciphers()), sets:from_list(pfs_ciphers()))).
secure_ciphers([]) -> [];
secure_ciphers([{_, rc4_128, _} | T]) -> secure_ciphers(T);
secure_ciphers([{_, des_cbc, _} | T]) -> secure_ciphers(T);
secure_ciphers([{dhe_rsa, _, _} | T]) -> secure_ciphers(T);
secure_ciphers([{_, _, md5} | T]) -> secure_ciphers(T);
secure_ciphers([H | T]) -> [H | secure_ciphers(T)].
pfs_ciphers([]) -> [];
pfs_ciphers([{dhe_dss, _, _} = H | T]) -> [H | pfs_ciphers(T)];
pfs_ciphers([{dhe_rsa, _, _} = H | T]) -> [H | pfs_ciphers(T)];
pfs_ciphers([{ecdhe_ecdsa, _, _} = H | T]) -> [H | pfs_ciphers(T)];
pfs_ciphers([{ecdhe_rsa, _, _} = H | T]) -> [H | pfs_ciphers(T)];
pfs_ciphers([_ | T]) -> pfs_ciphers(T).
accept(S) ->
{ok, Q} = ssl:transport_accept(S),
spawn(fun() -> accept(S) end),
ssl:ssl_accept(Q),
receive
Msg ->
io:format("~p~n", [Msg]),
ssl:send(Q, <<"HTTP/1.0 200 OK\r\n\r\nHello World\r\n">>),
ssl:close(Q)
end.
main(_) ->
ssl:start(),
{ok, P} = ssl:listen(443, [{certfile, "./aa.crt"}, {keyfile, "./aa.key"}, {ciphers, pfs_secure_ciphers()}, {versions, [tlsv1, 'tlsv1.1', 'tlsv1.2']}, {dhfile, "./dh4096.pem"}]),
accept(P),
receive
stop ->
ok
end.