Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions changelog.d/2-features/turn-dns
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implement TURN service discovery using SRV records
4 changes: 3 additions & 1 deletion charts/brig/templates/conf/_turn-servers-v2.txt.tpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{{ define "turn-servers-v2.txt" }}
{{- if eq $.Values.turn.serversSource "files" }}
{{ range .Values.turnStatic.v2 }}{{ . }}
{{ end -}}
{{ end }}
{{- end }}
{{ end }}
4 changes: 3 additions & 1 deletion charts/brig/templates/conf/_turn-servers.txt.tpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{{ define "turn-servers.txt" }}
{{- if eq $.Values.turn.serversSource "files" }}
{{ range .Values.turnStatic.v1 }}{{ . }}
{{ end -}}
{{ end }}
{{- end }}
{{ end }}
9 changes: 9 additions & 0 deletions charts/brig/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,17 @@ data:
{{- end }}

turn:
{{- if eq $.Values.turn.serversSource "dns" }}
serversSource: dns
baseDomain: {{ required ".turn.baseDomain must be configured if .turn.serversSource is set to dns" $.Values.turn.baseDomain }}
discoveryIntervalSeconds: {{ $.Values.turn.discoveryIntervalSeconds }}
{{- else if eq $.Values.turn.serversSource "files" }}
serversSource: files
servers: /etc/wire/brig/turn/turn-servers.txt
serversV2: /etc/wire/brig/turn/turn-servers-v2.txt
{{- else }}
{{- fail (cat "Invalid value for .turn.serversSource, expected dns or files, got: " $.Values.turn.serversSource) }}
{{- end }}
secret: /etc/wire/brig/secrets/turn-secret.txt
configTTL: 3600 # 1 hour
tokenTTL: 43200 # 12 hours
Expand Down
4 changes: 4 additions & 0 deletions charts/brig/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ spec:
- name: "brig-config"
configMap:
name: "brig"
{{- if eq $.Values.turn.serversSource "files" }}
- name: "turn-servers"
configMap:
name: "turn"
{{- end }}
- name: "brig-secrets"
secret:
secretName: "brig"
Expand All @@ -49,8 +51,10 @@ spec:
mountPath: "/etc/wire/brig/secrets"
- name: "brig-config"
mountPath: "/etc/wire/brig/conf"
{{- if eq $.Values.turn.serversSource "files" }}
- name: "turn-servers"
mountPath: "/etc/wire/brig/turn"
{{- end }}
env:
- name: LOG_LEVEL
value: {{ .Values.config.logLevel }}
Expand Down
2 changes: 2 additions & 0 deletions charts/brig/templates/turnconfigmap.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{{- if eq $.Values.turn.serversSource "files" }}
apiVersion: v1
kind: ConfigMap
metadata:
Expand All @@ -12,3 +13,4 @@ data:
{{- include "turn-servers.txt" . | indent 4 }}
turn-servers-v2.txt: |2
{{- include "turn-servers-v2.txt" . | indent 4 }}
{{- end }}
6 changes: 6 additions & 0 deletions charts/brig/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ turnStatic:
v2:
- turn:localhost:3478
- turn:localhost:3478?transport=tcp

turn:
serversSource: files # files | dns
# baseDomain: turn.example.com # Must be configured if serversSource is dns
discoveryIntervalSeconds: 10 # Used only if serversSource is dns

tests:
enableFederationTests: false
serviceAccount:
Expand Down
78 changes: 78 additions & 0 deletions docs/src/how-to/administrate/restund.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,84 @@ Restund (TURN)

.. _allocations:

Wire-Server Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~

The wire-server can either serve a static list of TURN servers to the clients or
it can discovery them using DNS SRV Records.

Static List
+++++++++++

To configure a static list of TURN servers to use, override
``values/wire-server/values.yaml`` like this:

.. code:: yaml

# (...)

brig:
# (...)
turnStatic:
v1:
# v1 entries can be ignored and are not in use anymore since end of 2018.
v2:
- turn:server1.example.com:3478 # server 1 UDP
- turn:server1.example.com:3478?transport=tcp # server 1 TCP
- turns:server1.example.com:5478?transport=tcp # server 1 TLS
- turn:server2.example.com:3478 # server 2 UDP
- turn:server2.example.com:3478?transport=tcp # server 2 TCP
- turns:server2.example.com:5478?transport=tcp # server 2 TLS
turn:
serversSource: files

DNS SRV Records
+++++++++++++++

To configure wire-server to use DNS SRV records in order to discover TURN
servers, override ``values/wire-server/values.yaml`` like this:

.. code:: yaml

# (...)

brig:
# (...)
turn:
serversSource: dns
baseDomain: prod.example.com
discoveryIntervalSeconds: 10

When configured like this, the wire-server would look for these 3 SRV records
every 10 seconds:

1. ``_turn._udp.prod.example.com`` will be used to discover UDP hostnames and port for all the
turn servers.
2. ``_turn._tcp.prod.example.com`` will be used to discover the TCP hostnames and port for all
the turn servers.
3. ``_turns._tcp.prod.example.com`` will be used to discover the TLS hostnames and port for
all the turn servers.

Entries with weight 0 will be ignored. Example:

.. code::

dig +retries=3 +short SRV _turn._udp.prod.example.com

0 0 3478 turn36.prod.example.com
0 10 3478 turn34..prod.example.com
0 10 3478 turn35.prod.example.com

At least one of these 3 lookups must succeed for the wire-server to be able to
respond correctly when ``GET /calls/config/v2`` is called. All successful
responses are served in the result.

In addition, if there are any clients using the legacy endpoint, ``GET
/calls/config``, (all versions of all mobile apps since 2018 no longer use this) they will be served by the servers listed in the
``_turn._udp.prod.example.com`` SRV record. This endpoint, however, will not
serve the domain names received inside the SRV record, instead it will serve the
first ``A`` record that is associated with each domain name in the SRV record.

