Here we’re going to take a look at configuring two Squid proxy servers to forward requests from an internal network with no connectivity to the Internet out to a DMZ network and then onto the Internet if required.
The configuration will allow us to select which domains should or should not be forwarded on to the next proxy server, allowing requests that are destined for domains within the internal network to not be forwarded to the next Squid proxy, while other requests to the DMZ network or the Internet will be forwarded to the next proxy.
Environment Overview
Before we get stuck into the configuration we’ll take a quick look at the overall environment in this particular situation and explain why this is something that you may want to do.
In this scenario we have two separate networks, an internal network and external network. The internal network has no direct access to the Internet, but it can connect to the external network. The external network on the other hand is able to connect out to the Internet via a Squid proxy server. There are servers running within both the internal and external networks which must be accessed from within the internal network by a client PC.
The services on the internal network are accessible on the internal.example.com domain while the services on the external network are accessible on the external.example.com domain.
The below diagram outlines the path a request by the client PC would take in order to reach a web site on the Internet.
From our client PC in the internal network we want to be able to access other services within the internal network, services within the external DMZ network and services on the Internet. We are going to do this by sending the request to a Squid proxy server that is located within the internal network (proxy.internal.example.com) which will forward requests destined to the same local network directly where they need to go.
Requests to external.example.com or the Internet will be forwarded from proxy.internal.example.com to the what is known as a parent Squid proxy server (proxy.external.example.com) which will then pass the requests to a server within the external network if this is what has been requested, otherwise will forward the request out to the Internet.
The parent Squid proxy is located in the external network and can connect to the Internet. If the client PC is accessing something within *.internal.example.com we do not want the internal Squid proxy server to forward the requests to the parent/external Squid proxy server in external.example.com as it will not know what to do with these requests and they will fail.
So basically anything request that is not destined for the internal.example.com network should be forwarded to the parent Squid proxy server proxy.external.example.com, from there the requests can either make their way to services in external.example.com DMZ network or out to the Internet as required.
Squid Proxy Configuration
Now let’s take a look at the configuration on our Squid proxy servers to make this happen. We’ll be covering the specific configuration required for the forwarding to work as described rather than discussing the full Squid configuration.
Internal Child Squid Proxy
acl local-servers dstdomain .internal.example.com cache_peer proxy.external.example.com parent 3128 0 no-query default cache_peer_domain proxy.external.example.com !.internal.example.com never_direct deny local-servers never_direct allow all
Firstly we are specifying an access control list (ACL) called local-servers which is defined as anything under the *.internal.example.com domain, which will be all fully qualified domain names (FQDN) of our services in the internal network.
Next we specify the parent Squid proxy server by using cache_peer, in this case we are using proxy.external.example.com on port 3128 as our default parent proxy server.
Following this we use cache_peer_domain to limit the domains that we will request from the parent proxy server. In this case we only want to forward requests out to the parent Squid proxy server at proxy.external.example.com if the requests are NOT for *.internal.example.com, “!” specifies not.
The never_direct directive allows us to use an ACL where requests should NEVER be forwarded directly to origin servers. This forces the use of a proxy server for all requests, except those in the internal network as we are denying local-server.
As this configuration is processed in order from top to bottom, after we deny access to the parent proxy for the domain specified in local-servers, we next allow everything else to be forwarded through to proxy.external.example.com
In my initial attempt at getting this working I did not include either of the never_direct directives (or the ACL as it is only used by this) and things were working for the most part, internal HTTP/HTTPS requests were working fine and going via the internal Squid proxy server and not being passed to the external proxy server as expected.
However I found that when requesting any *.external.example.com services or anything out on the Internet, only HTTP requests succeeded. HTTPS requests were not being passed to the parent proxy server and were not even showing up in /var/log/squid/access.log on the external proxy. The internal Squid proxy server was trying to send these out directly to the Internet, which of course is not allowed in this environment, so this failed.
This strange behaviour is essentially due to the lack of the never_direct configuration, which is needed to prevent direct connections even though a parent proxy has been defined.
External Parent Squid Proxy
acl child_proxy src 192.168.0.5/32 http_access allow child_proxy
The first line is simply creating an access control list called child_proxy which contains the source IP address of 192.168.0.5, this is the IP address of the internal proxy server that will be connecting in to the parent Squid proxy server.
The second line is simply allowing the child_proxy server in for HTTP/HTTPS traffic, without this configuration the requests from the internal child proxy server would be denied.
If you’re having any problems when loading a page have a look at the logs in the /var/log/squid directory on both the internal and external Squid proxy servers, as these can help give you a better understanding of what is going on.
At this point we can tail the access log on both access servers and load up a page from the *.internal.example.com network and see that the request only goes through proxy.internal.example.com. Any other requests including requests for *.external.example.com or from the Internet such as google.com will be passed through the proxy.external.com server which will then send the traffic as required.
Conclusion
As shown we have successfully configured a Squid proxy server within an internal network with no direct access to the Internet to forward select traffic destined for external networks to a parent Squid proxy server that is capable of completing these requests. All requests for the internal network will stay within the internal network and will not be forwarded out to the external DMZ network or Internet.
This part very good to know:
In my initial attempt at getting this working I did not include either of the never_direct directives (or the ACL as it is only used by this) and things were working for the most part, internal HTTP/HTTPS requests were working fine and going via the internal Squid proxy server and not being passed to the external proxy server as expected.
cheers
No problem, I remember it was pretty confusing at the time!
I just want to thank you for the great post, I learned how to use the cache_peer directive thanks to you!
No problem at all, happy to help!
Hello Jarrod,
Greetings from Tokyo. I also wanted to express my thanks for your post — I needed to set up exactly this kind of configuration, and the details you gave meant it took only a half-hour or so of tweaking and prodding to get up and running.
One thing I noticed is that in version 4 of squid, according to the documentation, the cache_peer_domain is deprecated. I have removed it with no ill effects. Also, I’m “trusting” my internal proxy to do access control by allowing, on the external proxy, any incoming request from the incoming proxy.
Thanks again!
Simon
Hey Simon, no problem at all! Thanks for letting me know about the version 4 changes 👍
Hello..
Good post. I have question on https.
Internal Proxy is Bluecoat Proxy-SG –> external Proxy Squid.
Internal Proxy configured for https interceptor.
External Proxy NATed to public IP.
http site no issues.
But when I access https site I get error message OCSP error.
Is there something we need to configure in Squid?
Thanks you in advance for help.
Thank you so much. I spent far too long trying to get external https requests working!
You’re a legend dude. This helped me get around internet censorship.