公司的代理服务器用的是squid,基于IP地址和MAC地址进行权限验证允许部分用户访问Internet。无奈列位高手们早已通晓盗用IP、MAC的方法来绕过squid的限制。近来考虑改为帐号认证。
由于同时在维护一个邮件服务器(qmail + vpopmail + mysql),邮件帐号用mysql管理,内网用户人手一邮箱。为了便于用户记忆,想直接使用邮件帐号和密码作为squid的帐号密码。
程序嘛,比较靠谱的是 mysql_auth ,无奈对c一窍不通,只能借鉴一下它的思路......干脆自己写一个吧。
其他已知资料:
《Squid中文权威指南》 ,第12章有一个perl的例子以及以下文字:
在squid和基本验证器之间的接口非常简单。squid发送用户名和密码到验证器进程,他们以空格分开并以新行结束。验证器在其他stdin里读取用户名和密码。在检查信用项后,验证器将OK或ERR写入stdout。
任何“不安全的URL”字符会参照RFC1738规则进行编码。这样,名字“jack+jill”变成了"jack%2bjill"。squid接受包含 空格的用户名和密码。例如“a password”变成了“a%20password”。在解码用户名和密码后,验证器程序能处理空格和其他的特殊字符。
要点总结:从stdin读取用户名和密码,用户名和密码以空格分隔,可能涉及解码。vpopmail里用户帐号和密码分别 是pw_name和pw_passwd列,建一个表squid,只有一列pw_name,把有权用户的用户名添加到表squid里,用pw_name列关 联两个表查询获得pw_passwd,和用户的输入做比较,一致即验证成功。
PHP代码如下:
# ! / usr/ bin/ php < ? php ini_set ( "display_errors" , false ) ; function valid( $ u , $ p , $ sql_link ) { $ result = false ; $ res = mysql_query ( "select pw_passwd from squid a, vpopmail b where a.pw_name='$u' and a.pw_name=b.pw_name" , $ sql_link ) ; $ rows = mysql_num_rows ( $ res ) ; if ( 1 = = $ rows ) { $ data = mysql_fetch_object ( $ res ) ; $ passwd = $ data - > pw_passwd; if ( $ passwd = = crypt ( $ p , $ passwd ) ) { $ result = true ; } } return $ result ; } while ( ! feof ( STDIN) ) { $ sql_link = mysql_connect ( "x.x.x.x" , "xxx" , "yyy" ) ; mysql_select_db ( "vpopmail" , $ sql_link ) ; $ input = trim ( fgets ( STDIN) ) ; $ data = explode ( ' ' , $ input ) ; $ username = rawurldecode ( $ data [ 0] ) ; $ password = rawurldecode ( $ data [ 1] ) ; if ( valid( $ username , $ password , $ sql_link ) ) { fwrite ( STDOUT, "OK/n" ) ; } else { fwrite ( STDOUT, "ERR/n" ) ; } mysql_close ( $ sql_link ) ; } ? > |
更进一步:squid基于mysql的用户+ip绑定认证
昨天写的《用php写一个squid验证辅助器(authentication helper)》实现了squid基于mysql的用户帐号认证,今天再进一步修改一下程序,支持基于mysql的用户+ip绑定认证功能。
使用/etc/squid/acl_valid_user.txt存放用户的ip和帐号信息,ip和帐号以空格分隔,帐号与mysql数据表里的用户帐号是一致的,格式如下:
192. 168. 1. 100 pangty 192. 168. 1. 200 test |
相应的修改squid.conf,使用ip_user_check来进行帐号与ip的关联检查
external_acl_type ip_user_check children= 5 % SRC % LOGIN / usr/ lib/ squid/ ip_user_check -f / etc/ squid/ acl_valid_user. txt acl acl_ip_user_check external ip_user_check acl acl_valid_user proxy_auth REQUIRED http_access allow acl_valid_user acl_ip_user_check http_access deny all auth_param basic program / usr/ lib/ squid/ my_auth. php auth_param basic children 5 auth_param basic realm 互联网访问权限验证 auth_param basic credentialsttl 2 hours auth_param basic casesensitive on |
my_auth.php验证辅助程序加入对acl_valid_user.txt的验证,原来在mysql里创建的squid表作废。
# ! / usr/ bin/ php
< ? php
ini_set ( "display_errors" , false ) ;
$ datafile = "/etc/squid/acl_valid_user.txt" ;
function valid( $ u , $ p , $ sql_link ) {
$ result = false ;
$ res = mysql_query ( "select pw_passwd from vpopmail where pw_name='$u'" , $ sql_link ) ;
$ rows = mysql_num_rows ( $ res ) ;
if ( 1 = = $ rows ) {
$ data = mysql_fetch_object ( $ res ) ;
$ passwd = $ data - > pw_passwd;
if ( $ passwd = = crypt ( $ p , $ passwd ) ) {
$ result = true ;
}
}
return $ result ;
}
$ data = file_get_contents ( $ datafile ) ;
$ line = preg_split ( "//n/" , $ data ) ;
foreach ( $ line as $ l ) {
$ l = trim ( $ l ) ;
if ( ! empty ( $ l ) ) {
list ( $ k , $ v ) = preg_split ( "/ +|/s+/" , $ l ) ;
$ userarr [ $ v ] = $ k ;
}
}
while ( ! feof ( STDIN) ) {
$ sql_link = mysql_connect ( "x.x.x.x" , "xxx" , "yyy" ) ;
mysql_select_db ( "vpopmail" , $ sql_link ) ;
$ input = trim ( fgets ( STDIN) ) ;
list ( $ u , $ p ) = split ( " " , $ input ) ;
$ username = rawurldecode ( $ u ) ;
$ password = rawurldecode ( $ p ) ;
if ( array_key_exists ( $ username , $ userarr ) & & valid( $ username , $ password , $ sql_link ) ) {
fwrite ( STDOUT, "OK/n" ) ;
} else {
fwrite ( STDOUT, "ERR/n" ) ;
}
mysql_close ( $ sql_link ) ;
}
? >
http://bbs.chinaunix.net/viewthread.php?tid=1276393