Captive Portal Customizado

Este artigo tem como objetivo o desenvolvimento de um Captive Portal, simples, funcional e customizado. Essa ferramenta é útil para o controle amigável de uso da internet em bares, restaurantes, hotéis aeroportos e ambientes semelhantes.

[ Hits: 161.187 ]

Por: Perfil removido em 24/09/2010


Preparação



Projeto inicial por Tiago Corcelli.

Essa ferramenta é útil para o controle amigável de uso da internet em bares, restaurantes, hotéis aeroportos e ambientes semelhantes.

Imagine a situação onde você quer oferecer internet sem fio de qualidade porém, quer e precisa manter o controle do uso e tornar o acesso restrito aos seu clientes que estão consumindo e pagando, ou lhe gerando receita de uma forma qualquer, pois uma internet wireless sem controle lhe traria a inconveniente situação em que pessoas desautorizadas e oportunistas usarem sua internet de graça.

Vamos lá então...

Para este propósito usei as seguintes ferramentas disponíveis e gratuitas, substitua ao seu modo para tal aplicativo de usa preferencia:
  • Distribuição Debian
  • PostgreSQL
  • Apache2
  • PHP5
  • DHCP3-SERVER
  • IPTABLES

Lembre de instalar o suporte a comunicação com o banco de dados SQL neste pacote, use o fórum para resolver as dependências.

Não abordarei em detalhes sobre o método de instalação das ferramentas utilizadas pois, acredito que para realizar estas tarefas, devem conhecer com certeza o uso do apt-get.

    Próxima página

Páginas do artigo
   1. Preparação
   2. Configurando/preparando o database
   3. Construindo a aplicação
   4. Enviando as liberações ao Iptables
   5. Preparando o Apache para o Captive Portal
Outros artigos deste autor

Como fazer seu programa Kylix chamar uma aplicação externa

Procurando software para gerenciar armazenamento... Pensou FreeNAS!

O jeito fácil e o jeito difícil de inserir paginação no Open/LibreOffice

Introdução a Threads e como implementá-las em Python

Montando partições em memória

Leitura recomendada

Instalando o phpBB num servidor Web

Implementando um tradutor de línguas no seu web site

Ambiente LAMP no Debian

Servidor LAMP + PHPMyAdmin + Webalizer

Estatísticas para todos

  
Comentários
[1] Comentário enviado por removido em 24/09/2010 - 07:35h

Vle cara estava precisando muuuito disso.

[2] Comentário enviado por removido em 24/09/2010 - 10:40h

Valeu cara, obrigado.
Faz aí tua necessidade, duvidas posta aí que será um prazer ajuda-los.
Descobri mais formas de agilizar esse sistema. Com um pouco de suor desenvolvi uma forma de tarifar o tempo de acesso, se houver necessidade.
Abraços !!!!

[3] Comentário enviado por nps em 24/09/2010 - 11:13h

Muito bom, vai servir para mim também..

[4] Comentário enviado por fagnerfjas em 25/09/2010 - 05:27h

Muito interessante o artigo, usei alguns pontos dele pra implementar um portal.

Gostaria de uma explicação de como posso fazer um redirecionamento pra uma página obrigatória com iptables, tipo um hotspot,

Desde já agradeço se poder me ajudar.

[5] Comentário enviado por removido em 26/09/2010 - 20:07h

Olá Mestre

Não entendi sua pergunta, a página está dentro de seu servidor(localmente) ou é queres direcionar para uma página da WEB? O iptables não trabalha com endereço 'não numéricos', agora se queres fazer autenticação na saída obriga todos passarem por ela, como tem no artigo, ainda podes usar páginas diferentes para redes diferentes, desde que usem gateways distintos no mesmo servidor físico, como fiz na minha aqui depois algumas leituras da doc do apache percebi que posso usar vários sites atribuindo uma porta onde esta "ouvindo" e direcionando ao diretório padrão pra porta em questão..... mas ve se isso te ajuda:


o apache por padrão está Listen da porta 80 em /var/www/
logo, se vc redirecionar o trafego da porta 80 pro seu servidor, vai aparecer a página hospedada nesse diretório, o redir seria assim:

exemplo da rede 10.10.10.10 netmask 255.255.255.0

#iptables -t nat -A PREROUTING -s 10.10.10.0/24 -p tcp --dport 80 -j DNAT --to ip_do_seu_servidor:80

isso fará com que todos que tentarem acessar a internet, tento seu servidor como gateway, sejam redirecionado para a pág em /var/www(ai dentro fica o index.html padrão do apache)

