Erlang SSL sockets example (ssl echo server & ssl client)

Today I decided to write about Erlang SSL module. It has very good documentation, but it is not so simple to find source code of a complete example in the Internet. So, I decided to publish one here in my blog.

Basically SSL sockets in Erlang are very similar to tcp sockets, but with its own particularities. You can read about Erlang TCP sockets in my previous article, if you have not done yet. You should also prepare SSL ceritificate, you can create self-signed SSL certificate or purchase it somewhere. For example you can get free SSL certificate from StartSSL, as I described in one of my previous articles.

Ok, let’s see how to establish a simple ssl connection (NOT THE MOST SECURE POSSIBLE IMPLEMENTATION!) between a client and a server. I will mention some security settings that one should pay attention little later here in my article.

So, here is the code of the server part:

-module(s).
-export([start/0, client/1, accept/1]).

start() ->
   ssl:start(),
   server(4000).

server(Port) ->
    {ok, LSocket} = ssl:listen(Port, [{certfile,"certificate.pem"}, {keyfile, "key.pem"}, {reuseaddr, true}, {active, false}]),
    spawn(fun() -> accept(LSocket) end).
    
accept(LSocket) ->
   {ok, Socket} = ssl:transport_accept(LSocket),
   Pid = spawn(fun() ->
        io:format("Connection accepted ~p~n", [Socket]),
        loop(Socket)
   end),
   ssl:controlling_process(Socket, Pid),
   accept(LSocket).

loop(Socket) ->
   ssl:setopts(Socket, [{active, once}]),
   receive
   {ssl,Sock, Data} ->
        io:format("Got packet: ~p~n", [Data]),
        ssl:send(Sock, Data),
        loop(Socket);
   {ssl_closed, Sock} ->
    	io:format("Closing socket: ~p~n", [Sock]);
   Error ->
        io:format("Error on socket: ~p~n", [Error])
   end.

I should notice the way how the socket mode is changed. Using other sockets we are using inets:setopts/2 function, but with ssl socket we have to use its own ssl:setopts/2 function.

As you might notice I have defined client/1 function for export, but code of this function is missed. I would like to separate it from the server code just to pay attentions that this is client code and was defined in the same module just for my own convenience. Here is the client function code:

client(N) ->
    {ok, Socket} = ssl:connect("localhost", 4000,  []),
    io:format("Client opened socket: ~p~n",[Socket]),
    ok = ssl:send(Socket, N),
    Value = receive
            {ssl,{sslsocket,new_ssl,_}, Data} ->
            	io:format("Client received: ~p~n",[Data])
            after 2000 ->
            	0
            end,
    ssl:close(Socket),
    Value.

I think there is no need to explain the code much, as Erlang has great documentation and main reason I am writing this article is that I wanted to publish complete and working code that simplifies learning and understanding of things.

Okay, now it is time to test everything we have. First of all lets compile the module and start the server:

$ erl
Eshell V5.8.5  (abort with ^G)
1> c(s).
{ok,s}
2> s:start().
<0.52.0>
Connection accepted {sslsocket,new_ssl,<0.54.0>}
Got packet: "Hello"
Closing socket: {sslsocket,new_ssl,<0.54.0>}

When the server is started we can send the packet to it and get a response, but do not forget to start ssl application via ssl:start().

$ erl
Eshell V5.8.5  (abort with ^G)
1> ssl:start().
ok
2> s:client("Hello").
Client opened socket: {sslsocket,new_ssl,<0.49.0>}
Client received: "Hello"
ok

As you can see messages arrived both sides. Now as I promissed above I am going to mention some possible security improvements. There are two options that you should pay attention - verify and depth

The verify option specifies how the peer should be verified:

  • 0 - Do not verify the peer,
  • 1 - Verify peer,
  • 2 - Verify peer, fail the verification if the peer has no certificate.

The depth option specifies the maximum length of the verification certificate chain. Depth = 0 means the peer certificate, depth = 1 the CA certificate, depth = 2 the next CA certificate etc. If the verification process does not find a trusted CA certificate within the maximum length, the verification fails.

Hope I have not missed anything important and article will be helpful for somebody. Let me know if I missed something or made some mistakes and follow my blog for more articles, hope they will be interesting.

Posted by:
Enjoyed this post? Share and Leave a comment below, thanks! :)