Transparent Squid authentication with

advertisement
Transparent Squid authentication with SquidTrust III
(ACL’s based on NDS or AD group membership.)
This article and the provided scripts are an update to the original tools located at:
http://www.novell.com/communities/node/12886/squid-authentication-novell-client-akasquidtrust
I felt that there were enough differences and new features that it warranted a new article,
and some detailed instructions.
Updates/differences:
-- Netware user name calls now made via NDS rather than bindry.
-- Ability to return Netware user and Group Membership information.
-- Ability to return Active Directory user and Group Membership information
-- Port changed from 6399 to 2199
-- Removed “who am I” from icon menu.
The difference between this solution and most other solutions is that most of the “heavy
lifting” is done on the workstation, rather than tying up cycles on the Squid Proxy server.
For the NDS username, this version makes a call to the Novell client files that come with
the Novell workstation client32. No tree walking or directory searching. This version also
has the ability to return a users’ group membership information based on an LDAP call
from the workstation to an eDirectory LDAP server.
Native Windows and Active Directory information is pulled from the machine via a small
VB script.
Source code and a precompiled binary (SquidTrustIII.exe) are available at
http://sourceforge.net/projects/squidtrust/
(look for version III)
To test:
Run the SquidTrustIII.exe (or the uncompiled script using Autohotkey
http://www.autohotkey.com/).
From the command prompt telnet to the workstation on port 2199.
Pressing a “1” will get the netware username returned.
Pressing a “2” will get the computer name returned.
Pressing a “3” will get the windows username returned.
Pressing a “4” will get a bunch of computer info returned.
(ComputerName,WindowsUserName,NWuserName,ip,macaddr,SN,modNum,YYYYMM-DD Hour:Min)
Pressing a “5” will return the current Netware users name followed by all of the groups
that the user is a member of (If the prerequisites are configured correctly).
Pressing a “6” will return the current Active Directory users name followed by all of the
groups that the user is a member of (If not a Domain member, just the local groups will
be returned).
Pressing a “7” will return the current Netware username and groups if the Novell client32
is installed on the workstation, otherwise, the Active Directory users name followed by
all of the groups that the user is a member of (If not on a Domain, just the local groups)
will be returned.
BASIC USAGE:
Exactly like the previous version.
1. Run the SquidTrustIII.exe on the workstation
2. Run the Perl Authentication helper on the Squid Proxy server.
3. See http://www.novell.com/communities/node/12886/squid-authenticationnovell-client-aka-squidtrust for instructions.
4. SquidTrustII runs off port 2199, don’t forget to make the appropriate changes in
firewalls etc…and don’t forget to chmod the script to 7777
BASIC PERL HELPER
Basic Perl auth. Helper code for SquidTrustIII:
[code]
#!/usr/bin/perl
use IO::Socket;
$|=1;
## Main loop (START), sets the loop to wait for an input <STDIN> and sets the input
to $host (clients IP address)
START: while ($host = <STDIN>) {
## Sets up the socket connection to the client computer
$port = 2199;
$sock = new IO::Socket::INET(PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp',
Timeout => '1',);
## if - else section to either print OK or ERR based on weather a successful connection was made
if ($sock =~ /IO::Socket/) {
#send a command to the workstation
$cmd = "1";
print $sock $cmd;
# print workstation response
$nwusername = <$sock>;
if ( length $nwusername > 0 )
{
print "OK user=$nwusername\n";
close $sock;
next START;
}
else
{
print "ERR\n";
close $sock;
next START;
}
} else {
print "ERR\n";
close $sock;
}
next START;
}
[/code]
The above procedure should work pretty much exactly like the previous version.
The above script is set to send a “1” ($cmd = "1";). To get a different response from the
SquidtrustIII.exe, just change that value. You should only use 1,2, or 3 as values in the above script.
The “Advanced” section, Squid ACL’s based on NDS/AD
Group Membership:
In this section I will show how to use the SquidTrustIII.exe to return a Netware users
name and group memberships.
I will then show how to apply Squid ACL’s based on a user’s group membership.
SquidtrustIII uses a LDAP call from the workstation to a Novell LDAP server to
return the current users name and group memberships.
There are 5 Prerequisites:
1. An eDirectory LDAP server
2. Your LDAP server must allow anonymous connections on port 389. SquidTrustIII
has no built in support for LDAP login/password, proxy access, or secure connections
(port 636). If you want/need these things, the code is open source….
3. The NDS attribute “Group Membership” must be mapped to the LDAP attribute
“groupMembership” – this is done under “Attribute mappings” of your LDAP Group
object.
4. The Group Membership attribute must be “readable” by “public”. This is done
under the properties of the root of your NDS tree. Make sure that it is marked as
“inheritable”. This is exposing your group memberships to any anonymous
connections, please make sure you understand the security ramifications.
To test that the attributes are set correctly, and that they are publicly viewable,
connect to your LDAP server with an LDAP browser as an “anonymous” connection
and make sure you can browse the LDAP directory, and see the groupMembership
attribute.
(Apache studio, and Softerra LDAP browser version 2.6 are both good LDAP
browsers with easy to use GUI’s…)
You must be able to see these attributes as an anonymous user, or SquidTrustIII will
not be able to pull the NDS group memberships.
5. DNS resolution.
By default, the SquidTrustIII.exe is hard coded to look for a DNS name of
“SQDLDAP”.
The name “SQDLDAP” is expected to resolve to your eDirectory LDAP server.
In most cases, simply adding a DNS entry to a DNS forwarder/server would be the
easiest and best solution. If you are running a Squid Proxy, chances are you have
access to some sort of name resolution process….
You could also add the entry to the client machines “hosts” file.
Ie:
# For example:
#
# 102.54.94.97 rhino.acme.com
# source server
#
38.25.63.10 x.acme.com
# x client host
127.0.0.1
localhost
10.1.3.175
freenasBACKUP.local
10.1.1.7 sqdldap
The last option would be to run the SquidTrustIII.exe file with an argument.
By default the exe will accept a single IP address (of your LDAP server) as an
argument.
like…
This method very convenient for testing, but probably not really a production ready
solution.
To test that DNS resolution is working, you should be able to ping “sqdldap” from
your workstations, and have it resolve to your eDirectory LDAP server
So…..DNS is not truly “required”, but it is by far the preferred method.
If all 5 of the prerequisites are met: and setup correctly, the SquidtrustIII.exe
should return the NDS user name and all of the group memberships of that user when
sent a “5”.
Nested groups may or may not work……untested.
If the machine is logged into a windows domain, sending a “6” should return the
domain user name, and all of the group memberships of that user.
ActiveDirectory (sending a “6” )
NDS (sending a “5” )
The returns are pretty much in the same format of
“<username>,<Group1>,<Group2>,<GroupX..>
Groups are separated by spaces in the NDS return, and by commas in the AD return.
Now we just use a Perl Authentication helper on the Squid Proxy to parse, and return
the information we want.
The helper is really pretty simple:
1. It waits for an IP address from a workstations http request
2. In the following code the helper sends back a “7” to the workstation on port 2199
3. the workstations SquidtrustIII.exe agent does it’s magic and sends the squid
helper back a string that contains the users name and group memberships.
4. split the string into an array
5. array[0] is always the username
6. search for group names defined in the if-else section
7. output the appropriate response (OK, ERR)
8. Start listening again.
“Advanced” Authentication helper Perl code:
Comments and code notes are included in the code.
(please note: code formatting may be off due to the cut/paste into a word processing document)
You will have to modify the code for your particular environment.
[code]
#!/usr/bin/perl
## Authentication helper for SquidTrustIII
## Scott Owen June/25/2012
## sowen-at-edzone.net
##
##
##
##
##
##
##
##
##
##
Squid authentication helper for use with the SquidtrustIII agent.
"ERR" or "OK" codes will be given depending on group membership
In this example
FULLACCESS membership = "OK user=username[FULLACCESS]"
LIMITEDaccess membership = "OK user=username[LIMITEDaccess]"
group4 membership = "OK user=username[group4]"
##
##
##
##
##
##
##
##
##
##
Any other group memberships, or no matching group memberships will cause an
"ERR" to be returned.
"ERR" and "OK user=" are the two states that squid expects from an auth.
helper.
The users login name will be changed to a format of: username[group]
This is the name that will show in access logs.
This will show the users name and the group membership that allowed the user
access to the proxy/cache.
use IO::Socket;
$|=1;
## Main loop (START), sets the loop to wait for an input <STDIN> and sets the
## input to $host (clients IP address)
START: while ($host = <STDIN>) {
## Sets up the socket connection to the client computer
$port = 2199;
$sock = new IO::Socket::INET(PeerAddr => $host,
PeerPort => $port,
Proto
=> 'tcp',
Timeout => '1',);
## "if - else" section to either print OK or ERR based on weather a successful
## connection was made, and then sort for group
## membership.
# set error code to zero
$errorcode = 0;
if ($sock =~ /IO::Socket/) {
#send a command to the workstation
$cmd = "7";
print $sock $cmd;
# print workstation response
$adusername = <$sock>;
# Check and make sure we got a response,
# if the response wasn't blank, split it apart
if ( length $adusername > 0 )
{
## print "$adusername\n";
@array = split (',', $adusername);
foreach my $array (@array)
{
# start parsing the response for group memberships.
# This part is pretty simple, just search the returned
#string for group names.
if ( $array =~ "FULLaccess"){
$errorcode = 1;
print "OK user=$array[0]\[FULLaccess\]\n";
close $sock;
next START;
}
else{
if ( $array =~ "LIMITEDaccess"){
$errorcode = 1;
print "OK user=$array[0]\[LIMITEDaccess\]\n";
close $sock;
next START;
}
else{
if ( $array =~ "group4"){
$errorcode = 1;
print "OK user=$array[0]\[group4\]\n";
close $sock;
next START;
}
## closing brackets for if/else statements
}
}
}
## if no group memberships matched, error out
if ($errorcode < 1 ){
print "ERR\n";
close $sock;
next START;
}
}
## if the socket response was blank, error out.
}
print "ERR\n";
close $sock;
$errorcode = 0;
next START;
}
[\code]
NDS response
AD response
Jumping between AD and NDS
The helper has basically changed the users name from “SOWEN” to
“SOWEN[FULLaccess]” and from “mringle” to “mringle[FULLaccess]”.
At this point the members of the FULLaccess group have a common string as part of their
Squid username, so it becomes very simple to apply Squid ACL’s based on weather their
username contains the string “FULLaccess”…..just avoid making any users with the
same string in their name.
I add the authentication helper to my Squid.conf something like this:
[code]
external_acl_type IPUser ttl=60 children=10 %SRC/usr/local/squid/SquidTrustIII.pl
acl AuthNDS external IPUser
http_access allow AuthNDS
auth_param basic program /usr/local/libexec/squid/squid_ldap_auth -v 2 -b
T=MYTREE -D cn=adminusername -w adminpassword -f
"(&(|(groupMembership=cn=LIMITEDaccess,o=INTERNET)(groupMembership=cn=FULLacces
s,o=INTERNET))(objectclass=User)(cn=%s))" -u uid -P 10.1.1.7
auth_param basic children 70
auth_param basic realm Welcome to my Internet Proxy, please enter your user
name and password to continue:
[\code]
I run the helper before the default LDAP (squid_ldap_auth), that way if the user gets
denied access via the auth helper, they have a chance to login with the standard LDAP
authentication mechanism.
As an example ACL using the group membership “FULLaccess”, I’ll send users that are
members of the “FULLaccess” group out the WAN IP address 9.11.15.11
[code]
acl Namecheck ext_user_regex [-i] .*FULLaccess*.*
tcp_outgoing_address 9.11.15.11 Namecheck
[\code]
Using the “ext_user_regex” acl should allow you to use almost any standard acl
directive(s).
Download