-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
turn: add TURN server #163
base: dev
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for getting this effort started! ❤️ Left some comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did another review round!
turncredentials_secret = "{{ .Env.TURN_SECRET | default "keepthissecret" }}"; | ||
turncredentials = { | ||
{ type = "{{ .Env.TURN_TYPE | default "turns" }}", | ||
host = "{{ .Env.TURN_HOST | default .Env.DOCKER_HOST_ADDRESS }}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the default be TURN_PUBLIC_IP ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prosody doesn't know about TURN_PUBLIC_IP in case TURN_PUBLIC_IP is not set from env file (got dynamically)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can detect it in the init file and re-export it, perhaps?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try to explain my view on it. TURN_HOST
is an announced FQDN for reach cluster of turn. It has use inside prosody for provide XEP-0215.
TURN_PUBLIC_IP
is a exactly external IP address of turn instance.
When we use TURN_HOST
="turn.example.com", conditionally, A
record can be turn.example.com TURN_PUBLIC_IP1, TURN_PUBLIC_IP2, TURN_PUBLIC_IP3
and client (that got TURN_HOST
via XEP-0215) goes to this scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other hand, if it's just a single setup. TURN_HOST can be DOCKER_HOST_ADDRESS (if not set) and TURN_PUBLIC_IP is dynamically set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not completely sure of the latest comment.. I guess, we should remove default set for "TURN_HOST" and make it force needed, because if TURN_PUBLIC_IP and DOCKER_HOST_ADDRESS is different, setup will broken. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I follow you here. I do understand that you could set a hostname. But if you don't, the IP that should be there is the publicc IP of the TURN server, right?
On hindsight DOCKER_HOST_ADDRESS was not a great name. I'll probably rename it to JVB_PUBLIC_IP in the future, which is a better name.
So, to me, it makes sense that the default is the TURN public IP, and not anything else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to use only TURN_HOST
for spreading hostname via XEP-0215. In this case we are suppose that:
a) the turn instance only one, and we exactly know how to reach it from outside.
b) the turn instance is multiple, but behind proxy. so, proxy knows how to reach each of them.
The TURN_HOST
is mandatory variable, otherwise do not enable turn functions.
@saghul WDYT?
Can I help here? I have free time... |
For information I finish a version that integrate a turn server into web container. It's not fair to create a new MR because it's base on this one at the begining. |
One thing that's currently missing is documentation: which ports one would need to open additionally. This should be added here: https://github.com/jitsi/docker-jitsi-meet#external-ports |
0cca664
to
e68067d
Compare
added in 14d717c |
Hi, any news on this? |
Having this in will be great. |
ping? |
@@ -47,6 +47,9 @@ If you want to use jibri too, first configure host as described in JItsi BRoadca | |||
and then run Docker Compose as follows: ``docker-compose -f docker-compose.yml -f jibri.yml up -d`` | |||
or to use jigasi too: ``docker-compose -f docker-compose.yml -f jigasi.yml -f jibri.yml up -d`` | |||
|
|||
If you want to enable TURN server, configure it and run Docker Compose as |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change needs to be applied to https://github.com/jitsi/handbook/blob/master/docs/devops-guide/docker.md (cf: #601)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there anything I can do to support his PR towards being merged? I'd really like to vacate Zoom with all of its problems for Jitsi Meet...
As I see we have only one unresolved conversation around it. So, if @saghul have a couple of minutes to take a look this, I beleive we will fastly resolve and merge it. |
@saghul could you have a look at this? Only you can save mankind from Zoom meetings :) |
Hi! Although I'm not really versed on all needed to make this work on docker, I could test it in my on premises installation. Would it help? We are using docker, but setting up TURN without docker. Yes... Our JMS doesn't currently have a TURN server... :( |
Thank you so much for this work! I look forward to see this! Jitsi community really rocks! |
Hi, is there anything that could be done here to move this forward? |
{{ if or (.Env.TURN_ENABLE_P2P | default "0" | toBool) (.Env.TURN_ENABLE_JVB | default "0" | toBool) }} | ||
turncredentials_secret = "{{ .Env.TURN_SECRET | default "keepthissecret" }}"; | ||
turncredentials = { | ||
{ type = "{{ .Env.TURN_TYPE | default "turns" }}", | ||
host = "{{ .Env.TURN_HOST | default "8.8.8.8" }}", | ||
port = {{ .Env.TURN_PORT | default "3478" }}, | ||
transport = "{{ .Env.TURN_TRANSPORT | default "tcp" }}" | ||
} | ||
} | ||
{{ end }} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The credential must be set in the prosody.cfg.lua files and not in the jitsi-meet.cfg.lua.
In jitsi-meet.cfg.lua you have to add the "turncredantials" in the module_enabled section of the meet.jitsi Virtualhost.
I've worked on this from the latest docker-jitsi-meet adding all the changes of the PR except for two:
I attach the patch which is mostly the same of the PR except for these two changes. I'd also be able to provide the terraform script that created the machines I'm testing in (in Digital Ocean). turn.diff Problems Jitsi works but I'm having some problems to test whether the turn server is working. I can't block the port 10000/udp with ufw. I've tried to block ports with ufw but it doesn't seem to have any effect perhaps due to this?. The other thing I've tried is to checking chrome://webrtc-internals (since I haven't been able to block 10000 this is not as useful as it could be). When I test with several participants I see in the some of the tabs "iceServers: [stun:meet-jit-si-turnrelay.jitsi.net:443]", but this is the same I see in a server where I have not applied the patch @netaskd Any way I could go on from here in order to provide help to advance this pull request? First option I can think of is to try other ways to block port 10000. Do other iptables management utilities have the same problem as ufw with respect to docker?, any advice on how to do block 10000/udp without stumbling on this problem? |
Hi, does this help? |
Docker generally doesn't play well out-of-the-box with firewall configuration tools such as UFW, shorewall, etc. Such tools generate IPTABLES rules based on some "easier" configuration format, while Docker itself leverages IPTABLES to "magically" configure NAT for the containers. If both tools are not aware of each other, they will overwrite or shadow each-other's IPTABLE rules. Both UFW and Shorwall have builtin support for Docker in their latest versions which is disabled by default. Enabling this feature will make UFW "docker-aware" and preserve Dockers IPTABLE rules when run. However, it is still rather complicated to block incoming connections to Docker via IPTABLE rules, due to the fact that NAT is processed before the FILTER rules, meaning that packets to Docker-configured ports are redirected into the corresponding container before the packets run through the FILTER chain of the host - therefor never hitting the rule. SolutionThe correct way to prevent access into a Docker container is to explicitly state
This will only allow access to port 10000 when the connection is coming from the Docker host itself and will deny access when coming from elsewhere. |
I also need this. How can I help the development? What's still open? |
@baccenfutter What I did was modify the docker-compose.yml at the root of the project by changing
Is that equivalent to what you suggested? (I don't know enough about docker and docker-compose to evaluate whether it is). In any case after doing that I was having problems with the audio/video from the videoconference which only worked momentarily and then stopped working. Perhaps there's some unexpected side effect to that way of restricting the port?, if that's not the case then my patch is not working when 10000/udp is blocked. @holtgrewe I did not try that because it seemed to me that I'd be changing more things than strictly needed (it would affect potentially other things). In order to evaluate whether the patch is working I need a test that isolates the changes so I wanted to only block 10000/udp and leave everything else the same. @netaskd @saghul There's a lot of interest in this PR and some people would like to help but we don't have the information on how to do it. As far as I understand there's just this change pending review but the turncredentials code in netaskd branch have changed since the time the review was requested. Could you provide some guidance if helping is possible? If it isn't it would be useful to know that too ;) |
jitsi#163 Fix prosody configuration Fix web configuration Fix name : turn => coturn Update README.md
--no-multicast-peers \ | ||
--realm=${TURN_REALM:-realm} \ | ||
--listening-ip=$(hostname -i) \ | ||
--external-ip=${TURN_PUBLIC_IP} \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per https://hub.docker.com/r/instrumentisto/coturn they recommend using the detect-external-ip
tool to automatically get the external IP. I did not check how that works, but I'm not sure as well to add a dependency on icanhazip.com
to get the TURN server up a good thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, the script detect-external-ip
do the same ;)
See https://github.com/instrumentisto/coturn-docker-image/blob/master/rootfs/usr/local/bin/detect-external-ip.sh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, should have checked it before. Awesome. I've been testing this and works great. My use case is on kubernetes and Im having some issues with networking, but that is another story.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been adopted for the upstream coturn
image, too, despite the strategy it uses is a little different.
See previous comment https://github.com/jitsi/docker-jitsi-meet/pull/163/files#r802157850
Read through all of this but didn't get it... will this also support adding an external TURN server without starting an additional coturn docker container which isn't needed in that case? |
What is the status of this PR, what discussion is still pending? The setup we are using is to split traffic with Envoy & also terminate TLS there. That way both Jitsi's NGINX/web container & CoTURN don't need to do TLS offloading. Example envoy.yaml configuration: # docker run -v $PWD:/etc/ssl/private -v $PWD:/data envoyproxy/envoy:v1.14.4 /usr/local/bin/envoy -c /data/envoy.yaml --mode validate
#
admin:
address:
socket_address: { address: 0.0.0.0, port_value: 9901 }
static_resources:
listeners:
# Main listener
- address:
socket_address: { address: 0.0.0.0, port_value: 4430 }
# TLS Inspector parses the SNI & ALPN settings
listener_filters:
- name: "envoy.filters.listener.tls_inspector"
typed_config: {}
# One filter chain per SNI & ALPN
filter_chains:
# shard-1 HTTP
- filter_chain_match: # shard-1 http
server_names: ["shard-1.eu.example.org"]
application_protocols: ["http/1.1", "h2"]
transport_socket: &tmpl_transport_socket
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificates:
- certificate_chain: { filename: "/etc/ssl/private/tls.crt" }
private_key: { filename: "/etc/ssl/private/tls.key" }
filters: &tmpl_http_filters
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
virtual_hosts:
- name: default
domains: "*"
routes:
- match: { prefix: "/" }
route: { cluster: service_shard1_nginx }
http_filters:
- name: envoy.filters.http.router
# shard-1 TURN
- filter_chain_match:
server_names: ["shard-1.eu.example.org"]
transport_socket: *tmpl_transport_socket
filters:
- name: envoy.filters.network.tcp_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
stat_prefix: tcp
cluster: service_shard1_turn
# fallback HTTP (redirects to Application Level router)
- filter_chain_match:
server_names: ["*.example.org"]
transport_socket: *tmpl_transport_socket
filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
virtual_hosts:
- name: default
domains: "*"
routes:
- match: { prefix: "/" }
route: { cluster: service_fallback }
http_filters:
- name: envoy.filters.http.router
# fallback for health check
- filter_chain_match:
transport_socket: *tmpl_transport_socket
filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: direct_http
route_config:
virtual_hosts:
- name: default
domains: "*"
routes:
- match: { prefix: "/" }
direct_response:
status: 200
body:
inline_string: "Fallback"
http_filters:
- name: envoy.filters.http.router
clusters:
- name: service_fallback
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
load_assignment:
cluster_name: service_fallback
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: nginx-internal
port_value: 80
- name: service_shard1_nginx
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
load_assignment:
cluster_name: service_shard1_nginx
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: nginx.shard-1.svc.cluster.local
port_value: 80
- name: service_shard1_turn
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
load_assignment:
cluster_name: service_shard1_turn
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: turn.shard-1.svc.cluster.local
port_value: 5349 I'm also working on an Envoy xDS API endpoint that serves this configuration dynamically. That would ease adding shards drastically in our Kubernetes setup. |
I've documented in the community my tests with a simple firewall and:
As far as I can see under with this setup for the videoconferences to work it's enough if the firewall allows 80, 443 (both outbound and inbound) and 10000 outbound. I know this PR does not include the multiplexing bit but I think this contributes to the conversation and the multiplexing part is an interesting direction for turn in docker-jitsi-meet to pursue |
# run coturn server with API auth method enabled. | ||
turnserver -n ${TURN_ADMIN_OPTIONS} \ | ||
--verbose \ | ||
--prod \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--no-software-attribute Production mode: hide the software version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good spot!
@@ -0,0 +1,13 @@ | |||
ARG VERSION | |||
FROM instrumentisto/coturn:${VERSION:-latest} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been deprecated: instrumentisto/coturn-docker-image@0a4a7f0
It is suggested to switch to the upstream image coturn/coturn
(🔗).
Hi Folks, This PR is still alive or somebody working on it? What kind of job is left to do? Also, I don't understand this PR. As I can see the main goal of this PR is to make it happen to configure an external TURN server for Jitsi and you have created a new image which will be a coTURN server for testing or if somebody wants to use it. Am I right? If it's true then I would like to help you to finish this, because from the commits and because of my lack of knowledge with the configuration I can't see another way to configure Jitsi containers to use TURN servers. If we can configure Jitsi to use TURN server, then there is a way to somehow force the relay through TURN with p2p connections? Can I just put a zero or false value into an env variable and force it? |
adds TURN server to the infrastructure.