SSL in Erlang/OTP

Peter H|gfeldt peter@REDACTED
Wed Nov 26 21:10:11 CET 2003


Yes, I agree that ssl:recv/x and ssl:send/x should behave as
gen_tcp:recv/x and gen_tcp:send/x do. 

I will add that request to the todo-list for the next release.

I also agree that there should be some kind of "pre_accept" that
returns a "raw" non-SSL socket, to be closed on reasons you have
mentioned (although I think a firewall is the proper agent for
denying attacks). 

I will add that request to the todo-list.

With a "pre_accept" and a "post_accept" that does SSL handshaking, it is
natural to add also a "pre_connect" and a corresponding "post_connect".
That will achieve your request for a "STARTTTLS"  command (there must of
course be a well-defined protocol on top for this). 

I will add that to the todo-list. 

/Peter

   
> Hello, Peter!
> 
> On Wed, 19 Nov 2003 20:37:35 +0100 (MET), you said:
> 
>  >> Can anyone help with following issues with SSL application?
>  >> 
>  >> * ssl:accept locks when when one TCP connection is established, but SSL
>  >> handshake is not finished.  E.g. if Yaws is listen for SSL connections on
>  >> port 443 and someone runs "telnet this.server 443" (note that this is not
>  >> SSL-enabled telnet), then noone will be able to retreive web pages via this
>  >> port until this connection will be closed.  As temporary solution I use
>  >> ssl:accept with small timeout value, but this is just workaround.  IMHO
>  >> ssl:accept should not have such behaviour.
> 
>  PH> In Erlang/OTP SSL you can have several processes, each waiting for an
>  PH> ssl:accept/N on one and the the same port. That is needed to obtain
>  PH> acceptable (no pun intended) parallellism.
> 
> I.e. I need to run several such processess?:
> 
> accept(ListenSocket, Opts) ->
>     case ssl:accept(ListenSocket) of
> 	{ok, Socket} ->
>             % Start new process for Socket
> 	    accept(ListenSocket, Opts);
> 	{error, Reason} -> ...
>     end.
> 
> But even if I run e.g. 1000 such parallell accepts, malicious user still can
> open 1000 connections with the way I describe above (with ssl:accept locking),
> which will make service unaccessible for other users.
> 
> So IMHO ssl:accept should return immediately after TCP connection to listened
> port will be established with new socket in "handshaking" state.  In this state
> must be possible to know sockname (e.g. to prevent many conections from one
> host), and data sended with ssl:send will be writed to queue, which will be
> sended after handshaking.
> 
>  PH> That it not practically possible with gen_tcp:accept/N (if you try it you
>  PH> will get an error return). I think gen_tcp should accept multiple accepts
>  PH> as well.
> 
>  >> * ssl:send locks if another process runs ssl:recv on the same port.  And I
>  >> can't use "{active, true}" option, because I need flow control.  Again, as
>  >> a temporary solution I use timeout value in ssl:recv/3, so ssl:send can
>  >> work several times in second.  But this makes notable increase of CPU load:
>  >> e.g. with ejabberd on jabber.ru (~440 connected users, ~100 using SSL) with
>  >> 20ms timeout -- CPU load is ~40%, with 200ms -- 9-12%, with SSL switched
>  >> off -- 3-4%.
> 
>  PH> When an SSL-connection has been established all data flow through gen_tcp
>  PH> to/from the SSL portprogram, which is then just a multiplexer of data
>  PH> (slow connections will not impair fast connections).
> 
>  PH> Seems as if your problem is really a gen_tcp problem?
> 
> I think this is ssl_broker problem, look:
> 
> %% recv - passive mode
> %%
> handle_call({recv, Client, Length, Timeout}, From, St) 
>   when St#st.status =/= closed, St#st.active == false ->
>     debug(St, "recv: client = ~w~n", [Client]),
>     Reply = gen_tcp:recv(St#st.proxysock, Length, Timeout),
>     {reply, Reply, St};
> 
> (This is part of ssl_broker.erl from R8B, but R9C do almost the same)
> 
> After ssl:recv call, appropriate ssl_broker process hangs inside gen_tcp:recv,
> and can't process other requests (including ssl:send).  It seems this can be
> solved by moving gen_tcp:recv call to another process...  What about something
> like this:
> 
> recv(Socket, Length, Timeout) when record(Socket, sslsocket) ->
>     Req = {recv, self()}, 
>     ProxySock = gen_server:call(Socket#sslsocket.pid, Req, infinity),
>     case gen_tcp:recv(St#st.proxysock, Length, Timeout) of
>         {ok, _} = Result -> Result;
>         {error, timeout} -> {error, timeout};
>         {error, Reason} = Error ->
>             gen_server:call(Socket#sslsocket.pid, {switch to closing state}, infinity),
>             Error
>     end.
> 
> handle_call({recv, Client}, From, St) 
>   when St#st.status =/= closed, St#st.active == false ->
>     debug(St, "recv: client = ~w~n", [Client]),
>     Reply = St#st.proxysock,
>     {reply, Reply, St};
> 
> I.e. gen_tcp:recv will be executed in process that calls ssl:recv.
> 
>  >> * (Feature Request) Many protocols have some kinds of STARTTLS command
>  >> (e.g. IMAP, POP3 (RFC2595), Jabber/XMPP).  So this would be great to have
>  >> ability to convert gen_tcp sockets to ssl ones.
> 
>  PH> Ok, I am not familiar with STARTTLS or similar, but I will investigate it.
> 
> Thanks!
> 




More information about the erlang-questions mailing list