Setting up Squid for NTLM Auth

Configuring Squid for use with NTLM Auth via a Windows NT domain controller

Note: The following learning process was forced upon me by a situation at work. I make no promises that this is the "right way" to do this.

Quick steps:

  1. Download
  2. Compile
  3. Install
  4. Configure
  5. Running and testing
  6. Auto configuration of browsers
  7. Misc

Here is everything the way I did it.

Note: I am running Red Hat Linux 8.0, Samba 2.2.7 rebuilt (see below), and Squid 2.5.STABLE5 with Windows NT 4 Server as the domain controller. The box is a P2-400, 128meg RAM, 4gig hard drive. Setup is for 10 users. There are some things that are different if you are using Samba 3.x that I don't cover here. Also, there may be some differences if you are using a newer Windows Server product and Active Directory.


1) Download

Samba is here.

Squid is here.

If you want or need to make rpms, get the src.rpms from your distribution (or a newer one) and install with:
rpm -ivh [package_name].src.rpm
Otherwise if an rpm is already available that you want to use:
rpm -ivh [package_name].rpm


2) Compile

Note that many newer Linux distros have the newer Squid package available for them, so check before taking the time to do it yourself. Winbind, however, may not have been built with challenge/response enabled.

For Samba, you need winbind compiled for challenge/response. To test your current installation, try:
wbinfo -a [domain]\\[user]%[password]
If only plain text is returned, you will need to recompile winbind with at least:
./config --with-winbind --with-winbind-auth-challenge
RedHat's Samba rpm, or at least 2.2.7 for RH8, is not built for winbind challenge/response.

For Squid and NTLM auth, you need at least:
./config --enable-ntlm-auth-helpers="winbind,SMB" \
--enable-external-acl-helpers="unix_group,wbinfo_group" \
--enable-auth="ntlm,basic" \
--with-winbind-auth-challenge \
--with-samba-sources="/[path_to_samba_sources]/" \ --enable-basic-auth-helpers="winbind"

You also need the Samba sources available for compiling Squid with NTLM capabilities.

Please read each package's documentation for other config options you may need to specify.

