[squid-users] help with acl order and deny_info pages

Amos Jeffries squid3 at treenet.co.nz
Thu Sep 24 11:02:35 UTC 2015


On 24/09/2015 7:30 p.m., Marko Cupać wrote:
> On Sun, 20 Sep 2015 21:43:26 +1200
> Amos Jeffries <squid3 at treenet.co.nz> wrote:
> 
>> On 17/09/2015 7:24 p.m., Marko Cupać wrote:
>>> On Thu, 17 Sep 2015 03:00:56 +1200
>>> Amos Jeffries <squid3 at treenet.co.nz> wrote:
>>>
>>>> On 17/09/2015 12:37 a.m., Marko Cupać wrote:
>>>>> Hi,
>>>>>
>>>>> I'm trying to setup squid in a way that it authenticates users via
>>>>> kerberos and grants different levels of web access according to
>>>>> ldap query of MS AD groups.After some trials and errors I have
>>>>> found acl order which apparently does not trigger
>>>>> reauthentication (auth dialogues in browsers although I don't
>>>>> even provide basic auth).
>>>>
>>>> What makes you think browser dialog box has anything to do with
>>>> Basic auth? All it means is that the browser does not know what
>>>> credentials will work. The ones tried (if any) have been rejected
>>>> with a challenge response (401/407) for valid ones. It may be the
>>>> browser password manager.
>>>>
>>>> If you are using only Kerberos auth then users enter their Kerberos
>>>> username and password into the dialog to allow the browser to fetch
>>>> the Kerberos token (or keytab entry) it needs to send to Squid.
>>>>
>>>>
>>>>> Here's relevant part:
>>>>>
>>>>> http_access deny !Safe_ports
>>>>> http_access deny CONNECT !SSL_ports
>>>>> http_access allow localhost manager
>>>>> http_access deny manager
>>>>> http_access deny to_localhost
>>>>> # INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
>>>>> http_access deny !auth all
>>>>> http_access allow !basic_domains !basic_extensions basic_users
>>>>> http_reply_access allow !basic_mimetypes basic_users
>>>>> http_access allow !advanced_domains !advanced_extensions
>>>>> advanced_users http_access allow expert_users all
>>>>> # INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
>>>>> http_access allow localhost
>>>>> http_access deny all
>>>>>
>>>>> I'd like to know which acl triggered the ban, so I've created
>>>>> custom error page:
>>>>>
>>>>> error_directory /usr/local/etc/squid/myerrors
>>>>> deny_info ERR_BASIC_EXTENSION basic_extensions
>>>>>
>>>>> The problem is that my custom error page does not trigger when I
>>>>> expect it to (member of basic_users accessing URL with extension
>>>>> listed in basic_extensions) - ERR_ACCESS_DENIED is triggered
>>>>> instead. I guess this is because of last matching rule which is
>>>>> http_access deny all.
>>>>
>>>> Perhapse.
>>>>
>>>> But, basic_extensions is never the last listed ACL in a denial
>>>> rule. There is never a deny action associated with the ACL. That
>>>> is why the deny_info response template is not being used.
>>>>
>>>>>
>>>>> Is there another way how I can order acls so that I don't trigger
>>>>> reauthentication while triggering deny_info?
>>>>
>>>> Not without the ACL definition details.
>>>>
>>>> Amos
>>>
>>> Hi Amos,
>>>
>>> thank you for looking into this. Here's complete squid.conf (I
>>> changed just private details such as domain, DN, password etc. in
>>> external_acl_type).
>>>
>>
>> <snip'ing bits of config not relevant to the answer>
>>
>>> auth_param negotiate
>>> program /usr/local/libexec/squid/negotiate_kerberos_auth \ -r -s
>>> GSS_C_NO_NAME
>> <snip>
>>> # ldap query for group membership
>>> external_acl_type adgroups ttl=60 children-startup=2
>>> children-max=10 %LOGIN
>>> \ /usr/local/libexec/squid/ext_ldap_group_acl -R \
>> <snip>
>>
>>
>> These ACLs...
>>
>>> # map ldap groups to squid acls
>>> acl basic_users external adgroups squid_basic
>>> acl advanced_users external adgroups squid_advanced
>>> acl expert_users external adgroups squid_expert
>>
>> ... to here ...
>>
>>
>> <snip>
>>> # require proxy authentication
>>> acl auth proxy_auth REQUIRED
>>
>> ... and the "auth" one will all trigger 407 challenges *if* they are
>> the last ACL on the line. Or if there are no credentials of any kind
>> given in the request.
>>
>>
>>>
>>> # custom error pages
>>> deny_info ERR_BASIC_DOMAIN basic_domains
>>> deny_info ERR_ADVANCED_DOMAIN advanced_domains
>>> deny_info ERR_BASIC_EXTENSION basic_extensions
>>> deny_info ERR_ADVANCED_EXTENSION advanced_extensions
>>>
>> <snip>
>>> # INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
>>> http_access deny !auth all
>>
>> Problem #1:
>>  Any client with halfway decent security will not simply broadcast
>> credentials on their first request of a new TCP connection, but will
>> wait for a 407 challenge to indicate both their need and the type of
>> credentials to send.
>>
>> The "all" on this line will prevent that 407 happening. Instead it
>> will simply produce a plain 403 ERR_ACCESS_DENIED for any request
>> lacking (Kerberos) credentials.
>>
>> NP: you can test whether this is your problem with a custom error
>> page:
>>
>>  acl test1 src all
>>  deny_info 499:ERR_ACCESS_DENIED test1
>>  http_access deny !auth test1
>>
>> Your access.log should show the 499 status when its line matches.
>>
>>
>>> http_access allow !basic_domains !basic_extensions basic_users
>>> http_access allow !advanced_domains !advanced_extensions
>>> advanced_users
>>
>> Basically okay. These will trigger 407 *if* (and only if) the client
>> sent Negotiate/Kerberos credentials AND does not have group permission
>> to access the URL being requested.
>>
>> Be aware this will probably produce the popups allowing users to
>> change their credentials to those of another user account with the
>> right group access. That may or may not be what you want.
>>
>>
>> I usually find that *these* lines are the ones people most want not to
>> popup. You have complex ACL tests so the order can be shuffled to
>> this:
>>
>>   http_access allow !basic_domains basic_users !basic_extensions
>>   http_access allow !advanced_domains
>> advanced_users !advanced_extensions
>>
>> Which prevents the popups from group checking.
>>
>> If you still want to retain the helper load reduction from having the
>> extension test first, then append " all" to each of those lines
>> instead of shuffling.
>>
>>
>>> http_access allow expert_users all
>>
>>
>>> # INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
>>> http_access allow localhost
>>> http_access deny all
>>>
>>
>> Problem 2:
>>
>> Requests which somehow happen to get past the "deny !auth all" rule
>> but not have a domain listed in your *_domains ACLs or _do_ match the
>> paired *_extensions ACLs - will get denied by this final rule.
>>
>> NP: you can test that like the earlier test, but use a different ACL
>> name and 49x status code.
> 
> Amos,
> 
> I'm grateful for your help, but I'm even more confused now. I
> changed http_access rules according to your advices, tried
> different combinations, but I still can't achieve intended
> behaviour. Perhaps I could try to better explain my goals, as maybe
> there is a better way to solve what I'm trying to achieve.
> 
> I want to have 4 levels of web access:
> expert access - if user is part of expert_users ad group
> advanced access - if user is part of advanced_users AD group
> basic access - if user is part of basic_users AD group
> no access - if user is not part of any AD groups
> 

