php寫的squid驗證輔助器


2008-11-08 23:17

公司的代理服務器用的是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

發佈了40 篇原創文章 · 獲贊 2 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章