{active, N} mode in erlang secure tcp - ssl

I write this simple code with ssltcp:
ssl:start().
{ok, ListenSocket} = ssl:listen(9999, [{certfile, "cert.pem"}, {keyfile, "key.pem"},{reuseaddr, true}]).
{ok, Socket} = ssl:transport_accept(ListenSocket).
ssl:ssl_accept(Socket).
ssl:setopts(Socket, [{active, once}]).
it works fine but when i replace {active, once} with {active, 3}, returns this error:
{error,{options,{socket_options,{active,3}}}}
How can use {active, N} mode in secure tcp?

The {active,N} mode is not implemented for SSL connections. I originally wrote the {active,N} mode and when I looked into possibly implementing it for SSL, I found that the way Erlang SSL sockets are implemented over the top of underlying TCP sockets involves changes on those sockets between active and passive modes as part of the protocol implementation, and so implementing {active,N} for SSL is not simply a matter of opening an underlying socket in that mode.

Related

What TLS/SSL protocol is in use when using tls_client_method?

I have the following source to connect websocket server using TLS/SSL protocol :
struct sessionTLS {
int sid;
SSL_CTX *ctx;
SSL *ssl;
};
sessionTLS tls ;
tls.ctx = SSL_CTX_new(TLS_client_method());
According to libressl manual : https://man.openbsd.org/SSL_CTX_new.3
TLS_method(), TLS_server_method(), TLS_client_method()
These are the general-purpose version-flexible SSL/TLS methods.
The actual protocol version used will be negotiated to the highest version
mutually supported by the client and the server. The supported protocols are
TLSv1, TLSv1.1, TLSv1.2, and TLSv1.3. Applications should use these methods
and avoid the version-specific methods described below.
Then I like to know how to know the actual protocol is ?! after negotiation done between server and client , there should be some messages showes like SSLV3 is the protocol, TLSV1 is the protocol, or else .
I am brand new in TLS/SSL, any suggestions, informations are great appreciated .

How to set TLS cipher for Go server?

I'm currently using the following listen and serve command to run a secure websocket/file server:
http.ListenAndServeTLS(":443", "site.crt","site.key", router)
However, I want to set the cipher to TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 and also set a min SSL/TLS version.
How can I do this?
I think I need to use this Config structure somehow, but I'm not sure how to do this.
2015: You can see an example in secrpc/tls_server.go:
tls.Listen("tcp", addr, &tls.Config{
Certificates: []tls.Certificate{cert},
CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
},
MinVersion: tls.VersionTLS12,
PreferServerCipherSuites: true,
})
See also go/issues/11047 for an example using ListenAndServeTLS: once you have defined your Config, you define your server:
server := &http.Server{Addr: ":4000", Handler: nil, TLSConfig: config}
server.L
In 2021, you also have "Automatic cipher suite ordering in crypto/tls" from Filippo Valsorda:
Go 1.17, recently released, takes over cipher suite preference ordering for all Go users.
While Config.CipherSuites still controls which TLS 1.0–1.2 cipher suites are enabled, it is not used for ordering, and Config.PreferServerCipherSuites is now ignored.
Instead, crypto/tls makes all ordering decisions, based on the available cipher suites, the local hardware, and the inferred remote hardware capabilities.

Installing an SSL certificate and running nitrogen webframe work over cowboy server over https

