25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-20 17:27:00 +01:00

* src/ejabberd_config.erl: Option outgoing_s2s_options to define

s2s outgoing behaviour: IPv4, IPv6 and timeout (thanks to Stephan
Maka)(EJAB-665)
* src/ejabberd_s2s_out.erl: Likewise
* src/ejabberd_socket.erl: Likewise
* src/ejabberd.cfg.example: Likewise
* doc/guide.tex: Likewise
* doc/guide.html: Likewise

SVN Revision: 1756
This commit is contained in:
Badlop 2008-12-26 11:45:08 +00:00
parent 11825e7a33
commit 682909e0fc
7 changed files with 121 additions and 30 deletions

View File

@ -1,3 +1,14 @@
2008-12-26 Badlop <badlop@process-one.net>
* src/ejabberd_config.erl: Option outgoing_s2s_options to define
s2s outgoing behaviour: IPv4, IPv6 and timeout (thanks to Stephan
Maka)(EJAB-665)
* src/ejabberd_s2s_out.erl: Likewise
* src/ejabberd_socket.erl: Likewise
* src/ejabberd.cfg.example: Likewise
* doc/guide.tex: Likewise
* doc/guide.html: Likewise
2008-12-26 Evgeniy Khramtsov <ekhramtsov@process-one.net> 2008-12-26 Evgeniy Khramtsov <ekhramtsov@process-one.net>
* src/odbc/ejabberd_odbc.erl: get rid of SERIALIZABLE isolation * src/odbc/ejabberd_odbc.erl: get rid of SERIALIZABLE isolation
@ -10,7 +21,7 @@
2008-12-24 Badlop <badlop@process-one.net> 2008-12-24 Badlop <badlop@process-one.net>
* src/aclocal.m4: Fixes in configure script: fix * src/aclocal.m4: Fixes in configure script: fix
disable-disable_zlib and disable-pam; in case of problems, PAM disable-ejabberd_zlib and disable-pam; in case of problems, PAM
verification aborts with error instead of warning. (EJAB-787) verification aborts with error instead of warning. (EJAB-787)
* src/configure.ac: Likewise * src/configure.ac: Likewise
* src/configure: Likewise * src/configure: Likewise

View File

@ -745,6 +745,10 @@ use STARTTLS for s2s connections.
file containing a SSL certificate. file containing a SSL certificate.
</DD><DT CLASS="dt-description"><B><TT>{domain_certfile, Domain, Path}</TT></B></DT><DD CLASS="dd-description"> </DD><DT CLASS="dt-description"><B><TT>{domain_certfile, Domain, Path}</TT></B></DT><DD CLASS="dd-description">
Full path to the file containing the SSL certificate for a specific domain. Full path to the file containing the SSL certificate for a specific domain.
</DD><DT CLASS="dt-description"><B><TT>{outgoing_s2s_options, Methods, Timeout}</TT></B></DT><DD CLASS="dd-description">
Specify which address families to try, in what order, and connect timeout in milliseconds.
By default it first tries connecting with IPv4, if that fails it tries using IPv6,
with a timeout of 10000 milliseconds.
</DD><DT CLASS="dt-description"><B><TT>{s2s_default_policy, allow|deny}</TT></B></DT><DD CLASS="dd-description"> </DD><DT CLASS="dt-description"><B><TT>{s2s_default_policy, allow|deny}</TT></B></DT><DD CLASS="dd-description">
The default policy for incoming and outgoing s2s connections to other Jabber servers. The default policy for incoming and outgoing s2s connections to other Jabber servers.
The default value is <TT>allow</TT>. The default value is <TT>allow</TT>.
@ -1032,6 +1036,10 @@ declarations of ACLs in the configuration file have the following syntax:
</PRE></DD><DT CLASS="dt-description"><B><TT>{resource, &lt;resource&gt;}</TT></B></DT><DD CLASS="dd-description"> Matches any JID with a resource </PRE></DD><DT CLASS="dt-description"><B><TT>{resource, &lt;resource&gt;}</TT></B></DT><DD CLASS="dd-description"> Matches any JID with a resource
<TT>&lt;resource&gt;</TT>. Example: <TT>&lt;resource&gt;</TT>. Example:
<PRE CLASS="verbatim">{acl, mucklres, {resource, "muckl"}}. <PRE CLASS="verbatim">{acl, mucklres, {resource, "muckl"}}.
</PRE></DD><DT CLASS="dt-description"><B><TT>{shared_group, &lt;groupname&gt;}</TT></B></DT><DD CLASS="dd-description"> Matches any member of a Shared Roster Group with name <TT>&lt;groupname&gt;</TT> in the virtual host. Example:
<PRE CLASS="verbatim">{acl, techgroupmembers, {shared_group, "techteam"}}.
</PRE></DD><DT CLASS="dt-description"><B><TT>{shared_group, &lt;groupname&gt;, &lt;server&gt;}</TT></B></DT><DD CLASS="dd-description"> Matches any member of a Shared Roster Group with name <TT>&lt;groupname&gt;</TT> in the virtual host <TT>&lt;server&gt;</TT>. Example:
<PRE CLASS="verbatim">{acl, techgroupmembers, {shared_group, "techteam", "example.org"}}.
</PRE></DD><DT CLASS="dt-description"><B><TT>{user_regexp, &lt;regexp&gt;}</TT></B></DT><DD CLASS="dd-description"> Matches any local user with a name that </PRE></DD><DT CLASS="dt-description"><B><TT>{user_regexp, &lt;regexp&gt;}</TT></B></DT><DD CLASS="dd-description"> Matches any local user with a name that
matches <TT>&lt;regexp&gt;</TT> on local virtual hosts. Example: matches <TT>&lt;regexp&gt;</TT> on local virtual hosts. Example:
<PRE CLASS="verbatim">{acl, tests, {user_regexp, "^test[0-9]*$"}}. <PRE CLASS="verbatim">{acl, tests, {user_regexp, "^test[0-9]*$"}}.

