Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfixes and config improvements #15

Merged
merged 6 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
env:
GF_SECURITY_ADMIN_PASSWORD: ${{ secrets.GF_SECURITY_ADMIN_PASSWORD }}
GF_SECURITY_ADMIN_USER: ${{ secrets.GF_SECURITY_ADMIN_USER }}
DOMAIN: ${{ secrets.DOMAIN }}
mickel8 marked this conversation as resolved.
Show resolved Hide resolved
REALM: ${{ secrets.DOMAIN }}
DIR_NAME: ${{ secrets.DIR_NAME }}
TAG: ${{ github.ref_name }}
with:
Expand All @@ -65,7 +65,7 @@ jobs:
rm -rf $DIR_NAME; mkdir $DIR_NAME
cd $DIR_NAME
git clone -b $TAG --depth 1 https://github.com/${{ github.repository }} .
echo "DOMAIN=$DOMAIN
echo "REALM=$REALM
GF_SECURITY_ADMIN_PASSWORD=$GF_SECURITY_ADMIN_PASSWORD
GF_SECURITY_ADMIN_USER=$GF_SECURITY_ADMIN_USER
TAG=${TAG#v}" > .env
Expand Down
32 changes: 23 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ mix run --no-halt
2. In Docker

```console
docker run ghcr.io/webrtc-elixir/rel:latest
docker run ghcr.io/elixir-webrtc/rel:latest
```

## Features and configuration
Expand Down Expand Up @@ -88,10 +88,24 @@ RELAY_IP=0.0.0.0
EXTERNAL_RELAY_IP=167.235.241.140
```

Remember to use the `DOMAIN` variable specific to your deployment. It's used in e.g. `REALM` STUN attributes.
Rel will try to open relay addresses in `49_152 - 65_535` port range, but this can be changed. `RELAY_PORT_END` must be greater than `RELAY_PORT_START`.
mickel8 marked this conversation as resolved.
Show resolved Hide resolved

```console
DOMAIN=my-amazing-turn.com
RELAY_PORT_START=35000
RELAY_PORT_END=45000
```

Remember to use the `REALM` variable specific to your deployment. It's used in `REALM` STUN attributes. See
[this section of RFC 2617](https://datatracker.ietf.org/doc/html/rfc2617#section-3.2.1) to learn about appropriate values for `REALM` attribute.

```console
REALM=my-amazing-turn.com
```

You can configure the number of running `listener` processes. By default, it is equal to number of running Erlang VM schedulers:

```console
LISTENER_COUNT=8
```

### Auth
Expand All @@ -100,12 +114,12 @@ Auth Provider is an HTTP endpoint that provides credentials required by *A REST
By default it is available at `http://127.0.0.1:4000/`, but the address, encryption and CORS can be configured:

```console
AUTH_PROVIDER_IP=127.0.0.1
AUTH_PROVIDER_PORT=4000
AUTH_PROVIDER_USE_TLS=false
KEY_FILE_PAHT=./rel.key
CERT_FILE_PATH./rel.cert
AUTH_PROVIDER_ALLOW_CORS=false
AUTH_IP=127.0.0.1
AUTH_PORT=4000
AUTH_USE_TLS=false
AUTH_KEYFILE=./rel.key
AUTH_CERTFILE./rel.cert
AUTH_ALLOW_CORS=false
```

### Metrics
Expand Down
32 changes: 16 additions & 16 deletions config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ defmodule ConfigUtils do

def parse_port(port) do
case Integer.parse(port, 10) do
{val, _rem} when val in 0..49_151 ->
{val, _rem} when val in 0..65_535 ->
val

_other ->
Expand Down Expand Up @@ -77,11 +77,11 @@ defmodule ConfigUtils do
end

# HTTPS for AuthProvider
use_tls? = System.get_env("AUTH_PROVIDER_USE_TLS", "false") |> ConfigUtils.is_truthy?()
keyfile = System.get_env("KEY_FILE_PATH")
certfile = System.get_env("CERT_FILE_PATH")
auth_use_tls? = System.get_env("AUTH_USE_TLS", "false") |> ConfigUtils.is_truthy?()
auth_keyfile = System.get_env("AUTH_KEYFILE")
auth_certfile = System.get_env("AUTH_CERTFILE")

if use_tls? and (is_nil(keyfile) or is_nil(certfile)) do
if auth_use_tls? and (is_nil(auth_keyfile) or is_nil(auth_certfile)) do
raise "Both KEY_FILE_PATH and CERT_FILE_PATH must be set is TLS is used"
end

Expand All @@ -101,7 +101,7 @@ relay_ip =
end

external_relay_ip =
case System.fetch_env("EXTERNAL_LISTEN_IP") do
case System.fetch_env("EXTERNAL_RELAY_IP") do
{:ok, addr} -> ConfigUtils.parse_ip_address(addr)
:error -> external_listen_ip
end
Expand All @@ -119,23 +119,23 @@ listener_count =

# AuthProvider/credentials configuration
config :rel,
auth_provider_ip:
System.get_env("AUTH_PROVIDER_IP", "127.0.0.1") |> ConfigUtils.parse_ip_address(),
auth_provider_port: System.get_env("AUTH_PROVIDER_PORT", "4000") |> ConfigUtils.parse_port(),
auth_provider_allow_cors?:
System.get_env("AUTH_PROVIDER_ALLOW_CORS", "false") |> ConfigUtils.is_truthy?(),
auth_provider_use_tls?: use_tls?,
keyfile: keyfile,
certfile: certfile
auth_ip: System.get_env("AUTH_IP", "127.0.0.1") |> ConfigUtils.parse_ip_address(),
auth_port: System.get_env("AUTH_PORT", "4000") |> ConfigUtils.parse_port(),
auth_allow_cors?: System.get_env("AUTH_ALLOW_CORS", "false") |> ConfigUtils.is_truthy?(),
auth_use_tls?: auth_use_tls?,
auth_keyfile: auth_keyfile,
auth_certfile: auth_certfile

# TURN server configuration
config :rel,
listen_ip: listen_ip,
external_listen_ip: external_listen_ip,
relay_ip: relay_ip,
external_relay_ip: external_relay_ip,
listen_port: System.get_env("UDP_LISTEN_PORT", "3478") |> ConfigUtils.parse_port(),
domain: System.get_env("DOMAIN", "example.com")
listen_port: System.get_env("LISTEN_PORT", "3478") |> ConfigUtils.parse_port(),
realm: System.get_env("REALM", "example.com"),
relay_port_start: System.get_env("RELAY_PORT_START", "49152") |> ConfigUtils.parse_port(),
relay_port_end: System.get_env("RELAY_PORT_END", "65535") |> ConfigUtils.parse_port()
mickel8 marked this conversation as resolved.
Show resolved Hide resolved

# Metrics endpoint configuration
config :rel,
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ services:
restart: on-failure
network_mode: host
environment:
DOMAIN: "${DOMAIN}"
REALM: "${REALM}"

node-exporter:
image: prom/node-exporter:v1.6.1
Expand Down
2 changes: 1 addition & 1 deletion lib/rel/auth_provider.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule Rel.AuthProvider do
def init(_opts), do: []

def call(conn, _opts) do
allow? = Application.fetch_env!(:rel, :auth_provider_allow_cors?)
allow? = Application.fetch_env!(:rel, :auth_allow_cors?)

if allow? do
CORSPlug.call(conn, CORSPlug.init([]))
Expand Down
10 changes: 6 additions & 4 deletions lib/rel/listener.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ defmodule Rel.Listener do
alias ExSTUN.Message.Type
alias ExSTUN.Message.Attribute.{Username, XORMappedAddress}

@buf_size 2 * 1024
@default_alloc_ports MapSet.new(49_152..65_535)
@buf_size 2 * 1024 * 1024

@spec start_link(term()) :: {:ok, pid()}
def start_link(args) do
Expand Down Expand Up @@ -198,7 +197,7 @@ defmodule Rel.Listener do
# origin_alloc_state. In most cases, this shouldn't be a problem as
# client is encouraged to refresh its allocation one minute
# before its deadline
:ok = :gen_udp.send(socket, c_ip, c_port, origin_response)
:ok = :socket.sendto(socket, origin_response, %{family: :inet, addr: c_ip, port: c_port})

{:error, :allocation_exists, _alloc_origin_state} ->
handle_error.(:allocation_exists, socket, c_ip, c_port, msg)
Expand Down Expand Up @@ -322,7 +321,10 @@ defmodule Rel.Listener do
|> Enum.map(fn alloc_origin_state -> Map.fetch!(alloc_origin_state, :alloc_port) end)
|> MapSet.new()

available_alloc_ports = MapSet.difference(@default_alloc_ports, used_alloc_ports)
relay_port_start = Application.fetch_env!(:rel, :relay_port_start)
relay_port_end = Application.fetch_env!(:rel, :relay_port_end)
default_alloc_ports = MapSet.new(relay_port_start..relay_port_end)
available_alloc_ports = MapSet.difference(default_alloc_ports, used_alloc_ports)

if MapSet.size(available_alloc_ports) == 0 do
{:error, :out_of_ports}
Expand Down
4 changes: 2 additions & 2 deletions lib/rel/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ defmodule Rel.Utils do
@spec build_error(atom(), integer(), Method.t()) ::
{response :: binary(), log_msg :: String.t()}
def build_error(reason, t_id, method) do
domain = Application.fetch_env!(:rel, :domain)
realm = Application.fetch_env!(:rel, :realm)
{log_msg, code, with_attrs?} = translate_error(reason)
error_type = %Type{class: :error_response, method: method}

attrs = [%ErrorCode{code: code}]

attrs =
if with_attrs? do
attrs ++ [%Nonce{value: build_nonce()}, %Realm{value: domain}]
attrs ++ [%Nonce{value: build_nonce()}, %Realm{value: realm}]
else
attrs
end
Expand Down
20 changes: 10 additions & 10 deletions lib/rel_app.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ defmodule Rel.App do
def start(_, _) do
Logger.info("Starting Rel v#{@version}")

auth_ip = Application.fetch_env!(:rel, :auth_provider_ip)
auth_port = Application.fetch_env!(:rel, :auth_provider_port)
use_tls? = Application.fetch_env!(:rel, :auth_provider_use_tls?)
keyfile = Application.fetch_env!(:rel, :keyfile)
certfile = Application.fetch_env!(:rel, :certfile)
auth_ip = Application.fetch_env!(:rel, :auth_ip)
auth_port = Application.fetch_env!(:rel, :auth_port)
auth_use_tls? = Application.fetch_env!(:rel, :auth_use_tls?)
auth_keyfile = Application.fetch_env!(:rel, :auth_keyfile)
auth_certfile = Application.fetch_env!(:rel, :auth_certfile)

auth_opts =
if use_tls? do
if auth_use_tls? do
[
scheme: :https,
certfile: certfile,
keyfile: keyfile
certfile: auth_certfile,
keyfile: auth_keyfile
]
else
[scheme: :http]
Expand All @@ -33,7 +33,7 @@ defmodule Rel.App do

metrics_ip = Application.fetch_env!(:rel, :metrics_ip)
metrics_port = Application.fetch_env!(:rel, :metrics_port)
metrics_opts = [metrics: metrics(), plug_cowboy_opts: [ip: metrics_ip, port: metrics_port]]
metrics_opts = [metrics: metrics(), port: metrics_port, plug_cowboy_opts: [ip: metrics_ip]]

children = [
Rel.ListenerSupervisor,
Expand All @@ -46,7 +46,7 @@ defmodule Rel.App do
metrics_endpoint = "http://#{:inet.ntoa(metrics_ip)}:#{metrics_port}/metrics"
Logger.info("Starting Prometheus metrics endpoint at: #{metrics_endpoint}")

scheme = if(use_tls?, do: "https", else: "http")
scheme = if(auth_use_tls?, do: "https", else: "http")
auth_endpoint = "#{scheme}://#{:inet.ntoa(auth_ip)}:#{auth_port}/"
Logger.info("Starting credentials endpoint at: #{auth_endpoint}")

Expand Down