TLS/SSL/DTLS OpenSSL/BoringSSL-based NIF library for Erlang using the same interface as erlang ssl
module.
This module contains interface functions for the SSL/TLS protocol.
At this moment not all methods available in ssl
module are implemented and also not all ssl_option
are supported.
The library is implemented in top of gen_tcp
and OpenSSL
API. Because SSL_*
API is not thread safe in order to make sure
that all calls for the same socket are not executed concurrently each socket has a gen_server to interact with native layer.
This way we don't have to use any kind of locking at native level. Also read/write operations are not taking place in the
gen_server
process, they take place in calling process, in order to avoid gen_server to become a bottleneck for the socket.
- DTLS support (both v1 and v1.2)
- RFC5077 for resuming sessions using ticketing
- Can be used with both OpenSSL or BoringSSL
The library is working with both OpenSSL or BoringSSL. Be default BoringSSL is used. To change the behavior you need to specify the
USE_BORINGSSL
environment variable:
USE_BORINGSSL=0 rebar compile
Add erltls
as a rebar dependency to your project:
{deps, [
{erltls, ".*", {git, "https://github.com/silviucpp/erltls.git", "master"}},
}.
Now you can use erltls
module the same way you are using ssl
:
%% server side
erltls:start(),
{ok, ListenSocket} = erltls:listen(9999, [
{certfile, "test/server.pem"},
{reuseaddr, true}
]),
{ok, Socket} = erltls:transport_accept(ListenSocket),
ok = erltls:ssl_accept(Socket),
ok = erltls:setopts(Socket, [{active, once}]),
receive AMessage -> io:format("recv:~p~n", [AMessage]) end,
ok = erltls:close(Socket),
ok = erltls:close(ListenSocket).
%% client side
erltls:start(),
{ok, Socket} = erltls:connect("localhost", 9999, [], infinity),
ok = erltls:send(Socket, "foo"),
ok = erltls:close(Socket).
erltls
can be easily used with ranch
by starting a listener with ranch_erltls
as the transport module:
{ok, _} = ranch:start_listener(tcp_echo, 100,
ranch_erltls, [{port, 5555}, {certfile, CertPath}],
echo_protocol, []).
Currently supported options also available in erlang ssl
:
{verify, verify_type()}
{depth, integer()}
{fail_if_no_peer_cert, boolean()}
{certfile, path()}
{keyfile, path()}
{password, string()}
{cacertfile, path()}
{dhfile, path()}
{ciphers, ciphers()}
Options currently related to erltls
only:
{use_session_ticket, boolean() | {boolean(), binary()}}
- Enables session reuse using tickets as described in RFC5077. In case the key is not specified the tickets will be signed using a random key. In order to specify the key use the format{true, <<"key_here">>}
.{reuse_sessions_ttl, integer()}
- The TTL of a session in seconds. In case the session is older than this TTL will not be possible to be reused. A full handshake will be negotiated.{protocol, protocol()}
- Specify the desired protocol. By default will negotiate highest available SSL/TLS version. Available protocols values are:sslv3 | tlsv1 | 'tlsv1.1' | 'tlsv1.2' | dtlsv1 | 'dtlsv1.2'
renegotiate/1
prf/5
negotiated_protocol/1
format_error/1
eccs/1
eccs/0
connection_information/2
session_reused/1
- Query, whether a reused session was negotiated during the handshake (make sense if session ticketing is enabled)
- working only with
{packet, 0}
inet option - Handshake process don't have a timeout implemented yet. So in
connect/*
orssl_accept/*
the timeout param is actually not counting the handshake process.
For benchmarks between different drivers see here