Search code examples
sslhttpserlangyaws

Yaws webserver running via HTTP but not via HTTPS


I have a yaws webserver. I'm trying to connect via https in local network. When I setup my server in yaws.conf for http, as follows, all works fine when I connect via http://0.0.0.0:80/myappmod in browser

<server *:80>
    port = 80
    listen = 0.0.0.0
    docroot = /home/anyuser/anydir/
    auth_log = true
    appmods = </, myappmod>
</server>

But the following config (with ssl) does not: (I connect via https://0.0.0.0:443/myappmod)

<server mydomain.com>
    port = 443
    docroot = /home/anyuser/anydir/
    listen = 0.0.0.0
    dir_listings = true
    auth_log = true
    appmods = </, myappmod> 
    <ssl>  
        keyfile = /home/anyuser/private-key.pem
        certfile = /home/anyuser/cert_by_ca.pem
        depth = 0
    </ssl>
</server>

The certificate is officially issued by certificate authority and generally works for other webservers under "mydomain.com". private-key format is this

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7WBJR0YV9bq4P
...
CAy+LaJpyW/b2vQ+He7t/rg=
-----END PRIVATE KEY-----

And .crt file is of this format:

-----BEGIN CERTIFICATE-----
MIIGgjCCBWqgAwIBAgIIZiCEI/Q/x7gwDQYJKoZIhvcNAQELBQAwgbQxCzAJBgNV
...
1CtNn+5v4lBpgzWS0ZSv5xkeskHjzXnRbjl7jzbkwUdseCZHwXc=
-----END CERTIFICATE-----

When I'm trying to connect, I get ERR_CONNECTION_RESET in Chrome and PR_END_OF_FILE_ERROR in firefox. What am I doing wrong? I can't find any more infos on the config in the official yaws docs. Can someone help please?

EDIT:

trace.log output from curl -v -k --trace-ascii trace.log https://0.0.0.0:443/:

== Info:   Trying 0.0.0.0:443...
== Info: Connected to 0.0.0.0 (127.0.0.1) port 443 (#0)
== Info: ALPN, offering h2
== Info: ALPN, offering http/1.1
== Info: TLSv1.0 (OUT), TLS header, Certificate Status (22):
=> Send SSL data, 5 bytes (0x5)
0000: .....
== Info: TLSv1.3 (OUT), TLS handshake, Client hello (1):
=> Send SSL data, 512 bytes (0x200)
0000: .......w.`0V;k.z;7...}1..Y..5.;..WjO.. .4.,30.....L.......3.../.
0040: ..Y.....>.......,.0.........+./...$.(.k.#.'.g.....9.....3.....=.
0080: <.5./.....u..................................3t.........h2.http/
00c0: 1.1.........1.....*.(.........................................+.
0100: .......-.....3.&.$... ....d>..xlz#..H.V...|.R.s.k.t..r..........
0140: ................................................................
0180: ................................................................
01c0: ................................................................
== Info: OpenSSL SSL_connect: Die Verbindung wurde vom Kommunikationspartner zurückgesetzt in connection to 0.0.0.0:443 
== Info: Closing connection 0
== Info: TLSv1.3 (OUT), TLS alert, decode error (562):
=> Send SSL data, 2 bytes (0x2)
0000: .2

EDIT2: Die Verbindung wurde vom Kommunikationspartner zurückgesetzt means: The connection was reset by the communication partner in English.

Is the decode error (562) due to invalid cert-file encoding? I must admid, that I got 2 files from godaddy.com: One .pem and one .crt file. Their contents looked identically to me. Content is as posted above.(I used the .pem file in yaws.conf). The key-file I am using is the output I copied from the cert sign request on godaddy.com. (Just copied it from their Web-TextBox and pasted it into a .txt file on ubuntu).

EDIT3:

openssl s_client -connect mydomain.com:443 (dns works for http//mydomain.de:80) gives me:

CONNECTED(00000003)
write:errno=104
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 310 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---

EDIT4:

So I produced some more output. First I verified, that my certificate is ok. Therefore I made an openssl-client and server the following way:

openssl s_server -accept 8443 -cert /etc/mydomain.pem -key /etc/mydomain.key -CAfile /etc/gd_bundle-g2-g1.crt

openssl s_client -connect localhost:8443 -cert /etc/mydomain.pem -key /etc/mydomain.key -CAfile /etc/gd_bundle-g2-g1.crt -verify 8 -verify_hostname mydomain.de

Which results in a successful handshake:

... Certificate and other data I do not want to post and:

SSL handshake has read 5658 bytes and written 373 bytes
Verification: OK
Verified peername: mydomain.de

... more data

Then I setup one http and one http server using the following config file. I further assured .pem and .key file can be accessible by yaws with chmod +777 (I know this is bad but I just wanted to be sure). Then I started the yaws server (with root priviliges, which I know is evil too, but until I figured out how to bind to priviliged ports as non-root, I go with that just for testing)

logdir = /var/log/yaws
ebin_dir = /usr/local/lib/yaws-appmods/ebin
include_dir = /usr/local/lib/yaws-appmods/include
max_connections = nolimit
keepalive_maxuses = nolimit
process_options = "[]"
acceptor_pool_size = 8
trace = false
use_old_ssl = false
copy_error_log = true
log_wrap_size = 0
log_resolve_hostname = false
fail_on_bind_err = true
pick_first_virthost_on_nomatch = false
keepalive_timeout = 30000
sni = enable

<server mydomain.de>
    port = 80
    listen = 192.168.178.75
    docroot = /home/my_non_root_user/my_appmod/
    auth_log = true
    appmods = </, my_appmod>
</server>


<server mydomain.de>
    port = 443
    docroot = /home/my_non_root_user/my_appmod/
    listen = 192.168.178.75
    dir_listings = true
    auth_log = true
    appmods = </, my_appmod>    
    <ssl>  
        keyfile = /etc/mydomain.key
        certfile = /etc/mydomain.pem
        depth = 0
    </ssl>
</server>

I also tried providing the ca-bundle, setting higher depths, and played with some other parameters, but all to no success. I got the same error as described above. In the following yaws output, one only can see that http is working. When I try to connect via https, there is no output produced. No worker, etc. I am very new to yaws and webservers in general. I like erlang very much, and just wanted to have a small webserver for my own. No production ready, sophisticated solution. I guess I did something wrong in my config file or have just incomplete knowledge about the whole webserver concept.

1> =INFO REPORT==== 30-Jan-2022::21:16:55.826108 ===
Yaws: Using config file /etc/yaws/yaws.conf

=ERROR REPORT==== 30-Jan-2022::21:16:55.839289 ===
use_old_ssl in yaws.conf is no longer supported - ignoring

=INFO REPORT==== 30-Jan-2022::21:16:55.904479 ===
yaws debug:Add path "/usr/local/lib/yaws-appmods/ebin"

=INFO REPORT==== 30-Jan-2022::21:16:55.906202 ===
yaws debug:Add path "/usr/lib/yaws/examples/ebin"

=INFO REPORT==== 30-Jan-2022::21:16:55.906272 ===
yaws debug:Running with id="default" 
Running with debug checks turned on (slower server) 
Logging to directory "/var/log/yaws"

=INFO REPORT==== 30-Jan-2022::21:16:55.911016 ===
Ctlfile : /root/.yaws/yaws/default/CTL

=INFO REPORT==== 30-Jan-2022::21:16:55.911698 ===
sync call startup:start 

ENSURE SSL: {ok,[]}

=INFO REPORT==== 30-Jan-2022::21:16:56.045817 ===
Trace directory "/var/log/yaws/trace_20220130_211656" created

=INFO REPORT==== 30-Jan-2022::21:16:56.055200 ===
Yaws: Listening to 192.168.178.75:443 for <1> virtual servers:
 - https://mydomain.de under /home/my_non_root_user/my_appmod

=INFO REPORT==== 30-Jan-2022::21:16:56.055388 ===
Yaws: Listening to 192.168.178.75:80 for <1> virtual servers:
 - http://mydomain.de under /home/my_non_root_user/my_appmod

Worker: <0.194.0> 
[2022-01-30 21:17:15.987] ===== CLI -> SRV =====
New (nossl) connection from 80.*.*.*:57260                // * are manually hidden numbers for stackoverflow post

Worker: <0.200.0> 
[2022-01-30 21:17:15.987] ===== CLI -> SRV =====
New (nossl) connection from 80.*.*.*:57262                // here too

Worker: <0.200.0> 
[2022-01-30 21:17:15.994] ===== CLI -> SRV =====
GET / HTTP/1.1
Connection: keep-alive
Accept: text/html, application/xhtml+xml, application/xml;q=0.9, image/avif, image/webp, image/apng, */*;q=0.8, application/signed-exchange;v=b3;q=0.9
Host: mydomain.de
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
Cookie: pvisitor=cc2529f0-abf8-4e78-80d2-85908b25f227
Accept-Language: en-US,en;q=0.9,de-DE;q=0.8,de;q=0.7
Accept-Encoding: gzip, deflate
Upgrade-Insecure-Requests: 1


Worker: <0.200.0> 
[2022-01-30 21:17:15.996] ===== SRV -> CLI =====
HTTP/1.1 200 OK
Server: Yaws 2.1.0
Date: Sun, 30 Jan 2022 20:17:15 GMT
Content-Length: 46
Content-Type: text/html


Worker: <0.200.0> 
[2022-01-30 21:17:16.203] ===== CLI -> SRV =====
Connection: keep-alive
Accept: image/avif, image/webp, image/apng, image/svg+xml, image/*, */*;q=0.8
Host: mydomain.de
Referer: http://mydomain.de/
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
Cookie: pvisitor=cc2529f0-abf8-4e78-80d2-85908b25f227
Accept-Language: en-US,en;q=0.9,de-DE;q=0.8,de;q=0.7
Accept-Encoding: gzip, deflate


Worker: <0.200.0> 
[2022-01-30 21:17:16.203] ===== SRV -> CLI =====
HTTP/1.1 405 Method Not Allowed
Server: Yaws 2.1.0
Date: Sun, 30 Jan 2022 20:17:16 GMT
Content-Length: 0
Content-Type: text/html

Solution

  • In your yaws.conf file, your keyfile parameter in the <ssl> block refers to a file with a .key suffix. According to the Erlang ssl module man page, that file should instead be in PEM format (i.e., a .pem file).

    • The ssl man page says if you leave out the keyfile parameter, it defaults to the same as certfile, so you could try dropping keyfile from your yaws.conf file to see if that helps.
    • If that doesn't work, you likely need to convert the .key file to a .pem file; this answer describes how to do it.