[squid-users] Help regarding access controls for TLS connections

Alex Rousskov rousskov at measurement-factory.com
Sun Oct 27 23:14:27 UTC 2024


On 2024-10-25 18:18, Erik Schulz wrote:

> I would like to use squid as an egress proxy, to prevent unauthorized egress.
> 
> Let's say that the only allowed egress is 'example.com'.
> I can define acl along the lines of:
> ```
> acl allowed_domains ssl::server_name .example.com
> http_access allow allowed_domains
> ```

> But can someone help me understand what actually happens?

A lot of thing happens, including: After parsing received HTTP(S) or FTP 
request, Squid checks http_access rules and either allows or denies the 
request. For HTTPS requests that are subject to ssl_bump rules, that 
processing happens multiple times, at various SslBump steps, as detailed 
at https://wiki.squid-cache.org/Features/SslPeekAndSplice

N.B. http_access check is a part of "Callout Sequence" referenced on the 
above page in step1 and step2. There are some bugs in the current Squid 
implementation of that document, but it is still a useful starting point.


> I want to avoid any DNS egress attack.

How do you define "DNS egress attack"? To the extent possible, please 
answer in terms of what Squid should or should not do with traffic Squid 
receives.


> The client does not have DNS access.
> Am I correct that the client can use HTTPS_PROXY without DNS, such
> that the proxy will perform the DNS lookup?

If you do not control the client, then you should assume that it can 
send any request to/through Squid. This includes sending an HTTPS 
requests without using DNS. Whether the proxy receiving the request is 
going to perform a DNS lookup is a separate question. Many factors 
affect that proxy decision.


> Can you help me understand how the acl checks the server_name?

You already know how server_name documentation answers this question. It 
is not clear to me what undocumented aspects you want to know about. 
Could you please clarify by asking a more specific question?


> In order to connect to the server, it must perform a DNS lookup, which
> causes a leak.

Sorry, I am not sure what "it" is in this context, but, as you probably 
already know from the same docs, "Unlike dstdomain, [ssl::server_name] 
ACL does not perform DNS lookups."

If Squid needs to connect to server X, and X is a domain name, Squid 
will (in most cases) attempt to resolve X to get server IP address(es), 
but that attempt happens before and/or after Sqiud evaluates 
ssl::server_name ACL.


> So the ACL must validate the server_name without a DNS lookup, and
> since the server IP is therefore unknown, without connecting to the
> server or verifying against its certificate.

During server_name ACL evaluation, Squid does not attempt to connection 
to any other server or service. The ACL match/mismatch decision is made 
by comparing various strings using either domain comparison function 
(for server_name) or regex evaluation (for server_name_regex).

The server IP address may or may not be known at ssl::server_name 
evaluation time.


> I'm assuming the hostname is known in the CONNECT phase of the request?

Assuming that CONNECT request has arrived at http_port, the answer 
depends on many factors, possibly including:

* whether the client supplied a hostname in CONNECT request headers;
* whether the client supplied a hostname in TLS SNI field;
* whether the CONNECT request is subject to ssl_bump rules;
* whether Squid is opening a tunnel to an origin server or cache_peer

> Is it possible to check against the connect hostname only?

Without SslBump, "dstdomain -n" would probably do that. With SslBump, 
"dstdomain -n" would probably do that during SslBump step1 (and step2 if 
client does not supply TLS SNI). All this needs careful testing though; 
there are many configuration parameters and request specifics at play here!


> The docs say that
>> "The ACL computes server name(s) using such information sources as CONNECT request URI, TLS client SNI, and TLS server certificate subject (CN and SubjectAltName). The computed server name(s) usually change with each SslBump step"
> 
> I find this concerning, because I assume the client could perform a
> request with an IP, and a forged SNI name that passes the acl.
> So I would like to only allow requests that declare FQDN hostname, and
> reject IP hostnames.

You probably can use dstdomain_reject to reject IP-based hostnames, but 
it may not be easy to do it reliably using regular expressions because 
IP addresses come in many forms. Squid is probably missing an 
"dst_is_ip" or similar ACL(s) to make such checks reliable.


> And, only perform validation against the CONNECT request URI.

See above regarding using "dstdomain -n" for this.


HTH,

Alex.



More information about the squid-users mailing list