如何确保使用ssl发送消息

时间:2012-08-30 15:10:31

标签: erlang

我正在实现一个gen_server,它作为ssl身份验证服务器的接口。如果收到的数据包错误(例如用户名和密码错误),则ssl服务器会断开连接。连接必须是持久的。

在我的gen_server中,我使用handle_cast / 2打开服务器的ssl连接:

 handle_cast(connect, State) ->
    ......
    case ssl:connect(Address, Port, Options, Timeout) of
        {ok, NewSocket} ->
           {noreply, State#state{socket=NewSocket}};
        {error, Reason} ->
           gen_server:cast(?SERVER, connect),
           {noreply, State#state{socket=undefined}};

然后我等待handle_cast / 2中的其他消息,例如可以使用:

发送
 gen_server:cast(Pid, {authenticate, User, Password}).

每当我收到这样的强制转换消息时,我会生成一个新函数,它使用gen_server:call / 3从服务器状态恢复SSL套接字,并将验证消息发送到SSL服务器。如果发送部分返回错误,我尝试重新连接,否则我在套接字上读了一会儿,以确保套接字没有关闭,如果是,我重新连接。

send_auth(_, _, 0) ->
    {error, max_num_reached}; 

send_auth(User, Password, Num) ->
    Socket = gen_server:call(?SERVER, socket),
    %% also a check that socket is not 'undefined'
    case ssl:send(Socket, AuthMessage) of
      ok ->
          case ssl:recv(Socket, 0, 2000) of
            {error, timeout} ->
                ok;
            _ ->
                gen_server:cast(?SERVER, connect),
                send_auth(User, Password, Num-1)
          end,
      {error, closed} ->
          gen_server:cast(?SERVER, connect),
          send_auth(User, Password, Num-1)
    end.

我做了很多测试,但每次,如果一条消息(不是最后一条消息)出错,则实际上不会传递以下消息。

如何授予所有有效的身份验证消息都传递到身份验证服务器?此外,只有在服务器尚未尝试连接的情况下才能确定服务器是否可以连接?否则就像DOS攻击一样!

1 个答案:

答案 0 :(得分:0)

  1. 据我所知,系统中只有一个身份验证服务器,为什么你不能在 gen_server 的init中连接到它?如果连接有些可靠,如果连接出现任何问题,可以直接杀死 gen_server ,让主管重新启动它。它可能会解决你的DOS问题。
  2. 当您使用 send_auth 生成其他进程时,您只需在参数中传递套接字连接,而不是执行gen_server调用。
  3. 为了保证交付,您需要在协议中添加某种确认。验证服务器应回复 send_auth ,并确认收到它。并且 send_auth 应该重试,直到它收到该确认或具有其他一些后备行为,以防万一。
相关问题