星期四, 5月 24, 2007

[linux]squid精選文章06

原文: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




沒有留言: