Captive Portal completo com o Squid no CentOS 7
Por Spawnzao em 17/01/2016 - 7,816 views
O captive portal para redes wireless são uma mão na roda, ainda mais em redes que utilizam autenticação ntlm ou outra autenticação via navegador. Entretanto, por mais que existam diversos captive portal disponíveis na internet, as vezes eles não se adequam perfeitamente as nossas necessidades, uns por se focarem em lan houses, outros por não serem compatíveis com nossa base de usuários (ex: ldap, mysql, sqlserver, …), outros por não terem um log completo de todos os acessos dos usuários, dentre outros problemas.
Então, utilizando o squid montei um captive portal, dividido em 3 partes.
No squid temos 2 scripts que fazem a verificação dos usuários autenticados e seus determinados ips, o primeiro script verifica se o ip da máquina está autenticado, caso não esteja, retorna HTTP Status Code 302 (redirecionamento) e a url do captive portal para o usuário se autenticar, caso o ip esteja autenticado ele prossegue a url desejada. No segundo script, verificamos novamente se o ip está autenticado, caso ele não esteja, retorna erro para o squid e a navegação é negada, caso ele esteja autenticado, ele busca no banco de dados o usuário e informa para o squid para que a sessão seja logada, impedindo que os acessos fiquem sem um usuário responsável. O squid está configurado em modo transparente, nas portas http (3128) e https (3129), entretanto no https estamos utilizando para tunelar todas as conexões, caso deseja abrir as conexões essa configuração deverá ser feita a parte. O firewall, captura todas as conexões de portas conhecidas e redireciona para o squid, as que utilizam texto plano, como por exemplo o telnet (porta 23), são redirecionadas para a porta 3128 e as conexões critografadas, como por exemplo o ssh (porta 22), são redirecionadas para a porta 3129. Com isso não saberemos qual a url acessada e qual o conteúdo, mas o ip e a porta para aquele determinado usuário estará salvo.
Para armazenar as sessões dos usuários autenticados utilizo o mysql, nele temos 3 tabelas, a primeira é a sessions, que armazena as sessões dos usuários autenticados, a segunda é a logs, que armazena tudo que acontece no captive portal e por último a tabela disallow, que armazena os usuários bloqueados, que não conseguirão fazer a autenticação no portal, tem como objetivo bloquear usuários coringas, convidados, usuários que violaram os termos de uso, dentre outros.
E por último o portal web que realiza a autenticação dos usuários, desenvolvido em PHP e subdividido em 2 partes, a primeira que realiza a verificação do nome e senha do usuário na base de dados LDAP e a segunda que realiza o gerenciamento das sessões, logs e usuários bloqueados utilizando o banco de dados mysql.
Deixar um pouco de conversa e colocar a mão na massa.
Depois de instalar o CentOS 7, vamos atualizá-lo.
yum update
Vamos desativar alguns serviços desnecessários.
systemctl disable firewalld systemctl disable NetworkManager
Desabilitar o Selinux.
sed -i -e 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
Vamos iniciar e habilitar o serviço de data e hora.
systemctl start ntpdate.service systemctl enable ntpdate.service
Vamos desativar o Ipv6 do servidor:
cd /etc/sysctl.d/ wget https://raw.githubusercontent.com/spawnzao/captiveportal/master/disable-ipv6.conf
Agora vamos reiniciar o servidor:
reboot
Vamos instalar todos os pacotes necessários:
yum install squid mariadb mariadb-server php httpd php-ldap php-mysql bind-chroot git svn
Vamos configurar o Squid:
/usr/lib64/squid/ssl_crtd -c -s /var/lib/ssl_db mv /etc/squid/squid.conf /etc/squid/squid.conf.orig cd /etc/squid/ wget https://raw.githubusercontent.com/spawnzao/captiveportal/master/squid.conf
Copiar os scripts do squid:
wget https://raw.githubusercontent.com/spawnzao/captiveportal/master/captiveportal.php wget https://raw.githubusercontent.com/spawnzao/captiveportal/master/url_redirect.php wget https://raw.githubusercontent.com/spawnzao/captiveportal/master/ip_auth.php
Vamos setar as permissões nos scripts:
chmod +x url_redirect.php chown squid:squid url_redirect.php chmod +x ip_auth.php chown squid:squid ip_auth.php
Vamos gerar um certificado para o Squid.
mkdir ssl_cert chown -R squid.squid /etc/squid/ssl_cert cd /etc/squid/ssl_cert openssl req -new -newkey rsa:1024 -days 1365 -nodes -x509 -keyout myca.pem -out myca.pem
Gerar a chave para utilizar nas estações Windows (caso deseja interceptar o trafego https):
openssl x509 -in myca.pem -outform DER -out myca.der
Vamos iniciar e habilitar o MariaDB (mysql):
systemctl start mariadb.service systemctl enable mariadb.service
Vamos realizar uma preparação segura do Banco de Dados MariaDB (mysql):
mysql_secure_installation
Vamos copiar a estrutura do database do captive portal:
cd /root wget https://raw.githubusercontent.com/spawnzao/captiveportal/master/captiveportal.sql
Vamos importar o SQL:
mysql -u root -p < captiveportal.sql
Adicionar o usuário captiveportal com a senha captiveportal para ter acesso completo ao database captiveportal, assim não precisamos utilizar o usuário root em nossas configurações de mysql.
mysql -u root -p GRANT ALL ON captiveportal.* TO captiveportal@localhost IDENTIFIED BY 'captiveportal'; flush privileges;
Vamos configurar o HTTPD (apache):
sed -i -e 's/Listen\ 80/Listen 81/g' /etc/httpd/conf/httpd.conf sed -i -e 's/#ServerName\ www.example.com:80/ServerName captiveportal.seweb.corp:81/g' /etc/httpd/conf/httpd.conf
Vamos configurar o timezone do PHP:
sed -i -e 's@;date.timezone\ =@date.timezone = America/Sao_Paulo@g' /etc/php.ini
Vamos baixar o Captive Portal web:
cd /var/www svn export --force https://github.com/spawnzao/captiveportal/trunk/http html/
Agora vamos configurar o Captive Portal Web:
cd html/ vim class.php
Vamos iniciar e habilitar o HTTPD (apache):
systemctl start httpd.service systemctl enable httpd.service
Vamos copiar o firewall, setar as permissões e executar o firewall:
cd /etc wget https://raw.githubusercontent.com/spawnzao/captiveportal/master/firewall chmod +x /etc/firewall /etc/firewall
Vamos editar o rc.local e adicionar o path do nosso firewall, assim nosso firewall será iniciado automaticamente quando reiniciarmos.
vim /etc/rc.local
/etc/firewall
Agora vamos habilitar o rc.local que por default no CentOS vem desabilitado:
chmod +x /etc/rc.d/rc.local
Vamos iniciar e habilitar o Squid:
systemctl start squid.service systemctl enable squid.service
Vamos agora configurar o Named (BIND), que será responsável por resolver os ips (Caso não queira configurar o DNS Server, só liberar o tráfego de DNS pelo firewall):
cd /etc mv named.conf named.conf.orig wget https://raw.githubusercontent.com/spawnzao/captiveportal/master/named.conf
Vamos iniciar e habilitar o Named:
systemctl start named.service systemctl enable named.service
Bom, agora é testar o Captive Portal.
Por favor, digam o que acharam da solução e em caso de dúvida postem um comentário.
May 22nd, 2016 on 19:53
Ola Amigo, muito bom, parabens!!Tentei colocar o squidguard junto mais nao consegui, quando coloco a linha para habilitar o squidguard no squid, ele simplesmente nao vai mais para o captive portal. Tem alguma ideia?
October 7th, 2016 on 16:03
Olá amigo, você teria como configurar a autenticação por mysql? estou com um cliente que não tem ldap
October 19th, 2016 on 11:44
antes de tudo desculpe minha pergunta, tinha que descobrir sozinho, na configuracao do class.php nao fiz nenhuma alteracao, neste caso a entrada no index.php do captive seria qual usuario e senha, pois nao consegui entrar
November 16th, 2016 on 12:28
Fabiano, o captive portal e o squidguard acabam tendo funções semelhantes dentro do squid e os mesmos não conseguem funcionar ao mesmo tempo. Tenho trabalhado em uma maneira de chamar o squidguard pelo script, entretanto a performance tem sido comprometida. Vou tentar algo compilado pra tentar melhorar a performance.
November 16th, 2016 on 12:35
Valdenir, para isso teria que alterar a página class.php e criar no mysql uma tabela de usuários. Posso te auxiliar nessa empreitada, você teria que construir uma função $this->loginMYSQL() semelhante a função $this->loginLDAP() que verifica o login e senha, depois alterar a chamada da mesma dentro da function login(). Não tenho prazos agora, mas eu vou lançar uma nova versão com a parte de mysql implementada.
November 16th, 2016 on 13:34
tb fiz isso coloquei no script, bom pra mim esta ate legal, tenho em torno de 140 acessos simultaneos
November 16th, 2016 on 13:54
Emerson, por default o captive portal está configurado para funcionar via LDAP, mas para isso é necessário configurar alguns parâmetros dentro do class.php, como por exemplo as variáveis: public $server = ‘ldaps://ad.seweb.corp’; public $users = ‘OU=Users,DC=seweb,DC=corp’; public $user_default = ‘administrator’; public $pass_default = ‘P@ssw0rd’; e a linha 113: $this->usermail = $this->user.’@seweb.corp‘. Com esses parâmetros configurados o captive portal estaria pronto para buscar os usuários e senhas do seu servidor LDAP.
November 16th, 2016 on 14:01
Fabiano, se vc quiser compartilhar como vc fez o script, posso adicionar aqui no site. No meu trampo utilizo o captive portal para a rede Wifi e temos uma média de 350 a 400 acessos simultâneos, e acabou que a performance não ficou muito boa. Eu monitorei o script no Linux e ele ficou meuito sobrecarregado, e com um programa compilado tenho a opção de utilizar Thread, o que melhoraria a performance.
December 5th, 2016 on 17:53
Olá, gostaria de estar te parabenizando pelo ótimo tutorial e lhe pedir auxílio quanto à modificar o class.php para pegar os usuários pela base mysql e não ldap. Não entendo muito sobre programação.
December 8th, 2016 on 10:24
Bom dia,
esse concerteza é um ótimo tutorial, mas gostaria de modificar o class.php para pegar usuarios tambem por mysql e nao ldap, poderia me ajudar com a modificação do script ?
December 13th, 2016 on 16:58
Olá, gostaria de parabenizar pelo tutorial e pedir ajuda com o class.php. Preciso fazer a autenticação pegando usuários no mysql e não no ldap. Poderia me ajudar com a modificação ?
February 10th, 2017 on 13:53
É possível usar esse solução para fazer autenticação usando as redes sociais ? tipo facebook, google+ e twitter.
December 8th, 2017 on 14:15
Hello Sir,
Good One Tutorial, but I am facing problem connecting with ldap, please also mail me the ldap configuration so i will successfully use this portal
Thanks in advance
December 12th, 2017 on 04:24
Tutorial was very good but I am stuck at LDAP bind and authentication will please also guide me for LDAP configuration on CENTOS 7.
August 7th, 2018 on 09:51
Quase resolvendo a autenticação MYSQL.
Se quiserem ajudar (ate onde consegui) :
CLASS.PHP
function connLDAP(){
$this->conn = mysql_connect($this->host_mysql,$this->user_mysql,$this->pass_mysql,$this->database_mysql);
mysql_select_db($this->database_mysql);
if(!$this->conn) {
echo “Erro (connect) MySQL: “.mysql_error();
} elseif (!mysql_select_db($this->database_mysql,$this->conn)) {
echo “Erro (select_db) MySQL: “.mysql_error();
}
}
function loginLDAP(){
$this->connLDAP();
$query = “SELECT login,senha FROM users where login = ‘”.$this->user.”‘”;
$link = mysqli_connect(“127.0.0.1”, “user_bd”, “password_bd”, “captiveportal”);
$result = mysqli_query($link, $query);
$row = mysqli_fetch_array($result);
$this->login = $row[0];
$this->senha = $row[1];
}
August 7th, 2018 on 10:02
Cheguei ate aqui no MYSQL :
Se quiserem
function connLDAP(){
$this->conn = mysql_connect($this->host_mysql,$this->user_mysql,$this->pass_mysql,$this->database_mysql);
mysql_select_db($this->database_mysql);
if(!$this->conn) {
echo “Erro (connect) MySQL: “.mysql_error();
} elseif (!mysql_select_db($this->database_mysql,$this->conn)) {
echo “Erro (select_db) MySQL: “.mysql_error();
}
}
function loginLDAP(){
$this->connLDAP();
$query = “SELECT login,senha FROM users where login = ‘”.$this->user.”‘”;
$link = mysqli_connect(“127.0.0.1”, “usuario_db”, “senha_db”, “captiveportal”);
$result = mysqli_query($link, $query);
$row = mysqli_fetch_array($result);
$this->login = $row[0];
$this->senha = $row[1];
}