aboutsummaryrefslogtreecommitdiff
path: root/src/mod_stun_disco.erl
diff options
context:
space:
mode:
authorHolger Weiss <holger@zedat.fu-berlin.de>2020-04-30 22:40:01 +0200
committerHolger Weiss <holger@zedat.fu-berlin.de>2020-04-30 22:40:01 +0200
commite4de03f3df9c2cf6fc6a8636f75fce6500e798d7 (patch)
tree3731a8db5760f5143e29cd61e300104c49bf3d87 /src/mod_stun_disco.erl
parentSet 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.erl30
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),