25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

mod_stun_disco: Try to resolve listener address

In some IPv6-only networks, hostnames that have no AAAA record are
resolved to an IPv6 address that's mapped to the host's IPv4 address.
This allows the IPv6-only clients to communicate with IPv4-only services
such as ejabberd's built-in STUN/TURN server.  If STUN/TURN clients try
to contact the IPv4 address directly rather than using the mapped IPv6
address, the connection will fail.

Therefore, try to resolve the IP address of local ejabberd_stun services
to the hostname and announce that hostname rather than the IP address if
(and only if) the hostname resolves back to the original IP address, and
not to any additional IPv4 or IPv6 address(es).

This can (and should) be reverted once IPv6 support is added to
ejabberd's built-in STUN/TURN server.
This commit is contained in:
Holger Weiss 2020-04-30 22:40:01 +02:00
parent 724d09a510
commit e4de03f3df

View File

@ -53,6 +53,8 @@
%% gen_iq_handler callback.
-export([process_iq/1]).
-include_lib("kernel/include/inet.hrl").
-include("logger.hrl").
-include("translate.hrl").
-include("xmpp.hrl").
@ -601,7 +603,8 @@ parse_listener({{Port, _Addr, Transport}, ?STUN_MODULE, Opts}) ->
[misc:ip_to_list(Addr), Port, Transport]),
[];
Addr ->
StunService = #service{host = Addr,
Host = maybe_resolve(Addr),
StunService = #service{host = Host,
port = Port,
transport = Transport,
restricted = false,
@ -610,7 +613,7 @@ parse_listener({{Port, _Addr, Transport}, ?STUN_MODULE, Opts}) ->
#{use_turn := true} ->
?DEBUG("Found STUN/TURN listener: ~s:~B (~s)",
[misc:ip_to_list(Addr), Port, Transport]),
[StunService, #service{host = Addr,
[StunService, #service{host = Host,
port = Port,
transport = Transport,
restricted = is_restricted(Opts),
@ -641,6 +644,29 @@ get_turn_ip(#{turn_ip := undefined}) -> misc:get_my_ip().
is_restricted(#{auth_type := user}) -> true;
is_restricted(#{auth_type := anonymous}) -> false.
-spec maybe_resolve(inet:ip_address()) -> binary() | inet:ip_address().
maybe_resolve(Addr) ->
case lookup(Addr, ptr) of
[Name] when is_list(Name) ->
case {lookup(Name, a), lookup(Name, aaaa)} of
{[Addr], []} ->
?DEBUG("Resolved address ~s to hostname ~s",
[misc:ip_to_list(Addr), Name]),
list_to_binary(Name);
{_, _} ->
?DEBUG("Won't resolve address ~s to hostname ~s",
[misc:ip_to_list(Addr), Name]),
Addr
end;
_ ->
?DEBUG("Cannot resolve address: ~s", [misc:ip_to_list(Addr)]),
Addr
end.
-spec lookup(string() | inet:ip_address(), a | aaaa | ptr) -> [any()].
lookup(Name, Type) ->
inet_res:lookup(Name, in, Type, [], timer:seconds(3)).
-spec call(host_or_hash(), term()) -> term().
call(Host, Request) ->
Proc = get_proc_name(Host),