For those of you interested in compiling your own RPMs, here is what I did:

  • Went to http://rpm.pbone.net/ and downloaded the source rpms, specifically squid-2.5.STABLE5-4.fc2.src.rpm and the one for the version of samba I choose to run. I only did this because I wanted the latest stable and could not find a pre-built rpm for RH8. You may be using a newer distro that already has binaries built for it, so check before wasting time compiling.
  • Installed with:
    rpm -ivh [package_name].src.rpm
  • cd to /usr/src/redhat/SPECS
  • Changed the samba.spec file as follows (I needed to recompile winbind):
    ...
    Summary: The Samba SMB server.
    Name: samba
    Version: 2.2.7
    Release: 5.8.0a
    ...
    %description
    ...
    TCP/IP (NetBT) protocols and does NOT need the NetBEUI (Microsoft Raw
    NetBIOS frame) protocol. Winbind built to support challenge/response.
    ...
            --with-acl-support \
            --with-winbind \
            --with-winbind-auth-challenge \
    ...
    %changelog
    * Wed Jun 30 2004 S. Yoder <computer_AT_flatmtn_DOT_com> 2.2.7-5.8.0a
    - rebuilt to enable --with-winbind-auth-challenge
    ...
  • Changed the squid.spec file as follows:
    ...
    Summary: The Squid proxy caching server.
    Name: squid
    Version: 2.5.STABLE5
    Release: 5.rh8
    ...
    Patch7: squid-2.5.STABLE5-warning.patch
    Patch8: squid-2.5.STABLE3-libntlmssp.patch
     
    Patch10: squid-2.5.STABLE5-wbinfo_group.patch
    ...
    %patch7 -p1 -b .warning
    %patch8 -p1 -b .libntlmssp
    %patch10 -p1
    ...
       --enable-ntlm-auth-helpers="winbind,SMB" \
       --enable-external-acl-helpers="ip_user,ldap_group,unix_group,wbinfo_group" \
       --enable-auth="ntlm,basic" \
       --with-winbind-auth-challenge \
       --with-samba-sources="/usr/src/redhat/BUILD/samba-2.2.7/" \
    ...
    %changelog
    * Wed Jul 1 2004 S. Yoder <computer_AT_flatmtn_DOT_com>
    - Fixed wbinfo_group.pl per http://bugzilla.redhat.com/bugzilla/long_list.cgi?bu
    - Fixed wbinfo_group.pl to change [domain]\\[user] to [domain]\[user]
    - Winbind auth using sources from samba-2.2.7-5.8.0.src.rpm
    ...
  • Note: change the path for "--with-samba-sources" to match where you have extracted your sources.
  • Installed the necessary packages for compiling: openjade, linuxdoc-tools, openldap-devel, pam-devel, openssl-devel, cyrus-sasl-devel, plus other packages those require and gcc.
  • Made a patch file for wbinfo_group.pl (after some debuging I found it needed changing, at least for my setup) that looks like:
    --- squid-2.5.STABLE5/helpers/external_acl/wbinfo_group/wbinfo_group.pl.orig
    +++ squid-2.5.STABLE5/helpers/external_acl/wbinfo_group/wbinfo_group.pl 2004-07-
    @@ -12,6 +12,11 @@
     #   Jerry Murdock <jmurdock@itraktech.com>
     #
     # Version history:
    +#   2004-06-30 S. Yoder <computer_AT_flatmtn_DOT_com>
    +#               Updated for new wbinfo output format and
    +#               fixed loop caused by shellwords per:
    +#               http://bugzilla.redhat.com/bugzilla/long_list.cgi?buglist=10266
    +#
     #   2002-07-05 Jerry Murdock <jmurdock@itraktech.com>
     #              Initial release
     #
    @@ -33,7 +38,9 @@
     sub check {
             local($user, $group) = @_;
             $groupSID = `wbinfo -n "$group"`;
    -        chop  $groupSID;
    +        # because wbinfo -n also returns the group number
    +        $groupSID = substr($groupSID,0,index($groupSID," ",0));
    +        #chop  $groupSID;
             $groupGID = `wbinfo -Y "$groupSID"`;
             chop $groupGID;
             &debug( "User:  -$user-\nGroup: -$group-\nSID:   -$groupSID-\nGID:   -$
    @@ -47,7 +54,18 @@
     while () {
             chop;
            &debug ("Got $_ from squid");
    -        ($user, $group) = &shellwords;
    +       # this causes a loop
    +        #($user, $group) = &shellwords;
    +        # instead use
    +        @H1=split(/\s+/, $_);
    +        $user = $H1[0];
    +        # this is added because my tests showed
    +        # IE (6, Win2k) was sending [domain]\\[name]
    +        if ($user =~ m/\\\\/) {
    +         $user =~ s|\\\\|\\|g;
    +        }
    +        $group = $H1[1];
    +        # continue original
            $ans = &check($user, $group);
            &debug ("Sending $ans to squid");
            print "$ans\n";
    (It goes in /usr/src/redhat/SOURCES/squid-2.5.STABLE5-wbinfo_group.patch)
  • Ran rpmbuild -bi [name].spec to test compiling.
  • Ran rpmbuild -bb [name].spec to build the binaries or rpmbuild -ba [name].spec to build all.

Note: I am running rpm 4.1.1-1.8x. If you are using RH8, please update to the latest or at least to the same version I am running. See rpm.org.

To download my rpm or view my full spec file, go here.


3) Install

Install Samba or replace with the updated winbindd, if you only needed that part fixed.

  • For non-package (ie rpm, deb, etc) installation:
    make
    make install
  • For rpm-based installation:
    rpm -ivh [package_name].rpm
    You will need at least samba and samba-common. May as well add samba-client so you can run smbclient if needed.

Install Squid.

  • For non-package installation:
    make
    make install
  • For rpm-based installation:
    rpm -ivh [package_name].rpm

Note: When installing Squid, via the rpm, you may get a dependency requirement for perl(Authen::Smb). You can get it from http://search.cpan.org/dist/Authen-Smb/. There is a rpm out there (check pbone), if you prefer. If you don't install the perl-Authen-Smb rpm, but instead compile it manually, then install the squid rpm using the --nodeps option (if there are no other dependencies and you manually install the perl module).


4) Configure

Read through Squid's FAQ #23

For Samba (/etc/samba/smb.conf) you need at least:

[global]
workgroup = [WORKGROUP]
netbios name = [MACHINE_NAME]
password server = [PDC]
security = domain
winbind uid = 10000-20000
winbind gid = 10000-20000
winbind use default domain = yes

You may also want to see my other Samba page. Note that you can put an IP in for the [PDC] if you don't have an internal DNS server or do not want to modify /etc/hosts.

Tip: If your box has multiple NICs, like mine, you may not want Samba to broadcast its presence on both interfaces. To make it only use one IP add the following, in [global]:
interfaces = [interface_ip]/32 127.0.0.1/8
bind only interfaces = yes

For Squid (/etc/squid/squid.conf) I have something like (please read the config file to see all the available options and what they mean):

# note if one network card, can drop [ip_of_first_nic]:
http_port [ip_of_first_nic]:3128
# note if only one network card, can drop next line
tcp_outgoing_address [ip_of_second_nic]
hierarchy_stoplist cgi-bin ?
cache_mem 4 MB
cache_swap_low 85
cache_swap_high 90
# note read the config file about this and adjust it
# to what your disk(s) can do, and allow for log files
cache_dir ufs /var/spool/squid 100 16 256
cache_access_log /var/log/squid/access.log
cache_log /var/log/squid/cache.log
cache_store_log /var/log/squid/store.log
pid_filename /var/run/squid.pid
 
# note: you may need to increase children based on your number of users
auth_param ntlm program /usr/lib/squid/wb_ntlmauth
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 off
auth_param basic program /usr/lib/squid/wb_auth
auth_param basic children 5
auth_param basic realm Squid proxy-caching web server
auth_param basic credentialsttl 2 hours
 
# only need this if you want to use Windows Domain Groups for acl(s)
external_acl_type nt_group ttl=0 concurrency=5 %LOGIN /usr/lib/squid/wbinfo_group.pl
 
acl all src 0.0.0.0/0.0.0.0
acl manager proto cache_object
acl localhost src 127.0.0.1/255.255.255.255
acl to_localhost dst 127.0.0.0/8
acl SSL_ports port 443 563
acl Safe_ports port 80
acl Safe_ports port 21
acl Safe_ports port 443 563
acl Safe_ports port 70
acl Safe_ports port 210
acl Safe_ports port 1025-65535
acl Safe_ports port 280
acl Safe_ports port 488
acl Safe_ports port 591
acl Safe_ports port 777
acl CONNECT method CONNECT
acl QUERY urlpath_regex cgi-bin \?
acl allowedurls dstdomain "/etc/squid/restrictedusers_allowedurls"
acl blockcache url_regex -i "/etc/squid/restrictedusers_blockcache"
# blockads is optional for this config
acl blockads url_regex -i "/etc/squid/blockads"
acl restrictedusers external nt_group XWebRestricted
acl unrestrictedusers external nt_group XWebAll
acl Authenticated proxy_auth REQUIRED
 
# Things never to cache
no_cache deny QUERY
# Enable this if you don't want any caching
#no_cache deny all
 
http_access allow manager localhost
http_access deny manager
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost
# blockads is optional for this config
http_access deny blockads
http_access deny blockcache restrictedusers
http_access allow allowedurls restrictedusers
http_access allow unrestrictedusers
http_access deny !Authenticated
http_access deny all
 
http_reply_access allow all
 
acl FTP proto FTP
always_direct allow FTP
 
cache_mgr [someone]
cache_effective_user squid
cache_effective_group squid
 
# I have very little RAM, so I set this off. YMMV
memory_pools off
forwarded_for on
error_directory /etc/squid/errors
coredump_dir /var/spool/squid
 
# note 33,2 lets you see which acl allowed or denied
debug_options ALL,1 33,2

/etc/squid/restrictedusers_allowedurls would be a text file that looks like:
.google.com
.yahoo.com
.yimg.com

/etc/squid/restrictedusers_blockcache, so they can't cheat and look at a cached page, would look like:
google.com.*cache
yahoo.com.*cache

Why allow restricted users to go to search sites at all? I think they should have the ability to look for things so they can request sites they think they need access to. I don't have the time to keep up with all the sites they could use for business purposes. The short summary should be enough for them to determine if it would be beneficial and enough to give the URL so management can review their request.

/etc/squid/blockads, and related acl+http_access, is something I use to block most urls used to display ads. You don't have to use it, but why not make this thing beneficial to your users as well. See the end of this page for the full text of what I am using.

Note on Squid ACLs: Take it in baby steps. I suggest not trying to do NTLM auth right away, but instead test using an IP address. This lets you make sure you've got your ACL logic working without having to worry if auth is working. An example ACL would look like:

...
acl all src 0.0.0.0/0.0.0.0
...
acl allowedurls dstdomain "/etc/squid/restrictedusers_allowedurls"
acl blockcache url_regex -i "/etc/squid/restrictedusers_blockcache"
# block specific ip
acl restrictedusers src [ip_address_to_restrict]/255.255.255.255
# allow specific ip
acl unrestrictedusers src [ip_address]/255.255.255.255
 
http_access allow manager localhost
...
http_access deny blockcache restrictedusers
http_access allow allowedurls restrictedusers
http_access allow unrestrictedusers
http_access deny all
...

Once you have it blocking or not blocking based on IP, then start trying the auth. Note that I am using Windows Domain Groups. You could also use a text file and block based on login name.

How to block based on browser (specifically IE and Gator)


5) Running and testing

