Erlang:使用SSL进行httpd

时间:2014-03-28 09:08:19

标签: ssl erlang inets

这是多么荒谬的设置是多么困难。我现在已经尝试了3天了。在互联网和本网站上寻求帮助,但没有任何效果。

我想要的是概念上的简单。我想要一个带有ssl的inets httpd服务器。让服务器启动并运行是没有问题的......无论如何都是非ssl。添加ssl时,它只是无法正常工作。

不要问什么错误,有多个错误,并且它们会根据我对配置所做的更改而改变。主要是它是一个浏览器错误,说证书没有授予执行此操作的权限,或者如果进行了更改,则会在erlang shell中发生一系列错误和进程崩溃。

我只想知道1)我需要什么样的证书,2)他们需要什么样的格式,以及3)在httpd服务器端,正是我需要的ssl配置选项。

没有类似Apache的配置或配置文件。我想要以编程方式进行配置选项。

如果有人可以帮忙解决这个问题,我会全力以赴。

2 个答案:

答案 0 :(得分:2)

使用Erlang R16B03,以下设置适用于我:

-module(inets_ssl).

-export([start/0]).

start() ->
  inets:start(),
  {ok, Pid} = inets:start(httpd, [
                                  {port, 22443},
                                  {server_name,"localhost"},
                                  {server_root,"./"},
                                  {document_root,"./"},
                                  {bind_address, any},
                                  {socket_type, {ssl, [{certfile, "./server.crt"}, 
                                                {keyfile, "./server.key"}]}},
                                  {mimetypes, [
                                               {"html", "text/html"}
                                              ]}
                                 ]),
  Pid.

可以使用以下命令生成cert(server.crt)和key(server.key)文件:

$ openssl genrsa -des3 -passout pass:x -out server.pass.key 2048
$ openssl rsa -passin pass:x -in server.pass.key -out server.key
$ openssl req -new -key server.key -out server.csr
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

取自https://devcenter.heroku.com/articles/ssl-certificate-self

假设index.html中存在document_root文件,则应该可以访问网址https://localhost:22443/index.html

答案 1 :(得分:0)

这对我使用 linux OTP 版本 22 和 windows OTP 版本 23 有用:

https://127.0.0.1:9999/db/api:get

当然我的证书没有签名(必须在 Firefox 中添加一个例外)并且在 Windows 中似乎我的连接刚刚重置。

然而 curl 对这两种情况都有效并且它设法建立了连接

curl -v -k https://127.0.0.1:9999/db/api:get

-module(api).
-export([start/0, get/3, main_handler/1]).

start() -> 
    try 
        inets:start(),
        ssl:start()
    catch 
        _ -> erlang:exit("Failed to start inets")
    end,

    case lists:member(main_handler_pid, registered()) of
        false -> 
            MainPid = spawn_link(api, main_handler, [0]),
            register(main_handler_pid, MainPid);
        _ -> ok
    end,
    try start_api_response() of 
        {State,Pid} -> erlang:display({State,Pid}),
        case State of 
        ok ->
            ok;
        _ -> 
            erlang:display(State)
        end
    catch 
         _:_ -> {"Error starting server"}
    end.


start_api_response() ->
    {State,Pid} = inets:start(httpd, [{port, 9999}, 
        {server_name, "localhost"}, 
        {socket_type, {ssl,[{certfile, "./cert.pem"}, {keyfile, "./key.pem"}]}},
        {document_root, "./"}, 
        {modules,[mod_esi,ssl,crypto]},
        {server_root, "./"}, 
        {bind_address, any},
         {mimetypes, [
                                               {"html", "text/html"}
                                              ]},
        {erl_script_alias, {"/db", [api,io]}}]),
    {State,Pid}.


main_handler(N) ->
    receive
        Pid -> 
            erlang:display("ping main: " ++ integer_to_list(N)),
            Pid ! N
    end,
    main_handler(N+1).

get(Sid, _Env, Input) ->
    main_handler_pid ! self(),
    erlang:display(Input),
    receive
        N -> 
            mod_esi:deliver(Sid, integer_to_list(N))
    end.

在我使用 127.0.0.1 而不是 localhost 并添加模块部分后它起作用了:

{modules,[mod_esi,ssl,crypto]}

之后我从服务器收到了一些 TLS 通知报告,它在 Windows 中似乎不起作用的原因是:

TLS server: In state hello at tls_record.erl:539 generated SERVER ALERT: Fatal - Unexpected Message
 - {unsupported_record_type,71}

我的小代码只是增加了一个计数器。

编辑:

ssl:cipher_suites(all,'tlsv1.3).

将可以通过网络浏览器执行获取命令,似乎它默认为旧的 tls 版本。

相关问题