Как я некоторое время назад выяснил на собственном опыте, ещё остались провайдеры, для получения безлимитного тарифа от которых требуется выдерживать определённое соотношение входящего и исходящего трафиков.
В моём случае, при размещении сервера на colocation в одном московском датацентре, исходящего должно было быть не менее чем в 4 раза больше чем входящего (уж извините за такой оборот). Соотношение рассчитывается как за сутки, так и общее за месяц. Нарушение любого из них — штраф.
Само по себе соотношение не выдерживалось из-за переодических объёмных заливок бэкапов на сервер. Вручную (гиг заслал, 4 гига скачал) — надоело.
Тут я вспомнил, что когда-то давно на каком-то сайте видел примитивный скрипт в пару строк на sh-скрипте, который делал такую балансировку сам. Тогда не сохранил, сейчас найти не смог. Пришлось писать самому. Результат и выставляю на всеобщее обозрение — авось кому пригодится.
Скрипт тестировался только под Ubuntu, но и под другими линуксами работать должен.
В отличие от того примитивного на sh, мой скрипт умеет выдерживать как дневное, так и месячное соотношение, ведёт логи, и тщательно шифруется от своего обнаружения (фальшивый трафик делается путём передачи файлов случайного размера через SSH, между вбросами делается интервал случайной длины). Ещё одно отличие (но уже со знаком минус) — требуется ответная нода с безлимитным трафиком, до которой можно поднять ssh соединение по ключу. Я использую свой домашний канал и роутер на нём.
Поставьте свои значения в переменные $interface, $logfile и $server.
В переменной $server фактически указаны параметры для команды ssh.
То есть, в моём случае, выполнив в консоли «ssh my-host.no-ip.org -p 1022 -i /home/user/.ssh/my-key» я подключаюсь без ввода пароля к своей ответной ноде (данные условные, конечно).
Вызов этого скрипта надо сделать при запуске системы (например из /etc/rc.local) или настроить в виде сервиса.
<?php
$interface="eth0"; // какой интерфейс отслеживать
$server="my-host.no-ip.org -p 1022 -i /home/user/.ssh/my-key"; // куда валить мусор
$logfile="/usr/local/logs/trafic-balancer.log"; // для всего скрипта перенаправление вывода делать нельзя, так как logrotate прибивает файл
$curdate=0;
function echolog($str)
{
global $logfile;
file_put_contents($logfile, $str, FILE_APPEND);
echo($str);
}
echolog("n".date('r')." tЗапускn");
while(true)
{
$f=@fopen("/proc/net/dev", "r");
$stat=null;
while($str=fgets($f))
{
if(strpos($str, $interface)!==false)
{
$stat=$str;
break;
}
}
fclose($f);
if($stat)
{
$stat=preg_replace("/s+/", " ", $stat);
$nums=explode(" ", $stat);
// трафик глобальный с пересчётом в мегабайты
$rx_g=round($nums[2]/1024/1024);
$tx_g=round($nums[10]/1024/1024);
$delta_g=$rx_g*4-$tx_g;
// трафик дневной
if($curdate!=date('j')) // начинается новый день
{
if($curdate)
echolog("n".date('r')." tРезультаты за $curdate число: RX:$rx_d Mb, TX:$tx_d Mb, дельта: $delta_d Mbn");
$curdate=date('j');
$rx_d=0;
$tx_d=0;
$rx_s=$rx_g;
$tx_s=$tx_g;
}
$rx_d=$rx_g-$rx_s;
$tx_d=$tx_g-$tx_s;
$delta_d=$rx_d*4-$tx_d;
$delta=max($delta_g, $delta_d);
if(($delta>0)&&(date('G')>8))
{
if($delta>1000) // если больше 1Г, то бьём на части
$size=round(rand(1000, min($delta/2, 5000))); // за один раз посылаем блок произвольного размера, но не слишком здоровый
else
$size=round(rand($delta*2, $delta*3)); // добиваем остаток с запасом чтоб кусками мелкими не качать
echolog("n".date('r')." tПревышение: общая дельта: $delta_g Mb, дневная дельта: $delta_d Mb, качаем $size Mbn");
passthru("dd if=/dev/zero bs=1M count=$size | ssh $server 'cat > /dev/null'");
}
else echolog('.');
}
else
echolog("n".date('r')." tСтатистика не читается!n");
sleep(round(rand(10, 600)));
}
?>
Автор: unwrecker