Страница 1 из 1

Учет трафика средствами MPD (External AAA)

Добавлено: 2010-12-02 15:03:52
kub3r
Всем доброго времени суток :)
http://mpd.sourceforge.net/doc5/mpd31.html#31 - реализация небольшой системы учета трафика штатными средствами MPD для демонстрации механизма работы MPD External AAA.

Требуется:
MPD, MySQL, PHP (iconv, hash, mcrypt, mysqli) и прямые руки :-D

Реализация:
(грубая, сырая, 30-и минутная с помощью подручных средств :sorry:)

mpd.conf

Код: Выделить всё

...
        set auth max-logins 1
        set auth acct-update 60
        set auth timeout 15
        set auth extauth-script /usr/local/etc/mpd5/auth.php
        set auth extacct-script /usr/local/etc/mpd5/acct.php
        set auth disable internal
        set auth enable ext-auth ext-acct acct-mandatory
...
auth.php

Код: Выделить всё

...
$db =@new mysqli("<HOST>", "<USER>", "<PASS>", "<NAME>");

/**
 * On invocation extauth/extacct scripts receive on stdin set of request 
 * attribute:value pairs terminated by empty line and must generate response
 * in same format on stdout.
 */
$request = array();
$response = array();

$fhandle = fopen("php://stdin", "r");
while ($line = fgets($fhandle)) {
	if ($line == "\n")
		break;

	if (preg_match("/^(.+):(.+)\n$/", $line, $matches))
		$request[$matches[1]] = $matches[2];
}
fclose($fhandle);

$result =@$db->query("SELECT `framed_ip_address`, `password` FROM `users` WHERE `username`='".$db->escape_string($request["USER_NAME"])."' AND `blocked`='0'");
if ($result && $result->num_rows > 0) {
	list($response["FRAMED_IP_ADDRESS"], $response["USER_PASSWORD"]) = $result->fetch_row();
	$response["USER_NAME"] = $request["USER_NAME"];
	/**
	 * Generates the NT-HASH from the given plaintext password.
	 * Implemented in PEAR Crypt_CHAP by Michael Bretterklieber
	 * http://pear.php.net/package/Crypt_CHAP
	 */
	$response["USER_NT_HASH"] = pack("H*", hash("md4", pack("H*", iconv("ASCII", "UTF-16", $response["USER_PASSWORD"]))));
	$response["RESULT"] = "UNDEF";

	$result->free();
} else
	$response["RESULT"] = "FAIL";

/**
 * On invocation extauth/extacct scripts receive on stdin set of request 
 * attribute:value pairs terminated by empty line and must generate response
 * in same format on stdout.
 */

$fhandle = fopen("php://stdout", "w");
foreach ($response as $key => $value)
	fputs($fhandle, "$key:$value\n");
fputs($fhandle, "\n");
fclose($fhandle);
...
acct.php

Код: Выделить всё

...
$db =@new mysqli("<HOST>", "<USER>", "<PASS>", "<NAME>");

$request = array();
$response = array();

/**
 * On invocation extauth/extacct scripts receive on stdin set of request 
 * attribute:value pairs terminated by empty line and must generate response
 * in same format on stdout.
 */
$fhandle = fopen("php://stdin", "r");
while ($line = fgets($fhandle)) {
	if ($line == "\n")
		break;

	if (preg_match("/^(.+):(.+)\n$/", $line, $matches))
		$request[$matches[1]] = $matches[2];
}
fclose($fhandle);

/**
 * ACCT_STATUS_TYPE: START UPDATE STOP
 */
switch ($request["ACCT_STATUS_TYPE"]) {
case "START":
	$query = "INSERT INTO acct VALUES ('%s', UNIX_TIMESTAMP(), 0, '%s', '%s', 0, 0, 0, 0, 0)";
	$query = sprintf($query,
		$request["ACCT_SESSION_ID"],
		$request["USER_NAME"],
		$request["PEER_ADDR"]);
	@$db->query($query);
	break;
case "UPDATE":
	$query = "UPDATE acct SET acct_session_time=%d, acct_input_octets=%d, acct_input_packets=%d, acct_output_octets=%d, acct_output_packets=%d WHERE acct_session_id='%s'";
	$query = sprintf($query,
		intval($request["ACCT_SESSION_TIME"]),
		intval($request["ACCT_INPUT_OCTETS"]),
		intval($request["ACCT_INPUT_PACKETS"]),
		intval($request["ACCT_OUTPUT_OCTETS"]),
		intval($request["ACCT_OUTPUT_PACKETS"]),
		$request["ACCT_SESSION_ID"]);
	@$db->query($query);
	break;
case "STOP":
	$query = "UPDATE acct SET session_stop=UNIX_TIMESTAMP() WHERE acct_session_id='%s'";
	$query = sprintf($query,
	    $request["ACCT_SESSION_ID"]);
	@$db->query($query);
	break;
}

