sexta-feira, 25 de abril de 2008

Compilando Mysql Proxy

Bom, necessitei usar o Mysql Proxy para fazer um Load Balance, e para variar um pouco não tinha o binário para instalar no RedHat 5 64 bits, aí começou a epopéia da compilação, diante da dificuldade resolvi coloborar com a comunidade e deixar um passo a passo da intalação, que segue :

Instalar as as dependências necessárias do sistema

yum install mysql-devel libevent-devel

Baixar a ultima versão do Mysql Proxy http://dev.mysql.com/downloads/mysql-proxy/
Baixar a ultima versão do Lua em http://www.lua.org/ftp/

Descompactar as versões em um diretório, farei isto em /usr/src

tar xzfv lua-5.1.3.tar.gz -C /usr/src
tar xzfv mysql-proxy-0.6.1.tar.gz -C /usr/src


Vamos primeiro compilar o Lua, como uso uma distribuição 64 bits e gosto que tudo estaja instalado conforme a distribuição, vou alterar alguma linhas do Makefile

cd /usr/src/lua-5.1.3
vi Makefile

INSTALL_TOP= /usr
INSTALL_LIB= $(INSTALL_TOP)/lib64
INSTALL_CMOD= $(INSTALL_TOP)/lib64/lua/$V


E compilar ...

make linux
make install


Bom agora vamos compilar o Mysql Proxy ...

cd /usr/src/mysql-proxy-0.6.1/

Aqui começa o pulo do gato, primeiramente as váriveis para compilar com o lua, a distribuição fala que necessita delas LUA_LIBS e LUA_CFLAGS, porém não fala de seu conteúdo, pois bem, depois de várias tentativas e algumas compilações na unha, acabei encontrando elas:

export LUA_LIBS="-L/usr/lib64/lua/5.1/ -llua -lm"
export LUA_CFLAGS=" "


Para aqueles que não alteraram o Makefile do Lua ...

export LUA_LIBS="-L/usr/local/lib/lua/5.1/ -llua -lm"
export LUA_CFLAGS=" "


Agora para gerar os Makefiles...

./configure LDFLAGS="-ldl"

Pronto, com estas parâmetros "ocultos" é só compilar e instalar...

make
make install


É só isto ... mas foram-se um bom tempo e muita dor de cabeça para chegar aqui ...

sexta-feira, 4 de abril de 2008

Reescrevendo URL a partir de parametros de outra URL

O processo consiste em reescrever a URL a partir do valor contido em uma variável de parâmetro da URL de origem
Exemplo:
de
http://localhost/template.aspx&palavra=ipod&acao=busca&menu=compareprecos&imageField.x=0&imageField.y=0

para
http://localhost/search?q=ipod&x=0&y=0

Onde :
localhost - é o servidor
/template.aspx - é a URL
&palavra=ipod&acao=busca&menu=compareprecos&imageField.x=0&imageField.y=0 - é parâmetro da URL
palavra=ipod - é a variável 'palavra' com seu valor 'ipod'
search - é a nova URL
?q=ipod&x=0&y=0 - é o novo parâmetro d URL contendo um valor de uma variável do parâmetro antigo

E o que desejamos é apenas este valor de uma unica variável o resto seria todo descartado, a principio o rewrite não faz isto, pois os mecanismos contido nele trata apenas do absoluto que é passado e não de seus parâmetros, apesar de conter uma variável que contem estes parâmetros (%{QUERY_STRING}), e isto é parte do que utilizaremos junto com um mecanismo que passa para um programa externo, o RewriteMap

- O parametro RewriteMap é utilizado da seguinte maneira:

RewriteMap MapName MapType:MapSource

Onde :
MapName é o nome do mapeamento em si
MapType é o tipo do mapeamento
MapSource é onde esta este mapeamento

Bom utilizarei como nome do mapeamento nome_mapeamento, e neste caso como terei que tratar todo o parâmetro, utilizarei um programa externo para isto, usarei o perl para isto e utilizarei como tipo de mapeamento o paremetro prg e logo a seguir o caminho completo de execução do programa, ficando assim

RewriteMap nome_mapeamento prg:/var/www/scripts/remapemento.pl

Observe que existirá o programa /var/www/scripts/remapemento.pl , logo abaixo descrevo ele.
E para chama-lo seria:

${ MapName : LookupKey }
${ MapName : LookupKey | DefaultValue }

Onde:
LookupKey é o parametro passado para o programa externo, normalmente alguma variavel do Rewrite
DefaultValue é um valor padrão caso não exista um ou valor na variavel passada

Assim ficamos com a seguinte regra no Rewrite :

