====== Squid - ACLs ======
ACLs (Access Control Lists) define who can and who cannot access which web pages when.
ACLs are processed sequentially, and must be defined before they can be used.
Complete list of [[Squid:ACLs:ACL Types|ACL Types]].
[[Squid:ACLs:ACL Example Usage|ACL Example Usage]].
----
===== ACL Syntax =====
acl name type definition1 definition2 definition3 ...
* **name**: Can be chosen arbitrarily.
* **type**: See [[Squid:ACLs:ACL Types|ACL Types]] for the different options. This can be also found in the ACCESS CONTROLS section in the /etc/squid/squid.conf file.
* **definitions...**: Depends on the individual ACL type and can also be read from a file. For example, “via” host names, IP addresses, or URLs.
Examples:
acl access_to_google dstdomain .google.com
acl access_to_search_engines dstdomain .yahoo.com .google.com
acl access_from_marketing_department src 10.52.0.0/16
acl need_to_authenticate proxy_auth
**NOTE:** Defining the ACLs alone does not actually block anything – it’s just a definition.
You must also define the access they need - see further below.
You can also use lists of definitions that are stored in files on your hard disk.
Let’s assume you have a list of search engines URLs that you want to allow:
.google.com
.yahoo.com
.altavista.com
Then the ACL for that file would look like:
acl access_to_search_engines dstdomain "/etc/squid/search-engines-urls.txt"
**NOTE:** The quotes are important here to tell Squid it needs to look up definitions in that file.
----
===== Using the ACLs - http_access =====
ACLs can be used in various places of your squid.conf.
The most useful feature is the **http_access** statement. It works similar to the way a firewall would handle rules.
**http_access** defines who is allowed to use the proxy and who can access what on the Internet.
* For each request that Squid receives it will look through all the **http_access** statements in order, from top to bottom. until it finds a line that matches.
* It then either accepts or denys depending on your setting.
* The remaining rules are ignored.
* The last entry should always be **http_access deny all**.
The general syntax of an http_access line is:
http_access (allow|deny) acl1 acl2 acl3 ...
Example:
http_access allow access_from_admins
http_access deny access_to_porn_urls
http_access allow access_during_lunchtime
http_access deny all
* This would allow accessing from the admins (whatever that ACL looks like – probably a src ACL pointing to the subnet where the admin workstations are in).
* For everyone else it will deny accesses to porn URLs.
* Then it would allow accesses from everyone to every web site during lunch time.
* And finally all other accesses would be denied.
Example 2:
acl localhost src 127.0.0.1/32 ::1
acl all src 0.0.0.0/0.0.0.0
http_access allow localhost
http_access deny all
* localhost has free access to everything while all other hosts are denied access completely.
Example 3:
acl localhost src 127.0.0.1/32 ::1
acl all src 0.0.0.0/0.0.0.0
acl teachers src 192.168.10.0/255.255.255.0
acl students src 192.168.20.0-192.168.30.0/255.255.255.0
acl lunch time MTWHF 12:00-13:00
http_access deny localhost
http_access allow teachers
http_access allow students lunch time
http_access deny all
* The group teachers always has access to the Internet.
* The group students only has access between Monday and Friday during lunch time.
**TIP**: For readability, within the configuration file /etc/squid/squid.conf, specify all **http_access** options as a block.
----
===== Combining ACLs (AND/OR) =====
Often you need to combine ACLs. Let’s say you want to allow access to google.com only for the back office. This combines two ACLS with an **AND**.
This would look like this:
http_access allow access_to_google.com access_from_back_office
If you wanted to use an **OR** and say either accesses from the back office or accesses to google.com are allowed then the line would look like this:
http_access allow access_to_google.com
http_access allow access_from_back_office
To summarize:
* **AND** means putting the conditions in one line.
* **OR** means using separate lines.
----
===== Custom error pages (deny_info) =====
By default when you deny access the user gets the error page that is stored in the **ERR_ACCESS_DENIED** file.
But you can define your own custom error pages and display them when you deny certain access. A simple example:
acl google dstdomain google.com
deny_info error-google google
http_access deny google
Put an error page into the directory where the HTML files are stored (look for error_directory in your squid.conf) and name it error-google. If the user tries to access www.google.com the access is denied and your error page is shown.
Careful when you combine ACLs on a http_access line. Example:
acl google dstdomain google.com
acl admin src 10.0.5.16
deny_info google error-google
http_access deny admin google
* This will deny access only for the user from the IP address 10.0.5.16 when www.google.com is accessed.
* As you can see the ACLs admin and google are combined. In such a combination the last ACL in the line is taken into account for lookups of **deny_info**.
* So it’s important that you define a **deny_info** for the google ACL.
----
===== Re-Authentication control =====
Usually when a user is authenticated at the proxy you cannot “log out” and re-authenticate.
The user has to close and re-open the browser windows to be able to re-login at the proxy.
A simple configuration will probably look like this:
acl my_auth proxy_auth REQUIRED
http_access allow my_auth
http_access deny all
Now there is a tricky change that was introduced in Squid 2.5.10. It allows to control when the user is prompted to authenticate. Now it’s possible to force the user to re-authenticate although the username and password are still correct. Example configuration:
acl my_auth proxy_auth REQUIRED
acl google dstdomain .google.com
http_access allow my_auth
http_access deny google my_auth
http_access deny all
In this case if the user requests www.google.com then the second **http_access** line matches and triggers re-authentication.
**NOTE:** It’s always the **last** ACL on a **http_access** line that “matches”.
If the matching ACL has to do with authentication a re-authentication is triggered.
If you didn’t want that you would need to switch the order of ACLs so that you get **http_access deny my_auth google**.
You might also run into an authentication loop if you are not careful.
Assume that you use LDAP group lookups and want to deny access based on an LDAP group (e.g. only members of a certain LDAP group are allowed to reach certain web sites). In this case you may trigger re-authentication although you don’t intend to. This config is likely wrong for you:
acl ldap-auth proxy_auth REQUIRED
acl ldapgroup-allowed external LDAP_group PROXY_ALLOWED
http_access deny !ldap-auth
http_access deny !ldapgroup-allowed
http_access allow all
The second **http_access** line would force the user to re-authenticate time and again if he/she is not member of the PROXY_ALLOWED group.
This is perhaps not what you want. You rather wanted to deny access to non-members.
So you need to rewrite this **http_access** line so that an ACL matches that has nothing to do with authentication. This is the correct example:
acl ldap-auth proxy_auth REQUIRED
acl ldapgroup-allowed external LDAP_group PROXY_ALLOWED
acl dummy src 0.0.0.0/0.0.0.0
http_access deny !ldap-auth
http_access deny !ldapgroup-allowed dummy
http_access allow all
This way the second **http_access** line still matches.
But it’s the dummy ACL which is now last in the line.
Since dummy is a static ACL (that always matches) and has nothing to do with authentication you will find that the access is just denied.
----
===== References =====
https://workaround.org/squid-acls/