公司的代理服務器用的是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 ) ; } ? > |
上述代碼保存爲/usr/lib/squid/my_auth.php,屬性如下:
-rwsr-x--- 1 root squid 843 09-25 15:12 /usr/lib/squid/my_auth.php
squid.conf的相關配置:
acl acl_valid_user proxy_auth REQUIRED
http_access allow acl_valid_user
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
更進一步: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