上一集最後有談到,在建立VPN 連線時,可以再加入帳號密碼的認證,同時可以做一些Log 及特別的管制。
例如:記錄對方什麼時間點登入,由那個IP登入進來,使用了多少流量,同時可以限制User 幾點可以登入,User可以使用的流量等等...
這一集主要來跟大家分享這些功能要如何實現。
OpenVPN: Building and Integrating Virtual Private Networks
前情提要:OpenVPN 建置筆記(第7集)
小瑞使用了,部份的shell script + PHP + MySql 來實作這些功能。
首先是在 server.conf 增加一些設定。
[root@vpnserver1 ~]# vi /etc/openvpn/server.conf
在最後加入tmp-dir /etc/openvpn/temp
auth-user-pass-verify /etc/openvpn/auth_sh.sh via-file
client-connect /etc/openvpn/client_connect.php
client-disconnect /etc/openvpn/client_disconnect.php
1. 建立一個 temp 目錄,如果不指定,會直接使用到/tmp 目錄。
2. 指定 auth-user-pass-verify 要認證的指令碼,及使用何種帳密傳遞的方式。
3. 指定 client-connect 連線後要執行的指令碼。
4. 指定 client-disconnect 斷線後要執行的指令碼。
在使用者登入時,系統會記錄一個環境變數,叫做common_name,記錄使用者登入的帳號,基本上就是使用這個User所分配憑證上的common name。
如果你完全不想用使用者憑證,只想使用自建的帳號密碼管理,那就在server.conf 中再加入:
client-cert-not-required
username-as-common-name
加入後,在後面的指令碼,取得common_name 時,就會變成使用者輸入的帳號。至於要用什麼方式,看各位朋友想怎麼控制?小瑞還是使用憑證上的common name,進行後續的控制,同時管控,一個憑證只可以登入一次。在登入中,其它有同樣憑證的人,就不可以重複登入。
小瑞寫了幾支控制的程式如下,請參考:
認證的shell script
[root@vpnserver1 ~]# vi /etc/openvpn/auth_sh.sh
#!/bin/bashfor stat in `php /etc/openvpn/auth_sql.php $1`
do
if [ "$stat" = "1" ]; then
echo "fall"
exit 1
else
echo "ok"
exit 0
fi
done
認證的php程式
[root@vpnserver1 ~]# vi /etc/openvpn/auth_sql.php
#! /usr/bin/php
《?PHP
include 'connect.php';
$i_filename = $argv[1];
$i_fp = fopen($i_filename,'r');
$i_username = chop(fgets($i_fp,4096));
$i_passwd = chop(fgets($i_fp,4096));
fclose ($i_fp);// get user info
$v_sql = "select userId,userPwd,timelimit,startTime,endTime from users where effective='Y' and userAcc='".$i_username."' and currentLogId is NULL";
$v_res = mysql_query($v_sql);// 沒有這個帳號
if (mysql_num_rows($v_res)==0)
{
echo '1';
exit;
}// get user info
list($userId,$userPwd,$timelimit,$startTime,$endTime)=mysql_fetch_row($v_res);// check passwd 密碼錯誤
if ($userPwd != $i_passwd)
{
echo '2';
exit;
}// check time limit 不在允許的時間內登入
if ($timelimit == 'Y') {
if (($startTime>date('H')) or ($endTime 《 date('H'))) {
echo '3';
exit;
}
}
// check pass 過關了
echo '0';
連線後要執行指令碼-php程式
[root@vpnserver1 ~]# vi /etc/openvpn/client_connect.php
#! /usr/bin/php
《?PHP
//資料庫連接
include 'connect.php';// get user common name 前面有提到的環境變數
$i_common_name = getenv(common_name);
$i_trusted_ip = getenv(trusted_ip);// get userId
$v_sql = "select userId from users where userAcc='".$i_common_name."'";
$v_res = mysql_query($v_sql);
list($userId)=mysql_fetch_row($v_res);// insert into logs 寫入記錄檔
$v_sql = "insert into logs (userId,loginTime,loginIp) values('".$userId."',now(),'".$i_trusted_ip."')";
$v_res = mysql_query($v_sql);// get logId
$logId = mysql_insert_id();// update users info 把目前的log id 更新回user 主檔
// 如果有別的電腦使用同一個帳號登入,這個 log id 帳不是空的null ,
// 認證程式就會認證失敗,可實現一個帳號只可以同時上線1次,除非登出,
// 才可以在別台電腦上登入
$v_sql = "update users set currentLogId='".$logId."' where userId='".$userId."'";
$v_res = mysql_query($v_sql);// pass 0 to end
echo '0';
?》
斷線後要執行指令碼-php程式
[root@vpnserver1 ~]# vi /etc/openvpn/client_disconnect.php
#! /usr/bin/php
《?PHP
//資料庫連接
include 'connect.php';// get user common name 前面有提到的環境變數
$i_common_name = getenv(common_name);
// user 的傳輸資料量
$i_bytes_received = getenv(bytes_received);
$i_bytes_sent = getenv(bytes_sent);// get userId
$v_sql = "select userId,currentLogId from users where userAcc='".$i_common_name."'";
$v_res = mysql_query($v_sql);
list($userId,$currentLogId)=mysql_fetch_row($v_res);// update logs 更新記錄檔
$v_sql = "update logs set logoutTime=now(), bytes_received='".$i_bytes_received."', bytes_sent='".$i_bytes_sent."' where logId = '".$currentLogId."'";
$v_res = mysql_query($v_sql);// update users info 把log id 清空,以便下次user 可以通過認證,登入系統
$v_sql = "update users set currentLogId = NULL where userAcc='".$i_common_name."'";
$v_res = mysql_query($v_sql);// pass 0 to end
echo '0';
?》
資料庫連接程式-php程式
[root@vpnserver1 ~]# vi /etc/openvpn/connect.php
《?PHP
$hostname = 'localhost';
$dbname = 'vpn';
$username = 'vpn';
$passwd = 'vpn999';if (!($link=mysql_connect($hostname , $username ,$passwd ))) {
printf("內部錯誤%d:%s\n",mysql_errno(),mysql_error());exit();
}
if (!mysql_select_db($dbname,$link)) {
printf("選擇%s資料庫錯誤",$dbname);
printf("內部錯誤%d:%s\n",mysql_errno(),mysql_error());
exit();
}
?》
將這些控制的程式,設定為可執行檔。
[root@vpnserver1 ~]# chmod +x /etc/openvpn/*.php
[root@vpnserver1 ~]# chmod +x /etc/openvpn/*.sh
控制的程式,只有這些,各位可以按自己的狀況做調整。 接著進入mysql 資料庫,建立相關的DB登入資料,及VPN控制的Table 及使用者資料。
資料庫啟動(如果沒有啟動的話)
[root@vpnserver1 ~]# service mysqld start
資料庫安全設定(如果之前沒有設定過的話)
[root@vpnserver1 ~]# /usr/bin/mysql_secure_installation
登入mysql(也可以使用phpMyAdmin,看個人習慣)
[root@vpnserver1 ~]# mysql -u root -p
建立VPN資料庫
mysql> CREATE DATABASE `vpn` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
建立VPN資料庫-使用者
mysql> CREATE USER 'vpn'@'localhost' IDENTIFIED BY 'vpn999'; (密碼自己更改)
開放vpn使用者可以使用VPN資料庫權限
mysql> GRANT USAGE ON *.* TO 'vpn'@'localhost' IDENTIFIED BY 'vpn999' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;
mysql> GRANT ALL PRIVILEGES ON `vpn` . * TO 'vpn'@'localhost' WITH GRANT OPTION ;
選擇使用VPN資料庫
mysql> use vpn ;
建立VPN User 表格
mysql> CREATE TABLE `users` (
`userId` int(11) NOT NULL auto_increment,
`userAcc` varchar(20) collate utf8_unicode_ci NOT NULL,
`userPwd` varchar(255) collate utf8_unicode_ci NOT NULL,
`userName` varchar(255) collate utf8_unicode_ci default NULL,
`userEmail` varchar(255) collate utf8_unicode_ci default NULL,
`desc` varchar(255) collate utf8_unicode_ci default NULL,
`effective` enum('Y','N') collate utf8_unicode_ci NOT NULL default 'Y',
`timelimit` enum('Y','N') collate utf8_unicode_ci NOT NULL default 'N',
`startTime` int(11) default '8',
`endTime` int(11) default '19',
`adminAcc` enum('Y','N') collate utf8_unicode_ci NOT NULL default 'N',
`currentLogId` int(11) default NULL,
PRIMARY KEY (`userId`),
UNIQUE KEY `userAcc` (`userAcc`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
程式碼有點亂,看一下貼圖,比較清楚。
建立使用者登入記錄檔表格
mysql> CREATE TABLE `logs` (
`logId` int(11) NOT NULL auto_increment,
`userId` int(11) NOT NULL,
`loginTime` datetime default NULL,
`logoutTime` datetime default NULL,
`loginIp` varchar(255) collate utf8_unicode_ci default NULL,
`bytes_received` int(11) default NULL,
`bytes_sent` int(11) default NULL,
PRIMARY KEY (`logId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
程式碼有點亂,看一下貼圖,比較清楚。
新增使用者帳號及密碼
mysql> INSERT INTO `vpn`.`users` (`userId`, `userAcc`, `userPwd`, `userName`, `userEmail`, `desc`, `effective`, `timelimit`, `startTime`, `endTime`, `adminAcc`, `currentLogId`) VALUES (NULL, 'client1', 'client999', 'Rico', 'rico@nuface.tw', 'Test Account', 'Y', 'Y', '8', '19', 'N', NULL);
程式碼有點亂,看一下貼圖,比較清楚。
到這裏,server 端的工作就己經完成了,接著修改 user 端的設定檔。
打開client1.opvn (視各位自己的狀況),在最後加入 :
auth-user-pass
到這個步驟,使用者就必須在登入時輸入帳號跟密碼了。
之後所有的登入資料,都會記錄在資料庫中。管理者可以知道User 什麼時候登入系統;什麼時候登出系統;傳輸了多少流量;由那個IP登入進來;都可以在資料庫中,看的一目了然了。至於更進階的控制,小瑞就不再獻醜,由各位同好自行發揮囉!以上希望對大家有幫助。
還有什麼還沒有寫的呢?其實做到這裏,包袱己經抖的差不多了,再抖的話,內衣內褲都快掉出來啦....會讓大家見笑的^_^
不過在VPN的應用上,真的還有終極的一招,也是小瑞OpenVPN剩下的最後一招。就是 site to site 的VPN建置,等下次有時間,再把這最後一招貼出來,跟大家分享,我的OpenVPN也就算是功德圓滿了。
site to site open vpn….待續!
請問怎樣登入到mysql的網頁?
還有如果參照上面的指令 帳號 密碼是多少?
謝謝您的回答
看你在開立 vpn 資料庫是, 的帳號密碼為何, 可以自己設定, 在範例文章中, 使用的帳號是VPN , 密碼是 vpn999 至於登入資料庫, 我都是用phpMyAdmin , 直接登入資料庫管理的頁面, 就可以查看, 使用者登入的狀況了!
大大你好,看完了你的介紹,受益良多,想請教一個關於SITE 2 SITE VPN問題
目前MOBILE01上面有一篇文章到使用多台 [TOMATO ROUTER] 架設SITE 2 SITE VPN,他們使用憑證的方式來建置,已經可達到多client/Server的實現,但大多是選用TAP模式來連接。想請問如果用TUN方式連接。
問題一 先決條件 是否就一定得先把每一SITE的subnet 錯開
否則會架設不起來 ex : 兩ROUTER皆使用192.168.1.x網段,是否就絕對的,無法建構起來site2site VPN
問題二 如果錯開了以後,那建構起來的VPN可以公同享有彼此的資源麼 ? ex : 區網遊戲,NAS存取,印表機分享,網方存取
問題三 如果要滿足問題二,是否一定得建置WINS server
WINS Server 可否建置在Tomato Router上面 ,避免End User的困擾。
如果建置 site to site VPN , 使用TAP/TUN 我覺得已經沒有差異了! 只要兩台router 可以連接, 在User 端都沒有感覺了!針對第1個問題, 要不要把兩個區域的subnet 錯開呢?我的建議是錯開, 在管理上會比較好.如果不錯開,在router 端,就要做NAT, 否則在routing 上會無法連通,因為2個區的網段一樣,封包真的不知要怎麼送!
問題二,錯開後,可以分享彼此的資源,因為你列的那些服務,都是走TCP/IP 的, 所以沒有問題
問題三, 我沒有 wins server , 就都可以通了, 不過我是用openvpn 架的, 我不是很確定, TOMATO ROUTER 的架法是不是也ok, 如果你是這TOMATO ROUTER 的架法…你可能要再測試看看!
以上參考囉^^
connect.php
這個程式的內容要空白嗎??
其他PHP不用include他來連線MYSQL嗎?
測試後可以! 感謝
但是用戶資料表裡面的startTime, endTime 有功能嗎?限制他們使用時間?
logs裡面沒有紀錄?是不是可以給完整的php?
如果有套用client-cert-not-required
username-as-common-name
那可以過濾同時只能單一帳號登入嗎?
任何帳號亂輸入都可以進去
抱歉,程式碼好像因為blog 的系統, 無法顯示出來, 我把部份字元改為全型字,應該可正常顯示,在COPY 程式用去應用時,要注意一下。
程式中有可以限制時間的功能,可以自行再發揮一下。
己更新原交章,請參考。
可以在PHP 認證時,先確認一下資料庫中的狀況, 如果己有登入,就不要通過認邆,這樣可以做到單一帳號登入。
請按之前的回覆,再測試看看。
[…] OpenVPN 建置筆記(第8集) window.___gcfg = {lang: 'zh-TW'}; (function() { var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = 'https://apis.google.com/js/plusone.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })(); 日期:2010/06/07 | 留言:3 個 | 作者:Rico | 瀏覽: 分類:MIS易筋經,網路篇 標籤:CentOS 5.4, Open VPN, OpenVPN 留言 (2) 引用 (1) […]
[…] 前情提要:OpenVPN 建置筆記(第8集) […]