Usar rotas de VPN como backup no pfSense
-
Veja bem, são 2 coisas diferentes!!
1 - O script rodou ok!!!
- Desliguei o ipsec na GUI
- Rodei o scrip com um ip que estava online e ele reportou que o ip estava on line e não desligou
- Rodei o script novamente com um ip que estava offline e dai ele ativou o ipsec na gui!
2 - Após ativar o ipsec na gui, percebi que o IPSEC oferece a opção de controle da VPN por vpn, então imaginei que ao invés do script ativer ou desativar todo o ipsec, ele poderia apenas ativar ou desativar apenas a conexão de vpn desejada sem parar todo o ipsec do sistema.
Dessa maneira, imagine que 2 links cairam, mas apenas 1 voltou a funcionar, o que já estivesse ok voltaria para o MPLS, o que estivesse ainda com problemas continuaria no VPN.Outra coisa, o script precisa aceitar como parâmetro a interface de rede que você deseja usar para fazer o teste de ping, pois quando a VPN estiver no ar o ping vai continuar dando ok pois estará indo pela VPN!!
Abraços!
-
Entendi.
Faz este teste para ver se a url individual resolve o problema:
Desabilita o script e o ipsec.
Depois roda só a url que você colou com os parametros da sua vpn backup do MPLS e vê se alem dela subir, ela se mantem no ar apos alguns updates ou algumas horas.
-
Após dar um paste na URL ele pensa um pouco mas não conecta não!!
Chequei a gui e o ipsec continua desligado após clicar no start da conexão de vpn, que continua aparecendo (porem com o x vermelho) no status do ipsec!
-
Nesta segunda versao do script, voce coloca qualquer parametro de ping como argumento e por ultimo o ip de destino.
require_once("util.inc"); require_once("functions.inc"); require_once("pkg-utils.inc"); require_once("globals.inc"); require_once("filter.inc"); require_once("shaper.inc"); require_once("ipsec.inc"); require_once("vpn.inc"); $ipsec=$config['ipsec']; $host=array_pop($argv); if (! is_ipaddr($host)){ print "invalid ip address!\n"; exit(1); } array_shift($argv); $args=implode(" ", $argv); exec("/sbin/ping -c 1 -t 1 $args $host",$ret,$exit1); if ($exit1 == 0) exec("/sbin/ping -c 1 -t 1 $args $host",$ret,$exit2); if ($exit2 == 0) exec("/sbin/ping -c 1 -t 1 $args $host",$ret,$exit3); $exit = ($exit1 + $exit2 + $exit3); if ($exit == 0){ #link online if (array_key_exists("enable",$ipsec)){ print "link online, disabling ipsec\n"; unset ($config['ipsec']['enable']); write_config(); vpn_ipsec_configure(); vpn_ipsec_refresh_policies(); filter_configure(); } else print "link online\n"; } else{ if (! array_key_exists("enable",$ipsec)){ print "link offline, enabling ipsec\n"; $config['ipsec']['enable']=""; write_config(); vpn_ipsec_configure(); vpn_ipsec_refresh_policies(); filter_configure(); } else print "link offline\n"; } ?>
ex: php -q ./check_ipsec.php -S 172.16.5.6 172.16.5.7
veja se assim voce consegue forçar a interface de saida do ping.
-
Talvez viajei na ideia, mas basicamente voce deve ter posto o ipsec como gateway default por isso na os outros pontos usavam a net do ponto A.
Oi Rafael,
Onde você altera a prioridade de rota do ipsec e como faríamos neste caso para o pfsense escolher entre dois caminhos para a mesma rede de destino?
-
Olá Marcello fiz o teste com a nova versão do script e está funcionando corretamente. vou instalar o pacote cron no pfsense e configurar o script para rodar.
Quero ver se começo a estudar os plugins e programação hoje, durante a semana é muito corrido para mim!!
Muitíssimo obrigado!!
-
Olá Marcelloc, tudo bem?
Rapaz lembra do script check_mpls que você fez para mim, então estou tentando ajustar aquele script para ao invés de desligar toda a estrutura do ipsec desligar apenas os túneis que passei como parâmetro.
Estou apanhando com isso a tarde toda mas até agora não entendi como fazer isso, poderia me dar uma força? Se estiver disponível eu te mando o script com as alterações ok!
Abraços!
-
fneto,
A opção de desabilitar o ipsec ou não envolve todos os tuneis, por isso o script roda nas pontas, onde só existe um túnel.
para derrubar somente um link, você vai precisar suar os comando do proprio ipsec, racoon-alguma coisa. Não tenho muita experiência com isso.
att,
Marcello Coutinho
-
Então Marcello, na verdade não, o que quero é apenas habilitar a opção "Disable this phase1" e "Disable this phase 2" na interface do pfsense, feito isso salvo a configuração e ele mata somente o túnel que eu passar o id como parâmetro entendeu!!
Não quero mexer com racoon nem nada disso, como você desabilitou o ipsec todo na interface achei que talvez pudesse me ajudar a encontrar a opção de desabilitar apenas os túneis.
Na verdade eu já identifiquei as variáveis nos array estudando os arquivos do pfSense, o que não estou conseguindo fazer é gravar as configurações!
-
as funções que gravam a configuração e aplicam os filtros estão todas juntas
write_config();
e as demais.
Dá uma olhada neste pedaço de código do dansguardian.
Nele eu vefico os valores do array e salvo caso haja alterações$count=0; if (is_array($config['installedpackages']['dansguardianphraseacl']['config'])) foreach($config['installedpackages']['dansguardianphraseacl']['config'] as $dansguardian_phrase){ #bannedphraselist if($dansguardian_phrase['banned_phraselist'] == "" && file_exists ($dansguardian_dir.'/lists/bannedphraselist.sample')){ $config['installedpackages']['dansguardianphraseacl']['config'][$count]['banned_phraselist']=base64_encode(file_get_contents($dansguardian_dir.'/lists/bannedphraselist.sample')); $load_samples++; } $includes=preg_replace($match,$replace,$dansguardian_phrase['banned_includes']); file_put_contents($dansguardian_dir."/lists/bannedphraselist.".$dansguardian_phrase['name'],($dansguardian_phrase['banned_enabled']?dg_text_area_decode($config['installedpackages']['dansguardianphraseacl']['config'][$count]['banned_phraselist']).$includes:""),LOCK_EX); #weightedphraselist if($dansguardian_phrase['weighted_phraselist'] == "" && file_exists ($dansguardian_dir.'/lists/weightedphraselist.sample')){ $config['installedpackages']['dansguardianphraseacl']['config'][$count]['weighted_phraselist']=base64_encode(file_get_contents($dansguardian_dir.'/lists/weightedphraselist.sample')); $load_samples++; } $includes=preg_replace($match,$replace,$dansguardian_phrase['weighted_includes']); file_put_contents($dansguardian_dir."/lists/weightedphraselist.".$dansguardian_phrase['name'],($dansguardian_phrase['weighted_enabled']?dg_text_area_decode($config['installedpackages']['dansguardianphraseacl']['config'][$count]['weighted_phraselist']).$includes:""),LOCK_EX); #exceptionphraselist if($dansguardian_phrase['exception_phraselist'] == "" && file_exists ($dansguardian_dir.'/lists/exceptionphraselist.sample')){ $config['installedpackages']['dansguardianphraseacl']['config'][$count]['exception_phraselist']=base64_encode(file_get_contents($dansguardian_dir.'/lists/exceptionphraselist.sample')); $load_samples++; } file_put_contents($dansguardian_dir."/lists/exceptionphraselist.".$dansguardian_phrase['name'],($dansguardian_phrase['exception_enabled']?dg_text_area_decode($config['installedpackages']['dansguardianphraseacl']['config'][$count]['exception_phraselist']):""),LOCK_EX); $count++; } if($load_samples > 0) write_config();
-
Meu código não está muito diferente na verdade está bem simples veja!
```
print "link online, disabling Tunnel\n";
//unset ($config['ipsec']['enable']);
$a_phase1 = $config['ipsec']['phase1'];
$p1index = $VPN_ID;
$a_phase1[$p1index]['disabled']=true;
//print "\nVPNID: ".$VPN_ID;
//print "\nHOST: ".$host;
//print "\nPhase1: ".$ph1ent['disabled'];
//print "\nPhase2: ".$ph2ent['disabled'];
write_config();
vpn_ipsec_configure();
vpn_ipsec_refresh_policies();
filter_configure(); -
Esse código executa sem dar erro nenhum, mas também não faz nada!
-
Já saquei, você esta alterando sua variável $a_phase1 e não a $config['ipsec']['phase1']
você tem duas opções, atribuir de volta o $a_phase1 para $config['ipsec']['phase1']
$config['ipsec']['phase1']=$a_phase1;
write_config();
.
.
.ou fazer o loop direto no array como te mostrei no exemplo do dansguardian.
Termine o loop antes de salvar as configurações, é mais saudável. :)
E é claro, sempre faça backup do seu xml antes de começar a programar.
-
Cara to quase lá, estou conseguindo desligar a phase 1 do tunnel sem problema nenhum, já a fase 2 fiz um código que funcionou, daí fui tentar melhorar o código e parou de funcionar de vez!
Segue abaixo o novo trecho de código, esse codigo desliga a phase 1 que escolho, mas não desliga a phase2!
Por que tenho que desligar a fase 1 e 2: porque se desligo apenas a fase 1 o pfsense não desativa as politicas SPD e a rota continua bagunçada, se desligo a fase 2 e 1 aí da certo!
require_once("util.inc"); require_once("functions.inc"); require_once("pkg-utils.inc"); require_once("globals.inc"); require_once("filter.inc"); require_once("shaper.inc"); require_once("ipsec.inc"); require_once("vpn.inc"); $ipsec=$config['ipsec']; $VPN_ID=array_pop($argv); $a_phase1 = &$config['ipsec']['phase1']; $a_phase2 = &$config['ipsec']['phase2']; $ikeid = $a_phase1[$VPN_ID]['ikeid']; //print_r(array_values($a_phase2)); $host=array_pop($argv); if (! is_ipaddr($host)){ print "invalid ip address!\n"; exit(1); } array_shift($argv); $args=implode(" ", $argv); exec("/sbin/ping -c 1 -t 1 $args $host",$ret,$exit1); if ($exit1 == 0) exec("/sbin/ping -c 1 -t 1 $args $host",$ret,$exit2); if ($exit2 == 0) exec("/sbin/ping -c 1 -t 1 $args $host",$ret,$exit3); $exit = ($exit1 + $exit2 + $exit3); if ($exit == 0){ #link online if (array_key_exists("enable",$ipsec)){ print "link online, disabling Tunnel\n"; //unset ($config['ipsec']['enable']); $a_phase1[$VPN_ID]['disabled']=""; //write_config(); if (is_array($a_phase2) && (count($a_phase2))) { foreach ($a_phase2 as $phase2) { if ($phase2['ikeid'] == $ikeid) { $a_phase2['disabled']=""; print "\n**************\n"; print_r(array_values($a_phase2)); //write_config(); } } } write_config(); vpn_ipsec_configure(); vpn_ipsec_refresh_policies(); filter_configure();
-
Neste ponto não seria o unset para sumir com a variavel disabled?
//unset ($config['ipsec']['enable']); $a_phase1[$VPN_ID]['disabled']="";
-
Não Marcelo, na verdade a variável disabled não existe por padrao. Quando eu marco a caixa na interface ele cria o valor no array!
De toda maneira deixa eu te adiantar meu progresso.
Consegui arrumar tudo e agora está tudo funcionando, eu consigo desativar a fase 1 e a fase 2 passando por parametro o número da VPN que quero desativar, no caso começa em 0 as políticas e vai aumentando de 1 em 1 as seguintes.
O problema agora está no fato de mesmo fazendo tudo isso as políticas de SPD criadas não estão sumindo, só somem se eu desligar o ipsec salvar e ligar novamente. Acho que essa solução é muito porca então estou tentando descobrir qual a função que recarrega os SPD's e chamar do nosso script.
require_once("util.inc"); require_once("functions.inc"); require_once("pkg-utils.inc"); require_once("globals.inc"); require_once("filter.inc"); require_once("shaper.inc"); require_once("ipsec.inc"); require_once("vpn.inc"); $ipsec=$config['ipsec']; $VPN_ID=array_pop($argv); $a_phase1 = &$config['ipsec']['phase1']; $a_phase2 = &$config['ipsec']['phase2']; $ikeid = $a_phase1[$VPN_ID]['ikeid']; //print_r(array_values($a_phase2)); $host=array_pop($argv); if (! is_ipaddr($host)){ print "invalid ip address!\n"; exit(1); } array_shift($argv); $args=implode(" ", $argv); exec("/sbin/ping -c 1 -t 1 $args $host",$ret,$exit1); if ($exit1 == 0) exec("/sbin/ping -c 1 -t 1 $args $host",$ret,$exit2); if ($exit2 == 0) exec("/sbin/ping -c 1 -t 1 $args $host",$ret,$exit3); $exit = ($exit1 + $exit2 + $exit3); if ($exit == 0){ #link online if (array_key_exists("enable",$ipsec)){ print "link online, disabling Tunnel\n"; //unset ($config['ipsec']['enable']); $a_phase1[$VPN_ID]['disabled']=""; //write_config(); if (is_array($a_phase2) && (count($a_phase2))) { foreach ($a_phase2 as &$phase2) { if ($phase2['ikeid'] == $ikeid) { $phase2['disabled']=""; //print "\n**************\n"; //print_r(array_values($a_phase2)); //write_config(); } } } vpn_ipsec_refresh_policies(); vpn_ipsec_configure(); //reload_tunnel_spd_policy($a_phase1, $a_phase2, $a_phase1, $a_phase2); write_config(); filter_configure(); } else print "link online\n"; } else{ if (! array_key_exists("enable",$ipsec)){ print "link offline, enabling ipsec\n"; $config['ipsec']['enable']=""; write_config(); vpn_ipsec_configure(); vpn_ipsec_refresh_policies(); filter_configure(); } else print "link offline\n"; } ?>
-
ok.
Ainda estou envolvido com o dansguardian, posso te ajudar quando terminar.
uma dica para publicar códigos, é usar o botão # (code). Assim fica mais fácil analisar o post.
-
Beleza, enquanto isso vou continuar tentando por aqui. Obrigado pela dica do code!
-
Olá Marcelloc gostaria de dizer que depois de muita briga consegui resolver totalmente o meu problema. Estou postando abaixo o script que gerei em PHP para ativar e/ou desativer os túneis IPSec individualmente apagando as políticas SPD quando necessário e servindo de maneira excelente para utilizar o tunel VPN como backup caso o link dedicado de comunicação de empresas pare de funcionar.
Obviamente que se tiver sugestões de melhoria por favor fique a vontade para fazer e melhorar o script. Este é o meu primeir script totalmente funcional para o pfSense, então testem em ambientes de homologação antes de colocar em produção!
Abraço a todos e Marcelloc, muito obrigado pelo script inicial que gerou esse aqui, sem ele nada disso seria possível.
exec("/sbin/ping -c 1 -t 1 -S $args $host",$ret,$exit1); if ($exit1 == 0) exec("/sbin/ping -c 1 -t 1 -S $args $host",$ret,$exit2); if ($exit2 == 0) exec("/sbin/ping -c 1 -t 1 -S $args $host",$ret,$exit3); $exit = ($exit1 + $exit2 + $exit3); if ($exit == 0){ #link online if (! isset($a_phase1[$VPN_ID]['disabled'])) { print "Link online, Disabling Tunnel!\n"; $a_phase1[$VPN_ID]['disabled']=""; if (is_array($a_phase2) && (count($a_phase2))) { foreach ($a_phase2 as &$phase2) { if ($phase2['ikeid'] == $ikeid) { $phase2['disabled']=""; } } } write_config(); /* flush SPD and SAD */ mwexec("/usr/local/sbin/setkey -F"); mwexec("/usr/local/sbin/setkey -FP"); vpn_ipsec_refresh_policies(); vpn_ipsec_configure(); filter_configure(); } else print "Link online, Tunnel already Disabled!\n"; } else{ if (isset($a_phase1[$VPN_ID]['disabled'])){ print "Link offline, Enabling Tunnel!\n"; unset ($a_phase1[$VPN_ID]['disabled']); if (is_array($a_phase2) && (count($a_phase2))) { foreach ($a_phase2 as &$phase2) { if ($phase2['ikeid'] == $ikeid) { unset ($phase2['disabled']); } } } write_config(); vpn_ipsec_refresh_policies(); vpn_ipsec_configure(); filter_configure(); } else print "Link offline, Tunnel already Enabled!\n"; } ?>
-
Foi mal, no último post o script saiu pela metade, segue agora o script completo!
/* check_mpls.php Este script tem como funcao habilitar ou desabilitar tuneis de VPN para serem usados como backup em caso de falhas em linhas dedicadas ou links ponto-a-ponto. Este script deve ser instalado no diretorio /usr/local/www, ter permisao de execucao e devera ser chamado atraves do cron na peridiocidade desejada. O script recebe como parametro o IP de origem para determinar a interface pela qual o teste sera realizado, o IP de destino que sera verificado se esta on-line ou n## e o nummero da VPN. No caso o numero da VPN e obtido contando-se apenas os itens de Fase 1 na configuracao do IPSec do pfSense de cima para baixo comecando do 0. Exemplo: php -q /usr/local/www/check_mpls.php <ip de="" origem=""> <ip a="" ser="" testado=""> <numero da="" vpn="" ipsec=""> php -q /usr/local/www/check_mpls.php 192.168.0.1 192.168.10.3 0 */ require_once("util.inc"); require_once("functions.inc"); require_once("pkg-utils.inc"); require_once("globals.inc"); require_once("filter.inc"); require_once("shaper.inc"); require_once("ipsec.inc"); require_once("vpn.inc"); $VPN_ID=array_pop($argv); $a_phase1 = &$config['ipsec']['phase1']; $a_phase2 = &$config['ipsec']['phase2']; $ikeid = $a_phase1[$VPN_ID]['ikeid']; $host=array_pop($argv); if (! is_ipaddr($host)){ print "invalid ip address!\n"; exit(1); } array_shift($argv); $args=implode(" ", $argv); exec("/sbin/ping -c 1 -t 1 -S $args $host",$ret,$exit1); if ($exit1 == 0) exec("/sbin/ping -c 1 -t 1 -S $args $host",$ret,$exit2); if ($exit2 == 0) exec("/sbin/ping -c 1 -t 1 -S $args $host",$ret,$exit3); $exit = ($exit1 + $exit2 + $exit3); if ($exit == 0){ #link online if (! isset($a_phase1[$VPN_ID]['disabled'])) { print "Link online, Disabling Tunnel!\n"; $a_phase1[$VPN_ID]['disabled']=""; if (is_array($a_phase2) && (count($a_phase2))) { foreach ($a_phase2 as &$phase2) { if ($phase2['ikeid'] == $ikeid) { $phase2['disabled']=""; } } } write_config(); /* flush SPD and SAD */ mwexec("/usr/local/sbin/setkey -F"); mwexec("/usr/local/sbin/setkey -FP"); vpn_ipsec_refresh_policies(); vpn_ipsec_configure(); filter_configure(); } else print "Link online, Tunnel already Disabled!\n"; } else{ if (isset($a_phase1[$VPN_ID]['disabled'])){ print "Link offline, Enabling Tunnel!\n"; unset ($a_phase1[$VPN_ID]['disabled']); if (is_array($a_phase2) && (count($a_phase2))) { foreach ($a_phase2 as &$phase2) { if ($phase2['ikeid'] == $ikeid) { unset ($phase2['disabled']); } } } write_config(); vpn_ipsec_refresh_policies(); vpn_ipsec_configure(); filter_configure(); } else print "Link offline, Tunnel already Enabled!\n"; } ?></numero></ip></ip>