/**
 * On invocation extauth/extacct scripts receive on stdin set of request 
 * attribute:value pairs terminated by empty line and must generate response
 * in same format on stdout.
 */
$fhandle = fopen("php://stdout", "w");
foreach ($response as $key => $value)
	fputs($fhandle, "$key:$value\n");
fputs($fhandle, "\n");
fclose($fhandle);
...
Таблицы:

Код: Выделить всё

CREATE TABLE IF NOT EXISTS `acct` (
  `acct_session_id` varchar(20) NOT NULL,
  `session_start` int(11) NOT NULL,
  `session_stop` int(11) NOT NULL,
  `user_name` varchar(20) NOT NULL,
  `peer_addr` varchar(15) NOT NULL,
  `acct_session_time` int(11) NOT NULL,
  `acct_input_octets` int(11) NOT NULL,
  `acct_input_packets` int(11) NOT NULL,
  `acct_output_octets` int(11) NOT NULL,
  `acct_output_packets` int(11) NOT NULL,
  KEY `acct_session_id` (`acct_session_id`),
  KEY `user_name` (`user_name`)
) ENGINE=MyISAM;

Код: Выделить всё

CREATE TABLE IF NOT EXISTS `users` (
  `username` varchar(16) NOT NULL,
  `password` varchar(16) NOT NULL,
  `blocked` tinyint(1) NOT NULL DEFAULT '0',
  `framed_ip_address` varchar(15) NOT NULL,
  UNIQUE KEY `username` (`username`),
  KEY `password` (`password`)
) ENGINE=MyISAM;
Думаю этого достаточно...

Re: Учет трафика средствами MPD (External AAA)

Добавлено: 2010-12-02 15:41:53
Гость
это что было?
если типа статьи то в раздел про сайт, пусть там и будет

Re: Учет трафика средствами MPD (External AAA)

Добавлено: 2010-12-02 15:44:34
hizel
а ведь тоже самое можно написать на шелле и понадобится только mysql-client

*представил sql injection через грамотно подставленный юзернейм*

Re: Учет трафика средствами MPD (External AAA)

Добавлено: 2010-12-02 15:49:36
kub3r
hizel,
1. Реализовать можно на чем угодно, право каждого.
2. Ошибки подправил.

Код: Выделить всё

...
/**
* ACCT_STATUS_TYPE: START UPDATE STOP
*/
switch ($request["ACCT_STATUS_TYPE"]) {
case "START":
   $query = "INSERT INTO acct VALUES ('%s', UNIX_TIMESTAMP(), 0, '%s', '%s', 0, 0, 0, 0, 0)";
   $query = sprintf($query,
      $db->escape_string($request["ACCT_SESSION_ID"]),
      $db->escape_string($request["USER_NAME"]),
      $db->escape_string($request["PEER_ADDR"]));
   @$db->query($query);
   break;
case "UPDATE":
   $query = "UPDATE acct SET acct_session_time=%d, acct_input_octets=%d, acct_input_packets=%d, acct_output_octets=%d, acct_output_packets=%d WHERE acct_session_id='%s'";
   $query = sprintf($query,
      intval($request["ACCT_SESSION_TIME"]),
      intval($request["ACCT_INPUT_OCTETS"]),
      intval($request["ACCT_INPUT_PACKETS"]),
      intval($request["ACCT_OUTPUT_OCTETS"]),
      intval($request["ACCT_OUTPUT_PACKETS"]),
      $db->escape_string($request["ACCT_SESSION_ID"]));
   @$db->query($query);
   break;
case "STOP":
   $query = "UPDATE acct SET session_stop=UNIX_TIMESTAMP() WHERE acct_session_id='%s'";
   $query = sprintf($query,
       $db->escape_string($request["ACCT_SESSION_ID"]));
   @$db->query($query);
   break;
}
...

Re: Учет трафика средствами MPD (External AAA)

Добавлено: 2010-12-02 16:07:08
hizel
держать на php на nas-е довольно странно, но пусть будет, чо :]