php写的squid验证辅助器

来源:互联网 发布:vscode golang 运行 编辑:程序博客网 时间:2024/04/28 16:23

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

原创粉丝点击