You can skip the Samba part if you have winbind working with challenge/response.

  • First, start up samba
    service smb start
  • Then join the domain (only need to do once) with:
    smbpasswd -j [DOMAIN] -r [PDC] -U [user_name]
  • Now start winbind
    service winbind start
  • Test joining the domain
    wbinfo -t
    (Should return "Secret is good")
  • Test challenge/response:
    wbinfo -a [domain]\\[user]%[password]

Now, on to Squid.

  • Initialize the cache (only need to do once or when you make changes to the disk cache):
    squid -z
  • Now run Squid:
    service squid start
  • Test getting if someone belongs to a Windows Domain group, if you are going to use this feature:
    cd /usr/lib/squid
    ./wbinfo_group.pl
    [domain]\[user] [domain]\[group]
    (press [ctrl]+[c] to exit)

    OK is returned if they are in the group, otherwise ERR.
  • Configure a browser to use your new proxy
    For IE: Go to Tools->Internet Options->Connections->LAN Settings
    For Mozilla: Go to Tools->Options->General->Connection Settings

Note on NTLM auth for IE: If the computer belongs to the Windows domain, you need to turn it on to avoid the dialog box pop-up. Go to Tools->Internet Options->Advanced tab and check "Enable Intergrated Windows Authentication" and then reboot your computer. Computers that are not members of the domain will pop-up no matter what (except for Win9x, so long as they have logged into the domain).

