ejabberd_stun: Support IPv6 for TURN

The stun application now supports RFC 6156: TURN Extension for IPv6, and
therefore needs separate IPv4 and IPv6 relay addresses.
This commit is contained in:
Holger Weiss 2020-05-19 21:42:41 +02:00
parent 858bfb4b80
commit 83fa637569
6 changed files with 44 additions and 21 deletions

View File

@ -64,7 +64,9 @@ listen:
module: ejabberd_stun
use_turn: true
## The server's public IPv4 address:
# turn_ip: 203.0.113.3
# turn_v4_ip: "203.0.113.3"
## The server's public IPv6 address:
# turn_v6_ip: "2001:db8::3"
-
port: 1883
ip: "::"

View File

@ -90,7 +90,7 @@ defmodule Ejabberd.Mixfile do
{:stringprep, "~> 1.0"},
{:fast_yaml, "~> 1.0"},
{:fast_tls, "~> 1.1"},
{:stun, git: "https://github.com/processone/stun", ref: "cb6549387e23737f39f44ba7656a351fd7b88c14", override: true},
{:stun, git: "https://github.com/processone/stun", ref: "481f4dbb8b5793659aedf44048d7c5fde968bfbb", override: true},
{:esip, "~> 1.0.32"},
{:p1_mysql, "~> 1.0"},
{:mqtree, "~> 1.0"},

View File