RewriteEngine on
RewriteMap nome_mapeamento prg:/var/www/scripts/remapemento.pl
RewriteRule ^/(template.aspx)$ /${nome_mapeamento:$1\&%{QUERY_STRING}} [R]


Para exemplificar, o programa em perl verifica se existe as variaveis com seus valores ( acao=busca e menu=compareprecos ) coletando o valor contido na variavel palavra , havendo a condição descrita reescreva para que na nova URL contenha apenas o valor coletado :

Exemplo

Entrada : template.aspx&palavra=ipod&acao=busca&menu=compareprecos&imageField.x=0&imageField.y=0

Saida : search?q=ipod&x=0&y=0

Abaixo o programa :

#!/usr/bin/perl
$| = 1;
debug=0;
# Cria o loop que ficará aguardando o repasse do rewrite
while () {
    open (RET,">>/tmp/retorno.log") if ( $debug );;
    $str = $_;
    $busca = "";
    $acao = 0;
    $menu = 0;
    print RET "$str\n" if ( $debug );
    # Separa os parametros em variavel=valor
    @array = split(/&/,$str);
    for ( @array ) {
        # Separa a variavel de seu valor
        @parte = split (/\=/);
        # Verifica se o nome da variavel é palavra se for salva seu valor
        if ( @parte[0] eq "palavra" ) {
            $busca = @parte[1] ;
            print RET "\n---\nbusca=$busca\n---\n" if ( $debug );
        }
        # Verifica primeira condição para reescrever varivel acao com valor busca
        if ( $_ eq "acao=busca" ) {
            $acao = 1;
        }
        # Verifica segunda condição para reescrever varivel menu com valor compareprecos
        if ( $_ eq "menu=compareprecos" ) {
            $menu = 1;
        }
        print RET "$_\n" if ( $debug );
    }
    # Satisfazendo as condicoes reescreve a URL caso contrario devolve ela sem alteraçao
    if (( $acao == 1) && ( $menu == 1 )) {
        print RET "search?q=$busca&x=0&y=0\n" if ( $debug );
        print "search?q=$busca&x=0&y=0\n" ;
    } else {
        int RET $str if ( $debug );
        print $str;
    }
    close (RET);
}

quarta-feira, 19 de março de 2008

Gerador de Kick Start p/ web

Necessitava de algo para gerar meus arquivos de kick start para instalar as máquinas virtuais do Xen diferente do disponibilizado pela distribuição, procurei algo prático na net e não encontrei, por isso desenvolvi em php um gerador , ainda é simples, falta fazer com que pegue a lista de arquivos gerados (para não ficar perdido no servidor) , aumentar as opções de parâmetros do kick start... mas para mim neste instante onde estou fazendo muita instalação de VMs é suficiente ... deixo aqui para quem precisar ... é só copiar abaixo da linha pontilhada ...

------------------------------------------------------------------------------------------------------
<?php
/*
* Gerador de arquivo kick start p/ instalação de Vms da Xen
* Criado por Jose Edson Moreno Jr < jemorenojr@ig.com.br >
* V 0.1 - 17/03/2008
*
*/
$ping = '/bin/ping';
// Diretorio relativo onde irão ficar os arquivos gerados
$dir_files = "files";
// URL de instalação
$url_fonte = "http://< servidor onde contem os arquivos de instalacao >/rhas51/" ;
// Senha que sera aplicado ao root (usar aspas simples para limitar a senha)
$senha_root = '$1$vd0kAVa5$FNusNrVU54bo2SBC2GV2A';
// Volume logico onde montara a VM
$dev_vm = "/dev/Vol";
// Dispositivo de rede utilizado na VM
$device = "eth0";

// Template para criar o arquivo ks
$ks="# Kickstart - Gerado por geraks.php em " . date("l d \of F Y H:i:s");
$ks= $ks . "\ninstall\nurl --url $url_fonte\n\n# debugging\n";
$ks= $ks . "#interactive\nlang en_US.UTF-8\nkeyboard br-abnt2\n\n";
$ks= $ks . "# Network information\n";
$ks1= "# Reboot after installation\nreboot\nrootpw --iscrypted $senha_root/\n";
$ks1= $ks1 . "firewall --disable\nauthconfig --enableshadow --enablemd5\nselinux --disable\n";
$ks1= $ks1 . "timezone --utc America/Sao_Paulo\n\n# Particionamento\nbootloader --location=mbr --driveorder=xvda\n";
$ks1= $ks1 . "clearpart --linux\npart / --fstype ext3 --size=100 --grow\npart swap --size=3000 --asprimary";
$ks1= $ks1 . "\n%packages\n@admin-tools\n@base\n@core\n@development-libs\n@development-tools\n";
$ks1= $ks1 . "@editors\n@system-tools\n@text-internet\npostfix\n\n%post\nrpm -e nss_ldap.i386\n";
$ks1= $ks1 . "rpm -e sendmail\nmkdir /iG\necho \"alias vi=vim\" > > /etc/profile\n";
$ks1= $ks1 . "echo \"set bg=dark\" > > /etc/vimrc\n";
$ip_erro=0;
$gateway_erro=0;
$mask_erro=0;
$dns_erro=0;
$app_erro=0;
$numero_erro=0;
$memoria_erro=0;
$bridge_erro=0;
$nome_vm_erro=0;
$virtual=0;
$ip="";
$gateway="";
$mask="255.255.255.0";
$dns="200.204.0.104";
$localizacao="spo";
$so="l";
$app="";
$tipoapp="a";
$numero="0";
$memoria="128";
$nome_vm="";
$bridge="xenbr0";
$Autoriza = "0" ;