Agora apenas para um entendimento mais profundo.


no meu caso usei uma coisa legal pois existiam duas redes onde cada uma devia passar por uma pág de autenticação diferente, vamos lá

abri o arquivos ports.conf em /etc/apache2/

inseri uma linha baixo de Listen 80 com o conteúdo

Listen 8080

ficando assim:

Listen 80
Listen 8080


dentro de
/sites-enabled
/sites-available
criei um arquivo de com o nome da minha outra página(chamada business) de autenticação com o seguinte conteúdo:


<VirtualHost *:8080>
Servername business
DocumentRoot /var/www/business
</VirtualHost>

dentro de 000-default que onde faço a autenticação da minha primeira rede, fiz o seguinte substitui o /var/www/ por /var/www/portal e joquei tudo da pág ai dentro desse diretório /var/www/portal

depois criei o diretório dentro de /var/www/business e criei minha pág de autenticação da segunda rede lá dentro daí meu redir no iptables ficou assim:


iptables -t nat -A PREROUTING -s 10.10.10.0/24 -p tcp --dport 80 -j DNAT --to 10.10.10.1:80 --->aqui estão as páginas da primeira rede aparece bonitinho


iptables -t nat -A PREROUTING -s 20.20.20.0/24 -p tcp --dport 80 -j DNAT --to 20.20.20.1:8080 ----->aqui estão as páginas da segunda rede aparece bonitinho


isso rodando no mesmo servidor que gerencia 3 redes além do Link de internet

eth0 --internet
eth1 --ADM
eth2 --1ª rede
eth3 --2ª rede

E depois de muito suor e noites de sono, tudo funciona redondinho, na segunda rede desenrolei até um sistema de tarifação por minuto que ficou bem legal!!!!

Espero ter ajudadoi, qualquer coisa posta aí... tamo aqui se ajudar mesmo!

Abraços!

[6] Comentário enviado por red_hather em 28/09/2010 - 10:38h

Caro Maurício,

Você esqueceu um pequeno detalhe, especificar os créditos do sistema que foi desenvolvido pelo meu amigo Tiago Corcelli. E ainda publicou sem a autorização do mesmo. Espero que utilize o bom senso para corrigir o post.

Atenciosamente,

Tayrone Oliveira

[7] Comentário enviado por removido em 28/09/2010 - 10:46h

Sim é verdade, mas não fiz sem autorização dele, usei a idéia como base e ele sabe disso...

Ele sabe que desenrolo muita coisa com ele, a idéia inicial foi dele sim... eu otimizei todo sistema com auxilio dele, o sistema que ele criou é mais completo que isso, tafira certinho o meu não faz nada além segurar a conexão(to desenvolnvendo outro pra tarifar diferente, to testanto)rsrsr, resto foi aprendizado mesmo e algumas pesquisas aqui perguntas com vcs posts da galera, ele é meu brother! Cara...

Ah me desculpe se não mencionei o nome , apenas não lembrei dele!

Tiago Corcelli Obrigado mesmo, véio vc é pau. Me desculpe mais uma vez, não fiz por maldade!!

Abraços!!


[8] Comentário enviado por Alexandresousa20 em 02/10/2010 - 20:44h

Ola comecei a desenvolver um Captive Portal baseado em sua dica que aproposito esta de parabems valeu eu procurei isso por 3 anos e so agora consegui algo que realmente funciona de verdade

esto usando a seguin te regra para forçar o cliente a ver a pagina de login.
iptables -t nat -A PREROUTING -s 192.168.25.0/24 -p tcp --dport 80 -j DNAT --to 192.168.25.1:82

agora a minha duvida e a seguinte gostaria que o cliente fizece o uso do squid com proxy transparente

esto rodando a seguinte regra apos a autenticação

iptables -t nat -A PREROUTING -s 192.168.25.2 -m mac --mac-source 00:03:0d:77:47:b5 -p tcp --dport 80 -j REDIRECT --to-port 3128

so que não esta funcionando.

agora mais uma pergunta como eu poderia redirecionar para a pagina de autenticação apenas um determinaod ip e bloquear os demais?

[9] Comentário enviado por removido em 02/10/2010 - 22:01h

Cara, tenta fazer o uso do proxy transparente, mas sem usar o -m (nada que impessa seu uso teóricamente) mas eu nunca fiz dessa forma, dentro do captive portal, das vezes que fiz assim, rolava de boa mas nunca configuração simples antes de começar a usar o captive portal, ficaria algo tipo


