On 11/10/23 08:19, Alex Rousskov wrote:
On 2023-10-10 12:17, Francesco Chemolli wrote:
what if we removed the configure option for FOLLOW_X_FORWARDED_FOR, and
made it unconditionally part of Squid?
Some Squid deployments will silently break AFAICT.
In what way specifically?
It is on by default,
Here, "it" should be viewed as a combination of FOLLOW_X_FORWARDED_FOR
and the directives that macro enables (by default). Unfortunately, some
of those directives are on by default[1]. This implies that, after we
remove FOLLOW_X_FORWARDED_FOR, a Squid built with
--disable-follow-x-forwarded-for will start doing something it was not
doing before, and the behavior changes should be assumed to be
significant until you can prove otherwise.
The Proof is in cf.data.pre:
"
NAME: follow_x_forwarded_for
...
DEFAULT_IF_NONE: deny all
DEFAULT_DOC: X-Forwarded-For header will be ignored.
"
Removing FOLLOW_X_FORWARDED_FOR will make installations which previously
were not able to run with follow_x_forwarded_for configured would begin
behaving as if "follow_x_forwarded_for deny all" was configured.
That is behaviorally the same as --disable-follow-x-forwarded-for.
and it is controlled by runtime configuration,
... but not in a good way: Squid code cannot tell whether
follow_x_forwarded_for is "enabled" beyond checking
FOLLOW_X_FORWARDED_FOR. It is possible to change that, but changing that
(and adjusting how other related directives are checked!) requires
non-trivial work. See (B) below.
I do not see a transition problem here.
As per the above cf.data.pre contents, only installations which already
were using --enable-follow-x-forwarded-for were able to set the related
configuration options. They would not see any change.
removing the compile-time option would ensure we have better testing
coverage.
Indeed. I support removal of this and similar unnecessary compile-time
options, but because related directives[1] are _on_ by default (in
--enable-follow-x-forwarded-for and equivalent builds), we should not
just enable this feature, screwing up folks that disabled it explicitly
in their builds.
IMO that is easily resolved. Just drop the DEFAULT_IF_NONE stanza from
cf.data.pre and modify the if-statement in
ClientRequestContext::clientAccessCheck() to set
http->request->indirect_client_addr whenever
"!Config.accessList.followXFF".
That will avoid any "screwing over" because the "indirect" IP would be
the same as the "direct" IP under the above default
follow_x_forwarded_for behavior.
Even if admin has misconfigured one of those *_indirect_client settings
the implicit/default "follow_x_forwarded_for deny all" makes the correct
IP be used.
Also, the current implementation of XFF code is fairly expensive -- it
requires slow ACL checks. If we just remove that FOLLOW_X_FORWARDED_FOR
guard, we will be adding quite a few wasted CPU cycles to all Squid
builds that (used to) disable that feature.
Dropping the "DEFAULT_IF_NONE" stanza entirely avoids all the ACL costs
by default, without changing the above behavior analysis that proves IMO
this feature as safe to enable.
Bonus: it would also avoid the ACL cycles currently wasted on
installations where the feature is already enabled but not configured.
Extra bonus: any logic which specifically relies on testing
(!)FOLLOW_X_FORWARDED_FOR can switch to checking
(!)Config.accessList.followXFF instead.
[1] squid.conf directives that are enabled by default in
--enable-follow-x-forwarded-for and equivalent builds include:
log_uses_indirect_client, adaptation_uses_indirect_client,
acl_uses_indirect_client, delay_pool_uses_indirect_client.
I see a few possible strategies here:
A) Make ./configure --disable-follow-x-forwarded-for fail. Easy to
implement but kind of goes against ./configure tradition and leaves a
backward compatibility hack in Squid code. It also forces admins that do
_not_ want this feature to disable 4+ directives they do not care about
-- bad UX. I am against this option.
Unnecessary. For reasons detailed above.
B) Make all *_uses_indirect_client and similar directives default to off
unless the configuration contains an explicit follow_x_forwarded_for
rule.
Warn if one of those directives is explicitly on when there are no
explicit follow_x_forwarded_for rules. This requires non-trivial work.
IMO this is optional. A "nice to have" UI behaviour that a lot of
squid.conf settings could do, but do not (yet).
The future ConfigParser redesign project changes are likely to make this
type of check a lot easier to implement in an entirely different way
than it would have to be done right now. So IMO there is no hurry to
rush/require this change.
That work will probably fix a few existing bugs. I support this option.
C) Just drop the DEFAULT_IF_NONE stanza from cf.data.pre and modify the
if-statement in ClientRequestContext::clientAccessCheck() like so:
"
if (!http->request->flags.doneFollowXff()) {
/* we always trust the direct client address for actual use */
http->request->indirect_client_addr = http->request->client_addr;
http->request->indirect_client_addr.port(0);
if (Config.accessList.followXFF &&
http->request->header.has(Http::HdrType::X_FORWARDED_FOR)) {
... current logic except above indirect_client_addr lines ...
}
return;
}
"
HTH
Amos
_______________________________________________
squid-dev mailing list
squid-dev@lists.squid-cache.org
https://lists.squid-cache.org/listinfo/squid-dev