Skip to content

Squid connector

The Squid connector — binary enforcegate-squid-connector, configured by squid-connector.conf — runs in one of two Squid helper roles:

  • url_rewrite_program (default invocation, the historical role) — receives every URL Squid sees and forwards the request to the engine for evaluation. The engine returns a verdict (permit, deny, warn, AUP) and the connector translates it back to Squid as either an unchanged URL (permit), a 302 redirect URL (block / warn / AUP verdicts), or a rewritten URL (advanced use).
  • external_acl_type (--acl invocation, new in 2026.35.0) — runs as a Squid external-ACL helper consulted at the SslBump peek step. Returns splice / bump / terminate for cert-pinned destinations the engine has policy on — see Pinned destinations. The fallback behaviour when the helper can't reach the engine is configured via [ssl_bump_acl].fail_action.

The two roles are wired into Squid by the deployment / toolbox layer (the generated squid.conf and inspect.conf), not by operators directly. Both roles open their own Defendr session to the engine over the same protocol; a deployment running both shows them as separate rows in show neighbor summary.

Communication with the engine uses the proprietary Defendr binary protocol over TCP, upgraded to TLS after mutual authentication.

Squid maintains a pool of connector processes (5 by default in the standalone image). Each helper holds a long-lived Defendr session to the engine; the engine's show-neighbor-summary reports one row per connector helper.

The connector binary is /usr/local/bin/enforcegate-squid-connector inside the standalone image. It runs as the squid user (added to the enforcegate group by the Dockerfile so it can read the shared config files).

Stdout is reserved for Squid

The connector's LoggerConsole (when [logging].type = "console") writes its log output to stderr, never stdout. Stdout is the url_rewrite_program protocol channel — every line on it is parsed by Squid as a verdict response, so any other content would corrupt the protocol.

