原文:http://www.chinaitpower.com/2005September/2005-09-13/196538.html
前天看了一下ncsa_auth認證程序的源碼,發現這個認證其實是非常簡單的。
squid啟動時運行ncsa_auth passwd密碼文件
如果你的認證用戶不是很多的話,寫個sh就可以解決問題了
ncsa_auth.sh
內容如下
#認證用戶名為abc密碼123
[code:1:e0e520c5be]
while true ; do
read a
user=`echo a| /usr/bin/cut -d ' ' -f1`
pass=`echo a|/usr/bin/cut -d ' ' -f2`
if [ "$user" == "abc" ] ; then
if [ "$pass" == "123" ] ; then
echo OK;
else
echo ERR;
fi
else
echo ERR
fi
done
#結束
呵呵,如果你的認證不是很頻繁的話。但是你希望與你的數據庫認證集成在一起的話
你也可以用php連結數據庫達到這個目的
在ncsa_auth.sh裡的內容應該如下:
/usr/local/bin/php /usr/local/etc/ncsa_auth.php
在ncsa_auth.php內容
[/code:1:e0e520c5be]
拋磚引玉,希望大家在用squid認證能夠有所啟發,當然如果你覺得效率低下的話就使用C,直接修改squid自帶的ncsa_auth.c加了數據庫查詢語句就行了。
ljily000 回復於:2005-03-06 21:11:31
:em27:
頂!
Good!
段譽 回復於:2005-03-12 04:00:37
頂上來,大家都瞭解一下。
BTW:請大家多多關注我們這個板子,多推薦好帖子,增加我們這個板子的精華數量。謝謝!!
shitian8848 回復於:2005-03-12 09:32:49
正在弄squid的認證呢,呵呵,謝謝樓主了。
UP!
platinum 回復於:2005-03-12 10:45:27
請教一下樓主
[code:1:4e08dde378]
while true ; do
read a
user=`echo a| /usr/bin/cut -d ' ' -f1`
pass=`echo a|/usr/bin/cut -d ' ' -f2`
if [ "$user" == "abc" ] ; then
if [ "$pass" == "123" ] ; then
echo OK;
else
echo ERR;
fi
else
echo ERR
fi
done
#結束
[/code:1:4e08dde378]
這個shell用於哪裡?
好像和squid認證無關啊~
另外,ncsa的密碼是MD5後的,而樓主這個shell是明碼
我只是想知道,這個shell是做什麼的呢?
60133056 回復於:2005-03-12 13:45:32
觀望 學習
wingger 回復於:2005-03-12 14:28:08
[quote:7f7046b6b5="platinum"]這個shell用於哪裡?
好像和squid認證無關啊~
另外,ncsa的密碼是MD5後的,而樓主這個shell是明碼
我只是想知道,這個shell是做什麼的呢?[/quote:7f7046b6b5]
我也想知道,是用這個來代替ncsa嗎?
還是解剖他的原理?
wxxszzz 回復於:2005-03-12 17:43:24
看了上面大家的回貼,我就再解釋一下吧。
我們使用htpasswd產生的那個密碼文件裡的密碼是用MD5加密的。
但是squid傳遞給ncsa_auth認證程序的密碼使用的是明碼,
然後由ncsa_auth認證程序再用md5加密傳給他的密碼後
再與用htpasswd產生的那個密碼文件裡的密碼相比較。
如果符合就認為密碼正確。
另外以上的sh與使用php密碼認證的程序。
就是接到squid的密碼後,不使用md5加密接收到的密碼,直接比較,
以上的兩個程序
他們都是可以直接替代ncsa_auth這個認證程序的。
OK,如果還有疑問,可以再提問,不過我覺得SQUID他這樣的認證是比較合理的。現時也比較直接明瞭,
設想一下,如果你的認證用戶非常多,如有1000人以上同時認證,我們可以簡單的使用上面的高級語言如C、php、perl、java等語言,只要他的代碼裡支持套接字sockets接口你就可以設計一個集中式的認證系統。
以PHP舉例:
代碼如頂摟的語言裡只是稍微修改一下。
[code:1:d8bd213a3b]
在ncsa_auth.php內容
[/code:1:d8bd213a3b]
這裡之後,一個比較好的認證中心這可以產生了。之所以選用PHP認證,是因為這段時間用PHP比較多。
這樣之後,你就可以使用多台SQUID,多台認證中心,一個中央數據庫。
呵呵,不知道各位看過我的解釋與說明之後,是不是有所啟發呢?
沒有做不到,只有想不到的事情。
platinum 回復於:2005-03-16 07:21:21
這個是ncsa_auth.c的源代碼
[code:1:2a9999c6f7]
/*
* ncsa_auth.c
*
* AUTHOR: Arjan de Vet
*
* Example authentication program for Squid, based on the original
* proxy_auth code from client_side.c, written by
* Jon Thackray .
*
* Uses a NCSA httpd style password file for authentication with the
* following improvements suggested by various people:
*
* - comment lines are possible and should start with a '#';
* - empty or blank lines are possible;
* - extra fields in the password file are ignored; this makes it
* possible to use a Unix password file but I do not recommend that.
*
*/
#include "config.h"
#if HAVE_STDIO_H
#include
#endif
#if HAVE_STDLIB_H
#include
#endif
#if HAVE_UNISTD_H
#include
#endif
#if HAVE_STRING_H
#include
#endif
#if HAVE_SYS_TYPES_H
#include
#endif
#if HAVE_SYS_STAT_H
#include
#endif
#if HAVE_CRYPT_H
#include
#endif
#include "util.h"
#include "hash.h"
static hash_table *hash = NULL;
static HASHFREE my_free;
typedef struct _user_data {
/* first two items must be same as hash_link */
char *user;
struct _user_data *next;
char *passwd;
} user_data;
static void
my_free(void *p)
{
user_data *u = p;
xfree(u->user);
xfree(u->passwd);
xfree(u);
}
static void
read_passwd_file(const char *passwdfile)
{
FILE *f;
char buf[8192];
user_data *u;
char *user;
char *passwd;
if (hash != NULL) {
hashFreeItems(hash, my_free);
}
/* initial setup */
hash = hash_create((HASHCMP *) strcmp, 7921, hash_string);
if (NULL == hash) {
fprintf(stderr, "ncsa_auth: cannot create hash table\n");
exit(1);
}
f = fopen(passwdfile, "r");
if (NULL == f) {
fprintf(stderr, "%s: %s\n", passwdfile, xstrerror());
exit(1);
}
while (fgets(buf, 8192, f) != NULL) {
if ((buf[0] == '#') || (buf[0] == ' ') || (buf[0] == '\t') ||
(buf[0] == '\n'))
continue;
user = strtok(buf, ":\n\r");
passwd = strtok(NULL, ":\n\r");
if ((strlen(user) > 0) & passwd) {
u = xmalloc(sizeof(*u));
u->user = xstrdup(user);
u->passwd = xstrdup(passwd);
hash_join(hash, (hash_link *) u);
}
}
fclose(f);
}
int
main(int argc, char **argv)
{
struct stat sb;
time_t change_time = 0;
char buf[256];
char *user, *passwd, *p;
user_data *u;
setbuf(stdout, NULL);
if (argc != 2) {
fprintf(stderr, "Usage: ncsa_auth \n");
exit(1);
}
while (fgets(buf, 256, stdin) != NULL) {
if ((p = strchr(buf, '\n')) != NULL)
*p = ''; /* strip \n */
if (stat(argv[1], sb) == 0) {
if (sb.st_mtime != change_time) {
read_passwd_file(argv[1]);
change_time = sb.st_mtime;
}
}
if ((user = strtok(buf, " ")) == NULL) {
printf("ERR\n");
continue;
}
if ((passwd = strtok(NULL, "")) == NULL) {
printf("ERR\n");
continue;
}
rfc1738_unescape(user);
rfc1738_unescape(passwd);
u = hash_lookup(hash, user);
if (u == NULL) {
printf("ERR\n");
} else if (strcmp(u->passwd, (char *) crypt(passwd, u->passwd))) {
printf("ERR\n");
} else {
printf("OK\n");
}
}
exit(0);
}
[/code:1:2a9999c6f7]
看了一下,關鍵問題是在這裡
[code:1:2a9999c6f7]
if ((user = strtok(buf, " ")) == NULL) {
printf("ERR\n");
continue;
}
if ((passwd = strtok(NULL, "")) == NULL) {
printf("ERR\n");
continue;
}
rfc1738_unescape(user);
rfc1738_unescape(passwd);
u = hash_lookup(hash, user);
if (u == NULL) {
printf("ERR\n");
} else if (strcmp(u->passwd, (char *) crypt(passwd, u->passwd))) {
printf("ERR\n");
} else {
printf("OK\n");
}
[/code:1:2a9999c6f7]
如果用ncsa_auth.php來做「認證中心」,squid又怎麼去調用呢?
wxxszzz 回復於:2005-03-16 10:04:32
你沒仔細看我項樓的貼子啊.
我寫得使用PHP認證是
squid先調用的是ncsa_auth.sh這個文件
也就是在squid.conf這個配置文件寫的認證程序為ncsa_auth.sh
而這個ncsa_auth.sh文件的內容就是調用php去執行ncsa_auth.php
ncsa_auth.sh這個文件的內容如下:
[code:1:5cb36057b4]
/usr/local/bin/php /usr/local/squid/etc/ncsa_auth.php
[/code:1:5cb36057b4]
#end
由這個ncsa_auth.sh來調用ncsa_auth.php
這樣就可以了啊.
然後再在ncsa_auth.php
裡面獲得squid傳遞的用戶名與密碼.
你仔細研究一下我樓上的那個貼子.
就應該能夠明白,如果你告訴我說不懂PHP,那我也無話可說了
platinum 回復於:2005-03-17 00:42:38
嘿嘿,還真不懂PHP,不過你的原理我是明白了
也可以
[code:1:b068d37ad6]
/bin/bash /xxx/ncsa_auth.sh
[/code:1:b068d37ad6]
這樣咯?
也可以多個squid通過一個認證服務器,那個服務器通過PHP+MYSQL進行處理,密碼或明或MD5,放到數據庫裡
如果這樣想,自由度真的很大
yxdyw 回復於:2005-04-04 10:14:42
wxxszzz
騎士:
一台ADSL,一台路由器,一台單網卡linux主機,adsl接入路由器,在路由器上面拔號共享上網,我現在在路由器上面開放主機linux,把所有的網關都改為linux主機地址,利用squid+iptables實現透明代理,不知道如何實現,其中如何控制局域網上網?謝謝
wxxszzz 回復於:2005-04-07 22:54:10
嘿嘿,大概很少有人會這麼做吧。
如果三個東東都在一個網段的話,只能實現HTTP透明代理成功。其他的遊戲啊QQ阿之類的就不行了。
要實現HTTP,你只要把80端口重定向到SQUID的端口3128端口就行了。
另外一個解決方案就是:
把那台LINUX的網卡再虛擬一塊網卡出來,做成兩個網段。
其中一個網段跟內網相同。另外一個網段跟路由器相同,當然路由器就只能改成跟linux的網段一樣羅。
這樣就成為了一個典型的雙網卡LINUX路由器了。所有的流量都經過LINUX再通過路由器出去。
至於如何在LINUX下一塊網卡綁定兩個地址,查查這個論壇的精華吧。
定義好了之後,最簡單的透明代理,使用IPTABLES只要三條語名。
[code:1:a7530cf441]
echo 1 >/proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0:1 -s 內網網段 -j MASQUERADE
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to LINUX內網地址:3128
[/code:1:a7530cf441]
OK
沒有留言:
張貼留言