I am developing an application using nitrogen web framework over cowboy web server. When i run the server over http is works perfectly well. Now in production the application must run on https.
I have modified the cowboy.config file in the etc directory of nitrogen from default
% vim: ts=4 sw=4 et ft=erlang
[
{cowboy,[
{bind_address,"127.0.0.1"},
{port,80},
{server_name,nitrogen},
{document_root,"./site/static"},
%% some comments.........
{static_paths, ["/js/","/images/","/css/","/nitrogen/","/favicon.ico"]}
]}
].
to this one
% vim: ts=4 sw=4 et ft=erlang
[
{cowboy,[
{bind_address,"127.0.0.1"},
{port,443},
{server_name,nitrogen},
{cacertfile, "Path/cacert.pem"},
{certfile, "Path/webservercert.pem"},
{keyfile, "Path/webserverkey.pem"},
{password, "webserverkeypassphrase"}
{document_root,"./site/static"},
%% some comments.........
{static_paths, ["/js/","/images/","/css/","/nitrogen/","/favicon.ico"]}
]}
].
Where Path is the absolute path to the SSL certificate that I generated and signed it by myself using openSSL. I take my site name as domainname.com but i first create a CA following openSSl documentation
I also modified the Supervisor callbacks in the nitrogen_sup.erl file found in nitrogen/site/scr from the default
%% ===================================================================
%% Supervisor callbacks
%% ===================================================================
init([]) ->
%% Start the Process Registry...
application:start(crypto),
application:start(nprocreg),
application:start(ranch),
%% Start Cowboy...
application:start(cowboy),
{ok, BindAddress} = application:get_env(cowboy, bind_address),
{ok, Port} = application:get_env(cowboy, port),
{ok, ServerName} = application:get_env(cowboy, server_name),
{ok, DocRoot} = application:get_env(cowboy, document_root),
{ok, StaticPaths} = application:get_env(cowboy, static_paths),
io:format("Starting Cowboy Server (~s) on ~s:~p, root: '~s'~n",
[ServerName, BindAddress, Port, DocRoot]),
Dispatch = init_dispatch(DocRoot, StaticPaths),
{ok, _} = cowboy:start_http(http, 100,
[
{port, Port}
], [
{env, [{dispatch, Dispatch}]},
{max_keepalive, 50}
]),
{ok, { {one_for_one, 5, 10}, []} }.
to this one below
%% ===================================================================
%% Supervisor callbacks
%% ===================================================================
init([]) ->
%% Start the Process Registry...
application:start(crypto),
application:start(nprocreg),
application:start(ranch),
%% Start Cowboy...
application:start(cowboy),
{ok, BindAddress} = application:get_env(cowboy, bind_address),
{ok, Port} = application:get_env(cowboy, port),
{ok, ServerName} = application:get_env(cowboy, server_name),
{ok, DocRoot} = application:get_env(cowboy, document_root),
{ok, StaticPaths} = application:get_env(cowboy, static_paths),
{ok, CAcertfile} = application:get_env(cowboy, cacertfile),
{ok, Certfile} = application:get_env(cowboy, certfile),
{ok, Keyfile} = application:get_env(cowboy, keyfile),
{ok, Password} = application:get_env(cowboy, password),
io:format("Starting Cowboy Server (~s) on ~s:~p, root: '~s'~n",
[ServerName, BindAddress, Port, DocRoot]),
Dispatch = init_dispatch(DocRoot, StaticPaths),
{ok, _} = cowboy:start_https(https, 100,
[
{port, Port},
{cacertfile, CAcertfile},
{certfile, Certfile},
{keyfile, Keyfile},
{password, Password}
], [
{env, [{dispatch, Dispatch}]},
{max_keepalive, 50}
]),
{ok, { {one_for_one, 5, 10}, []} }.
Using sync:go() the file compiles and reloads. However i closed nitrogen and started it again.
in the shell I use the curl utility to test if the server is listening
$ curl --cacert Absolute_path/cacert.pem -i https://domainname.com
the response is posite as the contents on the index page are displayed in the shell
However, when i go to Firefox browser it throws a security warning which i admitted an except that i known its cause i permanently add to the exceptions. When I try getting the page again the browser throws this error.
Secure Connection Failed
The key does not support the requested operation.
(Error code: sec_error_invalid_key)
.The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.
.Please contact the website owners to inform them of this problem. Alternatively, use the command found in the help menu to report this broken site.
When i checked in the nitrogen console if found this error report
(nitrogen#127.0.0.1)4> user#user:~/nitrogen/rel/nitrogen$
user#user:~/nitrogen/rel/nitrogen$ sudo ./bin/nitrogen console
Exec: /home/user/nitrogen/rel/nitrogen/erts-5.10.4/bin/erlexec -boot /home/user/nitrogen/rel/nitrogen/releases/2.2.2/nitrogen -mode interactive -config /home/user/nitrogen/rel/nitrogen/etc/app.config -config /home/user/nitrogen/rel/nitrogen/etc/cowboy.config -config /home/user/nitrogen/rel/nitrogen/etc/sync.config -args_file /home/dotshule/nitrogen/rel/nitrogen/etc/vm.args -- console
Root: /home/dotshule/nitrogen/rel/nitrogen
Erlang R16B03 (erts-5.10.4) [source] [smp:2:2] [async-threads:5] [hipe] [kernel-poll:true]
Eshell V5.10.4 (abort with ^G)
(nitrogen#127.0.0.1)1> Starting Cowboy Server (nitrogen) on 127.0.0.1:443, root: './site/static'
=ERROR REPORT==== 20-Feb-2014::14:51:12 ===
SSL: certify: tls_connection.erl:375:Fatal error: unknown ca
Now what i do not understand is whether the server is the one refusing my certificate or i have skipped a step, or one or two steps have gone wrong or the problem is on my self created CA (root certificate cacert.pem) or the problem is on openSSL!
I have now become suspicious that may be if i generate my CSR and send it to the trusted CA such as symantec, digcert, thawte, geotrust, ..etc. the resulting certificate may also fail to work.
I need your help please on this https of nitrogen over cowboy webserver issue. Thaks for all your help so far....
I'm not sure why cowboy would be throwing that particular error (tls_connection.erl is actually a part of Erlang, rather than Cowboy or Nitrogen).
That said, when it comes to running SSL with Nitrogen, I usually just recommend to users to use nginx as a reverse proxy in front of Nitrogen, and there are nginx configuration examples on the Nitrogen site at http://nitrogenproject.com/doc/config.html (scroll down to SSL-only example).
I realize that's not exactly ideal, so alternatively, I'd see if nginx or apache are able to successfully serve sample pages with the same key/cert combos. Obviously, the "unknown ca" error is saying that Erlang doesn't like the fact that it's a self-signed certificate. So you could experiment with using other signed certs/keys you may have lying around, or generate a real one for free at StartSSL.com and see if the error continues presenting itself.
Again, none of these are solid answers, but they should help point you in a number of directions to help solving your problems.
Personally, I run all my Nitrogen instances behind nginx and let nginx deal with the SSL and load-balancing.
My methodology actually works, I have successfully tested it using SYMANTEC and VERISIGN SSL certificates and it could be a formal way of installing SSL certificates on Cowboy web server.

Looking for a simple ssl erlang example

In the book Erlang Programming one of the exercises proposed was to print on screen the request coming from a browser using gen_tcp. I made it for http requests as follows:
-module(tcp).
-export([server/0, wait_connect/2]).
server() ->
{ok, ListenSocket} = gen_tcp:listen(1234, [binary, {active, false}]),
wait_connect(ListenSocket,0).
wait_connect(ListenSocket, Count) ->
{ok, Socket} = gen_tcp:accept(ListenSocket),
spawn(?MODULE, wait_connect, [ListenSocket, Count+1]),
get_request(Socket, [], Count).
get_request(Socket, BinaryList, Count) ->
Request = gen_tcp:recv(Socket, 0),
io:format("~p~n", [Request]).
Now I am wondering how this can be done in case of https request. Can you provide a very simple example, or point me to some resource on books or online?
Here is the user guide for Erlang SSL application:
Erlang -- SSL User Guide
The guide contains also, in the API chapter, a paragraph on updating existing connections to SSL.
Regarding your code, you should do something like:
on server and client side you have to issue:
ssl:start()
server side: handshake SSL (remember to set 'active' to false for the listening socket)
{ok, SSLSocket} = ssl:ssl_accept(Socket, [{cacertfile, "cacerts.pem"},
{certfile, "cert.pem"}, {keyfile, "key.pem"}]).
where "cacerts.pem", "cert.pem", "key.pem" are files related to SSL certification
client side: upgrade connection to SSL:
{ok, SSLSocket} = ssl:connect(Socket, [{cacertfile, "cacerts.pem"},
{certfile, "cert.pem"}, {keyfile, "key.pem"}], infinity).
As per documentation, now SSLSocket is a ssl channel that can be used to send messages like:
ssl:send(SSLSocket, "foo").
Hope this helps!
I would suggest to read the following article about SSL sockets in Erang that contains complete code of the SSL echo server and client.
Erlang SSL sockets example - ssl server & client)

How to set keepalive option for induvidual socket in VxWorks

Is there any way to set keepalive for induvidual socket descriptor in vxworks? I read in some documents that "SOL_TCP" option in setsockopt function will do such favors in linux. Is such facility available in VxWorks too? If so please provide related details regarding the same, like what are the include file we need to include and how to use such option etc.
From the VxWorks "Library Reference" manual (can be download):
OPTIONS FOR STREAM SOCKETS
The following sections discuss the socket options available for stream (TCP) sockets.
SO_KEEPALIVE -- Detecting a Dead Connection
Specify the SO_KEEPALIVE option to make the transport protocol (TCP) initiate a timer to detect a dead connection:
setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof (optval));
This prevents an application from hanging on an invalid connection. The value at optval for this option is an integer (type int), either 1 (on) or 0 (off).
The integrity of a connection is verified by transmitting zero-length TCP segments triggered by a timer, to force a response from a peer node. If the peer does not respond after repeated transmissions of the KEEPALIVE segments, the connection is dropped, all protocol data structures are reclaimed, and processes sleeping on the connection are awakened with an ETIMEDOUT error.
The ETIMEDOUT timeout can happen in two ways. If the connection is not yet established, the KEEPALIVE timer expires after idling for TCPTV_KEEP_INIT. If the connection is established, the KEEPALIVE timer starts up when there is no traffic for TCPTV_KEEP_IDLE. If no response is received from the peer after sending the KEEPALIVE segment TCPTV_KEEPCNT times with interval TCPTV_KEEPINTVL, TCP assumes that the connection is invalid. The parameters TCPTV_KEEP_INIT, TCPTV_KEEP_IDLE, TCPTV_KEEPCNT, and TCPTV_KEEPINTVL are defined in the file target/h/net/tcp_timer.h.
IP_TCP_KEEPINTVL and also TCP_KEEPIDLE, TCP_KEEPCNT options supported by setsockopt after vxworks 6.8 version. In former releases of vxworks you can change these values globally and all the sockets created effected.
Below question is an answer for how will it be done.
How to set TCP keep alive interval for a specific socket fd (Not system wide) in VxWorks?