#iptables -t nat -A PREROUTING -s 192.168.25.2 -p tcp --dport 80 -j REDIRECT --to-port 3128

Lembra de virificar tb, o squid.conf na real não me lembro, posso fazer um teste na segunda e te ajudar com certeza, ja usei da forma como queres e sei é possível.

Quanto a sua ultima pergunta, vai lá......

Pelo que entendí, queres que apenas determinados ip's, tenham acesso a internet após a autenticação, dica.... vc vai precisar parar e pensar um pouco, mas consegues com certeza.

Coloca os ips que queres liberar para passar pelo redicionamento da porta 80 ex.

#iptables -t nat -A PREROUTING -s 192.168.25.10 -p tcp --dport 80 -j DNAT --to 192.168.25.1:82

#iptables -t nat -A PREROUTING -s 192.168.25.11 -p tcp --dport 80 -j DNAT --to 192.168.25.1:82

Depois colocar toda a rede em DROP

assim
#iptables -A FORWARD -s 192.168.25.0/24 -j DROP

daí quando vc autenticar o cara que consegue passar pela página de autenticação essas regras mudarão apenas para os ips citados, que passam pela página de login, e os demais como não chegam nela, ficarão bloqueados e ainda se usar as config de proxy transparent, tem de "barrar" a entrada desses ips mesmo pela 3128 do squid... poderia ser

#iptables -A INPUT -s 192.168.25.0/24 -p tcp --dport 3128 -j DROP ficara toda a rede bloqueada, e vc inseri no srcipt de liberção mais um coisa pra que ele libere isso só que, claro com -I e não -A.. assim
#iptables -I INPUT -s 192.168.25.10 -j ACCEPT -> coloca essas que liberam pra carregar anteas das demais regras...... daí tudo com -I é add no início das tabelas e são respeitada pelas demais regras citadas com -A.

Espero ter ajudado

[10] Comentário enviado por Alexandresousa20 em 04/10/2010 - 10:46h

Consegui resolver este problema.
O que acontece era o seguinte
Quando eu executava a regra de redirecionamento
iptables -t nat -A PREROUTING -s 192.168.25.0/24 -p tcp --dport 80 -j DNAT --to 192.168.25.1:82
Estava usando a opção -A dai quando me falo sobre utilizar a opção -I eu fui ler alguns artigos sobre o firewall
http://focalinux.cipsga.org.br/guia/avancado/ch-fw-iptables.htm

Olha so o que descobri e seo Mudar a regre de redirecionemento do squid da opção -A para -I Funcionando

iptables -t nat -I PREROUTING -s 192.168.25.2 -p tcp --dport 80 -j REDIRECT --to-port 3128


Valeu muito obrigado pelas dicas

[11] Comentário enviado por danillorc em 09/10/2010 - 15:43h

NO MEU NUM DEU CERTO NÃO

eu to tentando fazer mas não deu certo, segui todo o procedimento, mas não deu certo,

se eu fizer somente conforme o amigo mauricio_savio com o apache sem nenhuma regra no iptables ou tirar as regras que existem:

# iptables -F
# iptables -F INPUT
# iptables -F OUTPUT

A pagina principal é captura, mas aí a internet não está compartilha e num funciona nada.
Se eu compartilhar a internet:

#iptables -F
#iptables -F INPUT
#iptables -F OUTPUT
#iptables -F POSTROUTING -t nat
#iptables -F PREROUTING -t nat
#echo 1 > /proc/sys/net/ipv4/ip_forward
#iptables -P FORWARD ACCEPT
#iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Fica com acesso a internet mas a pagina não é capturada.
Se eu acrestar a seguintes regras é tudo bloqueado e não é feito o redirecionamento.

#iptables -t nat -A PREROUTING -s 192.168.1.0/24 -p tcp --dport 80 -j DNAT --to 192.168.1.1:80

#iptables -A FORWARD -s 192.168.1.0/24 -j DROP

MAS EU CRIEI OUTRA FORMA DE FAZER A AUTENTICAÇÃO DOS CLIENTES:




[12] Comentário enviado por danillorc em 09/10/2010 - 16:15h

MAS EU CRIEI OUTRA FORMA DE FAZER A AUTENTICAÇÃO DOS CLIENTES:


