diff options
author | Holger Weiss <holger@zedat.fu-berlin.de> | 2020-04-30 22:40:01 +0200 |
---|---|---|
committer | Holger Weiss <holger@zedat.fu-berlin.de> | 2020-04-30 22:40:01 +0200 |
commit | e4de03f3df9c2cf6fc6a8636f75fce6500e798d7 (patch) | |
tree | 3731a8db5760f5143e29cd61e300104c49bf3d87 /src/mod_stun_disco.erl | |
parent | Set ejabberd version to 20.04 (diff) |
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.
Diffstat (limited to 'src/mod_stun_disco.erl')
-rw-r--r-- | src/mod_stun_disco.erl | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/src/mod_stun_disco.erl b/src/mod_stun_disco.erl index 52ced9b28..25b6a820d 100644 --- a/src/mod_stun_disco.erl +++ b/src/mod_stun_disco.erl @@ -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), |