To test Squid, try running as an IP or user that is restricted or denied. Then try as an IP or user who is not restricted or denied. Check out the log files - access.log and cache.log in /var/log/squid; to find information to help you in figuring out problems. Remember in squid.conf I had debug_options ALL,1 33,2? The "33,2" causes more info to be displayed in cache.log. You can set this to debug_options ALL,1 when you no longer need to debug.

Once things are working, you need to make sure Samba, Winbind, and Squid start on boot:
chkconfig smb on
chkconfig winbind on
chkconfig squid on

See Squid's FAQ #23 for ways to keep from having to run smbd and nmbd constantly.


6) Auto configuration of browsers

In IE you can check "Automatically detect settings" to have the browser go out and find what proxy settings should be used. This is quite handy, especially for your laptop users. Other browsers, such as Mozilla, can be given a URL to input rather than the user typing in the proxy info for each supported protocol.

Some links:
Squid FAQ #5
Another WPAD how-to
WPad and Active Directory
A reference made to the DHCP method

Being that I'm still using Windows NT 4 Server for DHCP, and that it does not support a type 252 entry, I decided to go with the DNS method. You can use both and even Active Directory Group Policy, if you run AD. Even if you don't have an internal DNS server, you can always use a host file that is placed on each workstation when they login (do that via a script) in order for the computer to be able to resolve wpad.[domain].[com].

For the DHCP method, create a type 252, AUTO-PROXY-CONFIG, entry that gives a URL to the proxy.pac file and you should be done. At least this is how other sites make it sound.