Criei um arquivo "iptablesCli.sh" com o seguinte conteudo em php
---------------------------------------------------------------------------------------------------------
#!/usr/bin/php -q
<?
{
$iptables0 = shell_exec("iptables -F inform");
$iptables1 = shell_exec("iptables -N inform");
$iptables2 = shell_exec("iptables -A INPUT -j inform");
$iptables3 = shell_exec("iptables -A FORWARD -j inform");

$link = mysqli_connect("localhost", "root", "123456") or die ("Não foi possível conectar1");
mysqli_select_db($link,"dados") or die("Não foi possível selecionar o banco de dados2");

$select = "SELECT * FROM clientes order by codigo";
if ($select != "") {
$Query = mysqli_query($link, $select) or die (mysql_error($link));

$i = 0;
while ($row = mysqli_fetch_array($Query)) {
$i++;
echo $i.' - '.$row['nome']."\n";
$iptables2 = shell_exec('iptables -A inform -d '.$row['ip'].' -j REJECT ');
echo "$iptables2"."<br>";
}
}
}
?>
-------------------------------------------------------------------------------------------------------------------

Coloca em ordem de codigo todos os cliente de uma tabela "cliente" q tem os campos "nome","ip","mac" etc...
Criei a 'chain' inform

quando esse programa é rodado todos os cliente são bloqueados.


para autenticar um cliente eu crei um index.php

---------------------------------------------------------------------------------------------------
<?
if($_POST)
{

$login = $_POST['EditNome'];
$senha = $_POST['EditSenha'];

$link = mysqli_connect("localhost", "root", "dtggas") or die ("Não foi possível conectar1");
mysqli_select_db($link,"dados") or die("Não foi possível selecionar o banco de dados2");

$select = "SELECT * FROM clientes WHERE login='$login' AND senha='$senha' order by codigo";
if ($select != "") {
$Query = mysqli_query($link, $select) or die (mysql_error($link));

$i = 0;
while ($row = mysqli_fetch_array($Query)) {
$i++;

$iptables2 = shell_exec("sudo iptables -R inform ".$row['codigo']." -d ".$row['ip']." -j ACCEPT");
echo "$iptables2";

echo "sudo iptables -R inform ".$row['codigo']." -d ".$row['ip']." -j ACCEPT";
$Cliente = fopen("/var/www/portal/log.log","a");
fwrite($Cliente,$row['codigo']." - ".$row['nome']." - ".$row['ip']." - ".$row['mac']."\n");
fclose($Cliente);
echo"
<form class='style1' action='index.php' name='login' method='post' style='width:300px; height:400px; z-index:4'><br>
<input style='width:100px; height:20px;' class='style1' type='text' name='EdtCod' id='EdtCod'>
<input style='width:100px; height:20px;' class='style1' type='text' name='Edtnome' id='Edtnome'>
<input style='width:100px; height:20px;' class='style1' type='text' name='EdtIP' id='EdtIP'>
<input style='width:100px; height:20px;' class='style1' type='text' name='EdtMac' id='EdtMac'>
<script type='text/javascript'>
document.login.EdtCod.value = '".$row['codigo']."';
document.login.Edtnome.value = '".$row['nome']."';
document.login.EdtIP.value = '".$row['ip']."';
document.login.EdtMac.value = '".$row['mac']."';
</script>
";

}

}

}

?>

------------------------------------------------------------------------------------------

A pagina autentica pois pega a range da chain
com -R eu substituo uma regra de acordom com a posição em uma chain pelo codigo do cliente q foi colocado em ordem.
o problema é q o cliente tem q ter o codigo em ordem sem 1,2,3,4,5,6,....

para que o cliente não seja bloqueado pelo comando do iptables: "iptables -A inform -d IP -j REJECT"

eu coloquei uma acl no squid q dá permissão para acessar a intranet ou o ip 192.168.1.1

"acl intranet dst 192.168.1.1"
"http_access allow inrtanet"

mas mesmo assim ainda tem um problema pois se o cliente fizer as confirações de proxy essa regras passam batido.

mas ficou beleza.


pra completar eu criei um sistema em delphi que pega a pagina de autenticação utilizando o componete indy
e autentica, sem precisa que o apache capture a pagina de login e senha.

O programa tem, é configurado com para rodar com Serial do HD, Mac, IP e nome da maquina, nome do cliente etc...

fica mais dificil, pro cara hackear, pois os cara tem que clonar Mac, IP, Serial do HD, Nome da maquina e ainda ter a senha e o login do cliente.

O programa fica sendo como um discador. quando o programa é encerrado ele bloquea novamente o cliente.


