WHMCS自动VPN开通
2012年1月19日
| 标签: FreeRadius, VPN, WHMCS
前段时间试用WHMCS时,也试着做了一个VPN自动销售自动开通的模块。VPN基于FreeRadius认证。
1. provide restsql interface on radius db
1. install restsql insto /radius/restsql
http://phprestsql.sourceforge.net/download.html
http://phprestsql.sourceforge.net/
1a. .htaccess
RewriteEngine On
RewriteBase /radius/restsql
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ index.php
1b. phprestsql.ini
[settings] baseURL = "/radius/restsql" [database] type = "mysql" ;type = "postgresql" server = "localhost" database = "radius" username = "radius" password = "xxxxxx" ;foreignKeyPostfix = "_uid" [renderers] text/xml = xml.php text/plain = plain.php text/html = html.php [mimetypes] xml = text/xml txt = text/plain
1c. phprestsql.php
#function parseRequestData
$parts = explode('=', $pair, 2);
#function PHPRestSQL
/*
$lastPart = array_pop($urlParts);
$dotPosition = strpos($lastPart, '.');
if ($dotPosition !== FALSE) {
$this->extension = substr($lastPart, $dotPosition + 1);
$lastPart = substr($lastPart, 0, $dotPosition);
}
array_push($urlParts, $lastPart);
*/
1d. change primary key of usercheck, usergroup to username
2. WHMCS freeraidus server module
array( "Type" => "text", "Size" => "10", "Description" => "MB" )
);
return $configarray;
}
function freeradius_CreateAccount($params) {
# ** The variables listed below are passed into all module functions **
$serviceid = $params["serviceid"]; # Unique ID of the product/service in the WHMCS Database
$pid = $params["pid"]; # Product/Service ID
$producttype = $params["producttype"]; # Product Type: hostingaccount, reselleraccount, server or other
$domain = $params["domain"];
$params["username"] = $params["clientsdetails"]["email"];
$username = $params["username"];
$password = $params["password"];
$clientsdetails = $params["clientsdetails"]; # Array of clients details - firstname, lastname, email, country, etc...
$customfields = $params["customfields"]; # Array of custom field values for the product
$configoptions = $params["configoptions"]; # Array of configurable option values for the product
# Product module option settings from ConfigOptions array above
$configoption1 = $params["configoption1"];
# Additional variables if the product/service is linked to a server
$server = $params["server"]; # True if linked to a server
$serverid = $params["serverid"];
$serverip = $params["serverip"];
$serverusername = $params["serverusername"];
$serverpassword = $params["serverpassword"];
$serveraccesshash = $params["serveraccesshash"];
$serversecure = $params["serversecure"]; # If set, SSL Mode is enabled in the server config
$url = "http://" .$serverip ."/radius/restsql/radcheck"; # URL to WHMCS API file
$postfields["username"] = $clientsdetails["email"];
$postfields["attribute"] = "Cleartext-Password";
$postfields["op"] = ":="; #action performed by the [[API:Functions]]
$postfields["value"] = $password;
$query_string = "";
foreach ($postfields as $k=>$v) $query_string .= $k ."=" .$v ."\n";
$successful = True;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $serverusername .":" .$serverpassword);
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
$data = curl_exec($ch);
if (curl_error($ch)) {
$successful = False;
$result = "Error Message(user): " .curl_errno($ch) ."- " .curl_error($ch);
} else {
$ret = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ( $ret != 201 ) {
$successful = False;
$result = "HTTP Return Code(user): " .$ret;
}
}
curl_close($ch);
if ( $successful ) {
$url = "http://" .$serverip ."/radius/restsql/radusergroup"; # URL to WHMCS API file
unset($postfields);
$postfields["username"] = $clientsdetails["email"];
$postfields["groupname"] = "VIP";
$query_string = "";
foreach ($postfields as $k=>$v) $query_string .= $k ."=" .$v ."\n";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $serverusername .":" .$serverpassword);
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
$data = curl_exec($ch);
if (curl_error($ch)) {
$successful = False;
$result = "Error Message(usergroup): " .curl_errno($ch) ."- " .curl_error($ch);
} else {
$ret = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ( $ret != 201 ) {
$successful = False;
$result = "HTTP Return Code(usergroup): " .$ret;
}
}
curl_close($ch);
}
if ($successful) {
$result = "success";
}
return $result;
}
function freeradius_TerminateAccount($params) {
$serviceid = $params["serviceid"]; # Unique ID of the product/service in the WHMCS Database
$pid = $params["pid"]; # Product/Service ID
$producttype = $params["producttype"]; # Product Type: hostingaccount, reselleraccount, server or other
$domain = $params["domain"];
$params["username"] = $params["clientsdetails"]["email"];
$username = $params["username"];
$password = $params["password"];
$clientsdetails = $params["clientsdetails"]; # Array of clients details - firstname, lastname, email, country, etc...
$customfields = $params["customfields"]; # Array of custom field values for the product
$configoptions = $params["configoptions"]; # Array of configurable option values for the product
# Product module option settings from ConfigOptions array above
$configoption1 = $params["configoption1"];
# Additional variables if the product/service is linked to a server
$server = $params["server"]; # True if linked to a server
$serverid = $params["serverid"];
$serverip = $params["serverip"];
$serverusername = $params["serverusername"];
$serverpassword = $params["serverpassword"];
$serveraccesshash = $params["serveraccesshash"];
$serversecure = $params["serversecure"]; # If set, SSL Mode is enabled in the server config
$url = "http://" .$serverip ."/radius/restsql/radcheck/" .$clientsdetails["email"]; # URL to WHMCS API file
$successful = True;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $serverusername .":" .$serverpassword);
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
if (curl_error($ch)) {
$successful = False;
$result = "Error Message(user): " .curl_errno($ch) ."- " .curl_error($ch);
} else {
$ret = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ( $ret != 204 ) {
$successful = False;
$result = "HTTP Return Code(user): " .$ret;
}
}
curl_close($ch);
$url = "http://" .$serverip ."/radius/restsql/radusergroup/" .$clientsdetails["email"]; # URL to WHMCS API file
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $serverusername .":" .$serverpassword);
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
if (curl_error($ch)) {
$successful = False;
$result = "Error Message(usergroup): " .curl_errno($ch) ."- " .curl_error($ch);
} else {
$ret = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ( $ret != 204 ) {
$successful = False;
$result = "HTTP Return Code(usergroup): " .$ret;
}
}
curl_close($ch);
if ($successful) {
$result = "success";
}
return $result;
}
function freeradius_SuspendAccount($params) {
# Code to perform action goes here...
if ($successful) {
$result = "success";
} else {
$result = "Error Message Goes Here...";
}
return $result;
}
function freeradius_UnsuspendAccount($params) {
# Code to perform action goes here...
if ($successful) {
$result = "success";
} else {
$result = "Error Message Goes Here...";
}
return $result;
}
function freeradius_ChangePassword($params) {
# Code to perform action goes here...
if ($successful) {
$result = "success";
} else {
$result = "Error Message Goes Here...";
}
return $result;
}
function freeradius_ChangePackage($params) {
# Code to perform action goes here...
if ($successful) {
$result = "success";
} else {
$result = "Error Message Goes Here...";
}
return $result;
}
function freeradius_ClientArea($params) {
$username = $params["clientsdetails"]["email"];
$password = $params["password"];
$clientdetails = $params["clientdetails"];
$server = $params["server"]; # True if linked to a server
$serverid = $params["serverid"];
$serverip = $params["serverip"];
$serverusername = $params["serverusername"];
$serverpassword = $params["serverpassword"];
$serveraccesshash = $params["serveraccesshash"];
$serversecure = $params["serversecure"]; # If set, SSL Mode is enabled in the server config
$url = "http://" .$serverip ."/radius/usage_check.php3?login=" .$username; # URL to WHMCS API file
$successful = True;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_GET, 1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $serverusername .":" .$serverpassword);
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
if (curl_error($ch)) {
$successful = False;
$result = "Error Message(user): " .curl_errno($ch) ."- " .curl_error($ch);
} else {
$ret = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ( $ret != 200 ) {
$successful = False;
$result = "HTTP Return Code(user): " .$ret;
}
}
curl_close($ch);
if ( $successful ) {
$code = $data;
} else {
$code = $result;
}
return $code;
}
function freeradius_AdminLink($params) {
$code = '';
return $code;
}
function freeradius_LoginLink($params) {
echo "";
}
function freeradius_reboot($params) {
# Code to perform reboot action goes here...
if ($successful) {
$result = "success";
} else {
$result = "Error Message Goes Here...";
}
return $result;
}
function freeradius_shutdown($params) {
# Code to perform shutdown action goes here...
if ($successful) {
$result = "success";
} else {
$result = "Error Message Goes Here...";
}
return $result;
}
function freeradius_ClientAreaCustomButtonArray() {
$buttonarray = array(
"Reboot Server" => "reboot",
);
return $buttonarray;
}
function freeradius_AdminCustomButtonArray() {
$buttonarray = array(
"Reboot Server" => "reboot",
"Shutdown Server" => "shutdown",
);
return $buttonarray;
}
function freeradius_extrapage($params) {
$pagearray = array(
'freeradiusfile' => 'example',
'breadcrumb' => ' > Example Page',
'vars' => array(
'var1' => 'demo1',
'var2' => 'demo2',
),
);
return $pagearray;
}
function freeradius_UsageUpdate($params) {
$serverid = $params['serverid'];
$serverhostname = $params['serverhostname'];
$serverip = $params['serverip'];
$serverusername = $params['serverusername'];
$serverpassword = $params['serverpassword'];
$serveraccesshash = $params['serveraccesshash'];
$serversecure = $params['serversecure'];
# Run connection to retrieve usage for all domains/accounts on $serverid
# Now loop through results and update DB
foreach ($results AS $domain=>$values) {
update_query("tblhosting",array(
"diskused"=>$values['diskusage'],
"dislimit"=>$values['disklimit'],
"bwused"=>$values['bwusage'],
"bwlimit"=>$values['bwlimit'],
"lastupdate"=>"now()",
),array("server"=>$serverid,"domain"=>$values['domain']));
}
}
function freeradius_AdminServicesTabFields($params) {
$result = select_query("mod_customtable","",array("serviceid"=>$params['serviceid']));
$data = mysql_fetch_array($result);
$var1 = $data['var1'];
$var2 = $data['var2'];
$var3 = $data['var3'];
$var4 = $data['var4'];
$fieldsarray = array(
'Field 1' => '
',
'Field 2' => '
3. Customized VPN usage page in clientarea
3a. usage_check.php3 (based on user_admin.php3)
-1; $i--){
$days[$i] = date($config[sql_date_format],$now_tmp);
$now_tmp -= 86400;
}
$day++;
//$now -= ($day * 86400);
$now -= 604800;
$now += 86400;
for ($i = $day; $i <= 6; $i++){
$days[$i] = date($config[sql_date_format],$now);
// $now -= 86400;
$now += 86400;
}
$daily_used = $weekly_used = $monthly_used = $lastlog_session_time = '-';
$extra_msg = '';
$used = array('-','-','-','-','-','-','-');
$link = @da_sql_pconnect($config);
if ($link){
if ($monthly_limit != 'none' || $config[counter_monthly_calculate_usage] == 'true'){
$search = @da_sql_query($link,$config,
"SELECT sum(acctsessiontime) AS sum_sess_time FROM $config[sql_accounting_table] WHERE username = '$login'
AND acctstarttime >= '$month_start' AND acctstarttime <= '$now_str';");
if ($search){
$row = @da_sql_fetch_array($search,$config);
$monthly_used = $row[sum_sess_time];
}
else
echo "Database query failed: " . da_sql_error($link,$config) . "\n";
}
if ($monthly_traffic_limit != 'none' || $config[counter_monthly_calculate_usage] == 'true'){
$search = @da_sql_query($link,$config,
"SELECT sum(acctinputoctets + acctoutputoctets) AS sum_sess_traffic FROM $config[sql_accounting_table] WHERE username = '$login'
AND acctstarttime >= '$month_start' AND acctstarttime <= '$now_str';");
if ($search){
$row = @da_sql_fetch_array($search,$config);
$monthly_traffic_used = $row[sum_sess_traffic];
}
else
echo "Database query failed: " . da_sql_error($link,$config) . "\n";
}
$search = @da_sql_query($link,$config,
"SELECT COUNT(*) AS counter FROM $config[sql_accounting_table] WHERE username = '$login'
AND acctstoptime >= '$week_str' AND acctstoptime <= '$now_str'
AND (acctterminatecause LIKE 'Login-Incorrect%' OR
acctterminatecause LIKE 'Invalid-User%' OR
acctterminatecause LIKE 'Multiple-Logins%');");
if ($search){
$row = @da_sql_fetch_array($search,$config);
$tot_badlogins = $row[counter];
}
else
echo "Database query failed: " . da_sql_error($link,$config) . "\n";
for($i = 0; $i <=6; $i++){
if ($days[$i] == '')
continue;
$search = @da_sql_query($link,$config,
"SELECT sum(acctsessiontime) AS sum_sess_time FROM $config[sql_accounting_table] WHERE
username = '$login' AND acctstoptime >= '$days[$i] 00:00:00'
AND acctstoptime <= '$days[$i] 23:59:59';");
if ($search){
$row = @da_sql_fetch_array($search,$config);
$used[$i] = $row[sum_sess_time];
if ($daily_limit != 'none' && $used[$i] > $daily_limit)
$used[$i] = "" . time2str($used[$i]) . "";
else
$used[$i] = time2str($used[$i]);
if ($today == $i){
$daily_used = $row[sum_sess_time];
if ($daily_limit != 'none'){
$remaining = $daily_limit - $daily_used;
if ($remaining <=0)
$remaining = 0;
$log_color = ($remaining) ? 'green' : 'red';
if (!$remaining)
$extra_msg = '(Out of daily quota)';
}
$daily_used = time2str($daily_used);
if ($daily_limit != 'none' && !$remaining)
$daily_used = "$daily_used";
}
}
else
echo "Database query failed: " . da_sql_error($link,$config) . "\n";
}
if ($monthly_limit != 'none'){
$tmp = $monthly_limit - $monthly_used;
if ($tmp <=0){
$tmp = 0;
$extra_msg .= '(Out of monthly quota)';
}
if (!is_numeric($remaining))
$remaining = $tmp;
if ($remaining > $tmp)
$remaining = $tmp;
$log_color = ($remaining) ? 'green' : 'red';
}
if ($monthly_limit != 'none' || $config[counter_monthly_calculate_usage] == 'true'){
$monthly_used = time2str($monthly_used);
if ($monthly_limit != 'none' && !$tmp)
$monthly_used = "$monthly_used";
}
if ($monthly_traffic_limit != 'none'){
$tmp = $monthly_traffic_limit - $monthly_traffic_used;
if ($tmp <=0){
$tmp = 0;
$extra_msg .= '(Out of monthly traffic quota)';
}
}
if ($monthly_traffic_limit != 'none' || $config[counter_monthly_calculate_usage] == 'true'){
$monthly_traffic_used = bytes2str($monthly_traffic_used);
if ($monthly_traffic_limit != 'none' && !$tmp)
$monthly_traffic_used = "$monthly_traffic_used";
}
}
else
echo "Could not connect to SQL database\n";
$monthly_traffic_limit = (is_numeric($monthly_traffic_limit)) ? bytes2str($monthly_traffic_limit) : $monthly_traffic_limit;
$monthly_limit = (is_numeric($monthly_limit)) ? time2str($monthly_limit) : $monthly_limit;
$weekly_limit = (is_numeric($weekly_limit)) ? time2str($weekly_limit) : $weekly_limit;
$daily_limit = (is_numeric($daily_limit)) ? time2str($daily_limit) : $daily_limit;
$session_limit = (is_numeric($session_limit)) ? time2str($session_limit) : $session_limit;
$remaining = (is_numeric($remaining)) ? time2str($remaining) : $remaining;
if ($item_vals['Dialup-Access'][0] == 'FALSE' || (!isset($item_vals['Dialup-Access'][0]) && $attrmap['Dialup-Access'] != '' && $attrmap['Dialup-Access'] != 'none'))
$msg =<< The user account is locked
EON;
else
$msg =<< $remaining $extra_msg
EON;
$lock_msg = $item_vals['Dialup-Lock-Msg'][0];
if ($lock_msg != '')
$descr =<<$lock_msg
EON;
else
$descr = '-';
$expiration = $default_vals['Expiration'][0];
if ($item_vals['Expiration'][0] != '')
$expiration = $item_vals['Expiration'][0];
if ($expiration != ''){
$expiration = strtotime($expiration);
if ($expiration != -1 && $expiration < time())
$descr = <<User Account has expired
EOM;
}
require('../html/usage_check.html.php3');
?>
3b. usage_check.html.php3
使用统计 EOM; ?>
- 本月流量统计 本月使用时长 今天使用时长 最大限额 $monthly_traffic_limit $monthly_limit $daily_limit 已经使用 $monthly_traffic_used $monthly_used $daily_used 相关文章:
- Acct-Interim-Interval : 控制FreeRadius的用量测量更新周期
- HostGator空间和WHMCS试用
- L2TP/IPSec VPN安装配置 – Amazon EC2
- PPTP VPN安装配置 – Amazon EC2
- FreeRadius安装配置整理

有没兴趣帮我做一套成品?可以做成销售VPN用的。你报价,我诚心。
多谢您关爱。主要的过程及代码自己已经在博客上公开分享。如果您有特别的需要,可以给我发邮件: admin@fallday.org
学习了,原来还有这样一个思路.我想问一下,用phprestsql 是谁都可以构造post去提交,还是有相应的验证机制?
谁都可以访问自然是不行。访问是有用户密码保护的