Mission
To write a Python program which can be used to authenticate for Squid proxy server. This is useful when you don’t want to configure complex systems like LDAP, ntlm etc.
Use Cases
- When you want to authenticate clients using mysql database.
- When you want to authenticate clients using flat files or /etc/passwd file or some custom service on your network.
How to proceed
From auth_param section in squid.conf file:
Specify the command for the external authenticator. Such a program reads a line containing "username password" and replies "OK" or "ERR" in an endless loop. "ERR" responses may optionally be followed by a error description available as %m in the returned error page.
By default, the basic authentication scheme is not used unless a program is specified.
That clearly states that our python program should read a line from standard input (stdin) and write the appropriate response to the standard output (stdout). But there are some issues with I/O. The output should be unbuffered and should be flushed to standard output immediately after the response is known.
So, lets see a small program where we authenticate using a function ‘matchpassword()‘. This function returns True when username, password pair matches and returns False when they mismatch.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #!/usr/bin/python import sys import socket """USAGE:The function returns True if the user and passwd match False otherwise""" def matchpasswd(login,passwd): # Write your own function definition. # Use mysql, files, /etc/passwd or some service or whatever you want pass while True: # read a line from stdin line = sys.stdin.readline() # remove '\n' from line line = line.strip() # extract username and password from line username = line[:line.find(' ')] password = line[line.find(' ')+1:] if matchpasswd(username, password): sys.stdout.write('OK\n') else: sys.stdout.write('ERR\n') # Flush the output to stdout. sys.stdout.flush() |
Save the above file somewhere. We save this example file in /etc/squid/custom_auth.py .Now, we have the function for authenticating clients. We need to configure squid to use custom_auth.py . Below is the squid configuration for telling squid to use the above program as basic authenticator.
1 2 3 4 5 6 7 8 9 10 11 | # you need to specify /usr/bin/python if your file is not executable and needs an interpreter to be invoked. # Replace /usr/bin/python with /usr/bin/php , if you write auth program in php. auth_param basic program /usr/bin/python /etc/squid/custom_auth.py # how many instances of the above program should run concurrently auth_param basic children 5 # display some message to clients when they are asked for username, password auth_param basic realm Please enter your proxy server username and password # for how much time the authentication should be valid auth_param basic credentialsttl 2 hours # whether username, password should be case sensitive or not auth_param basic casesensitive on |
Now, to force clients to authenticate, configure the acls as follow. Below we assume, you want to force all clients on your lan to authenticate for using proxy server.
1 2 3 4 5 6 | # acl to force proxy authentication acl authenticated proxy_auth REQUIRED # acl to define IPs from your lan acl lan src 192.168.0.0/16 # acl to force clients on your lan to authenticate http_access allow lan authenticated |
Now, reload/restart squid. That’s all we need to write and use a custom authentication plugin for squid.
Limitation
Username can’t contain spaces. Otherwise program will not be able to parse/extract username, password from standard input.