In a container, docker logs captures both streams interleaved (with the connector's lines tagged [connector] by the container log pipeline). For a bare-metal Squid forwarding to a remote engine, redirect them separately: 2>connector.log.

SIGTERM is normal

Squid sends SIGTERM to surplus connector helpers when load drops (the idle= argument to url_rewrite_children controls this). The connector logs SIGTERM received, exiting at [info] — this is expected behaviour, not an error. Squid spawns replacements on demand.

Configuration file

The connector reads its configuration from a TOML file. The default location is /etc/enforcegate/squid-connector.conf.

[global]

The [global] section defines per-connector identification parameters and timers.

Name Type Description Default
asn string Connector's Autonomous System Number (ASN). 64512
ip string Connector's identifier in dotted-decimal notation. 127.0.0.1
retry integer Retry timer interval, in milliseconds. 30000
timeout integer Timeout timer interval, in milliseconds. 60000
dead integer Dead timer interval, in milliseconds. 180000

asn

The Autonomous System Number (ASN) of the connector. A unique 16-bit integer (1–65534) identifying a distinct administrative entity in the EnforceGate ecosystem. Default 64512.

ip

The connector's identifier. As of this writing it is used solely for administrative purposes and does not necessarily reflect the actual source IP of the engine session.

retry

Retry timer interval in milliseconds. Default 30 000 ms (30 s).

timeout

Duration after which an inactive engine is considered timed out. A keepalive is sent to verify the engine is still alive.

dead

Time after which an unresponsive engine is declared dead. The connector tears down the local session state and re-establishes from scratch.

[engine.<name>]

One sub-table per engine that the connector is allowed to connect to. The standalone image ships with exactly one entry ([engine.remote], pointing at loopback) and the engine pinned to the same host.

Name Type Description Default Required
net string Transport protocol (currently only "tcp"). "tcp" Optional
host string Hostname or IP address of the engine. Mandatory
port integer Engine destination port (Defendr listener). 11224 Optional
key string Shared authentication key. Mandatory

Example:

[engine.remote]
net  = "tcp"
host = "127.0.0.1"
port = 11224
key  = "abcdef1234567890"

host

The hostname or IP address of the engine.

port

The TCP port to connect to. Default 11224 matches the engine's [connectors.local] listener.

key

Mandatory key attribute

EnforceGate enforces mutual peer authentication between the engine and the connectors. The key attribute is mandatory and must be explicitly configured. The connector silently aborts with no diagnostic if the key is missing.

The shared authentication key for mutual peer authentication. Any string of up to 128 characters; longer keys are truncated. Must match the engine's [connectors.<name>].key value (case-sensitive).

In the standalone image, the generate-engine-key boot one-shot writes the same random 32-character key into both files on first boot.

[redirector]

The [redirector] table configures how the connector parses the request line Squid pipes to it on stdin.

Name Type Description Default
request_line_format integer Squid request-line format the connector expects. 1

request_line_format

  • 0standard. URL only, all other Squid macros ignored. The engine sees only the URL — no client IP, no SNI, no headers. The captive-portal "Proceed anyway" CTA cannot be rendered in this mode (the ack_token emit precondition checks !clientIp.empty()).
  • 1QF-3 (default). URL plus 17 tab-separated extras parsed positionally into the engine's HTTPAttributes (client IP, MAC, username, listener IP/port, method, protocol, scheme, TLS version, SNI, domain, port, path, User-Agent, Referer, Accept, Accept-Language). Must be paired with the corresponding url_rewrite_extras directive in squid.conf — see Squid integration below.

[tls]

The [tls] section governs the connector's TLS posture when connecting to the engine.

Name Type Description Default
disable bool Disable TLS support. false

disable

Disable TLS support entirely. The connector will not attempt to upgrade the Defendr session to TLS and will use unencrypted communication instead.

Security risks

We strongly recommend against disabling TLS. Disabling it leaves all communication between the engine and the connector vulnerable to man-in-the-middle attacks and eavesdropping. Disable only on loopback inside a single container for explicit performance benchmarking.

Performance considerations

Disabling TLS may improve performance by reducing the per-request processing overhead associated with encryption — at the cost of security. The shipped standalone image uses TLS by default even on loopback for defence in depth.

[ssl_bump_acl]

Consulted only when the connector is launched in --acl mode (Squid external_acl_type helper role; the url_rewrite_program role is separate). The connector returns a peek-step verdict to Squid based on the engine's pin: rules — see Pinned destinations.

Name Type Description Default
fail_action string The verdict the helper returns when it can't reach the engine (session down, timeout). One of splice, bump, terminate. Default splice for availability — pinned apps keep working through an engine blip instead of breaking under a forced bump. bump is the right choice for inspection-first deployments; terminate for fail-closed postures. "splice"

The --acl connector role is wired by the deployment layer (the generated inspect.conf / init-ssl-bump.sh), not authored by operators directly. Operators set fail_action if their availability vs inspection trade-off differs from the default.

Squid integration

In the standalone image the connector is launched by Squid as a url_rewrite_program helper. The shipped squid.conf carries:

squid.conf (shipped default)
url_rewrite_program /usr/local/bin/enforcegate-squid-connector -c /etc/enforcegate/squid-connector.conf
url_rewrite_children 5 startup=1 idle=1 concurrency=0
url_rewrite_extras "%>a\t%>eui\t%un\t%>la\t%>lp\t%>rm\t%>rv\t%>rs\t%ssl::>negotiated_version\t%ssl::>sni\t%>rd\t%>rP\t%>rp\t%{User-Agent}>h\t%{Referer}>h\t%{Accept}>h\t%{Accept-Language}>h"

acl CONNECT method CONNECT
url_rewrite_access deny CONNECT
url_rewrite_access allow all

url_rewrite_bypass off

The url_rewrite_extras macros are TAB-separated (literal U+0009, not the two-character escape) and parsed positionally by the connector. A field-count mismatch throws on the first request with a clear diagnostic — there is no silent fallback.

CONNECT requests are not sent to the rewriter

url_rewrite_access deny CONNECT ensures the connector is never asked about a CONNECT host:port request. Without this guard, a blocked-host policy would respond with a deny-redirect URL, Squid would emit HTTP/1.1 302 Found on the CONNECT itself (a protocol violation), and browsers would surface NS_ERROR_CONNECTION_REFUSED. With ssl_bump active, blocking still works end-to-end: Squid bumps the CONNECT, the in-plaintext inner GET flows through the rewriter, and the deny-redirect is delivered inside the bumped TLS session.

For deploying a standalone Squid on a different host that forwards to a remote EnforceGate engine, replicate this stanza in that host's squid.conf, install the enforcegate-squid-connector binary plus its squid-connector.conf (with [engine.remote].host pointing at the engine's reachable address), and ensure the connector binary has read access to the conf file.