processone / eturnal

STUN / TURN standalone server
https://eturnal.net
Apache License 2.0
225 stars 22 forks source link

TLS example #32

Closed matiaslopezd closed 1 year ago

matiaslopezd commented 1 year ago

Hi @weiss! Thanks for this awesome TURN server with a wonderful YAML setup file. 🤗

I've some doubts about how to setup correctly the TLS. I'm using certbot to generate certificates and expose ports 80 and 443 (TLS) both UDP/TCP.

To avoid the read permission I used a script that copies the .pem files and changes the ownership to the eturnal user, using the --deploy-hook (certbot). This script (after copying and changing the ownership) reloads the configuration with eturnalctl reload.

Also, I ensure to open ports 80 and 443.

Considering the above scenario do you know why I can’t get rflx ICE candidates (tested on trickle ICE test page)

This only happens when I setup to work over TLS.

I'm very happy to share an example config with TLS when discover why can't get rflx candidates 😩

matiaslopezd commented 1 year ago

Update:

I'm only getting candidates from port 80/UDP no TLS.

ufw rules:

443/tcp                    ALLOW       Anywhere                  
443/udp                    ALLOW       Anywhere                  
80/udp                     ALLOW       Anywhere                  
80/tcp                     ALLOW       Anywhere                  
49152:65535/tcp            ALLOW       Anywhere                  
49152:65535/udp            ALLOW       Anywhere     
443/tcp (v6)               ALLOW       Anywhere (v6)             
443/udp (v6)               ALLOW       Anywhere (v6)             
80/udp (v6)                ALLOW       Anywhere (v6)             
80/tcp (v6)                ALLOW       Anywhere (v6)             
49152:65535/tcp (v6)       ALLOW       Anywhere (v6)             
49152:65535/udp (v6)       ALLOW       Anywhere (v6)
matiaslopezd commented 1 year ago

My bad! Sorry! Works perfectly!

I made a typo mistake testing with turn:my-server.com:443?transport=tcp the error was that the SRV turn needs to be turns using port 443. 😭

I suggest adding a human-readable error when the TLS files don't have read permissions for the eturnal user. Because it currently prints the error: erl_call: failed to connect to node with address "127.0.0.1:3470"

weiss commented 1 year ago

Works perfectly!

Glad to hear that!

I suggest adding a human-readable error when the TLS files don't have read permissions for the eturnal user. Because it currently prints the error: erl_call: failed to connect to node with address "127.0.0.1:3470"

Looks like some weird issue with the communication between eturnalctl and the running eturnal instance. "Weird" because that case is supposed to yield a different message (Node is not running!). I can't reproduce the problem by changing permissions of PEM files, if they aren't readable I see a proper error message on startup:

[critical] Failed to load configuration from /etc/eturnal.yml: Invalid value of parameter 'eturnal->tls_crt_file': Failed to read file '/etc/eturnal/certificate.pem': permission denied

Any idea how I could try to reproduce the issue?

matiaslopezd commented 1 year ago

Yes, @weiss! Try to change them to an invalid path like etc/eturnal/ts/cert.pem instead /etc/eturnal/tls/cert.pem them reload the service with (APT linux-based) service eturnal restart. The eturnalctl restart send the command but does not wait for the exit code, so if you use eturnalctl check the status service eturnal status.

I take advantage of asking, using the eturnalctl reload when updating de TLS files on YAML needs to reload the service?

weiss commented 1 year ago

Thanks. I'm still not able to reproduce the problem when using eturnalctl foreground (directly or via systemd):

