Daniele Duca
BOFH excuse for today:  vi needs to be upgraded to vii
Server date is: 25/6/2017

This site best viewed with eyes

Say NO to software patents!

12/08/05 - Release 0.1

I had the need to setup a squid server to bring up a ssh tunnel to another squid server "on demand", that means "bring up the connection only when a client want to go there, and bring it down 30 minutes after last request came".

After one day of digging, coding and beer, this is what I've done; probably is not perfect and could be improved, but "It Just Works (TM)". :)

1) Basic squid knowledge
2) Basic openssh knowledge and a RSA key for the remote host
3) Perl
4) My ondemandssh.pl and vpncheck scripts

Configure the ondemandssh.pl script according to your settings:
1) <YOURREMOTELOGINHERE> is the username you have on the remote server
2) <REMOTEPORTHERE> is the port on which the remote ssh server listens to (usally 22)
3) <LOCALIPHERE> is your local ip address
4) <REMOTESQUIDIPHERE> is the ip address of the remote squid server
5) <REMOTESQUIDPORTHERE> is the port on which the remote squid listens to
6) <REMOTEHOSTHERE> is the (public) ip addresso of the remote ssh server
7) <YOURRSAKEYHERE> is the path to your RSA key

So, assuming you have remote userid "squid", the remote ssh server listens to port 22, your local ip is, the remote squid ip:port is, the remote ssh server has the ip address and the path to you RSA key is /home/staff/rsa, your ssh line would be

ssh -q -l squid -p 22 -L10.10.10.10:3129: -2 -i /home/staff/rsa

Run this command on the command line and you should automagically get logged in on the remote host. After the login try, on the local machine:

$ telnet 3129
Connected to
Escape character is '^]'.

HTTP/1.0 400 Bad Request
Server: squid/2.5.STABLE10
Mime-Version: 1.0
Date: Thu, 08 Dec 2005 10:14:02 GMT
Connection closed by foreign host.

This means that the tunnel is working. That response comes from the remote squid.
Assuming the url you want to trigger the ssh tunnel is, let's say, "http://intranet.example.com", change following lines on the perl script:

if ($url =~ /^http:\/\/intranet\.example\.com/)
my $url = URI->new( '' );
if ($count>=30) { print "..."; exit;} else { print "302:http://intranet.example.com\n"; }

To test if the script works correctly, open a consoles and launch the script:

$ ./ondemandssh.pl
(wait some seconds and the following line should appear)

If you look a "ps ax" you'll probably see that the ssh tunnel has been brought up. If not... well... check permissions and things like that.. :)
Now edit the "vpncheck" script. This is much simpler, the only parameter you have to change is <YOURREMOTELOGINHERE>. Change it to your remote userid (in our example "squid") and install it on your crontab with the following line:

* * * * * /bin/vpncheck 2&>1 /dev/null

"vpncheck" works checking every minute the last access time of "/tmp/vpnactive" file. This file is being touched everytime a request for the intranet comes to the perl script. After 30 minutes of no intranet access, the ssh tunnel is killed.

Now it's time to configure squid. Since this is not "Configuring squid for dummies" :) I'll show you only the relevant lines you need to change/add to your squid.conf file:

cache_peer parent 3129 0 proxy-only no-query
cache_peer_domain intranet.example.com
auth_param ntlm program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp
external_acl_type wbinfo_group_helper ttl=3D300 %LOGIN /usr/lib/squid/wbinfo_group.pl
auth_param ntlm children 5
auth_param ntlm max_challenge_reuses 0
auth_param ntlm max_challenge_lifetime 2 minutes
auth_param ntlm use_ntlm_negotiate on
auth_param basic program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-basic
auth_param basic children 5
auth_param basic realm Squid proxy-caching web server
auth_param basic credentialsttl 2 hours
redirect_program /usr/lib/squid/ondemandssh.pl
acl our_networks src
acl authenticated proxy_auth REQUIRED
acl intranetauthorized external wbinfo_group_helper IntranetAuthorized
acl tointranet dstdomain intranet.example.com
redirector_access allow tointranet
redirector_access deny all
http_access allow intranetauthorized tointranet
never_direct allow tointranet
http_access deny tointranet
http_access allow our_networks authenticated
http_access allow localhost
http_access deny all

As you probably see, I'm doing extra authorization checks. In this specific case, before letting someone go to http://intranet.example.com, I check if that username is part of the AD group "IntranetAuthorized". Integration with AD domains and NTLM authentication are not covered in this HOWTO, but you can find lot of informations around. (hint: google)

I hope this will help you as much as it helped me :) If you have questions, please let me know.

No liability for the contents of this document can be accepted. Use the concepts, examples and other content at your own risk. There may be errors and inaccuracies that may damage your system. Proceed with caution, and although this is highly unlikely, the author does not and can not take any responsibility for any damage to your system that may occur as a direct or indirect result of information that is contained within this document. You are strongly recommended to make a backup of your system before proceed and adhere to the practice of backing up at regular intervals.

Informations on this page are released under the GNU FDL License
This page last updated: 08/12/05