Squid's access control scheme is relatively comprehensive and difficult for some people to understand. There are two different components: ACL elements, and access lists. An access list consists of an allow or deny action followed by a number of ACL elements.
Note: The information here is current for version 2.4.
Squid knows about the following types of ACL elements:
Not all of the ACL elements can be used with all types of access lists (described below). For example, snmp_community is only meaningful when used with snmp_access. The src_as and dst_as types are only used in cache_peer_access access lists.
The arp ACL requires the special configure option --enable-arp-acl. Furthermore, the ARP ACL code is not portable to all operating systems. It works on Linux, Solaris, and some *BSD variants.
The SNMP ACL element and access list require the --enable-snmp configure option.
Some ACL elements can cause processing delays. For example, use of src_domain and srcdom_regex require a reverse DNS lookup on the client's IP address. This lookup adds some delay to the request.
Each ACL element is assigned a unique name. A named ACL element consists of a list of values. When checking for a match, the multiple values use OR logic. In other words, an ACL element is matched when any one of its values is a match.
You can't give the same name to two different types of ACL elements. It will generate a syntax error.
You can put different values for the same ACL name on different lines. Squid combines them into one list.
There are a number of different access lists:
An access list rule consists of an allow or deny keyword, followed by a list of ACL element names.
An access list consists of one or more access list rules.
Access list rules are checked in the order they are written. List searching terminates as soon as one of the rules is a match.
If a rule has multiple ACL elements, it uses AND logic. In other words, all ACL elements of the rule must be a match in order for the rule to be a match. This means that it is possible to write a rule that can never be matched. For example, a port number can never be equal to both 80 AND 8000 at the same time.
If none of the rules are matched, then the default action is the opposite of the last rule in the list. Its a good idea to be explicit with the default action. The best way is to thse the all ACL. For example:
acl all src 0/0 http_access deny all
Define an ACL that corresponds to your client's IP addresses. For example:
acl myclients src 172.16.5.0/24Next, allow those clients in the http_access list:
http_access allow myclients
acl someserver dstdomain .someserver.com no_cache deny someserver
As an example, we will assume that you would like to prevent users from accessing cooking recipes.
One way to implement this would be to deny access to any URLs that contain the words ``cooking'' or ``recipe.'' You would use these configuration lines:
acl Cooking1 url_regex cooking acl Recipe1 url_regex recipe http_access deny Cooking1 http_access deny Recipe1 http_access allow allThe url_regex means to search the entire URL for the regular expression you specify. Note that these regular expressions are case-sensitive, so a url containing ``Cooking'' would not be denied.
Another way is to deny access to specific servers which are known to hold recipes. For example:
acl Cooking2 dstdomain gourmet-chef.com http_access deny Cooking2 http_access allow allThe dstdomain means to search the hostname in the URL for the string ``gourmet-chef.com.'' Note that when IP addresses are used in URLs (instead of domain names), Squid-1.1 implements relaxed access controls. If the a domain name for the IP address has been saved in Squid's ``FQDN cache,'' then Squid can compare the destination domain against the access controls. However, if the domain is not immediately available, Squid allows the request and makes a lookup for the IP address so that it may be available for future reqeusts.
You can use ident lookups to allow specific users access to your cache. This requires that an ident server process runs on the user's machine(s). In your squid.conf configuration file you would write something like this:
ident_lookup on acl friends user kim lisa frank joe http_access allow friends http_access deny all
Another option is to use proxy-authentication. In this scheme, you assign usernames and passwords to individuals. When they first use the proxy they are asked to authenticate themselves by entering their username and password.
In Squid v2 this authentication is hanled via external processes. For information on how to configure this, please see Configuring Proxy Authentication.
Pedro L Orso has adapted the Apache's htpasswd into a CGI program called chpasswd.cgi.
If you use a user ACL in squid conf, then Squid will perform an ident lookup for every client request. In other words, Squid-1.1 will perform ident lookups for all requests or no requests. Defining a user ACL enables ident lookups, regardless of the ident_lookup setting.
However, even though ident lookups are performed for every request, Squid does not wait for the lookup to complete unless the ACL rules require it. Consider this configuration:
acl host1 src 10.0.0.1 acl host2 src 10.0.0.2 acl pals user kim lisa frank joe http_access allow host1 http_access allow host2 palsRequests coming from 10.0.0.1 will be allowed immediately because there are no user requirements for that host. However, requests from 10.0.0.2 will be allowed only after the ident lookup completes, and if the username is in the set kim, lisa, frank, or joe.
You've probably noticed (and been frustrated by) the fact that you cannot combine access controls with terms like ``and'' or ``or.'' These operations are already built in to the access control scheme in a fundamental way which you must understand.
For example, the following access control configuration will never work:
acl ME src 10.0.0.1 acl YOU src 10.0.0.2 http_access allow ME YOUIn order for the request to be allowed, it must match the ``ME'' acl AND the ``YOU'' acl. This is impossible because any IP address could only match one or the other. This should instead be rewritten as:
acl ME src 10.0.0.1 acl YOU src 10.0.0.2 http_access allow ME http_access allow YOUOr, alternatively, this would also work:
acl US src 10.0.0.1 10.0.0.2 http_access allow US
I have read through my squid.conf numerous times, spoken to my neighbors, read the FAQ and Squid Docs and cannot for the life of me work out why the following will not work.
I can successfully access cachemgr.cgi from our web server machine here, but I would like to use MRTG to monitor various aspects of our proxy. When I try to use 'client' or GET cache_object from the machine the proxy is running on, I always get access denied.
acl manager proto cache_object acl localhost src 127.0.0.1/255.255.255.255 acl server src 18.104.22.168/255.255.255.255 acl all src 0.0.0.0/0.0.0.0 acl ourhosts src 22.214.171.124/255.255.0.0 http_access deny manager !localhost !server http_access allow ourhosts http_access deny all
The intent here is to allow cache manager requests from the localhost and server addresses, and deny all others. This policy has been expressed here:
http_access deny manager !localhost !server
The problem here is that for allowable requests, this access rule is not matched. For example, if the source IP address is localhost, then ``!localhost'' is false and the access rule is not matched, so Squid continues checking the other rules. Cache manager requests from the server address work because server is a subset of ourhosts and the second access rule will match and allow the request. Also note that this means any cache manager request from ourhosts would be allowed.
To implement the desired policy correctly, the access rules should be rewritten as
http_access allow manager localhost http_access allow manager server http_access deny manager http_access allow ourhosts http_access deny allIf you're using miss_access, then don't forget to also add a miss_access rule for the cache manager:
miss_access allow manager
You may be concerned that the having five access rules instead of three may have an impact on the cache performance. In our experience this is not the case. Squid is able to handle a moderate amount of access control checking without degrading overall performance. You may like to verify that for yourself, however.
For the srcdomain ACL type, Squid does a reverse lookup of the client's IP address and checks the result with the domains given on the acl line. With the src ACL type, Squid converts hostnames to IP addresses at startup and then only compares the client's IP address. The src ACL is preferred over srcdomain because it does not require address-to-name lookups for each request.
You can debug your access control configuration by setting the debug_options parameter in squid.conf and watching cache.log as requests are made. The access control routes correspond to debug section 28, so you might enter:
debug_options ALL,1 28,9
[ Parents ] / \ / \ [ Proxy A ] --- [ Proxy B ] | | USER
Proxy A sends and ICP query to Proxy B about an object, Proxy B replies with an ICP_HIT. Proxy A forwards the HTTP request to Proxy B, but does not pass on the authentication details, therefore the HTTP GET from Proxy A fails.
Only ONE proxy cache in a chain is allowed to ``use'' the Proxy-Authentication request header. Once the header is used, it must not be passed on to other proxies.
Therefore, you must allow the neighbor caches to request from each other without proxy authentication. This is simply accomplished by listing the neighbor ACL's first in the list of http_access lines. For example:
acl proxy-A src 10.0.0.1 acl proxy-B src 10.0.0.2 acl user_passwords proxy_auth /tmp/user_passwds http_access allow proxy-A http_access allow proxy-B http_access allow user_passwords http_access deny all
acl GOOD dst 10.0.0.1 acl BAD dst 0.0.0.0/0.0.0.0 http_access allow GOOD http_access deny BAD
There is a subtle problem with domain-name based access controls when a single ACL element has an entry that is a subdomain of another entry. For example, consider this list:
acl FOO dstdomain boulder.co.us vail.co.us co.us
In the first place, the above list is simply wrong because the first two (boulder.co.us and vail.co.us) are unnecessary. Any domain name that matches one of the first two will also match the last one (co.us). Ok, but why does this happen?
The problem stems from the data structure used to index domain names in an access control list. Squid uses Splay trees for lists of domain names. As other tree-based data structures, the searching algorithm requires a comparison function that returns -1, 0, or +1 for any pair of keys (domain names). This is similar to the way that strcmp() works.
The problem is that it is wrong to say that co.us is greater-than, equal-to, or less-than boulder.co.us.
For example, if you said that co.us is LESS than fff.co.us, then the Splay tree searching algorithm might never discover co.us as a match for kkk.co.us.
similarly, if you said that co.us is GREATER than fff.co.us, then the Splay tree searching algorithm might never discover co.us as a match for bbb.co.us.
The bottom line is that you can't have one entry that is a subdomain of another. Squid-2.2 will warn you if it detects this condition.
It is dangerous to allow Squid to connect to certain port numbers. For example, it has been demonstrated that someone can use Squid as an SMTP (email) relay. As I'm sure you know, SMTP relays are one of the ways that spammers are able to flood our mailboxes. To prevent mail relaying, Squid denies requests when the URL port number is 25. Other ports should be blocked as well, as a precaution.
There are two ways to filter by port number: either allow specific ports, or deny specific ports. By default, Squid does the first. This is the ACL entry that comes in the default squid.conf:
acl Safe_ports port 80 21 443 563 70 210 1025-65535 http_access deny !Safe_portsThe above configuration denies requests when the URL port number is not in the list. The list allows connections to the standard ports for HTTP, FTP, Gopher, SSL, WAIS, and all non-priveleged ports.
Another approach is to deny dangerous ports. The dangerous port list should look something like:
acl Dangerous_ports 7 9 19 22 23 25 53 109 110 119 http_access deny Dangerous_ports...and probably many others.
Please consult the /etc/services file on your system for a list of known ports and protocols.
Note: The information here is current for version 2.2.
No, it does not.
This example allows only the special_client to access the special_url. Any other client that tries to access the special_url is denied.
acl special_client src 10.1.2.3 acl special_url url_regex ^http://www.squid-cache.org/Doc/FAQ/$ http_access allow special_client special_url http_access deny special_url
Let's say you have two workstations that should only be allowed access to the Internet during working hours (8:30 - 17:30). You can use something like this:
acl FOO src 10.1.2.3 10.1.2.4 acl WORKING time MTWHF 08:30-17:30 http_access allow FOO WORKING http_access deny FOO
acl USER1 proxy_auth Dick acl USER2 proxy_auth Jane acl DAY time 06:00-18:00 http_access allow USER1 DAY http_access deny USER1 http_access allow USER2 !DAY http_access deny USER2
Note: The information here is current for version 2.3.
The following ACL entry gives inconsistent or unexpected results:
acl restricted src 10.0.0.128/255.0.0.128 10.85.0.0/16The reason is that IP access lists are stored in ``splay'' tree data structures. These trees require the keys to be sortable. When you use a complicated, or non-standard, netmask (255.0.0.128), it confuses the function that compares two address/mask pairs.
The best way to fix this problem is to use separate ACL names for each ACL value. For example, change the above to:
acl restricted1 src 10.0.0.128/255.0.0.128 acl restricted2 src 10.85.0.0/16
Then, of course, you'll have to rewrite your http_access lines as well.
Yes, for some operating systes. Squid calls these ``ARP ACLs'' and they are supported on Linux, Solaris, and probably BSD variants.
NOTE: Squid can only determine the MAC address for clients that are on the same subnet. If the client is on a different subnet, then Squid can not find out its MAC address.
To use ARP (MAC) access controls, you first need to compile in the optional code. Do this with the --enable-arp-acl configure option:
% ./configure --enable-arp-acl ... % make clean % makeIf src/acl.c doesn't compile, then ARP ACLs are probably not supported on your system.
If everything compiles, then you can add some ARP ACL lines to your squid.conf:
acl M1 arp 01:02:03:04:05:06 acl M2 arp 11:12:13:14:15:16 http_access allow M1 http_access allow M2 http_access deny all
If ACLs are giving you problems and you don't know why they aren't working, you can use this tip to debug them.
In squid.conf enable debugging for section 32 at level 2. For example:
debug_options ALL,1 32,2The restart or reconfigure squid.
From now on, your cache.log should contain a line for every request that explains if it was allowed, or denied, and which ACL was the last one that it matched.
Yes, use the maxconn ACL type in conjunction with http_access deny. For example:
acl losers src 126.96.36.199/24 acl 5CONN maxconn 5 http_access deny 5CONN losers
Given the above configuration, when a client whose source IP address is in the 188.8.131.52/24 subnet tries to establish 6 or more connections at once, Squid returns an error page. Unless you use the deny_info feature, the error message will just say ``access denied.''
Note, the maxconn ACL type is kind of tricky because it uses less-than comparison. The ACL is a match when the number of established connections is greater than the value you specify. Because of that, you don't want to use the maxconn ACL with http_access allow.
Also note that you could use maxconn in conjunction with a user type (ident, proxy_auth), rather than an IP address type.
In Squid-2.3 we changed the way that Squid matches subdomains. There is a difference between .foo.com and foo.com. The first matches any domain in foo.com, while the latter matches only ``foo.com'' exactly. So if you want to deny bar.foo.com, you should write
acl yuck dstdomain .foo.com http_access deny yuckTo be safe, you probably want to list both forms in your access lists, for example:
acl yuck dstdomain .foo.com foo.com http_access deny yuck