Squid has an extensive, but somewhat confusing, set of access controls. The most important thing to understand is the difference between ACL types, elements, and rules, and how they work together to allow or deny access.

Squid has about 20 different ACL types. These refer to certain aspects of an HTTP request or response, such as the client’s IP address (the src type), the origin server’s hostname (the dstdomain type), and the HTTP request method (the method type).

An ACL element consists of three components: a type, a name, and one or more type-specific values. Here are some simple examples:

acl Foo src 1.2.3.4
acl Bar dstdomain www.cnn.com
acl Baz method GET


The above ACL element named Foo would match a request that comes from the IP address 1.2.3.4. The ACL named Bar matches a www.cnn.com URL. The Baz ACL matches an HTTP GET request. Note that we are not allowing or denying anything yet.

For most of the ACL types, an element can have multiple values, like this:

acl Argle src 1.1.1.8 1.1.1.28 1.1.1.88
acl Bargle dstdomain www.nbc.com www.abc.com www.cbs.com
acl Fraggle method PUT POST

A multi-valued ACL matches a request when any one of the values is a match. They use OR logic. The Argle ACL matches a request from 1.1.1.8, from 1.1.1.28, or from 1.1.1.88. The Bargle ACL matches requests to NBC, ABC, or CBS web sites. The Fraggle ACL matches a request with the methods PUT or POST.

Now that you’re an expert in ACL elements, its time to graduate to ACL rules. These are where you say that a request is allowed or denied. Access list rules refer to ACL elements by their names and contain either the allow or deny keyword. Here are some simple examples:

http_access allow Foo
http_access deny Bar
http_access allow Baz

It is important to understand that access list rules are checked in order and that the decision is made when a match is found. Given the above list, let’s see what happens when a user from 1.2.3.4 makes a GET request for www.cnn.com. Squid encounters the allow Foo rule first. Our request matches the Foo ACL, because the source address is 1.2.3.4, and the request is allowed to proceed. The remaining rules are not checked.

How about a PUT request for www.cnn.com from 5.5.5.5? The request does not match the first rule. It does match the second rule, however. This access list rule says that the request must be denied, so the user receives an error message from Squid.

How about a GET request for www.oreilly.com from 5.5.5.5? The request does not match the first rule (allow Foo). It does not match the second rule, either, because www.oreilly.com is different than www.cnn.com. However, it does match the third rule, because the request method is GET.

Of course, these simple ACL rules are not very interesting. The real power comes from Squid’s ability to combine multiple elements on a single rule. When a rule contains multiple elements, each element must be a match in order to trigger the rule. In other words, Squid uses AND logic for access list rules. Consider this example:

http_access allow Foo Bar
http_access deny Foo

The first rule says that a request from 1.2.3.4 AND for www.cnn.com will be allowed. However, the second rule says that any other request from 1.2.3.4 will be denied. These two lines restrict the user at 1.2.3.4 to visiting only the www.cnn.com site. Here’s an even more complex example:

http_access deny Argle Bargle Fraggle
http_access allow Argle Bargle
http_access deny Argle

These three lines allow the Argle clients (1.1.1.8, 1.1.1.28, and 1.1.1.88) to access the Bargle servers (www.nbc.com, www.abc.com, and www.cbs.com), but not with PUT or POST methods. Furthermore, the Argle clients are not allowed to access any other servers.

One of the common mistakes often made by new users is to write a rule that can never be true. It is easy to do if you forget that Squid uses AND logic on rules and OR logic on elements. Here is a configuration that can never be true:

acl A 1.1.1.1
acl B 2.2.2.2
http_access allow A B

The reason is that a request cannot be from both 1.1.1.1 AND 2.2.2.2 at the same time. Most likely, it should be written like this:

acl A 1.1.1.1 2.2.2.2
http_access allow A

Then, requests from either 1.1.1.1 or 2.2.2.2 are allowed.

Access control rules can become long and complicated. When adding a new rule, how do you know where it should go? You should put more-specific rules before less-specific ones. Remember that the rules are checked in order. When adding a rule, go through the current rules in your head and see where the new one fits. For example, let’s say that you want to deny requests to a certain site, but allow all others. It should look like this:

acl XXX www.badsite.net
acl All src 0/0
http_access deny XXX
http_access allow All

Now, what if you need to make an exception for one user, so that she can visit that site? The new ACL element is:

acl Admin 3.3.3.3

and the new rule should be:

http_access allow Admin XXX

but where does it go? Since this rule is more specific than the deny XXX rule, it should go first:

http_access allow Admin XXX
http_access deny XXX
http_access allow All

If we place the new rule after deny XXX, it will never even get checked. The first rule will always match the request and she will not be able to visit the site.

When you first install Squid, the access control rules will deny every request. To get things working, you’ll need to add an ACL element and a rule for your local network. The easiest way is to write an source IP address ACL element for your subnet(s). For example:

acl MyNetwork src 192.168.0.0/24

Then, search through squid.conf for this line:

# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS

After that line, add an http_access line with an allow rule:

http_access allow MyNetwork

Once you get this simple configuration working, feel free to move on to some of the more advanced ACL features, such as username-based proxy authentication.