function testa_ip($ip) {
global $ping;
/* Retornos possiveis
0 - ip ok e existe na rede
1 - ip ok e nao existe na rede
2 - ip inválido
*/
$ret_ip = 0;
// Testa a válidade do ip
if (($longip = ip2long($ip)) !== false) {
// Testa se o ip existe na rede
system ( "$ping -c 1 $ip > /dev/null 2 > /dev/null",$ret_ip);
return $ret_ip;
} else {
return 2;
}
}

function testa_mask ($mask)
{
/* Testa a mascara convertendo para binario e verificando a seguencia de
* bits, para uma mascara correta não pode se ter no digitos mais significativos
* sequencia de bits alternando
*/
$mask_bin = decbin (ip2long ( $mask ));
$pos = strlen ($mask_bin) - 1;
$erro = 0;
if (( $pos == 31 ) || ( $pos == 0 )) {
$flag_bit = 0;
while ( $pos > -1 ) {
if ( $mask_bin[$pos] == 1 ) {
$flag_bit = 1;
}
if (( $mask_bin[$pos] == 0 ) && ( $flag_bit == 1)) {
$erro = 1;
}
$pos = $pos - 1;
}
} else {
$erro = 1;
}
return $erro;
}


print ( '
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html lang="pt-BR" >
< head >
< title >Gerador de kickstart para instalar VMs< /title >
< meta name="GENERATOR" content="Quanta Plus" >
< meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
< /head >
< body >

< /body >
');
if ( $_POST ) {
// verifica as variaveis do POST
if ($_POST['ip'] == "") {
$ip_erro = 3;
} else {
$ip=$_POST['ip'];
$ip_erro = testa_ip ( $ip );
if ( $ip_erro == 0 ) {
$ip_erro = 1;
} else if ( $ip_erro == 1 ) {
$ip_erro = 0;
}
}
if ($_POST['gateway'] == "") {
$gateway_erro = 3;
} else {
$gateway=$_POST['gateway'];
$gateway_erro = testa_ip ( $gateway );
}
if ($_POST['mask'] == "") {
$mask_erro = 3;
} else {
$mask=$_POST['mask'];
$mask_erro = testa_mask ( $mask );
}
if ($_POST['dns'] == "") {
$dns_erro = 3;
} else {
$dns_erro = 0;
$dns=$_POST['dns'];
$dns_erro = testa_ip ( $dns );
}
if ($_POST['app'] == "") {
$app_erro = 1;
} else {
$app_erro = 0;
$app=$_POST['app'];
}
$localizacao=$_POST['localizacao'];
$so=$_POST['SO'];
$tipoapp=$_POST['Tipo_App'];
if ($_POST['numero'] == "") {
$numero_erro = 1;
} else {
$numero_erro = 0;
$numero = $_POST['numero'];
}
if ($_POST['memoria'] == "") {
$memoria_erro = 1;
} else {
$memoria_erro = 0;
$memoria = $_POST['memoria'];
if ( $memoria < 128 ) {
$memoria_erro = 2;
}
}
if ($_POST['bridge'] == "") {
$bridge_erro = 1;
} else {
$bridge_erro = 0;
$bridge = $_POST['bridge'];
}
if ($_POST['nome_vm'] == "") {
$nome_vm_erro = 1;
} else {
$nome_vm_erro = 0;
$nome_vm = $_POST['nome_vm'];
}
if (isset ($_POST['Autoriza'])) {
$Autoriza = 1;
}
// Verifica de houve algum erro , havendo não gera arquivo
$erro = $ip_erro + $gateway_erro + $mask_erro + $dns_erro + $app_erro + $numero_erro + $memoria_erro + $bridge_erro + $nome_vm_erro;
if (( $erro == 0) || ( $Autoriza == 1 )){
$host = $app. "-" . $localizacao . "-" . $so . $tipoapp ."-v" . $numero;
$file = realpath ("./") . "/" . $dir_files . "/" . $host . ".cfg";
$fileo = fopen("$file","wr") or exit("Unable to open $file !");
$dados = $ks . "network --bootproto=static --device=$device --gateway=";
$dados = $dados . "$gateway --ip=$ip --nameserver=$dns --netmask=$mask --hostname=$host --onboot=on\n";
$dados = $dados . $ks1;
if (! fwrite($fileo,$dados)){ exit("Unable to write $file !"); }
fclose($fileo);
print ('
< div align="center" >
< h2 >< strong >Arquivo gerado com sucesso !< /strong >< /h2 >
< p >Execute no servidor Xen o comando:< /p >
< table align="center" >
< tbody >
< tr >
< td >
< p align="left" >< h3 >
/usr/sbin/virt-install --name=');
print ("$nome_vm \< br >\n");
print ("--file=$dev_vm/$nome_vm --ram=$memoria --network=bridge:$bridge \< br >\n");
print ("--vnc --paravirt --location=$url_fonte \< br >\n");
print ("-x ks=http://" . $_SERVER['SERVER_NAME'] . dirname($_SERVER['PHP_SELF']) . "/files/" . $host . ".cfg< br >\n" );
print ('
< /h3 >
< /p >
< /td >
< /tr >
< /tbody >
< /table >
< /div >
< /html >
');
} else {
preenchimento() ;
}
} else {
preenchimento() ;
}

function preenchimento ()
{
global $ip_erro, $gateway_erro, $mask_erro, $dns_erro, $app_erro, $numero_erro, $memoria_erro, $bridge_erro;
global $nome_vm_erro, $ip, $gateway, $mask, $dns, $app, $numero, $memoria, $nome_vm, $bridge, $virtual;
global $so, $localizacao, $tipoapp ;
print ('
< table align="center" >< FORM method="POST" >
< tbody >
< tr >
< th align="left" >IP< /th >
< td >< input type="text" name="ip" title="IP da máquina virtual" align="left"');
print (" value = \"$ip\" >\n");
if ( $ip_erro != 0 ) {
print (" < br >\n < div align=\"center\" style=\"color : #ff0404; text-align : center;\" >\n");
if ( $ip_erro == 1 ) {
print ("< strong >IP já existe< /strong >\n");
}
if ( $ip_erro == 2 ) {
print ("< strong >IP inválido< /strong >\n");
}
if ( $ip_erro == 3 ) {
print ("< strong >Preenchimento obrigátorio< /strong >\n");
}
print ("< /div >\n");
}
print ('
< /td >
< /tr >
< tr >
< th align="left" >Mask< /th >
< td >< input type="text" name="mask" title="Máscara do IP da máquina virtual" align="left"');
print (" value = \"$mask\" >\n");
if ( $mask_erro != 0 ) {
print (" < br >\n < div align=\"center\" style=\"color : #ff0404; text-align : center;\" >\n");
if ( $mask_erro == 1 ) {
print ("< strong >Mascara inválida< /strong >\n");
}
if ( $mask_erro == 3 ) {
print ("< strong >Preenchimento obrigátorio< /strong >\n");
}
print ("< /div >\n");
}
print ('
< /td >
< /tr >
< tr >
< th align="left" >Gateway< /th >
< td >< input type="text" title="Gateway do IP da máquina virtual" name="gateway"');
print (" value = \"$gateway\" >\n");
if ( $gateway_erro != 0 ) {
print (" < br >\n < div align=\"center\" style=\"color : #ff0404; text-align : center;\" >\n");
if ( $gateway_erro == 1 ) {
print ("< strong >Gateway não responde< /strong >\n");
}
if ( $gateway_erro == 2 ) {
print ("< strong >IP Gateway inválido< /strong >\n");
}
if ( $gateway_erro == 3 ) {
print ("< strong >Preenchimento obrigátorio< /strong >\n");
}
print ("< /div >\n");
}
print ('
< /td >
< /tr >
< tr >
< th align="left" >DNS Server< /th >
< td >< input type="text" name="dns" title="Servidor primário de DNS da máquina virtual" align="left"');
print (" value = \"$dns\" >\n");
if ( $dns_erro != 0 ) {
print (" < br >\n < div align=\"center\" style=\"color : #ff0404; text-align : center;\" >\n");
if ( $dns_erro == 1 ) {
print ("< strong >DNS não responde< /strong >\n");
}
if ( $dns_erro == 2 ) {
print ("< strong >IP DNS inválido< /strong >\n");
}
if ( $dns_erro == 3 ) {
print ("< strong >Preenchimento obrigátorio< /strong >\n");
}
print ("< /div >\n");
}
print ('
< /td >
< /tr >
< tr >
< th rowspan="5" align="left" bgcolor="Silver" >Hostname< /th >
< td bgcolor="Silver" >< input type="text" name="app" title="Nome do aplicativo que será parte do hostname da máquina virtual" align="left" ');
print (" value = \"$app\" >\n");
if ( $app_erro == 1 ) {
print (" < br >\n < div align=\"center\" style=\"color : #ff0404; text-align : center;\" >\n");
print ("< strong >Preenchimento obrigátorio< /strong >\n");
print ("< /div >\n");
}
print ('
< /td >
< tr >
< td bgcolor="Silver" >
< SELECT title="Nome do local de hospedagem que será parte do hostname da máquina virtual" name="localizacao" >
< option value="spo" ');
if ( $localizacao == 'spo' ) {
print (" selected=\"selected\" ");
}
print (' >Sao Paulo - SPO< /option >
< option value="poa"');
if ( $localizacao == 'poa' ) {
print (" selected=\"selected\" ");
}
print (' >Porte Alegre - POA< /option >
< option value="brb"');
if ( $localizacao == 'brb' ) {
print (" selected=\"selected\" ");
}
print (' >Brasília - BRB< /option >
< /SELECT >
< /td >
< /tr >
< tr >
< td bgcolor="Silver" >
< SELECT name="SO" title="Nome do S.O. que será parte do hostname da máquina virtual" >
< option value="l" ');
if ( $so == 'l' ) {
print (" selected=\"selected\" ");
}
print (' >Linux< /option >
< option value="w"');
if ( $so == 'w' ) {
print (" selected=\"selected\" ");
}
print (' >Windows< /option >
< option value="s"');
if ( $so == 's' ) {
print (" selected=\"selected\" ");
}
print (' >Solaris< /option >
< /SELECT >
< /td >
< /tr >
< TR >
< td bgcolor="Silver" >
< SELECT name="Tipo_App" title="Nome do tipo de aplicativo que será parte do hostname da máquina virtual" >
< option value="a" ');
if ( $tipoapp == 'a' ) {
print (" selected=\"selected\" ");
}
print (' >Aplicação< /option >
< option value="d"');
if ( $tipoapp == 'd' ) {
print (" selected=\"selected\" ");
}
print (' >Database< /option >
< option value="x"');
if ( $tipoapp == 'x' ) {
print (" selected=\"selected\" ");
}
print (' >Xen< /option >
< option value="v"');
if ( $tipoapp == 'v' ) {
print (" selected=\"selected\" ");
}
print (' >Vmware< /option >
< /SELECT >
< /td >
< /tr >
< tr >
< td align="left" bgcolor="Silver" >Número da Maquina
< input type="text" name="numero" title="Número de identificacao que será parte do hostname da máquina virtual" size="3" ');
print (" value = \"$numero\" >\n");
if ( $numero_erro == 1 ) {
print (" < br >\n < div align=\"center\" style=\"color : #ff0404; text-align : center;\" >\n");
print ("< strong >Preenchimento obrigátorio< /strong >\n");
print ("< /div >\n");
}
print ('
< /td >
< /tr >
< tr >
< th align="left" >Nome da VM< /th >
< td align="left" >< input type="text" title="Nome da VM na máquina XEN, será o nome do arquivo" name="nome_vm" ');
print (" value = \"$nome_vm\" >\n");
if ( $nome_vm_erro != 0 ){
print (" < br >\n < div align=\"center\" style=\"color : #ff0404; text-align : center;\" >\n");
print ("< strong >Preenchimento obrigátorio< /strong >\n");
print ("< /div >\n");
}
print ('
< /td >
< /tr >
< tr >
< th align="left" >Memória da VM (Mb)< /th >
< td align="left" >< input type="text" title="Quantidade de memória alocada pela VM na máquina XEN" name="memoria" size="4" ');
print (" value = \"$memoria\" >\n");
if ( $memoria_erro != 0 ){
print (" < br >\n < div align=\"center\" style=\"color : #ff0404; text-align : center;\" >\n");
if ( $memoria_erro == 1 ) {
print ("< strong >Preenchimento obrigátorio< /strong >\n");
} else {
print ("< strong >Valor tem que ser superior a 128 Mb< /strong >\n");
}
print ("< /div >\n");
}
print ('
< /td >
< /tr >
< tr >
< th align="left" >Bridge no Xen< /th >
< td align="left" > < input type="text" title="Nome da bridge na máquina XEN, que será alocada a VM" name="bridge" ');
print (" value = \"$bridge\" >\n");
if ( $bridge_erro == 1 ) {
print (" < br >\n < div align=\"center\" style=\"color : #ff0404; text-align : center;\" >\n");
print ("< strong >Preenchimento obrigátorio< /strong >\n");
print ("< /div >\n");
}
print ('
< /td >
< /tr >
< TR >< TD >< /TD >< /TR >
< tr >
< th colspan="2" align="center" >< INPUT type="submit" name="Gera" value="Gera Arquivo" >< /th >
< /tr >
< /tbody >
< /FORM >
< /table >' );
if (( $gateway_erro == 1 ) || ( $dns_erro == 1 )) {
print ('
< table align="center" >< FORM method="POST" name="Autoriza" >
< tbody > .
< tr >
< th colspan="2" align="center" >');
if ( $gateway_erro == 1 ) {
print (" < BR >\n < div align=\"center\" style=\"color : #ff0404; text-align : center;\" >\n");
print ("< strong >Nao foi possível checar Gateway, possivelmente problema com a rede< /strong >\n");
print ("< /div >\n");
}
if ( $dns_erro == 1 ) {
print (" < BR >\n < div align=\"center\" style=\"color : #ff0404; text-align : center;\" >\n");
print ("< strong >Nao foi possivel checar DNS, possivelmente problema com a rede< /strong >\n");
print ("< /div >\n");
}
print ('< input type="hidden" name="ip" value = "' . $ip . "\" >\n");
print ('< input type="hidden" name="mask" value = "' . $mask . "\" >\n");
print ('< input type="hidden" name="gateway" value = "' . $gateway . "\" >\n");
print ('< input type="hidden" name="dns" value = "' . $dns . "\" >\n");
print ('< input type="hidden" name="app" value = "' . $app . "\" >\n");
print ('< input type="hidden" name="localizacao" value = "' . $localizacao . "\" >\n");
print ('< input type="hidden" name="SO" value = "' . $so . "\" >\n");
print ('< input type="hidden" name="Tipo_App" value = "' . $tipoapp . "\" >\n");
print ('< input type="hidden" name="numero" value = "' . $numero . "\" >\n");
print ('< input type="hidden" name="nome_vm" value = "' . $nome_vm . "\" >\n");
print ('< input type="hidden" name="memoria" value = "' . $memoria . "\" >\n");
print ('< input type="hidden" name="bridge" value = "' . $bridge . "\" >\n");
print ('
< INPUT type="hidden" name="Autoriza" value="1" >
< INPUT type="submit" name="Gera" value="Assumirei o erro e prosseguirei" >< /th >
< /tr > .
< /tbody >
< /FORM >
< /table > ');
}
print ('
< /html >
');
}

? >

quinta-feira, 13 de março de 2008

Introdução

Basicamente o módulo recent faz o que o nome mesmo diz, cria uma tabela dinâmica com endereços IPs "recentes" que obedeçam uma determinada regra.
Criar regras como, por exemplo, manter a porta 5900 (VNC Client) fechada e liberá-la quando um pessoa mandar 3 pacotes syn para as portas 1, 2 e 3, respectivamente, deixando assim a porta fechada e quando quiser é apenas enviar um telnet básico nas portas definidas que será aberta para o seu ip. Se alguém tentar fazer um portscanner não conseguirá nada, porque a porta estará fechada.
Bloquear uma tentativa de Brute Force pelas suas tentativas freqüentes de mandar um pacote syn para o firewall. Um exemplo disso é a utilização do brutus ou um simples shell script fazendo um laço com o expect tentando se logar no porta 22 (SSH)
# iptables -m recent -help
.....
recent v1.3.5 options:
[!] --set Add source address to list, always matches.
[!] --rcheck Match if source address in list.
[!] --update Match if source address in list, also update last-seen time.
[!] --remove Match if source address in list, also removes that address from list.
--seconds seconds For check and update commands above.
Specifies that the match will only occur if source address last seen within
the last 'seconds' seconds.
--hitcount hits For check and update commands above.
Specifies that the match will only occur if source address seen hits times.
May be used in conjunction with the seconds option.
--rttl For check and update commands above.
Specifies that the match will only occur if the source address and the TTL
match between this packet and the one which was set.
Useful if you have problems with people spoofing their source address in order
to DoS you via this module.
--name name Name of the recent list to be used. DEFAULT used if none given.
--rsource Match/Save the source address of each packet in the recent list table (default).
--rdest Match/Save the destination address of each packet in the recent list table
.
Exemplo - Block Brute Force in FTP

Simples regra para limitar a 2 conexões em um espaço de tempo de 300 segundos. Se o ip tentar se conectar mais de duas vezes em menos de 300 segundos, a conexão dele será bloqueada. E após este tempo (300 segundos) será liberada novamente (vale lembrar, que é feito balacemento de carga, então o numero de tentativas é multiplicada pelo numero de maquinas no sistema).
iptables -F
iptables -A INPUT -p tcp -s 10.24.70.0/24 -j ACCEPT
iptables -A INPUT -p tcp -s 10.24.71.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 21 -m state --state NEW -m recent --set --name FTPBLOCK
iptables -A INPUT -p tcp --dport 21 -m state --state NEW -m recent --update --seconds 300 \
--hitcount 3 --name FTPBLOCK -j LOG --log-level alert --log-prefix "FTP SCAN blocked: "
iptables -A INPUT -p tcp --dport 21 -m state --state NEW -m recent --update --seconds 300 \
--hitcount 3 --name FTPBLOCK -j DROP

Descrição do exemplo


iptables -A INPUT -p tcp --dport 21 -m state --state NEW -m recent --set --name FTPBLOCK

Verifique na tabela de entrada (-A INPUT) quando chegar um pacote de nova conexão (-m state NEW) na porta 21 (--dport 21), ative o módulo recent (-m recent) e se não existir, crie uma tabela de nome FTPBLOCK (--name FTPBLOCK)

iptables -A INPUT -p tcp --dport 21 -m state --state NEW -m recent --update --seconds 300 \
--hitcount 3 --name FTPBLOCK -j LOG --log-level alert --log-prefix "FTP SCAN blocked: "

Verifique na tabela de entrada (-A INPUT) quando chegar um pacote de nova conexão (-m state NEW) na porta 21 (--dport 21), ative o módulo recent (-m recent) e verifique (--update) se na tabela FTPBLOCK (--name FTPBLOCK) existe a entrada do ip de origem, se existir, verifique se este tem três (3) entradas (--hitcount 3) em menos de 5 minutos (--seconds 300), se for verdade, adicione uma entrada de nome "FTP SCAN blocked" no arquivo de log com nivel de alerta (--log-level alert) no syslog do kernel.

iptables -A INPUT -p tcp --dport 21 -m state --state NEW -m recent --update --seconds 300 \
--hitcount 3 --name FTPBLOCK -j DROP

Verifique na tabela de entrada (-A INPUT) quando chegar um pacote de nova conexão (-m state NEW) na porta 21 (--dport 21), ative o módulo recent (-m recent) e verifique (--update) se na tabela FTPBLOCK (--name FTPBLOCK) existe a entrada do ip de origem, se existir, verifique se este tem três (3) entradas (--hitcount 3) em menos de 5 minutos (--seconds 300), se for verdade,recuse (DROP) o pacote .

Teste do modulo recent

Neste exemplo , basta fazer 3 tentativas de conexão ao ftp e verá que ficará bloqueado, para ver a lista de ips bloqueados:
cat /proc/net/ipt_recent/FTPBLOCK

Utilizando VLAN em VMs XEN

Recursos Necessários
  • Switch com suporte a vlan's (802.1q)
  • Placa de rede com o mesmo suporte (a maioria das placas suportam)
Detalhes da VLAN
  • Primeiramente não se pode existir em Trunk apenas com uma VLAN, é necessário haver pelo menos 2 VLANs quando se usa o IEEE 802.1Q, se houver apenas uma VLAN tudo deixa de funcionar.
  • Para se utilizar da VLAN no XEN, temos que ter em mente que a VLAN utilizada pela VM não poderá ter um ip, apenas terá que ser levantado, o que nos leva a solução do primeiro problema, a necessidade de 2 VLANs no minimo para a existencia do Trunk, portando para a maquina principal ou temos uma outra VLAN com ip, ou temos uma outra interface com ip e mais uma VLAN sem ip
  • A VLAN utilizada pela bridge não pode ser acessada por um alias da interface com a VLAN (ex: eth0.260:1), não funciona, ela até levanta e funciona normalmente , mas no momento que sobe a bridge tudo deixa de funcionar
Procedimentos de uso da VLAN no XEN
  • Primeiramente levantaremos as 2 VLANs necessárias, como exemplo serão utilizadas as TAGs 260 e 261 da VLAN, sendo uma para ser usada na bridge (sem ip) e outra para acesso ao servidor xen (com ip 16.16.16.1 e gateway 16.16.16.254)
vconfig set_name_type DEV_PLUS_VID_NO_PAD
vconfig add eth0 260
vconfig add eth0 261
ip link set eth0.260 address fe:ff:ff:ff:ff:ff
ip addr add 16.16.16.1/24 brd + dev eth0.261
ip link set eth0.260 up
ip link set eth0.261 up
ip route add default via 16.16.16.254 dev eth0.261
  • Na seqüencia habilitamos a bridge com a interface com VLAN (sem ip)
brctl addbr xenbr260
ip link set xenbr260 up
brctl addif eth0.260
- O resto é procedimento normal de configuração da XEN , assinalando a bridge ao arquivo de configuração da VM e na VM colocando um IP que seja permitido a VLAN

Esquema do funcionamento


Netcat - Canivete suiço de rede

- Introdução:

O netcat é um utilitário que permite escrita e leitura de dados atraves de conexão de rede, usando o proolo TCP/IP. Ele ainda permite especificar a porta que será transmitido, independe de onde será o server (listen) se na origem ou destino.
No caso de substituição do scp, permite usar o processamento que seria p/ encriptar no processo de compactação da transmissão.
Usando o programa pv se consegue ter uma visualização da taxa de transmissão

- Copia de diretório

- Na maquina destino
nc -vlp port_escuta_detino | tar xzvp
-Na maquina origem
tar cpz ./ | nc ip_destino port_escuta_detino

- Copia de partição

- Na maquina origem
dd if=/dev/hdb5 | gzip -9 | nc -l porta_escuta_origem
- Na maquina destino
nc ip_origem porta_escuta_origem | pv -b > myhdb5partition.img.gz

- Transferindo arquivo

- Na maquina origem
cat backup.iso | nc -l 3333
- Na maquina destino
nc  ip_origem porta_escuta_origem > backup.iso
Com status da transferência
- Na maquina origem
cat backup.iso | pv -b  | nc -l 3333
- Na maquina destino
nc  ip_origem porta_escuta_origem | pv -b > backup.iso

quarta-feira, 28 de março de 2007

Acesso com VNC via SSH

Acesso com VNC via SSH

(Conexão Segura e Criptografada)

Uma conexão via VNC normalmente não é segura, primeiramente devido ao próprio tipo de conexão que não é criptografado, possibilitando a obteção da senha com um simples sniffer, segundo porque a maquina que ira receber a conexão fica exposta, ainda mais se for na internet.

Bom diante do fato, primeiro que é necessário a conexão, segundo não se quer investir mais na segurança, crie o processo abaixo, para que exista a conexão, porém criptografado, o qual garante que os dados trafegados não serão violados.


Pré Requisitos:

  • Servidor dentro da rede de ssh, para prover apenas a conexão, no momento pré suponho que exista isso
  • Software VNC instalado em ambas as máquinas que estarão envolvidas, não entrarei no mérito de como obter e configurar, o google resolve isto !
  • Software cliente de ssh Putty instalado na máquina cliente de VNC, para baixar Putty


Procedimento:

Baixar o software putty e colocar no lugar que achar melhor em seu sistema, apenas crie um link p/ o acesso ao programa, após feito isto execute-o, irá aparecer a tela da ilustração 1.

Ilustração 1 - Endereçamento de conexão ssh

Como mostra a Ilustração 1, coloque o endereço do servidor de ssh, pode ser IP ou um nome de servidor de domínio no campo “Host Nome (or IP address), após isto atribua um nome a sessão no campo “Saved Session”, isto permitirá salvar toda a configuração.

Após isto selecione o item em “Tunnels” em “Category” irá aparecer a tela da ilustração 2.

Ilustração 2 - Configuração de tunel

Iremos preencher os seguintes campos, “Source port” com “5800” e “Destination” com o endereço da maquina que tem o servidor de VNC ou a que será controlada pelo VNC, este endereço terá que conter a porta de conexão, exemplo 192.168.1.33:5800, após iremos clicar no botão “Add”.

Feito isto iremos cadastrar a segunda porta do VNC a “5900” em “Source port” e o endereço da maquina servidora de VNC em “Destination”, exemplo 192.168.1.33:5900, e clicar no botão “Add”

As Ilustrações 3, 4 e 5 exemplificam este processo.

Ilustração 3 - Cadastro da primeira porta e destino do servidor de VNC


Ilustração 4 - Cadastro da segunda porta e destino do servidor de VNC


Ilustração 5 - Cadastro das portas e destino do servidor de VNC

Após isto selecionamos o item “Session” em “Category” e salvamos as configurações clicando no botão “Save” como a ilustração 6.


Ilustração 6 - Salvando as configurações

Após isto, clicar no botão “Open” e efetuar a conexão ssh, irá pedir um usuário e senha que já estarão previamente cadastrada no servidor de ssh, após efetuar a conexão minimizar a janela e iniciar o cliente VNC, no endereço do servidor de VNC coloque 127.0.0.1, isto fará com que o putty capture as portas 5800 e 5900 chamdas no loopback local e redireione para a maquina cadastrado no tunelamento.


This all Folks !