Okay. Your ACLs are defined right for that.

 acl basic_users external adgroups squid_basic
 acl advanced_users external adgroups squid_advanced
 acl expert_users external adgroups squid_expert


> Here's the difference in web access for groups:
> expert access - allow all
> advanced access - allow except some extensions and domains
> basic access - allow except some more extensions and domains
> no access - allow nothing

Which is:

  # authentication required for any access at all
  http_access deny !auth

  # expert access - allow all
  http_access allow expert_users all

  # advanced access - allow except some extensions and domains
  http_access deny some_domains
  http_access deny some_extensions
  http_access allow advanced_users all

  # basic access - allow except some more extensions and domains
  http_access deny more_domains
  http_access deny more_extensions
  http_access allow basic_users all

  # no access - allow nothing
  http_access deny all


What you need to add to this is deny_info for each of the "deny" lines
ACL. You can have two templates one for domains and one for extensions.
Re-use the ext template for both of the some_extensions and
more_extensions. Ditto for the domains template.

> 
> When a user is redirected to error page, there should be enough info
> about error:
> - user as seen by squid (or no user if not authenticated)
> - group as seen by squid (or no group)
> - acl that triggered the ban (not the last deny rule)

This is not possible. It is always the combination of multiple ACLs
matching and non-matching that leads to a denial.

The closest you can get is the above config with one ACL per line/rule
and a deny_info for each of the ones used on deny lines.


The codes that can be used in the error pages are detailed at
<http://wiki.squid-cache.org/Features/CustomErrors>
specifically the %a code can be used to expand the user name. But the
group and ACL name details are not passed and would have to be inferred
by which template is being used.

Amos


More information about the squid-users mailing list