# service eturnal restart
Job for eturnal.service failed because the control process exited with error code.
See "systemctl status eturnal.service" and "journalctl -xe" for details.
# journalctl -q --no-hostname -n 9 -u eturnal
Sep 15 12:06:20 systemd[1]: Stopped eturnal STUN/TURN server.
Sep 15 12:06:20 systemd[1]: Starting eturnal STUN/TURN server...
Sep 15 12:06:20 eturnalctl[5160]: Exec: /opt/eturnal/erts-13.0.3/bin/erlexec -noinput +Bd -boot /opt/eturnal/releases/1.10.1+25/start -mode embedded -boot_var SYSTEM_LIB_DIR /opt/eturnal/lib -config /opt/eturnal/releases/1.10.1+25/sys.config -args_file /o
Sep 15 12:06:20 eturnalctl[5160]: Root: /opt/eturnal
Sep 15 12:06:20 eturnalctl[5160]: /opt/eturnal
Sep 15 12:06:20 eturnalctl[5160]: [critical] Failed to load configuration from /etc/eturnal.yml: Invalid value of parameter 'eturnal->tls_crt_file': Failed to read file '/etc/eturnal/ts/cert.pem': no such file or directory
Sep 15 12:06:20 systemd[1]: eturnal.service: Main process exited, code=exited, status=1/FAILURE
Sep 15 12:06:20 systemd[1]: eturnal.service: Failed with result 'exit-code'.
Sep 15 12:06:20 systemd[1]: Failed to start eturnal STUN/TURN server.

But!

eturnalctl restart

Yes, I do see the problem when using that command: This does special Erlang magic to restart the service without actually restarting the VM process, which fails if the VM process isn't running in the first place. So if you edit your configuration to point to an unreadable PEM file and then perform the following sequence of commands:

  1. eturnalctl restart
  2. eturnalctl restart

… then the first restart will fail due to the invalid configuration, and (this is the real problem) there's unfortunately no way to report this back to the eturnalctl caller. The actual eturnal process will exit != 0 and produce the proper error message I've shown above, which is printed to the standard output if eturnal was started in the foreground (e.g., via systemd), or is logged to e.g. /var/log/eturnal/erlang.log.* if eturnal was started via eturnalctl daemon. Either way, the second restart invocation then fails to contact a running eturnal instance since it's dead, and in that case, the error message you've shown is expected indeed.

Are you using our init script rather than systemd to control the service? I guess we should modify that script to avoid eturnalctl restart due to the possibility of silent failure, and to just use eturnalctl stop && eturnalctl daemon instead.

Just by the way, using eturnalctl reload would avoid the problem. That command would exit != 0 and print a proper error message. The eturnal instance would log the issue and refuse to reload the configuration.

using the eturnalctl reload when updating de TLS files on YAML needs to reload the service?

It reopens the listen sockets, which isn't strictly necessary but keeps things simple and doesn't hurt. Running TURN sessions aren't affected by a reload.

matiaslopezd commented 1 year ago

@weiss I'm using the systemd to control the service. I installed it on Ubuntu 22 TLS.

So if I'm understanding correctly, is possible to execute eturnaltcl reload without restarting the VM and disconnecting TURN sessions?

I think based on the issue to ensure the YAML file is properly configurated would be great to add the -t Nginx-like command. eturnalctl -t to verify the YAML it's ok.

Finally, I want to contribute with production-ready docs using OS installation or docker setup + TLS, but following best practices in terms of security. What concerns do I need to have using docker?

Thanks!

weiss commented 1 year ago

@weiss I'm using the systemd to control the service.

Ok but systemctl restart eturnal would not use eturnalctl restart, you should see the output I've shown above.

So if I'm understanding correctly, is possible to execute eturnaltcl reload without restarting the VM and disconnecting TURN sessions?

Yes. (systemctl reload eturnal would do the same thing.)

I think based on the issue to ensure the YAML file is properly configurated would be great to add the -t Nginx-like command. eturnalctl -t to verify the YAML it's ok.

Yes I was thinking about that before, just not as trivial to implement as you'd think. I'd hope in practice, eturnalctl reload would do the trick: If the new config is fine it's applied, if it isn't it's ignored and a helpful error message is returned/logged.

Finally, I want to contribute with production-ready docs using OS installation or docker setup + TLS, but following best practices in terms of security. What concerns do I need to have using docker?

The existing documentation mentiones how to run the container with minimal privileges. If you see stuff missing from those docs, feel free to open another issue.

Thanks for your feedback!