How to see how many people are currently connected to the restund server
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
21 changes: 15 additions & 6 deletions libs/dns-util/src/Wire/Network/DNS/Effect.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{-# LANGUAGE TemplateHaskell #-}

-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <[email protected]>
Expand All @@ -14,10 +16,10 @@
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.
{-# LANGUAGE TemplateHaskell #-}

module Wire.Network.DNS.Effect where

import qualified Data.IP as IP
import Imports
import Network.DNS (Domain, Resolver)
import qualified Network.DNS as DNS
Expand All @@ -26,16 +28,23 @@ import qualified Wire.Network.DNS.SRV as SRV

data DNSLookup m a where
LookupSRV :: Domain -> DNSLookup m SRV.SrvResponse
LookupA :: Domain -> DNSLookup m (Either DNS.DNSError [IP.IPv4])

makeSem ''DNSLookup

runDNSLookupDefault :: Member (Embed IO) r => Sem (DNSLookup ': r) a -> Sem r a
runDNSLookupDefault =
interpret $ \(LookupSRV domain) -> embed $ do
interpret $ \action -> embed $ do
rs <- DNS.makeResolvSeed DNS.defaultResolvConf
DNS.withResolver rs $ \resolver ->
SRV.interpretResponse <$> DNS.lookupSRV resolver domain
DNS.withResolver rs $ flip runLookupIO action

runDNSLookupWithResolver :: Member (Embed IO) r => Resolver -> Sem (DNSLookup ': r) a -> Sem r a
runDNSLookupWithResolver resolver = interpret $ \(LookupSRV domain) ->
embed (SRV.interpretResponse <$> DNS.lookupSRV resolver domain)
runDNSLookupWithResolver resolver = interpret $ embed . runLookupIO resolver

runLookupIO :: Resolver -> DNSLookup m a -> IO a
runLookupIO resolver action =
case action of
LookupSRV domain -> do
SRV.interpretResponse <$> DNS.lookupSRV resolver domain
LookupA domain ->
DNS.lookupA resolver domain
8 changes: 4 additions & 4 deletions libs/wire-api/src/Wire/API/Call/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ data TurnURI = TurnURI
_turiPort :: Port,
_turiTransport :: Maybe Transport
}
deriving stock (Eq, Show, Generic)
deriving stock (Eq, Show, Ord, Generic)

turnURI :: Scheme -> TurnHost -> Port -> Maybe Transport -> TurnURI
turnURI = TurnURI
Expand Down Expand Up @@ -293,7 +293,7 @@ instance Arbitrary TurnURI where
data Scheme
= SchemeTurn
| SchemeTurns
deriving stock (Eq, Show, Generic)
deriving stock (Eq, Show, Ord, Generic)
deriving (Arbitrary) via (GenericUniform Scheme)

instance BC.ToByteString Scheme where
Expand All @@ -318,7 +318,7 @@ instance FromJSON Scheme where
data TurnHost
= TurnHostIp IpAddr
| TurnHostName Text
deriving stock (Eq, Show, Generic)
deriving stock (Eq, Show, Ord, Generic)
deriving anyclass (ToJSON, FromJSON)

instance BC.FromByteString TurnHost where
Expand Down Expand Up @@ -360,7 +360,7 @@ parseTurnHost h = case BC.fromByteString host of
data Transport
= TransportUDP
| TransportTCP
deriving stock (Eq, Show, Generic)
deriving stock (Eq, Show, Ord, Generic)
deriving (Arbitrary) via (GenericUniform Transport)

instance BC.ToByteString Transport where
Expand Down
3 changes: 2 additions & 1 deletion services/brig/brig.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,8 @@ test-suite brig-tests
ViewPatterns
ghc-options: -O2 -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -Wpartial-fields -fwarn-tabs -optP-Wno-nonportable-include-path -funbox-strict-fields -threaded -with-rtsopts=-N
build-depends:
aeson
HsOpenSSL >=0.10
, aeson
, base
, binary
, bloodhound
Expand Down
5 changes: 5 additions & 0 deletions services/brig/brig.integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,13 @@ zauth:
legalHoldAccessTokenTimeout: 30

turn:
serversSource: files # files | dns
servers: test/resources/turn/servers.txt
serversV2: test/resources/turn/servers-v2.txt
# If configured to dns, also configure:
# baseDomain: example.com
# discoveryIntervalSeconds: 10

# This should be the same secret as used by the TURN servers
secret: test/resources/turn/secret.txt
configTTL: 3600
Expand Down
1 change: 1 addition & 0 deletions services/brig/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ tests:
- -threaded
- -with-rtsopts=-N
dependencies:
- HsOpenSSL >=0.10
- aeson
- base
- binary
Expand Down
2 changes: 1 addition & 1 deletion services/brig/src/Brig/App.hs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ newEnv o = do
g <- geoSetup lgr w $ Opt.geoDb o
let turnOpts = Opt.turn o
turnSecret <- Text.encodeUtf8 . Text.strip <$> Text.readFile (Opt.secret turnOpts)
turn <- Calling.mkTurnEnv (Opt.servers turnOpts) (Opt.serversV2 turnOpts) (Opt.tokenTTL turnOpts) (Opt.configTTL turnOpts) turnSecret sha512
turn <- Calling.mkTurnEnv (Opt.serversSource turnOpts) (Opt.tokenTTL turnOpts) (Opt.configTTL turnOpts) turnSecret sha512
let sett = Opt.optSettings o
nxm <- initCredentials (Opt.setNexmo sett)
twl <- initCredentials (Opt.setTwilio sett)
Expand Down
Loading