For the DNS method:

  • First create an A record of wpad.[domain].[com], or a CNAME record of wpad, that points to your internal web server. If you don't have an internal DNS server you can use a hosts file on the workstation. If your web server is hosted off-site or you don't have one, you can run Apache or TUX on the same box as Squid (if you have enough memory) or another box or even install Apache for Windows on a workstation. IIS on a workstation will be limited to 10 simultaneous connections. (WPAD = Web Proxy Auto-Discovery Protocol)
  • Now create your proxy.dat, for the DNS method, and/or a proxy.pac, for the DHCP method, in a ASCII text editor, such as notepad or VI. It should look something like (there is a more complex example in the Squid FAQ):
    function FindProxyForURL(url,host)
    { if(isPlainHostName(host)||
        isInNet(host,"192.168.1.0","255.255.255.0")) return "DIRECT";
      else return "PROXY 192.168.1.253:3128; DIRECT";
    }
  • You'll also want this file to be called proxy.pac and wpad.dat, for various methods. You can either create them as symbolic links, if using a Unix file system and the web server is configured to allow following of sym links:
    ln -s proxy.dat wpad.dat
    or use Apache's redirect in either its config file or a .htaccess file in the root directory, if redirect is allowed in the config file overrides:
    Redirect /wpad.dat http://wpad.[domain].[com]/proxy.dat
    or just copy the files to the new names, remembering to change all of them if you modify one.
  • Now you need to add the correct mime type to your web server. For Apache it is:
    AddType application/x-ns-proxy-autoconfig .dat
    Which can go in your Apache config file or in the root .htaccess file.
  • Then you need to make sure your web server is configured to allow you to access it via the name wpad.[domain].[com]. For Apache you may need to add this to the config file:
    NameVirtualHost *:80
     
    <VirtualHost *:80>
         ServerName www.[domain].[com]
         ServerAlias [domain].[com] wpad.[domain].[com]
         DocumentRoot /var/www/html
    </VirtualHost>
  • Restart Apache after making changes to its config file.
  • Now in IE, go to Tools->Internet Options->Connections->LAN Settings and check "Automatically detect settings". For Mozilla, go to Tools->Options->General->Connection Settings and select "Automatic proxy configuration URL:" and give it a URL like http://wpad.[domain].[com]/proxy.dat.

If you are having problems, check that wpad.[domain].[com] can be resolved by using nslookup, on Windows, or dig, on Linux. Then check that you can directly access http://wpad.[domain].[com]/proxy.dat. For IE, you may need to "flush" its cache of the proxy info (thank you, MS). To do this, clear the "Auto detect", close IE, re-open IE, re-enable "Auto detect", close IE, re-open IE. Supposedly this started with IE 5.5.

Mozilla/Firefox/Netscape cannot, at this time, use the WPAD method for automatically retrieving proxy settings. However, they do have a place to specify a URL to the config file. For Mozilla/Firefox, see Tools->Options->>General->Connection Settings. To configure this for all users edit all.js or firefox.js, depending on software and version, and add:

// Setup proxy
pref("network.proxy.autoconfig_url", "http://wpad.[domain].[com]/proxy.dat");
pref("network.proxy.no_proxies_on",  "localhost, 127.0.0.1, .[domain].[com]");
pref("network.proxy.type",           2);

Note that Mozilla, or at least my Firefox 0.9, appears to have problems if a startup page uses a URL that requires access through the proxy to load. From a packet capture it appears that occasionally the request for the start page is made before retrieving the proxy settings. See Bug 100022.


7) Misc

If you are having problems with Java applets causing a basic auth pop-up, try upgrading to the latest J2RE, from Sun, or re-installing.

Other Squid related things:
SquidGuard - "An ultrafast and free filter, redirector and access controller"
Viralator - AV scanner plug-in
DansGuardian - web content filter, not free for business use
DG AV plug-in

My /etc/squid/blockads file:

(^|\.)doubleclick\.
(^|\.)fastclick\.
(^|\.)clickstream\.
(^|\.)clickthrutraffic\.
(^|\.)clickthru\.
(^|\.)clickxchange\.
(^|\.)valuestream\.
(^|\.)valuexchange\.
(^|\.)valueclick\.
(^|\.)dimexchange\.
(^|\.)dimeclick\.
(^|\.)adbanner\.
(^|\.)adclick\.
(^|\.)ad-flow\.
(^|\.)adflow\.
(^|\.)adimg\.
(^|\.)adimage\.
(^|\.)adimages\.
(^|\.)adlog\.
(\/|\.)admt\.
(^|\.)ads\.
/ads/
(\/|\.)adserv\.
(^|\.)adserver\.
(^|\.)adservere\.
(^|\.)adsremote\.
(\/|\.)adsrv
(^|\.)adstream\.
(^|\.)adtrix\.
(^|\.)adv\.
(^|\.)advert\.
(^|\.)advertising\.com
(^|\.)adxchange\.
(\/|\.)atdmt\.
(^|\.)banner\.
(^|\.)banners\.
(^|\.)gator\.
us\.yimg\.com/a/

For other methods of blocking ads with Squid:
A list of servers you can download
Ad Zapper
Ad Zapper how-to