@ -36,7 +36,7 @@
{mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.7"}}},
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme.git", {tag, "1.0.5"}}},
{base64url, ".*", {git, "https://github.com/dvv/base64url.git", {tag, "v1.0"}}},
{if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", "cb6549387e23737f39f44ba7656a351fd7b88c14"}}},
{if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", "481f4dbb8b5793659aedf44048d7c5fde968bfbb"}}},
{if_var_true, sip, {esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.33"}}}},
{if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql",
{tag, "1.0.15"}}}},

View File

@ -245,8 +245,9 @@ filter(_, _, _, _) ->
%%%===================================================================
transform_listener(Opts, Acc) ->
Opts1 = transform_request_handlers(Opts),
Opts2 = remove_inet_options(Opts1),
collect_listener_certfiles(Opts2, Acc).
Opts2 = transform_turn_ip(Opts1),
Opts3 = remove_inet_options(Opts2),
collect_listener_certfiles(Opts3, Acc).
transform_request_handlers(Opts) ->
case lists:keyfind(module, 1, Opts) of
@ -258,6 +259,14 @@ transform_request_handlers(Opts) ->
Opts
end.
transform_turn_ip(Opts) ->
case lists:keyfind(module, 1, Opts) of
{_, ejabberd_stun} ->
replace_turn_ip(Opts);
_ ->
Opts
end.
replace_request_handlers(Opts) ->
Handlers = proplists:get_value(request_handlers, Opts, []),
Handlers1 =
@ -322,6 +331,15 @@ remove_xmlrpc_access_commands(Opts) ->
true
end, Opts).
replace_turn_ip(Opts) ->
lists:filtermap(
fun({turn_ip, Val}) ->
warn_replaced_option(turn_ip, turn_v4_ip),
{true, {turn_v4_ip, Val}};
(_) ->
true
end, Opts).
remove_inet_options(Opts) ->
lists:filter(
fun({Opt, _}) when Opt == inet; Opt == inet6 ->

View File

@ -101,20 +101,20 @@ prepare_turn_opts(Opts, _UseTurn = false) ->
set_certfile(Opts);
prepare_turn_opts(Opts, _UseTurn = true) ->
NumberOfMyHosts = length(ejabberd_option:hosts()),
TurnIP = case proplists:get_value(turn_ip, Opts) of
TurnIP = case proplists:get_value(turn_v4_ip, Opts) of
undefined ->
MyIP = misc:get_my_ip(),
case MyIP of
{127, _, _, _} ->
?WARNING_MSG("Option 'turn_ip' is undefined and "
"the server's hostname doesn't "
?WARNING_MSG("Option 'turn_v4_ip' is undefined "
"and the server's hostname doesn't "
"resolve to a public IPv4 address, "
"most likely the TURN relay won't be "
"working properly", []);
_ ->
ok
end,
[{turn_ip, MyIP}];
[{turn_v4_ip, MyIP}];
_ ->
[]
end,
@ -161,8 +161,10 @@ listen_opt_type(use_turn) ->
econf:bool();
listen_opt_type(ip) ->
econf:ip();
listen_opt_type(turn_ip) ->
listen_opt_type(turn_v4_ip) ->
econf:ipv4();
listen_opt_type(turn_v6_ip) ->
econf:ipv6();
listen_opt_type(auth_type) ->
econf:enum([anonymous, user]);
listen_opt_type(auth_realm) ->
@ -183,7 +185,8 @@ listen_opt_type(certfile) ->
listen_options() ->
[{shaper, none},
{use_turn, false},
{turn_ip, undefined},
{turn_v4_ip, undefined},
{turn_v6_ip, undefined},
{auth_type, user},
{auth_realm, undefined},
{tls, false},

View File

@ -602,8 +602,8 @@ parse_listener({{Port, _Addr, Transport}, ?STUN_MODULE, Opts}) ->
case get_listener_ip(Opts) of
{127, _, _, _} = Addr ->
?INFO_MSG("Won't auto-announce STUN/TURN service with loopback "
"address: ~s:~B (~s), please specify a public 'turn_ip'",
[misc:ip_to_list(Addr), Port, Transport]),
"address: ~s:~B (~s), please specify a public "
"'turn_v4_ip'", [misc:ip_to_list(Addr), Port, Transport]),
[];
Addr ->
Host = maybe_resolve(Addr),
@ -632,16 +632,16 @@ parse_listener({_EndPoint, Module, _Opts}) ->
[].
-spec get_listener_ip(map()) -> inet:ip_address().
get_listener_ip(#{ip := { 0, 0, 0, 0}} = Opts) -> get_turn_ip(Opts);
get_listener_ip(#{ip := {127, _, _, _}} = Opts) -> get_turn_ip(Opts);
get_listener_ip(#{ip := { 10, _, _, _}} = Opts) -> get_turn_ip(Opts);
get_listener_ip(#{ip := {172, 16, _, _}} = Opts) -> get_turn_ip(Opts);
get_listener_ip(#{ip := {192, 168, _, _}} = Opts) -> get_turn_ip(Opts);
get_listener_ip(#{ip := { 0, 0, 0, 0}} = Opts) -> get_turn_v4_ip(Opts);
get_listener_ip(#{ip := {127, _, _, _}} = Opts) -> get_turn_v4_ip(Opts);
get_listener_ip(#{ip := { 10, _, _, _}} = Opts) -> get_turn_v4_ip(Opts);
get_listener_ip(#{ip := {172, 16, _, _}} = Opts) -> get_turn_v4_ip(Opts);
get_listener_ip(#{ip := {192, 168, _, _}} = Opts) -> get_turn_v4_ip(Opts);
get_listener_ip(#{ip := IP}) -> IP.
-spec get_turn_ip(map()) -> inet:ip_address().
get_turn_ip(#{turn_ip := {_, _, _, _} = TurnIP}) -> TurnIP;
get_turn_ip(#{turn_ip := undefined}) -> misc:get_my_ip().
-spec get_turn_v4_ip(map()) -> inet:ip_address().
get_turn_v4_ip(#{turn_v4_ip := {_, _, _, _} = TurnIP}) -> TurnIP;
get_turn_v4_ip(#{turn_v4_ip := undefined}) -> misc:get_my_ip().
-spec is_restricted(map()) -> boolean().
is_restricted(#{auth_type := user}) -> true;