Se quiserem trocar ideias fica meu email: danilloregis@hotmail.com

blz.

[13] Comentário enviado por removido em 13/10/2010 - 22:14h

Ah cara, gostei muito disso aí, ja estava mesmo pensando em como autenticar o cliente dessa forma e ainda não tive tempo de pensar em nada....

Entendi a idéia, ficou show de bola. Parabéns!

Quanto a não funcionar, manda-me um e-mail vou add vc aqui pra conversarmos, podemos nos ajudar com certeza!
O alexandresousa20 ta conseguindo de boa, ja fez até algumas melhorias e é ferinha como vc!

Abraços

[14] Comentário enviado por danillorc em 14/10/2010 - 20:31h

Na realidade eu fiz todo um sistema, há uns 3 anos atrás eu criei um sistema no linux feito em Lazarus, com base de dados firebird, que fazia um controle de cliente e financeiro, amarrava o mac ao ip, controlava os downloads por tipo de arquivo, bloqueio de determinados sites e etc.. no squid, cadastrava a banda pra cada cliente ou todos os clientes de uma só vez com CBQ Shaper usando CBQ+Cache Full (Squid) com marcação de pacote, cadastrava o cliente no DHCP3 pelo mac, tirava um extrato de cada cliente através do sarg, fazia monitoramento do cliente com tail e grep, mostrava quais os clientes conectados, fazia o monitoramento de consumo por pacote ou por Kb/Mb/Gb, pingava uma determinada faixa de ips, o sistema fazia isso e umas coisas a mais, mas aí eu tinha que acessar o servidor toda vez q iria cadastrar um cliente ou monitorar um. Depois eu criei o mesmo sistema no delphi, pegando a base de dados em rede, mas fiquei com dificuldade em fazer os dois sistemas se comunicarem, pq eu queria fazer isso atraves de socketes, mas não encontrei nenhum componente pro lazarus, fazia uma comunicação entre os dois a base de ganbiarra, mas num gostei não.
Depois eu fiz a mesma coisa com Apache, html, php, mysql, só q eu não gostei por causa de keyloogers na casa dos clientes quando eu ia dar manuntenção, aqui tem uns cara esperto. Foi aí que eu fiz outro sistema com delphi e php, e através do delphi com o componente indy, acesso as paginas em php, e faço o cadastro cadastro.

Mais ou menos assim:

Código pascal:

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
Valores,Retorno : TStringList;
begin

Valores := TStringList.Create;
Retorno := TStringList.Create;
Valores.Clear;
Valores.Add('EditNome=' + edtNome.text);
Valores.Add('EditSenha=' + edtSenha.text);
try
Retorno.Text := Idhttp1.Post('http://servidor/autenticacao/aut.php', Valores);
finally
Valores.Free;
Retorno.Free;
end;

end;

Dessa forma não preciso acessar a web para digitar senhas ou cadastrar os clientes.

Dá pra fazer em qualquer pagina de cadastro, hotspot e etc.

É bom pela segurança, por exemplo: pegando o Hotspot do Mikrotik, em vez de capiturar a pagina de login, basta redirecionar com outra pagina informando que está bloqueado para acesso até q seja efetuado o login, login q será feito através do programa em delphi.

Tem também umas ferramentas feito em fpc q faz alguns controles como adm, uso também como uma especie de cgi entre php e fpc.


Se alguém manjar de Delphi eu mando os fontes.

[15] Comentário enviado por celso_linuxer em 26/01/2015 - 00:54h


pessoal sou iniciante e nunca criei um banco no postgres poderiam me dar os comandos passo a passo. Obrigado

[16] Comentário enviado por marceloviana em 17/09/2015 - 20:56h


Maurício, como vai?

Como fez para resolver os acessos HTTPS no primeiro redirecionamento.
Por exemplo, se no primeiro acesso do usuário, ele digitar https://gmail.com, o redirecionamento acontece ou ocorre um erro de SSL?

Estou construindo um Captive Portal mas esbarrei neste problema.

[17] Comentário enviado por robertoduha em 11/04/2018 - 19:14h

Olá! Gente, este tópico ainda está ativo? Preciso urgente fazer esse portal funcionar. Alguém socorre por favor? ;-) Ocorre o seguinte erro quando envio o form de login: "ip-do-portal não consegue atender a esta solicitação no momento". Por curiosidade, troquei o submit apontando para um teste tipo phpinfo.... tambem dá mesmo erro. No entanto, apontando o mesmo phpinfo direto, funciona.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts