mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-22 16:20:52 +01:00
Support for X-Forwarded-For HTTP header (EJAB-1356)
This commit is contained in:
parent
ce0219c569
commit
74f86bef6a
@ -807,7 +807,7 @@ The available modules, their purpose and the options allowed by each one are:
|
|||||||
\titem{\texttt{ejabberd\_http}}
|
\titem{\texttt{ejabberd\_http}}
|
||||||
Handles incoming HTTP connections.\\
|
Handles incoming HTTP connections.\\
|
||||||
Options: \texttt{captcha}, \texttt{certfile}, \texttt{http\_bind}, \texttt{http\_poll},
|
Options: \texttt{captcha}, \texttt{certfile}, \texttt{http\_bind}, \texttt{http\_poll},
|
||||||
\texttt{request\_handlers}, \texttt{tls}, \texttt{web\_admin}\\
|
\texttt{request\_handlers}, \texttt{tls}, \texttt{trusted\_proxies}, \texttt{web\_admin}\\
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
|
|
||||||
@ -929,6 +929,10 @@ This is a detailed description of each option allowed by the listening modules:
|
|||||||
which can be enabled in \ejabberd{} with the option \term{starttls}.
|
which can be enabled in \ejabberd{} with the option \term{starttls}.
|
||||||
If this option is set, you should also set the \option{certfile} option.
|
If this option is set, you should also set the \option{certfile} option.
|
||||||
The option \term{tls} can also be used in \term{ejabberd\_http} to support HTTPS.
|
The option \term{tls} can also be used in \term{ejabberd\_http} to support HTTPS.
|
||||||
|
\titem{\{trusted\_proxies, all | [IpString]\}} \ind{options!trusted\_proxies}
|
||||||
|
Specify what proxies are trusted when an HTTP request contains the header \term{X-Forwarded-For}
|
||||||
|
You can specify \term{all} to allow all proxies, or specify a list of IPs in string format.
|
||||||
|
The default value is: \term{["127.0.0.1"]}
|
||||||
\titem{web\_admin} \ind{options!web\_admin}\ind{web admin}This option
|
\titem{web\_admin} \ind{options!web\_admin}\ind{web admin}This option
|
||||||
enables the Web Admin for \ejabberd{} administration which is available
|
enables the Web Admin for \ejabberd{} administration which is available
|
||||||
at \verb|http://server:port/admin/|. Login and password are the username and
|
at \verb|http://server:port/admin/|. Login and password are the username and
|
||||||
|
@ -366,13 +366,15 @@ process_request(#state{request_method = Method,
|
|||||||
LQ ->
|
LQ ->
|
||||||
LQ
|
LQ
|
||||||
end,
|
end,
|
||||||
{ok, IP} =
|
{ok, IPHere} =
|
||||||
case SockMod of
|
case SockMod of
|
||||||
gen_tcp ->
|
gen_tcp ->
|
||||||
inet:peername(Socket);
|
inet:peername(Socket);
|
||||||
_ ->
|
_ ->
|
||||||
SockMod:peername(Socket)
|
SockMod:peername(Socket)
|
||||||
end,
|
end,
|
||||||
|
XFF = proplists:get_value('X-Forwarded-For', RequestHeaders, []),
|
||||||
|
IP = analyze_ip_xff(IPHere, XFF, Host),
|
||||||
Request = #request{method = Method,
|
Request = #request{method = Method,
|
||||||
path = LPath,
|
path = LPath,
|
||||||
q = LQuery,
|
q = LQuery,
|
||||||
@ -412,13 +414,15 @@ process_request(#state{request_method = Method,
|
|||||||
request_headers = RequestHeaders,
|
request_headers = RequestHeaders,
|
||||||
request_handlers = RequestHandlers} = State)
|
request_handlers = RequestHandlers} = State)
|
||||||
when (Method=:='POST' orelse Method=:='PUT') andalso is_integer(Len) ->
|
when (Method=:='POST' orelse Method=:='PUT') andalso is_integer(Len) ->
|
||||||
{ok, IP} =
|
{ok, IPHere} =
|
||||||
case SockMod of
|
case SockMod of
|
||||||
gen_tcp ->
|
gen_tcp ->
|
||||||
inet:peername(Socket);
|
inet:peername(Socket);
|
||||||
_ ->
|
_ ->
|
||||||
SockMod:peername(Socket)
|
SockMod:peername(Socket)
|
||||||
end,
|
end,
|
||||||
|
XFF = proplists:get_value('X-Forwarded-For', RequestHeaders, []),
|
||||||
|
IP = analyze_ip_xff(IPHere, XFF, Host),
|
||||||
case SockMod of
|
case SockMod of
|
||||||
gen_tcp ->
|
gen_tcp ->
|
||||||
inet:setopts(Socket, [{packet, 0}]);
|
inet:setopts(Socket, [{packet, 0}]);
|
||||||
@ -468,6 +472,31 @@ process_request(State) ->
|
|||||||
ejabberd_web:make_xhtml([#xmlel{ns = ?NS_XHTML, name = 'h1', children =
|
ejabberd_web:make_xhtml([#xmlel{ns = ?NS_XHTML, name = 'h1', children =
|
||||||
[#xmlcdata{cdata = <<"400 Bad Request">>}]}])).
|
[#xmlcdata{cdata = <<"400 Bad Request">>}]}])).
|
||||||
|
|
||||||
|
%% Support for X-Forwarded-From
|
||||||
|
analyze_ip_xff(IP, [], _Host) ->
|
||||||
|
IP;
|
||||||
|
analyze_ip_xff({IPLast, Port}, XFF, Host) ->
|
||||||
|
[ClientIP | ProxiesIPs] = string:tokens(XFF, ", ")
|
||||||
|
++ [inet_parse:ntoa(IPLast)],
|
||||||
|
TrustedProxies = case ejabberd_config:get_local_option(
|
||||||
|
{trusted_proxies, Host}) of
|
||||||
|
undefined -> [];
|
||||||
|
TPs -> TPs
|
||||||
|
end,
|
||||||
|
IPClient = case is_ipchain_trusted(ProxiesIPs, TrustedProxies) of
|
||||||
|
true ->
|
||||||
|
{ok, IPFirst} = inet_parse:address(ClientIP),
|
||||||
|
?DEBUG("The IP ~w was replaced with ~w due to header "
|
||||||
|
"X-Forwarded-For: ~s", [IPLast, IPFirst, XFF]),
|
||||||
|
IPFirst;
|
||||||
|
false ->
|
||||||
|
IPLast
|
||||||
|
end,
|
||||||
|
{IPClient, Port}.
|
||||||
|
is_ipchain_trusted(_UserIPs, all) ->
|
||||||
|
true;
|
||||||
|
is_ipchain_trusted(UserIPs, TrustedIPs) ->
|
||||||
|
[] == UserIPs -- ["127.0.0.1" | TrustedIPs].
|
||||||
|
|
||||||
recv_data(State, Len) ->
|
recv_data(State, Len) ->
|
||||||
recv_data(State, Len, []).
|
recv_data(State, Len, []).
|
||||||
|
Loading…
Reference in New Issue
Block a user