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

Alex Rousskov rousskov at measurement-factory.com
Mon Oct 28 16:05:28 UTC 2024


On 2024-10-28 11:47, Erik Schulz wrote:

> I realized later that I was applying 'localnet' rules before the
> dstdomain rules, which was the cause of the unauthorized dns lookup.
> By rearranging the rules, such that `dstdomain -n` rules are tested
> first, there is no dns lookup.

Glad you are making progress!


> Well, I do see a reverse dns lookup for
> the client's ip, that I can't explain, but even if that is the case,
> it would require client IP spoofing. But I don't understand why the
> reverse lookup happens. I'm only testing `src`, not `srcdomain`.

Check access_log (including its default in your Squid build). Some of 
the logformat %codes require reverse DNS lookups (e.g., %<A). Same for 
icap_log and some other logs, but they are not enabled by default IIRC.

If logs are not to blame directly, check whether your Squid code has the 
equivalent of the following commit (available in v6+ but not in v5 
AFAICT): 
https://github.com/squid-cache/squid/commit/a8c7a1107de9d9365dfe10749821f74aeedac777


If you want to preclude Squid from making prohibited DNS queries, the 
safest bet may be in configuring Squid to use a DNS resolver (running on 
the same box as Squid) that does not make prohibited DNS queries.  And 
whenever that resolver receives a prohibited DNS query, investigate what 
triggered it -- there may be more bugs in Squid that result in unwanted 
DNS queries. Belt and suspenders...


HTH,

Alex.


> ----
> # deny if not authenticated
> auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd
> acl authenticated proxy_auth REQUIRED
> http_access deny !authenticated
> 
> # deny if not allowed domains
> acl user_user2 proxy_auth user2
> acl allowed_domains2 dstdomain -n .example.com
> http_access deny user_user2 !allowed_domains2
> 
> # deny public ip
> acl localnet_src src 0.0.0.1-0.255.255.255
> acl localnet_src src 10.0.0.0/8
> acl localnet_src src 100.64.0.0/10
> acl localnet_src src 169.254.0.0/16
> acl localnet_src src 172.16.0.0/12
> acl localnet_src src 192.168.0.0/16
> acl localnet_src src fc00::/7
> acl localnet_src src fe80::/10
> http_access deny !localnet_src
> 
> # deny local destination (resolved hostname)
> acl localnet_dst dst 0.0.0.1-0.255.255.255
> acl localnet_dst dst 10.0.0.0/8
> acl localnet_dst dst 100.64.0.0/10
> acl localnet_dst dst 169.254.0.0/16
> acl localnet_dst dst 172.16.0.0/12
> acl localnet_dst dst 192.168.0.0/16
> acl localnet_dst dst fc00::/7
> acl localnet_dst dst fe80::/10
> http_access deny localnet_dst
> 
> acl Safe_ports port 80
> acl Safe_ports port 443
> http_access deny !Safe_ports
> 
> cache deny all
> 
> http_access allow
> ----
> 
> Regarding what DNS egress attack is:
> The use of a forward proxy ("egress controller") is to prevent
> unauthorized egress, i.e. leaking any data, including TLS or CA
> private keys, which can be relatively few bytes.
> Unauthorized DNS egress is low bandwidth, but that doesn't matter.
> Here is a ChatGPT explanation of what a DNS egress attack is:
> ---
> A DNS egress attack exploits DNS queries to stealthily extract
> sensitive information from within a network. Here’s how it operates
> and why it’s effective:
> - DNS as a Covert Channel: DNS requests are typically unfiltered and
> allowed through most firewalls. Attackers use DNS requests to
> exfiltrate data by embedding information in DNS queries, which often
> bypasses traditional egress filters.
> - Steganography in DNS Requests: Attackers encode sensitive
> information (like passwords or encryption keys) into DNS request
> subdomains. For example, a query like data1234.attacker.com can encode
> data (data1234) before resolving to the attacker-controlled domain.
> - Recursive Resolver Complicity: Since DNS queries are recursively
> resolved, intermediate DNS resolvers help propagate the data-laden
> requests to the final DNS server controlled by the attacker. This adds
> complexity to tracking and blocking the egress path.
> - Low Detectability: Normal DNS queries blend into typical network
> traffic, making these attacks hard to detect, especially if small
> amounts of data are exfiltrated over time.
> - Mitigation Gaps: Most firewalls overlook the payload within DNS
> queries, focusing instead on blocking IPs or domains, which doesn't
> stop the encoding of sensitive data in the DNS request itself.
> - DNS data egress attacks are potent because they exploit a
> foundational internet protocol for covert data transmission. Solutions
> demand vigilant DNS traffic analysis and strict egress filtering
> policies.
> ---
> 
> On Mon, Oct 28, 2024 at 12:14 AM Alex Rousskov
> <rousskov at measurement-factory.com> wrote:
>>
>> 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.
>>
>> _______________________________________________
>> squid-users mailing list
>> squid-users at lists.squid-cache.org
>> https://lists.squid-cache.org/listinfo/squid-users



More information about the squid-users mailing list