View File

@ -870,6 +870,10 @@ There are some additional global options:
file containing a SSL certificate. file containing a SSL certificate.
\titem{\{domain\_certfile, Domain, Path\}} \ind{options!domain\_certfile} \titem{\{domain\_certfile, Domain, Path\}} \ind{options!domain\_certfile}
Full path to the file containing the SSL certificate for a specific domain. Full path to the file containing the SSL certificate for a specific domain.
\titem{\{outgoing\_s2s\_options, Methods, Timeout\}} \ind{options!outgoing\_s2s\_options}
Specify which address families to try, in what order, and connect timeout in milliseconds.
By default it first tries connecting with IPv4, if that fails it tries using IPv6,
with a timeout of 10000 milliseconds.
\titem{\{s2s\_default\_policy, allow|deny\}} \titem{\{s2s\_default\_policy, allow|deny\}}
The default policy for incoming and outgoing s2s connections to other Jabber servers. The default policy for incoming and outgoing s2s connections to other Jabber servers.
The default value is \term{allow}. The default value is \term{allow}.

View File

@ -186,6 +186,13 @@
%%{{s2s_host, "goodhost.org"}, allow}. %%{{s2s_host, "goodhost.org"}, allow}.
%%{{s2s_host, "badhost.org"}, deny}. %%{{s2s_host, "badhost.org"}, deny}.
%%
%% Outgoing S2S options
%%
%% Preferred address families (which to try first) and connect timeout
%% in milliseconds.
%%
%%{outgoing_s2s_options, [ipv4, ipv6], 10000}.
%%% ============== %%% ==============
%%% AUTHENTICATION %%% AUTHENTICATION

View File

@ -330,6 +330,8 @@ process_term(Term, State) ->
add_option(language, Val, State); add_option(language, Val, State);
{outgoing_s2s_port, Port} -> {outgoing_s2s_port, Port} ->
add_option(outgoing_s2s_port, Port, State); add_option(outgoing_s2s_port, Port, State);
{outgoing_s2s_options, Methods, Timeout} ->
add_option(outgoing_s2s_options, {Methods, Timeout}, State);
{s2s_use_starttls, Port} -> {s2s_use_starttls, Port} ->
add_option(s2s_use_starttls, Port, State); add_option(s2s_use_starttls, Port, State);
{s2s_certfile, CertFile} -> {s2s_certfile, CertFile} ->

View File

@ -119,6 +119,8 @@
-define(INVALID_XML_ERR, -define(INVALID_XML_ERR,
xml:element_to_string(?SERR_XML_NOT_WELL_FORMED)). xml:element_to_string(?SERR_XML_NOT_WELL_FORMED)).
-define(SOCKET_DEFAULT_RESULT, {error, badarg}).
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% API %%% API
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
@ -206,7 +208,7 @@ open_socket(init, StateData) ->
_ -> _ ->
open_socket1(Addr, Port) open_socket1(Addr, Port)
end end
end, {error, badarg}, AddrList) of end, ?SOCKET_DEFAULT_RESULT, AddrList) of
{ok, Socket} -> {ok, Socket} ->
Version = if Version = if
StateData#state.use_v10 -> StateData#state.use_v10 ->
@ -239,34 +241,40 @@ open_socket(_, StateData) ->
{next_state, open_socket, StateData}. {next_state, open_socket, StateData}.
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
open_socket1(Addr, Port) -> %% IPv4
?DEBUG("s2s_out: connecting to ~s:~p~n", [Addr, Port]), open_socket1({_,_,_,_} = Addr, Port) ->
Res = case catch ejabberd_socket:connect( open_socket2(inet, Addr, Port);
Addr, Port,
[binary, {packet, 0}, %% IPv6
{active, false}]) of open_socket1({_,_,_,_,_,_,_,_} = Addr, Port) ->
{ok, _Socket} = R -> R; open_socket2(inet6, Addr, Port);
{error, Reason1} ->
?DEBUG("s2s_out: connect return ~p~n", [Reason1]), %% Hostname
catch ejabberd_socket:connect( open_socket1(Host, Port) ->
Addr, Port, lists:foldl(fun(_Family, {ok, _Socket} = R) ->
[binary, {packet, 0}, R;
{active, false}, inet6]); (Family, _) ->
{'EXIT', Reason1} -> Addrs = get_addrs(Host, Family),
?DEBUG("s2s_out: connect crashed ~p~n", [Reason1]), lists:foldl(fun(_Addr, {ok, _Socket} = R) ->
catch ejabberd_socket:connect( R;
Addr, Port, (Addr, _) ->
[binary, {packet, 0}, open_socket1(Addr, Port)
{active, false}, inet6]) end, ?SOCKET_DEFAULT_RESULT, Addrs)
end, end, ?SOCKET_DEFAULT_RESULT, outgoing_s2s_families()).
case Res of
{ok, Socket} -> open_socket2(Type, Addr, Port) ->
{ok, Socket}; ?DEBUG("s2s_out: connecting to ~p:~p~n", [Addr, Port]),
{error, Reason} -> Timeout = outgoing_s2s_timeout(),
?DEBUG("s2s_out: inet6 connect return ~p~n", [Reason]), case (catch ejabberd_socket:connect(Addr, Port,
{error, Reason}; [binary, {packet, 0},
{active, false}, Type],
Timeout)) of
{ok, _Socket} = R -> R;
{error, Reason} = R ->
?DEBUG("s2s_out: connect return ~p~n", [Reason]),
R;
{'EXIT', Reason} -> {'EXIT', Reason} ->
?DEBUG("s2s_out: inet6 connect crashed ~p~n", [Reason]), ?DEBUG("s2s_out: connect crashed ~p~n", [Reason]),
{error, Reason} {error, Reason}
end. end.
@ -1000,6 +1008,23 @@ test_get_addr_port(Server) ->
end end
end, [], lists:seq(1, 100000)). end, [], lists:seq(1, 100000)).
get_addrs(Host, Family) ->
Type = case Family of
inet4 -> a;
ipv4 -> a;
inet6 -> aaaa;
ipv6 -> aaaa
end,
case inet_res:getbyname(Host, Type) of
{ok, #hostent{h_addr_list = Addrs}} ->
?DEBUG("~s of ~s resolved to: ~p~n", [Type, Host, Addrs]),
Addrs;
{error, Reason} ->
?DEBUG("~s lookup of '~s' failed: ~p~n", [Type, Host, Reason]),
[]
end.
outgoing_s2s_port() -> outgoing_s2s_port() ->
case ejabberd_config:get_local_option(outgoing_s2s_port) of case ejabberd_config:get_local_option(outgoing_s2s_port) of
Port when is_integer(Port) -> Port when is_integer(Port) ->
@ -1008,6 +1033,36 @@ outgoing_s2s_port() ->
5269 5269
end. end.
outgoing_s2s_families() ->
case ejabberd_config:get_local_option(outgoing_s2s_options) of
{Families, _} when is_list(Families) ->
Families;
undefined ->
%% DISCUSSION: Why prefer IPv4 first?
%%
%% IPv4 connectivity will be available for everyone for
%% many years to come. So, there's absolutely no benefit
%% in preferring IPv6 connections which are flaky at best
%% nowadays.
%%
%% On the other hand content providers hesitate putting up
%% AAAA records for their sites due to the mentioned
%% quality of current IPv6 connectivity. Making IPv6 the a
%% `fallback' may avoid these problems elegantly.
[ipv4, ipv6]
end.
outgoing_s2s_timeout() ->
case ejabberd_config:get_local_option(outgoing_s2s_options) of
{_, Timeout} when is_integer(Timeout) ->
Timeout;
{_, infinity} ->
infinity;
undefined ->
%% 10 seconds
10000
end.
%% Human readable S2S logging: Log only new outgoing connections as INFO %% Human readable S2S logging: Log only new outgoing connections as INFO
%% Do not log dialback %% Do not log dialback
log_s2s_out(false, _, _) -> ok; log_s2s_out(false, _, _) -> ok;

View File

@ -30,6 +30,7 @@
%% API %% API
-export([start/4, -export([start/4,
connect/3, connect/3,
connect/4,
starttls/2, starttls/2,
starttls/3, starttls/3,
compress/1, compress/1,
@ -94,7 +95,10 @@ start(Module, SockMod, Socket, Opts) ->
end. end.
connect(Addr, Port, Opts) -> connect(Addr, Port, Opts) ->
case gen_tcp:connect(Addr, Port, Opts) of connect(Addr, Port, Opts, infinity).
connect(Addr, Port, Opts, Timeout) ->
case gen_tcp:connect(Addr, Port, Opts, Timeout) of
{ok, Socket} -> {ok, Socket} ->
Receiver = ejabberd_receiver:start(Socket, gen_tcp, none), Receiver = ejabberd_receiver:start(Socket, gen_tcp, none),
SocketData = #socket_state{sockmod = gen_tcp, SocketData = #socket_state{sockmod = gen_tcp,