WHMCS自动VPN开通

2012年1月19日 | 标签: , ,

前段时间试用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' => '
',
     'Field 4' => $var4, # Info Output Only
    );
    return $fieldsarray;

}

function freeradius_AdminServicesTabFieldsSave($params) {
    update_query("mod_customtable",array(
        "var1"=>$_POST['modulefields'][0],
        "var2"=>$_POST['modulefields'][1],
        "var3"=>$_POST['modulefields'][2],
    ),array("serviceid"=>$params['serviceid']));
}
?>

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





使用统计 
- 本月流量统计 本月使用时长 今天使用时长
最大限额 $monthly_traffic_limit $monthly_limit $daily_limit
已经使用 $monthly_traffic_used $monthly_used $daily_used
EOM; ?>

相关文章:

  1. Acct-Interim-Interval : 控制FreeRadius的用量测量更新周期
  2. HostGator空间和WHMCS试用
  3. L2TP/IPSec VPN安装配置 – Amazon EC2
  4. PPTP VPN安装配置 – Amazon EC2
  5. FreeRadius安装配置整理
  1. EDRIC
    2012年1月31日02:26

    有没兴趣帮我做一套成品?可以做成销售VPN用的。你报价,我诚心。

  2. fallday
    2012年1月31日12:51

    多谢您关爱。主要的过程及代码自己已经在博客上公开分享。如果您有特别的需要,可以给我发邮件: admin@fallday.org

  3. 2012年2月21日19:49

    学习了,原来还有这样一个思路.我想问一下,用phprestsql 是谁都可以构造post去提交,还是有相应的验证机制?

  4. fallday
    2012年2月21日20:51

    谁都可以访问自然是不行。访问是有用户密码保护的