Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions src/anyp/TrafficMode.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,22 @@ namespace AnyP
class TrafficMode
{
public:
/** marks HTTP accelerator (reverse/surrogate proxy) traffic
/** marks HTTP Proxy (forward proxy) traffic
*
* Indicating the following are required:
* - URL in absolute form (exceptions for CONNECT and OPTIONS methods)
* - NAT is prohibited
* - WWW-Auth* is restricted to cache manager
*/
Comment thread
yadij marked this conversation as resolved.
bool forwardProxy = false;

/** marks HTTP Gateway (accelerator/reverse/surrogate proxy) traffic
*
* Indicating the following are required:
* - URL translation from relative to absolute form
* - restriction to origin peer relay recommended
*/
bool accelSurrogate = false;
bool gatewaySurrogate = false;

/** marks ports receiving PROXY protocol traffic
*
Expand Down Expand Up @@ -73,10 +82,11 @@ class TrafficMode
*/
bool tunnelSslBumping = false;

/** true if the traffic is in any way intercepted
*
*/
bool isIntercepted() { return natIntercept||tproxyIntercept ;}
/// whether the traffic is in any way intercepted
bool isIntercepted() const { return natIntercept||tproxyIntercept ;}

/// whether HTTP proxy (forward-proxy) traffic is expected
bool isForwardProxy() const { return forwardProxy || (!gatewaySurrogate && !isIntercepted()); }
Copy link
Copy Markdown
Contributor

@rousskov rousskov Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see no reason to imply that there is some other (unnamed) mode that has the same "forward proxy" meaning as forwardProxy mode. If we add a forwardProxy data member, it should be mutually exclusive with the other port modes (even if this new mode does not have to be explicitly set in squid.conf).

Suggested change
bool isForwardProxy() const { return forwardProxy || (!gatewaySurrogate && !isIntercepted()); }
bool isForwardProxy() const { return forwardProxy; }

Edit: GitHub duplicated an earlier version of this change request while I was writing my review. I have deleted that earlier variation after spotting it in the posted review version.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method needs to return true when neither accel/gateway nor intercept/tproxy mode has been set. For backward compatibility with existing configurations before "proxy" mode existed as a setting.

};

} // namespace AnyP
Expand Down
119 changes: 57 additions & 62 deletions src/cache_cf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3479,47 +3479,7 @@ parse_port_option(AnyP::PortCfgPointer &s, char *token)
{
/* modes first */

if (strcmp(token, "accel") == 0) {
if (s->flags.isIntercepted()) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": Accelerator mode requires its own port. It cannot be shared with other modes.");
self_destruct();
return;
}
s->flags.accelSurrogate = true;
s->vhost = true;
} else if (strcmp(token, "transparent") == 0 || strcmp(token, "intercept") == 0) {
if (s->flags.accelSurrogate || s->flags.tproxyIntercept) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": Intercept mode requires its own interception port. It cannot be shared with other modes.");
self_destruct();
return;
}
s->flags.natIntercept = true;
Ip::Interceptor.StartInterception();
/* Log information regarding the port modes under interception. */
debugs(3, DBG_IMPORTANT, "Starting Authentication on port " << s->s);
debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (interception enabled)");
} else if (strcmp(token, "tproxy") == 0) {
if (s->flags.natIntercept || s->flags.accelSurrogate) {
debugs(3,DBG_CRITICAL, "FATAL: " << cfg_directive << ": TPROXY option requires its own interception port. It cannot be shared with other modes.");
self_destruct();
return;
}
s->flags.tproxyIntercept = true;
Ip::Interceptor.StartTransparency();
/* Log information regarding the port modes under transparency. */
debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (TPROXY enabled)");

if (s->flags.proxySurrogate) {
debugs(3, DBG_IMPORTANT, "Disabling TPROXY Spoofing on port " << s->s << " (require-proxy-header enabled)");
}

if (!Ip::Interceptor.ProbeForTproxy(s->s)) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": TPROXY support in the system does not work.");
self_destruct();
return;
}

} else if (strcmp(token, "require-proxy-header") == 0) {
if (strcmp(token, "require-proxy-header") == 0) {
s->flags.proxySurrogate = true;
if (s->flags.tproxyIntercept) {
// receiving is still permitted, so we do not unset the TPROXY flag
Expand All @@ -3528,61 +3488,61 @@ parse_port_option(AnyP::PortCfgPointer &s, char *token)
}

} else if (strncmp(token, "defaultsite=", 12) == 0) {
if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": defaultsite option requires Acceleration mode flag.");
if (!s->flags.gatewaySurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": defaultsite option requires 'gateway' mode flag.");
self_destruct();
return;
}
safe_free(s->defaultsite);
s->defaultsite = xstrdup(token + 12);
} else if (strcmp(token, "vhost") == 0) {
if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "WARNING: " << cfg_directive << ": vhost option is deprecated. Use 'accel' mode flag instead.");
if (!s->flags.gatewaySurrogate) {
debugs(3, DBG_CRITICAL, "WARNING: " << cfg_directive << ": vhost option is deprecated. Use 'gateway' mode flag instead.");
}
s->flags.accelSurrogate = true;
s->flags.gatewaySurrogate = true;
s->vhost = true;
} else if (strcmp(token, "no-vhost") == 0) {
if (!s->flags.accelSurrogate) {
debugs(3, DBG_IMPORTANT, "ERROR: " << cfg_directive << ": no-vhost option requires Acceleration mode flag.");
if (!s->flags.gatewaySurrogate) {
debugs(3, DBG_IMPORTANT, "ERROR: " << cfg_directive << ": no-vhost option requires 'gateway' mode flag.");
}
s->vhost = false;
} else if (strcmp(token, "vport") == 0) {
if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": vport option requires Acceleration mode flag.");
if (!s->flags.gatewaySurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": vport option requires 'gateway' mode flag.");
self_destruct();
return;
}
s->vport = -1;
} else if (strncmp(token, "vport=", 6) == 0) {
if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": vport option requires Acceleration mode flag.");
if (!s->flags.gatewaySurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": vport option requires 'gateway' mode flag.");
self_destruct();
return;
}
s->vport = xatos(token + 6);
} else if (strncmp(token, "protocol=", 9) == 0) {
if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": protocol option requires Acceleration mode flag.");
if (!s->flags.gatewaySurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": protocol option requires 'gateway' mode flag.");
self_destruct();
return;
}
s->transport = parsePortProtocol(ToUpper(SBuf(token + 9)));
} else if (strcmp(token, "allow-direct") == 0) {
if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": allow-direct option requires Acceleration mode flag.");
if (!s->flags.gatewaySurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": allow-direct option requires 'gateway' mode flag.");
self_destruct();
return;
}
s->allow_direct = true;
} else if (strcmp(token, "act-as-origin") == 0) {
if (!s->flags.accelSurrogate) {
debugs(3, DBG_IMPORTANT, "ERROR: " << cfg_directive << ": act-as-origin option requires Acceleration mode flag.");
if (!s->flags.gatewaySurrogate) {
debugs(3, DBG_IMPORTANT, "ERROR: " << cfg_directive << ": act-as-origin option requires 'gateway' mode flag.");
} else
s->actAsOrigin = true;
} else if (strcmp(token, "ignore-cc") == 0) {
#if !USE_HTTP_VIOLATIONS
if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": ignore-cc option requires Acceleration mode flag.");
if (!s->flags.gatewaySurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": ignore-cc option requires 'gateway' mode flag.");
self_destruct();
return;
}
Expand Down Expand Up @@ -3694,6 +3654,37 @@ parse_port_option(AnyP::PortCfgPointer &s, char *token)
}
}

