Tutorial - SquidGuard + LdapGroup (permissão por grupo no ad)
-
Pessoal,
O ccesario começou a alterar um script que extrai os usuarios de um grupo específico para aplica nas acls do squidguard.
Peguei com ele hoje e consegui integrar o script no pfsense.
squidguard_ldap.php (v1 March 14, 2012)
// based on http://samjlevy.com/2011/02/using-php-and-ldap-to-list-of-members-of-an-active-directory-group/ // pfsense integration by marcelloc and ccesario # AD HOST (required) $ldap_host = "192.168.3.1"; # AD DIRECTORY DN(required) $ldap_dn = "DC=domain,DC=local"; # BIND USER(required) $user_bind = "cn=squidguard,cn=Users,DC=domain,DC=local"; # PASSWORD BIND(required) $password = "super_secret_password"; #if you need to apply any prefix or sufix to retreived user #example: prefix user with domain(required) #$user_mask="DOMAIN\USER"; $user_mask="USER"; #################### # End of user options # #################### require_once("/etc/inc/util.inc"); require_once("/etc/inc/functions.inc"); require_once("/etc/inc/pkg-utils.inc"); require_once("/etc/inc/globals.inc"); #mount filesystem writable conf_mount_rw(); function explode_dn($dn, $with_attributes=0) { $result = ldap_explode_dn($dn, $with_attributes); foreach($result as $key => $value) { $result[$key] = $value; } return $result; } function get_ldap_members($group,$user,$password) { global $ldap_host; global $ldap_dn; $LDAPFieldsToFind = array("member"); $ldap = ldap_connect($ldap_host) or die("Could not connect to LDAP"); // OPTIONS TO AD ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION,3); ldap_set_option($ldap, LDAP_OPT_REFERRALS,0); ldap_bind($ldap, $user, $password) or die("Could not bind to LDAP"); $results = ldap_search($ldap,$ldap_dn,"cn=" . $group,$LDAPFieldsToFind); $member_list = ldap_get_entries($ldap, $results); $group_member_details = array(); foreach($member_list[0] as $list) if (is_array($list)) foreach($list as $member) { $member_dn = explode_dn($member); $member_cn = str_replace("CN=","",$member_dn[0]); $member_search = ldap_search($ldap, $ldap_dn, "(CN=" . $member_cn . ")"); $member_details = ldap_get_entries($ldap, $member_search); $group_member_details[] = array($member_details[0]['samaccountname'][0]); } ldap_close($ldap); array_shift($group_member_details); return $group_member_details; } // Read Pfsense config global $config,$g; $id=0; $apply_config=0; if (is_array ($config['installedpackages']['squidguardacl']['config'])) foreach($config['installedpackages']['squidguardacl']['config'] as $group) { $members=""; echo "Group : " . $group['name']."\n"; $result = get_ldap_members($group['name'],$user_bind,$password); foreach($result as $key => $value) { if (preg_match ("/\w+/",$value[0])) $members .= "'".preg_replace("/USER/",$value[0],$user_mask)."' "; } if (!empty($members)) if($config['installedpackages']['squidguardacl']['config'][$id]['source'] != $members){ $config['installedpackages']['squidguardacl']['config'][$id]['source'] = $members; $apply_config++; } $id++; } if ($apply_config > 0){ print "user list from LDAP is different from current group, applying new configuration..."; write_config(); include("/usr/local/pkg/squidguard.inc"); squidguard_resync(); print "done\n"; } #mount filesystem read-only conf_mount_ro(); ?>
squidguard_ldap.php (v1.1 Sep 9, 2013)
// based on http://samjlevy.com/2011/02/using-php-and-ldap-to-list-of-members-of-an-active-directory-group/ // pfsense integration by marcelloc and ccesario // ldapsearch -x -h 192.168.11.1 -p 389 -b OU=Internet,DC=domain,DC=local -D CN=Proxyauth,OU=PROXY,DC=domain,DC=local -w PASS # AD HOST (required) $ldap_host = "192.168.1.1"; # AD DIRECTORY DN(required) $ldap_dn = "OU=INTERNET,DC=domain,DC=local"; # BIND USER(required) $user_bind = "CN=Proxyauth,OU=PROXY,DC=domain,DC=com"; # PASSWORD BIND(required) $password = "passwd"; #if you need to apply any prefix or sufix to retreived user #example: prefix user with domain(required) #$user_mask="DOMAIN\USER"; $user_mask="USER"; ####################### # End of user options # ####################### require_once("/etc/inc/util.inc"); require_once("/etc/inc/functions.inc"); require_once("/etc/inc/pkg-utils.inc"); require_once("/etc/inc/globals.inc"); #mount filesystem writable conf_mount_rw(); function explode_dn($dn, $with_attributes=0) { $result = ldap_explode_dn($dn, $with_attributes); if (is_array($result)) { foreach($result as $key => $value) { $result[$key] = $value; } } return $result; } function get_ldap_members($group,$user,$password) { global $ldap_host; global $ldap_dn; $LDAPFieldsToFind = array("member"); $ldap = ldap_connect($ldap_host) or die("Could not connect to LDAP"); // OPTIONS TO AD ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION,3); ldap_set_option($ldap, LDAP_OPT_REFERRALS,0); ldap_bind($ldap, $user, $password) or die("Could not bind to LDAP"); $results = ldap_search($ldap,$ldap_dn,"cn=" . $group,$LDAPFieldsToFind); $member_list = ldap_get_entries($ldap, $results); $group_member_details = array(); if (is_array($member_list[0])) foreach($member_list[0] as $list) if (is_array($list)) foreach($list as $member) { $ldap_dn_user = preg_replace('/^cn=([^,]+),/i','',$member); $member_dn = explode_dn($member); if (!empty($member_dn[0])) { $member_cn = str_replace("CN=","",$member_dn[0]); $member_search = ldap_search($ldap, $ldap_dn_user, "(CN=" . $member_cn . ")"); $member_details = ldap_get_entries($ldap, $member_search); // If group have a other group as member (only 1 level) if(is_array($member_details[0]['member'])) { //print "############\nmembers\n###########\n"; //var_dump ($member_details[0]['member']); foreach($member_details[0]['member'] as $sub_member) { $sub_ldap_dn_user = preg_replace('/^cn=([^,]+),/i','',$sub_member); $sub_member_dn = explode_dn($sub_member); if (!empty($sub_member_dn[0])) { $sub_member_cn = str_replace("CN=","",$sub_member_dn[0]); $sub_member_search = ldap_search($ldap, $sub_ldap_dn_user, "(CN=" . $sub_member_cn . ")"); $sub_member_details = ldap_get_entries($ldap, $sub_member_search); $group_member_details[] = array($sub_member_details[0]['samaccountname'][0]); } } //echo "#########################################\nsub_group\n"; //var_dump($group_member_details); //echo "#########################################\n"; } else $group_member_details[] = array($member_details[0]['samaccountname'][0]); } } ldap_close($ldap); return $group_member_details; } //Log info log_error("Running squidGuard LDAP sync"); // Read Pfsense config global $config,$g; $id=0; $apply_config=0; if (is_array($config['installedpackages']['squidguardacl']['config'])) { foreach($config['installedpackages']['squidguardacl']['config'] as $group) { $members=""; echo "Group : " . $group['name']."\n"; $result = get_ldap_members($group['name'],$user_bind,$password); asort($result); foreach($result as $key => $value) { if (preg_match ("/\w+/",$value[0])) $members .= "'".preg_replace("/USER/",strtolower($value[0]),$user_mask)."' "; } if (!empty($members)) { if($config['installedpackages']['squidguardacl']['config'][$id]['source'] != $members){ $config['installedpackages']['squidguardacl']['config'][$id]['source'] = $members; $apply_config++; } } echo "\t --> Members : " . $members . "\n\n"; $id++; } } if ($apply_config > 0) { log_error("squidGuard LDAP sync: user list from LDAP is different from current group, applying new configuration..."); print "user list from LDAP is different from current group, applying new configuration..."; write_config(); include("/usr/local/pkg/squidguard.inc"); squidguard_resync(); print "done\n"; } #mount filesystem read-only conf_mount_ro(); ?>
Para executar o script no squiguard:
-
Copie/crie o arquivo par ao seu pfsense
-
Edite os parametros do inicio do script
-
Altere o nome dos grupos do squidguard para o mesmo nome do grupo no ad
-
execute o script via console
O procedimento no squidguard é manual/via cron para não 'atrapalhar' o timeline de um pacote suportado pelo core team(eu acho).
Claro que para o dansguardian, o script já estará integrado na interface gráfica e com suporte a multiplos servidores LDAP. ;)
att,
Marcello Coutinho -
-
Obrigado pela ajuda Marcello.
Pessoal, quem testar, por favor comente aqui :)
[]s
Carlos
-
Você conseguiu testar?
Acho que da forma que o script ficou é até mais econômico na questão de consumo de recursos já que ele não vai no ad a cada acesso para verificar o grupo.
-
Você conseguiu testar?
Acho que da forma que o script ficou é até mais econômico na questão de consumo de recursos já que ele não vai no ad a cada acesso para verificar o grupo.
Olá Marcello!
Testado e aprovado.
Coloquei no cron a cada 1 minuto.
Ficou ótimo!
Obrigado pela ajuda!
-
Publiquei o script na minha conta do github para faciliar a configuração
https://github.com/downloads/marcelloc/pfsense-packages/squidguard_ldap.php
att,
Marcello Coutinho -
pegando o bonde andando…. eu fiz um script um tempo atras exatamente para suprir a necessidade de um cliente com isso, fazer acl por grupo, segue então como fiz:
Aplicar o patch no pfsense (com o pacote já instalado), com o comando abaixo:
fetch -q -o /tmp/ http://www.mundounix.com.br/~gugabsd/squidguard-ldap-search.patch && cd /usr/local/pkg && patch -p0 < /tmp/squidguard-ldap-search.patch
Execute em Diagnostics > command prompt
Vai aparecer uma opção nova na configuração do squidguard, conforme a figura abaixo:
Configure o seu Ldap DN e senha (igual ao do squid)
E crie uma acl baseada na da figura abaixo:
No exemplo acima, o grupo é o CN=ti (é tudo uma linha só, sem quebra)
Qualquer dúvida, da um grito ai.
Abraços
-
Excelente patch Luiz Gustavo! :)
Depois de aplicado, o squidguard vai buscar no ad o grupo do usuário a cada acesso ou a lista é extraída e aplicada nos arquivos?
De qualquer forma, lista de acesso por grupo já está 100% compatível com squidguard e dansguardian, basta escolher.
OFF topic:
Você tem alguma carta na manga para autenticar/logar o usuário do captive portal no squid/squidguard/dansguardian?O pfsense esta ficando monstruosamente poderoso ::)
-
Depois de aplicado, o squidguard vai buscar no ad o grupo do usuário a cada acesso ou a lista é extraída e aplicada nos arquivos?
OFF topic:
Você tem alguma carta na manga para autenticar/logar o usuário do captive portal no squid/squidguard/dansguardian?Depois de aplicado, ele busca na consulta, da forma original documentada no squidguard (http://www.squidguard.org/Doc/authentication.html)
o src fica sendo uma consulta ldap, na verdade, pode ser qualquer tipo de consulta, não só de grupo.
No exemplo que dei é exatamente pra ver se o cara bate no grupo especificado.
Você tem alguma carta na manga para autenticar/logar o usuário do captive portal no squid/squidguard/dansguardian?
Não entendi ? usando que base ? é fazer ficar transparente ? tipo o usuário do captive portal já estar logado no squid?
-
Não entendi ? usando que base ? é fazer ficar transparente ? tipo o usuário do captive portal já estar logado no squid?
Aproveitar a autenticação ja feita no captive portal, logando o usuário no squid sem precisar abrir outra tela de usuário e senha.
Uma mistura de auth_ident com consulta a base de usuários ativos do captive portal.
-
Luiz Gustavo!!!
Ótima notícia!!!!Muito interessante :)
Qual a possibilidade disso ser incorporado ao pacote oficial!?
Obrigado
att,
-
Qual a possibilidade disso ser incorporado ao pacote oficial!?
Não sei, depende do mantenedor, eu fiz o patch para atender uma necessidade localizada de cliente.
Eu vou postar na lista gringa e vamos ver o que o mantenedor acha.
Apesar que seria legal mexer nesse patch para filtrar melhor o campo do search do ldap.
-
Boa noite, Gustavo! Como vai?
Como você explicou, eu estou aplicando o seu script, mas não está aparecendo nenhuma opção do LDAP. O que você acha que pode ser fera?
Fique com Deus! Bom final de semana!
-
Foi mal pessoal, consegui resolver aqui. Apareceu a opção do LDAP, mas eu estacionei aqui. Help!?
Alguém poderia me ajudar, por favor?
Obrigado!
-
Foi mal pessoal, consegui resolver aqui. Apareceu a opção do LDAP, mas eu estacionei aqui. Help!?
Alguém poderia me ajudar, por favor?
Obrigado!
Como esta o seu cenário ? já tem o squid autenticando via ldap (no AD) e funcionando ?
A ideia do patch é ter uma opção de filtragem no squidguard baseada em consulta ldap, no caso da configuração no squidguard, é colocar uma entrada de usuário com permissão para listar a arvore do ldap e criar uma acl baseada em uma busca via ldap, conforme a documentação do proprio squidguard [1].
[1] http://www.squidguard.org/Doc/authentication.html (veja item 2 da documentação)
-
Obrigado pela ajuda Luis Gustavo!
A base eu entendi. A minha dúvida é, eu tenho que replicar os meus grupos do AD manualmente no Squidguard?
Ex: Tenho um grupo no AD chamado: Programação | Tenho que ir no Group ACL do Squidquard e criá-lo também?
Bom final de semana! E obrigado pela atenção!
-
A base eu entendi. A minha dúvida é, eu tenho que replicar os meus grupos do AD manualmente no Squidguard?
Ex: Tenho um grupo no AD chamado: Programação | Tenho que ir no Group ACL do Squidquard e criá-lo também?
Não, basta criar uma entrada conforme o print que mandei anteriormente apontando para o seu grupo no AD que ele vai verificar se o usuário logado pelo o squid esta no grupo ou não para validar a ACL que você esta criando.
Entendeu, a ideia é filtrar (ACL) por grupo do AD (ldap), dessa forma você consegue por exemplo, criar um bloqueio de sites para o grupo XYZ no AD, assim, basta no windows você selecionar quem faz parte ou não do grupo.
É usar a imaginação.
E isso não se limita a grupo, pode ser uma arvore do AD diferente, uma outra abordagem de DN, etc….. é uma busca ldap, o exemplo que citei é para grupos, mas pode ser qualquer coisa.
Abraços
-
Replico o que eu disse na lista pfsense-pt:
Show,
Mas adianto que o patch ainda é muito cru, eu fiz para consolidar uma
necessidade de um cliente, mas de qualquer forma, do jeito que esta, ele
é funcional e não só para fazer consulta a grupo do AD e sim para
qualquer tipo de busca via ldap.Assim que puder, eu vou mexer um pouco mais no patch, para filtrar
melhor aquela string do ldapsearch e fazer uma abordagem melhor na
entrada de dados.Abraços
-
Você alterou a regra do campo onde fica a string do ldap?
Quanto estava testando o outro patch ele me pareceu bem restritivo.
Este patch foi feito em cima da última versão do pacote?
att,
Marcello Coutinho -
Obrigado irmão!
Estarei fazendo os testes e postando os resultados, assim que possível.
Fique na santa paz, Luis Gustavo!
-
Você alterou a regra do campo onde fica a string do ldap?
Quanto estava testando o outro patch ele me pareceu bem restritivo.
Este patch foi feito em cima da última versão do pacote?
Sim, claro ! senão não funciona….
olha o código que você vai ver a serie de "ifs" que coloquei para tratar a entrada da string do ldap (é nessa parte que eu digo que tenho que melhorar, até para evitar strings gigantes e pensar em poder colocar mais de uma string de busca na acl)
E sim, esta para a ultima versão, se não o patch falha ;)
abraços