static void
parse_port_mode(AnyP::PortCfgPointer &s, char *token)
{
if (strcmp(token, "proxy") == 0) {
s->flags.forwardProxy = true;

} else if (strcmp(token, "gateway") == 0 || strcmp(token, "accel") == 0) {
s->flags.gatewaySurrogate = true;
s->vhost = true;

} else if (strcmp(token, "transparent") == 0 || strcmp(token, "intercept") == 0) {
s->flags.natIntercept = true;
Ip::Interceptor.StartInterception();
/* Log information regarding the port modes under interception. */
debugs(3, DBG_IMPORTANT, "Starting Authentication on port " << s->s);
debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (interception enabled)");

} else if (strcmp(token, "tproxy") == 0) {
s->flags.tproxyIntercept = true;
Ip::Interceptor.StartTransparency();
/* Log information regarding the port modes under transparency. */
debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (TPROXY enabled)");

if (!Ip::Interceptor.ProbeForTproxy(s->s))
throw TextException("TPROXY support in the system does not work.", Here());
} else {
// not a mode, check as option.
parse_port_option(s, token);
}
}

void
add_http_port(char *portspec)
{
Expand Down Expand Up @@ -3733,6 +3724,10 @@ parsePortCfg(AnyP::PortCfgPointer *head, const char *optionName)
s->transport = parsePortProtocol(protoName); // default; protocol=... overwrites
parsePortSpecification(s, token);

// port mode (or first option)
if ((token = ConfigParser::NextToken()))
parse_port_mode(s, token);

/* parse options ... */
while ((token = ConfigParser::NextToken())) {
parse_port_option(s, token);
Expand Down Expand Up @@ -3815,7 +3810,7 @@ dump_generic_port(StoreEntry * e, const char *n, const AnyP::PortCfgPointer &s)
else if (s->flags.proxySurrogate)
storeAppendPrintf(e, " require-proxy-header");

else if (s->flags.accelSurrogate) {
else if (s->flags.gatewaySurrogate) {
storeAppendPrintf(e, " accel");

if (s->vhost)
Expand Down Expand Up @@ -3847,7 +3842,7 @@ dump_generic_port(StoreEntry * e, const char *n, const AnyP::PortCfgPointer &s)
storeAppendPrintf(e, " name=%s", s->name);

#if USE_HTTP_VIOLATIONS
if (!s->flags.accelSurrogate && s->ignore_cc)
if (!s->flags.gatewaySurrogate && s->ignore_cc)
storeAppendPrintf(e, " ignore-cc");
#endif

Expand Down
Loading
Loading