You are on page 1of 18

Introduo

Todos que trabalham com redes mistas, Windows e GNU/Linux, sabem que sempre h problemas com
interoperabilidade entre elas no que diz respeito base de usurios OpenLDAP, LDAP AD, Active Directory etc, j
que algumas solues trabalham com autenticao padro, que pode ser tanto o LDAP do AD quanto OpenLDAP,
enquanto outras so mais especficas.
Especificamente, abordarei um cenrio contendo Active Directory e OpenLDAP.
Veremos como fazer a sincronizao das bases para que, quando criarmos um usurio ou grupo, este ser criado
tanto na base OpenLDAP quanto na base Active Directory, tambm, posteriores alteraes como mudana de
grupos, nomes, descrio devem ser sincronizadas entre as bases deixando-as consistentes.
Estudo de caso
Este o cenrio apresentado:
Um servidor Active Directory Windows 2008 Server (AD01);
Um servidor OpenLDAP (LX01).
O servidor Active Directory (AD01) pode fazer todos os servios para a rede Microsoft funcionar com domnio, DNS,
PDC etc, ou seja, uma rede Microsoft normal que muito implementada.
Teremos o servidor OpenLDAP que pode ser utilizado para qualquer aplicao que suporte consultas LDAP, tendo,
como exemplo, a mais comum delas: um proxy Squid.
Na prtica, com a sincronizao de bases, quando criarmos o usurio "evandro.nabor" na base OpenLDAP, o
usurio ser replicado para o AD01. Existe uma considerao a ser feita a respeito das senhas, pois no possvel
ler a senha digitada pelo usurio no OpenLDAP e escrev-la no Active Directory, mas este assunto ser abordado
mais a frente.
Sendo assim, aps o cenrio implementado, teremos a criao de um nico usurio com a mesma senha, tanto
para domnio quanto para outras aplicaes, como o j citado proxy.
Soluo
Tratarei a sincronizao neste sentido: OpenLDAP Active Directory
Portanto, os usurios a partir de agora, devero ser criados na base OpenLDAP para serem sincronizados para o
AD01.
O software para isso o LSC, que faz vrios tipos de sincronizao entre bases LDAP e outras.
Basicamente, ele ser encarregado de testar todos os atributos configurados e efetuar a sincronizao.
Dados do cenrio:
LX01: OpenLDAP e LSC - Debian Squeeze - 172.31.1.28
AD01: Active Directory - Windows 2008 Server - 172.31.1.99
Instalao e configurao
No abordarei a instalao do Active Directory e nem do OpenLDAP, pois existem centenas de artigos a respeito na
internet.
AD01
Crie um usurio com privilgio administrador chamado LSC no Active Directory, o programa ir us-lo para as
importaes.
Instalar o servio de Active Directory Certificate Services e exportar uma chave para utilizarmos no GNU/Linux:
Configuring an SSL Certificate for Microsoft Active Directory confluence.atlassian.com
Object 1
LX01
Java:
# cd /usr/src
# wget http://javadl.sun.com/webapps/download/AutoDL?BundleId=73850 -O java.tar.gz -O java.tar.gz
# tar zxvf java.tar.gz
# mv jre1.7.0_13 /usr/local/java
# export JAVA_HOME=/usr/local/java && echo "export JAVA_HOME=/usr/local/java" >> ~/.bashrc
Certificado:
# $JAVA_HOME/bin/keytool -import -keystore $JAVA_HOME/lib/security/cacerts -file ChaveDoWin2008.crt
Obs.: Quando for solicitada, a senha padro : changeit
LSC
# cd /usr/src
# wget http://tools.lsc-project.org/attachments/download/317/lsc-core-1.2.2-dist.tar.gz
# tar zxvf lsc-core-1.2.2-dist.tar.gz
# mv lsc-1.2.2/ /usr/local/lsc && cd /usr/local/lsc
O arquivo de configurao do LSC o etc/lsc.properties.
Este um exemplo que montei para fazer a sincronia do nosso cenrio. Voc dever modific-lo conforme suas
necessidades. Todas as documentaes so encontradas na pgina do LSC, mas de qualquer maneira, este arquivo
foi extremamente comentado por min:
#/usr/local/lsc/etc/lsc.properties
# Evandro Nabor
##############
### Origem ###
##############
# base OpenLDAP
src.java.naming.security.principal=cn=Manager,dc=texas,dc=local
src.java.naming.security.credentials=3v4ndrO
src.java.naming.security.authentication=simple
src.java.naming.referral=ignore
src.java.naming.provider.url=ldap://172.31.1.28/dc=texas,dc=local
src.java.naming.ldap.version=3
src.java.naming.ldap.derefAliases=never
src.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
###################
### Destino ###
###################
# base ActiveDirectory
# repare que utilizo SSL com exportacao do certificado do AD e importacao pro java do linux
dst.java.naming.security.principal=CN=LSC,CN=Users,DC=texas,DC=local
dst.java.naming.security.credentials=3v4ndrO
dst.java.naming.security.authentication=simple
dst.java.naming.referral=ignore
dst.java.naming.provider.url=ldaps://172.31.1.99/DC=texas,DC=local
dst.java.naming.ldap.version=3
dst.java.naming.ldap.derefAliases=never
dst.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
dst.java.naming.ldap.pageSize = 1000
#dst.java.naming.tls = true
###############
### Tarefas ###
###############
#definindo tarefa para sincronia de usuarios
lsc.tasks=user
#definindo tarefa para sincronia de grupos
lsc.tasks=group
### User ###
#opcoes de permissao para update, deletar e criar em ambas as bases
lsc.tasks.user.condition.create = 1
lsc.tasks.user.condition.update = 1
lsc.tasks.user.condition.delete = 1
lsc.tasks.user.condition.modrdn = 1
#esta opcao serve pra decidir como sera criado o usuario no activedirectory. ex.
cn=evandro.nabor,cn=users,dc=texas,dc=local
lsc.tasks.user.bean=org.lsc.beans.SimpleBean
lsc.tasks.user.dn = "CN=" + srcBean.getAttributeValueById("uid") + ",CN=Users"
# Source
#opcoes de selecao dos usurios no ldap, perceba os filtros para que o programa funciona dos dois lados,
tanto quando cria um usuario e ele eh replicado pra o
#AD quanto pra quando deleta um usuario ele compara as duas bases e deleta o usuario no AD
lsc.tasks.user.srcService=org.lsc.jndi.SimpleJndiSrcService
lsc.tasks.user.srcService.filterAll=(&(objectClass=inetOrgPerson)(uid=*)(!(givenName=MailList)))
lsc.tasks.user.srcService.filterId = (&(objectClass=inetOrgPerson)(|(uid={uid})(uid={sAMAccountName})))
lsc.tasks.user.srcService.baseDn=ou=pessoas
# campos que serao replicados, eh importante colocar todos que serao replicados e mais tarde nas opcoes de
sincronia definir como sera a sincronia
lsc.tasks.user.srcService.attrs= uid sambaLogonScript homeDirectory postalCode postOfficeBox
# campo de volta, eh a pesquisa reversa que ele faz para que quando seja deletado algum usuario do
OpenLDAP ele seja tambem deletado do AD
lsc.tasks.user.srcService.pivotAttrs = uid
# Destination
# opcoes para selecao de usuarios no AD repare que filtro algumas contas padrao do windows para q elas
nunca sofrao alteracoes e nao tenha problema
lsc.tasks.user.dstService=org.lsc.jndi.SimpleJndiDstService
lsc.tasks.user.dstService.baseDn=cn=Users
# idem source
lsc.tasks.user.dstService.attrs = sAMAccountName userAccountControl objectClass userPrincipalName
pwdLastSet scriptPath homeDirectory displayName givenName unicodePwd
lsc.tasks.user.dstService.filterAll=(&(sAMAccountName=*)(objectClass=user)(!
(sAMAccountName=Administrator))(!(sAMAccountName=Guest))(!(sAMAccountName=krbtgt))(!
(sAMAccountName=LSC)))
lsc.tasks.user.dstService.filterId = (&(objectClass=user)(sAMAccountName={uid}))
# idem source
lsc.tasks.user.dstService.pivotAttrs = sAMAccountName
### Group ###
# tarefa para sincronizar grupos
#regras de update, criar e deletar
lsc.tasks.group.condition.create = 1
lsc.tasks.group.condition.update = 1
lsc.tasks.group.condition.delete = 1
lsc.tasks.group.condition.modrdn = 1
# como sera criado o grupo no AD, ex. cn=IT,cn=users,dc=texas,dc=local
lsc.tasks.group.dn = "CN=" + srcBean.getAttributeValueById("cn") + ",CN=Users"
lsc.tasks.group.bean=org.lsc.beans.SimpleBean
# Source
# opcoes para selecao de grupos no OpenLDAP, repare os filtros para alguns grupos nunca sejam replicados
pro AD como Domain Users, para nao confindir com os padroes do Win.
lsc.tasks.group.srcService=org.lsc.jndi.SimpleJndiSrcService
lsc.tasks.group.srcService.filterAll = (&(objectClass=posixGroup)(cn=*)(!(cn=Print Operators))(!(cn=Backup
Operators))(!(cn=Administrators))(!(cn=Domain Users))(!(cn=Admins))(!(cn=Default))(!(cn=Domain
Admins))(!(cn=Domain Computers))(!(cn=Domain Guests))(!
(cn=Replicators))(!(cn=Account Operators)))
lsc.tasks.group.srcService.filterId = (&(objectClass=posixGroup)(cn={cn}))
lsc.tasks.group.srcService.baseDn=ou=Grupos
lsc.tasks.group.srcService.attrs=cn objectClass memberUid
lsc.tasks.group.srcService.pivotAttrs = cn
# Destination
# opcpes para o destino, mesmo padrao de selecao para q os grupos default do Win nao sejam deletados
lsc.tasks.group.dstService=org.lsc.jndi.SimpleJndiDstService
lsc.tasks.group.dstService.baseDn=cn=Users
lsc.tasks.group.dstService.attrs = cn objectClass member sAMAccountName
lsc.tasks.group.dstService.pivotAttrs = cn
lsc.tasks.group.dstService.filterAll = (&(objectClass=group)(sAMAccountName=*)(!
(sAMAccountName=DnsAdmins))(!(sAMAccountName=DnsUpdateProxy))(!(sAMAccountName=Domain
Computers))(!(sAMAccountName=Domain Controllers))(!
(sAMAccountName=Schema Admins))(!(sAMAccountName=Enterprise Admins))(!(sAMAccountName=Cert
Publishers))(!(sAMAccountName=Domain Admins))(!(sAMAccountName=Domain Users))(!
(sAMAccountName=Domain Guests))(!(sAMAccountName=Group Policy
Creator Owners))(!(sAMAccountName=RAS and IAS Servers))(!(sAMAccountName=Allowed RODC Password
Replication Group))(!(sAMAccountName=Denied RODC Password Replication Group))(!
(sAMAccountName=Read-only Domain Controllers))(!
(sAMAccountName=Enterprise Read-only Domain Controllers)))
lsc.tasks.group.dstService.filterId = (&(objectClass=group)(cn={cn}))
###################
### Syncoptions ###
###################
# opcoes de sicronia, ou seja, quais campos serao sincornizados entre bases e se eh necessario algum
remanejamento de campo, ou incluir texto,
# ex. o campo de script de logon no ldap do AD chama-se scriptPath no openldap chama-se
sambaLogonScript portanto
# eh preciso fazer um mapemaento para que o campo sambaLogonScript do OpenLDAP seja escrito no
scriptPath do AD.
# OpenLDAP -> AD
### User ###
lsc.syncoptions.user = org.lsc.beans.syncoptions.PropertiesBasedSyncOptions
lsc.syncoptions.user.default.action = F
lsc.syncoptions.user.objectClass.action = F
# o que inserir de atributos
lsc.syncoptions.user.objectClass.force_value = "top";"user";"person";"organizationalPerson"
# uid -> DisplayName
lsc.syncoptions.user.displayName.create_value = srcBean.getAttributeValueById("uid")
# uid -> givenName
lsc.syncoptions.user.givenName.create_value = srcBean.getAttributeValueById("uid")
# uid -> sAMAccountName
lsc.syncoptions.user.sAMAccountName.create_value = srcBean.getAttributeValueById("uid")
# sambaLogonScript -> scriptPath
lsc.syncoptions.user.scriptPath.action = F
lsc.syncoptions.user.scriptPath.force_value = srcBean.getAttributeValueById("postalCode")
# uid -> userPrincipalName
lsc.syncoptions.user.userPrincipalName.force_value = srcBean.getAttributeValueById("uid") + "@texas.local"
# homeDirectory -> homeDirectory
lsc.syncoptions.user.homeDirectory.action = F
lsc.syncoptions.user.homeDirectory.force_value = srcBean.getAttributeValueById("postOfficeBox")
# opcoes de controle do AD
lsc.syncoptions.user.userAccountControl.create_value = AD.userAccountControlSet( "0",
[ AD.UAC_SET_PASSWD_NOTREQD,AD.UAC_SET_NORMAL_ACCOUNT ])
# password nao precisa ser mudado no proximo logon
lsc.syncoptions.user.pwdLastSet.create_value = "-1"
# senha padrao setada na importacao do usuario do OpenLDAP pro AD
lsc.syncoptions.user.unicodePwd.action = F
lsc.syncoptions.user.unicodePwd.create_value = AD.getUnicodePwd("3v4ndrO")
### Group ### # opcoes de sincronia para grupos
lsc.syncoptions.group = org.lsc.beans.syncoptions.PropertiesBasedSyncOptions
# nome do grupo
# cn -> sAMAccountName
lsc.syncoptions.group.sAMAccountName.create_value = srcBean.getAttributeValueById("cn")
lsc.syncoptions.group.default.action = F
# atributos de grupo
lsc.syncoptions.group.objectClass.force_value = "top";"group"
# membro dos grupos, eh um javascript que entra dentro dos grupos do OpenLDAP e busca usuarios
# e replica para o determinado grupo no AD
lsc.syncoptions.group.member.delimiter = $
lsc.syncoptions.group.member.force_value = \
var umembers = \
srcBean.getAttributeValuesById("memberUid").toArray() ; \
for (var i=0; i p\try { \
umembers[i] = ldap.attribute(ldap.list("CN=Users","(sAMAccountName=" + (umembers[i]) +
")").get(0), 'distinguishedName').get(0) \
} catch (e) { \
umembers[i]=null; \
} \
} \
var members = new Array(); \
var j=0; \
for (var i=0; i<umembers.length; i++) { \
if (umembers[i]!=null) members[j++]=umembers[i]; \
} \
members;
OpenLDAP
Para exemplificar, criei uma base com seis usurios e trs grupos, insira o contedo em um arquivo ldif e importe
para dentro do seu servidor LDAP:
# baseteste.ldif
dn: dc=texas,dc=local
objectClass: top
objectClass: dcObject
objectClass: organization
dc: texas
o: Texas LDAP
dn: ou=pessoas,dc=texas,dc=local
objectClass: top
objectClass: organizationalUnit
ou: pessoas
dn: ou=grupos,dc=texas,dc=local
ou: grupos
objectClass: organizationalUnit
objectClass: top
dn: uid=enabor,ou=pessoas,dc=texas,dc=local
objectClass: posixAccount
objectClass: top
objectClass: inetOrgPerson
gidNumber: 0
givenName: evandro
sn: nabor
displayName: enabor
uid: enabor
homeDirectory: /home/enabor
cn: enabor
uidNumber: 27635
dn: uid=sman,ou=pessoas,dc=texas,dc=local
objectClass: posixAccount
objectClass: top
objectClass: inetOrgPerson
gidNumber: 0
givenName: super
sn: man
displayName: sman
uid: sman
homeDirectory: /home/sman
cn: sman
uidNumber: 10548
dn: uid=lluthor,ou=pessoas,dc=texas,dc=local
objectClass: posixAccount
objectClass: top
objectClass: inetOrgPerson
gidNumber: 0
givenName: lex
sn: luthor
displayName: lluthor
uid: lluthor
homeDirectory: /home/lluthor
cn: lluthor
uidNumber: 37975
dn: uid=lverde,ou=pessoas,dc=texas,dc=local
objectClass: posixAccount
objectClass: top
objectClass: inetOrgPerson
gidNumber: 0
givenName: lanterna
sn: verde
displayName: lverde
uid: lverde
homeDirectory: /home/lverde
cn: lverde
uidNumber: 24873
dn: uid=bwayne,ou=pessoas,dc=texas,dc=local
objectClass: posixAccount
objectClass: top
objectClass: inetOrgPerson
gidNumber: 0
givenName: bruce
sn: wayne
displayName: bwayne
uid: bwayne
homeDirectory: /home/bwayne
cn: bwayne
uidNumber: 25788
dn: cn=it,ou=grupos,dc=texas,dc=local
objectClass: posixGroup
objectClass: top
cn: it
memberUid: enabor
memberUid: bwayne
memberUid: sman
gidNumber: 58946
dn: cn=managers,ou=grupos,dc=texas,dc=local
objectClass: posixGroup
objectClass: top
cn: managers
gidNumber: 61470
memberUid: lluthor
memberUid: lverde
Iniciando a sincronizao
Para iniciar a sincronizao, acesse /usr/local/lsc e execute o comando:
# bin/lsc -f etc/ -s all -c all
Se tudo ocorrer bem, a sada dever ser igual a essa:
Feb 04 22:02:59 - INFO - Starting sync for user
Feb 04 22:02:59 - INFO - Connecting to LDAP server ldap://172.31.1.28/dc=texas,dc=local as
cn=Manager,dc=texas,dc=local
Feb 04 22:03:00 - INFO - Connecting to LDAP server ldaps://172.31.1.99/DC=texas,DC=local as
CN=LSC,CN=Users,DC=texas,DC=local
Feb 04 22:03:01 - INFO - # Adding new entry CN=lverde,CN=Users for user
dn: CN=lverde,CN=Users,DC=texas,DC=local
changetype: add
userPrincipalName: lverde@texas.local
pwdLastSet: -1
sAMAccountName: lverde
unicodePwd:: IgAzAHYANABuAGQAcgBPACIA
userAccountControl: 544
objectClass: organizationalPerson
objectClass: person
objectClass: user
objectClass: top
givenName: lverde
displayName: lverde
Feb 04 22:03:01 - INFO - # Adding new entry CN=bwayne,CN=Users for user
dn: CN=bwayne,CN=Users,DC=texas,DC=local
changetype: add
userPrincipalName: bwayne@texas.local
pwdLastSet: -1
sAMAccountName: bwayne
unicodePwd:: IgAzAHYANABuAGQAcgBPACIA
userAccountControl: 544
objectClass: organizationalPerson
objectClass: person
objectClass: user
objectClass: top
givenName: bwayne
displayName: bwayne
Feb 04 22:03:01 - INFO - # Adding new entry CN=lluthor,CN=Users for user
dn: CN=lluthor,CN=Users,DC=texas,DC=local
changetype: add
userPrincipalName: lluthor@texas.local
pwdLastSet: -1
sAMAccountName: lluthor
unicodePwd:: IgAzAHYANABuAGQAcgBPACIA
userAccountControl: 544
objectClass: organizationalPerson
objectClass: person
objectClass: user
objectClass: top
givenName: lluthor
displayName: lluthor
Feb 04 22:03:02 - INFO - # Adding new entry CN=sman,CN=Users for user
dn: CN=sman,CN=Users,DC=texas,DC=local
changetype: add
userPrincipalName: sman@texas.local
pwdLastSet: -1
sAMAccountName: sman
unicodePwd:: IgAzAHYANABuAGQAcgBPACIA
userAccountControl: 544
objectClass: organizationalPerson
objectClass: person
objectClass: user
objectClass: top
givenName: sman
displayName: sman
Feb 04 22:03:02 - INFO - # Adding new entry CN=enabor,CN=Users for user
dn: CN=enabor,CN=Users,DC=texas,DC=local
changetype: add
userPrincipalName: enabor@texas.local
pwdLastSet: -1
sAMAccountName: enabor
unicodePwd:: IgAzAHYANABuAGQAcgBPACIA
userAccountControl: 544
objectClass: organizationalPerson
objectClass: person
objectClass: user
objectClass: top
givenName: enabor
displayName: enabor
Feb 04 22:03:02 - INFO - All entries: 5, to modify entries: 5, modified entries: 5, errors: 0
Feb 04 22:03:02 - INFO - Starting clean for user
Feb 04 22:03:02 - INFO - All entries: 5, to modify entries: 0, modified entries: 0, errors: 0
Feb 04 22:03:02 - INFO - Starting sync for group
Feb 04 22:03:02 - INFO - # Adding new entry CN=it,CN=Users for group
dn: CN=it,CN=Users,DC=texas,DC=local
changetype: add
member: CN=bwayne,CN=Users,DC=texas,DC=local
member: CN=enabor,CN=Users,DC=texas,DC=local
member: CN=sman,CN=Users,DC=texas,DC=local
cn: it
sAMAccountName: it
objectClass: group
objectClass: top
Feb 04 22:03:02 - INFO - # Adding new entry CN=managers,CN=Users for group
dn: CN=managers,CN=Users,DC=texas,DC=local
changetype: add
member: CN=lverde,CN=Users,DC=texas,DC=local
member: CN=lluthor,CN=Users,DC=texas,DC=local
cn: managers
sAMAccountName: managers
objectClass: group
objectClass: top
Feb 04 22:03:02 - INFO - All entries: 2, to modify entries: 2, modified entries: 2, errors: 0
Feb 04 22:03:02 - INFO - Starting clean for group
Feb 04 22:03:02 - INFO - All entries: 2, to modify entries: 0, modified entries: 0, errors: 0
Consulte o Active Directory e ver que os usurios e grupos foram criados na base.
Caso a sada apresente erros, fique atento para as configuraes no arquivo "lsc.properties" e com a questo do
certificado, pois perceba que estou sempre utilizando LDAPS para acessar o AD.
Senhas
O nico problema da soluo com relao s senhas, pois no possvel empurrar os Hashs dos usurios do
OpenLDAP para dentro do Active Directory, j que este usa um tipo diferente de Hash. Tambm no possvel ler
senhas do Active Directory.
A soluo que encontrei para este caso, foi a padronizao de uma tela para os usurios alterarem suas senhas.
Esta tela pode ser uma pgina em PHP que insira o Hash da senha digitada, tanto na base OpenLDAP quanto no
Active Directory.
Existem muitos tutoriais sobre como desenvolver uma pgina desse tipo para inserir a senha no OpenLDAP. Para o
Active Directory, chame esse script em sua pgina com os devidos parmetros (crditos a: www.barncrew.com)
que ele ir inserir a senha de maneira correta na base:
# chpass_ad.pl
#
# Para usar: ./chpass_ad.pl usuario senha
#
#!/usr/bin/perl -w
use Net::LDAP;
use Unicode::String qw(utf8);
# ARGV dos parametros usuario e senha
my $username = $ARGV[0];
my $passwd = $ARGV[1];
### ActiveDirectory Server
my $adsvr='172.31.1.99';
my $adbinddn='cn=LSC,cn=users,dc=texas,dc=local';
my $adpw='3v4ndrO';
########## ActiveDirectory #############
# Conecta do AD
my $ad=Net::LDAP->new($adsvr,
version => 3,
scheme => 'ldaps',
port => 636,
)
or die "nao eh possivel conectar $adsvr: $@";
# faz a busca com o usuario passado
$result=$ad->bind($adbinddn, password=>$adpw);
# procura o usuario q sera trocada senha
$result = $ad->search(
base => "cn=users,dc=texas,dc=local",
filter => "(samAccountName=$username)",
attrs => ['distinguishedName']
);
$result->code && die $result->error;
if ($result->entries != 1 ) { die "ERRO: Usuario nao encontrado no AD: $username" };
my $entry = $result->entry(0);
my $dnad = $entry->get_value('distinguishedName');
my $unicodePwd = utf8(chr(34).$passwd.chr(34))->utf16le();
# muda a senha !
$result = $ad->modify(
$dnad,
replace => {
unicodePwd => $unicodePwd,
}
);
$result->code && die $result->error;
print "AD : FEITO: ${username} password mudado.\n";
$ad->unbind();
Concluso
A soluo proposta capaz de resolver problemas em redes que precisam de centralizao de usurios quando a
necessidade de operao com bases diferentes imprescindvel.
Os parmetros usados nos programas envolvidos foram preparados para o cenrio proposto, mas, posteriores
alteraes podem e devem ser feitas para correta implementao em um ambiente de produo.
Introduo
A ideia principal do artigo a centralizao do ambiente em uma base nica, no caso uma das melhores o Ldap.
Imaginemos o cenrio, uma empresa denominada Acme Lun, far seu atual servidor de DNS(Bind), em vez de
consultar as zonas em arquivos locais (.db), consultar em uma base LDAP.
Partirei do princpio que j temos um servidor LDAP operante e um DNS Bind com suas zonas prontas, e mais um
servidor no qual faremos o novo Bind. Utilizei Debian 5 em todas as maquinas.
Compilando o I!D com suporte ao LDAP
O bind dos repositrios no vem com suporte ao LDAP, ento no adianta instal-lo com apt-get que este no
funcionar, portanto teremos de compilar do fonte ativando ento o suporte a LDAP.
Comecemos baixando o fonte do bind9 e o back-end bind-ldap.
Bind9:
ftp://ftp.epix.net/pub/isc/bind9/9.7.1rc1/bind-9.7.1rc1.tar.gz
Back-End ldap sdb:
http://bind9-ldap.bayour.com/bind-sdb-ldap-1.0.tar.gz
# cd /root
# mkdir -p bind/tars
# cd bind/tars
# wget ftp://ftp.epix.net/pub/isc/bind9/9.7.1rc1/bind-9.7.1rc1.tar.gz
# wget http://bind9-ldap.bayour.com/bind-sdb-ldap-1.0.tar.gz
# tar -zxvf bind-sdb-ldap-1.0.tar.gz
# tar -zxvf bind-9.7.1rc1.tar.gz
# mv bind-* ..
Copiando os arquivos necessrios para a compilao com suporte a LDAP:
# cd /root/bind-sdb-ldap-1.0
# cp ldapdb.c ../bind-9.7.1rc1/bin/named/
# cp ldapdb.h ../bind-9.7.1rc1/bin/named/include/
Agora faremos alteraes em alguns arquivos antes de compilar:
# cd /root/bind/bind-9.7.1rc1/bin/named/
# vim(rules!) Makefile.in
Procure pelas linhas e altere-as deixando como mostrado abaixo:
DBDRIVER_OBJS = ldapdb.@O@
DBDRIVER_SRCS = ldapdb.c
DBDRIVER_INCLUDES = -I/usr/local/include
DBDRIVER_LIBS = -L/usr/local/lib -lldap -llber -lresolv
No mesmo diretrio do Makefile.in, edite o arquivo main.c.
Procure pela linha que contem /* #include "xxdb.h" */ e adicione logo abaixo dela #include <ldapdb.h>.
No mesmo arquivo procure a linha /* xxdb_init(); */ substitua por ldapdb_init();
Por ltimo procure a linha /* xxdb_clear(); */ e substitua por ldapdb_clear();
Salve o arquivo e feche-o.
Agora estamos prontos para compilar o bind com suporte a nova base.
Antes de iniciarmos certifique-se que tem os pacotes necessrios instalados:
# apt-get install gcc make libldap2-dev openssl libssl-dev
Feito isso proceda:
# cd /root/ bind-9.7.1rc1/
# ./configure --with-openssl=/usr --disable-ipv6
# make
# make install
Ok, temos o bind instalado, agora precisamos acertar configuraes e diretrios.
Sempre preferi trabalhar com o bind no conceito de chroots para aumentar a segurana, ento, vamos configurar a
gaiola.
Criando a chroot
Criar diretrios:
# mkdir -p /chroot/named
# cd /chroot/named
# mkdir dev etc logs
# mkdir -p var/run
# mkdir - p conf/secondaries
Trazer o arquivo timezone para a chroot:
# cp /etc/localtime /chroot/named/etc
Criar os nodes:
# mknod /chroot/named/dev/null c 1 3
# mknod /chroot/named/dev/zero c 1 5
# mknod /chroot/named/dev/random c 1 8
Criar um usurio e grupo para o bind:
# groupadd named
# useradd -g named -d /chroot/named -s /bin/true named
# passwd -l named
"ontando os ar#ui$os de configurao
Primeiro criaremos o named.conf, que o arquivo principal do bind, repare que as zonas de root servers e as
outras zonas padres ficaram na prpria mquina, ou seja, no consultar no ldap.
# vim /chroot/named/etc/named.conf
Por hora adicione este contedo dentro do arquivo:
options {
directory "/conf";
pid-file "/var/run/named.pid";
statistics-file "/var/run/named.stats";
dump-file "/var/run/named.db";
empty-zones-enable no;
# esconda sua "verdadeiro" numero de versao
version "[seguro]";
};
# root servers
zone "." {
type hint;
file "db.rootcache";
};
# localhost - zona de encaminhamento
zone "localhost" {
type master;
file "db.localhost";
notify no;
};
# localhost - zona reversa
zone "0.0.127.in-addr.arpa" {
type master;
file "db.127.0.0";
notify no;
};
Cria tambm um link simblico do named.conf para o /etc para facilitar administrao:
# ln -sf /chroot/named/etc/named.conf /etc/named.conf
Perceba que nosso named.conf aponta para trs arquivos:
db.127.0.0
db.localhost
db.rootcache
Criaremos agora eles, ento a comear pelo db.rootcache.
Se a mquina que estamos instalando tem acesso a internet, ele pode ser criado com o comando:
# dig @a.root-servers.net . ns > /chroot/named/conf/db.rootcache
Criando os outros dois:
# vim /chroot/named/conf/db.127.0.0
E cole o contedo:
; db.127.0.0
$TTL 86400
@ IN SOA localhost. root.localhost. (
1 ; Serial
28800 ; Refresh
14400 ; Retry
3600000 ; Expire
86400 ) ; Minimum
IN NS localhost.
1 IN PTR localhost.
Salve e feche o arquivo.
# vim /chroot/named/conf/db.localhost
e cole o contedo:
; db.localhost
$TTL 86400
@ IN SOA @ root (
42 ; serial (d. adams)
3H ; refresh
15M ; retry
1W ; expiry
1D ) ; minimum
IN NS @
IN A 127.0.0.1
Salve e feche o arquivo.
C%ecando permiss&es no C'(OO)
Este script gerencia perfeitamente todas as permisses que precisamos dentro do diretrio chroot.
# verifica.permissoes
cd /chroot/named
chown -R root.named .
find . -type f -print | xargs chmod u=rw,og=r # regular files
find . -type d -print | xargs chmod u=rwx,og=rx # directories
chmod o= etc/*.conf
touch conf/secondaries/.empty # placeholder
find conf/secondaries/ -type f -print | xargs chown named.named
find conf/secondaries/ -type f -print | xargs chmod ug=r,o=
chown root.named conf/secondaries/
chmod ug=rwx,o= conf/secondaries/
chown root.root var/
chmod u=rwx,og=x var/
chown root.named var/run/
chmod ug=rwx,o=rx var/run/
chown root.named logs/
chmod ug=rwx,o=rx logs/
Copie o contedo acima e cole num arquivo novo em /chroot/verifica.permissoes.
Agora s executarmos:
# sh -x /chroot/verifica.permissoes
A sada ser algo como:
+ cd /chroot/named
+ chown -R root.named .
+ find . -type f -print
+ xargs chmod u=rw,og=r
+ find . -type d -print
+ xargs chmod u=rwx,og=rx
+ chmod o= etc/named.conf etc/rndc.conf
+ touch conf/secondaries/.empty
+ find conf/secondaries/ -type f -print
+ xargs chown named.named
+ find conf/secondaries/ -type f -print
+ xargs chmod ug=r,o=
+ chown root.named conf/secondaries/
+ chmod ug=rwx,o= conf/secondaries/
+ chown root.root var/
+ chmod u=rwx,og=x var/
+ chown root.named var/run/
+ chmod ug=rwx,o=rx var/run/
Agora as permisses dos nossos diretrios esto todas ok.
Script para inicializao do servio:
#start.named
cd /chroot/named
touch named.run
chown named.named named.run
chmod ug=rw,o=r named.run
PATH=/usr/local/sbin:$PATH named \
-t /chroot/named \
-u named \
-c /etc/named.conf
Crie um arquivo start.named dentro do /chroot/ e cole o contedo acima nele.
Transforme o mesmo em executvel com o comando:
# chmod a+x /chroot/start.named
No execute o script ainda!
Configurando o rndc
Crie o arquivo rndc.conf dentro de /chroot/named/etc/rndc.conf e adicione o seguinte contedo:
#rndc.conf
options {
default-server 127.0.0.1;
default-key "rndckey";
};
server 127.0.0.1 {
key "rndckey";
};
key "rndckey" {
algorithm "hmac-md5";
secret "COLOQUE SUA CHAVE";
};
Adicione as seguintes entradas no incio do arquivo /chroot/named/etc/named.conf:
controls {
inet 127.0.0.1 allow { 127.0.0.1; } keys { rndckey; };
};
key "rndckey" {
algorithm "hmac-md5";
secret "COLOQUE SUA CHAVE";
};
Perceba que nos dois arquivos temos a frase COLOQUE SUA CHAVE, ento, substituiremos esta por a respectiva
chave.
Para gerar a chave faa:
# dnssec-kegen -a HMAC-MD5 -b 256 -n HOST rndc
Ento voc ter dois arquivos no diretrio onde executou o comando.
Os nomes sero algo como Krndc.+157+48683.private e Krndc.+157+48683.key, mas nos estamos interessados
somente no Krndc.+157+48683.private, dentro dele ter uma linha como essa informando a chave Key:
QQMI5z8cceUIzA0UkPlbOEP3RH3sLEfSNVfWGmawjPo=, copie somente a chave e cole nos arquivos substituindo a
frase COLOQUE SUA CHAVE.
Remova os dois arquivos que foram gerados.
Feito isso estamos prontos para iniciar o servio e verificar se tudo est ok.
# cd /chroot/named
# ./start.named
Verifique se tudo est ok atravs do comando:
# rndc status
A sada deve ser algo parecido com:
version: 9.7.1rc1 ([seguro])
number of zones: 3
debug level: 0
xfers running: 0
xfers deferred: 0
soa queries in progress: 0
query logging is OFF
recursive clients: 0/0/1000
tcp clients: 0/100
server is up and running
Para facilitar a administrao utilize o seguinte script:
#named init
export PATH=/usr/local/sbin:$PATH # needed for rndc
case "$1" in
start)
# Start daemons.
echo -n "Levantando o named: "
sh /chroot/start.named
echo
;;
stop)
# Stop daemons.
echo -n "Derrubando o named: "
rndc stop
echo "done"
;;
esac
exit 0
Cole o contedo dentro de um novo arquivo chamado named em /etc/init.d e de permisso de execuo para ele.
Assim quando quiser levantar o processo use:
# /etc/init.d/named start
e pra derrubar:
# /etc/init.d/named stop
Inicialize o servio e faa um teste com o dig, no se esquea de alterar no arquivo /etc/resolv.conf apontar para o
127.0.0.1.
# dig www.google.com.br
Obrigatoriamente devemos ter algo parecido com o seguinte resultado:
; <<>> DiG 9.7.1rc1 <<>> www.google.com.br
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53404
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 4, ADDITIONAL: 4
;; QUESTION SECTION:
;www.google.com.br. IN A
;; ANSWER SECTION:
www.google.com.br. 345600 IN CNAME www.google.com.
www.google.com. 604800 IN CNAME www.l.google.com.
www.l.google.com. 300 IN A 64.233.163.104
;; AUTHORITY SECTION:
google.com. 172799 IN NS ns2.google.com.
google.com. 172799 IN NS ns1.google.com.
google.com. 172799 IN NS ns3.google.com.
google.com. 172799 IN NS ns4.google.com.
;; ADDITIONAL SECTION:
ns1.google.com. 345600 IN A 216.239.32.10
ns2.google.com. 345600 IN A 216.239.34.10
ns3.google.com. 345600 IN A 216.239.36.10
ns4.google.com. 345600 IN A 216.239.38.10
;; Query time: 1784 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Jan 24 20:31:15 2011
;; MSG SIZE rcvd: 235
Ok, agora temos um servidor de DNS configurado e funcionando, esperando somente as zonas do LDAP.
Montando as zonas
Novo schema dnszone.
necessria a incluso de um novo schema no servidor openldap.
http://www.venaas.no/ldap/bind-sdb/dnszone-schema.txt
Baixe o arquivo, salve no diretrio schemas do servidor ldap, adicione mais uma entrada no arquivo slapd.conf e
reinicie o servio.
Exemplo de zona em ldap:
dn: ou=DNS,dc=acme,dc=lun
objectClass: top
objectClass: organizationalUnit
ou: DNS
dn: zoneName=acme.lun,ou=DNS,dc=acme,dc=lun
zoneName: acme.lun
relativeDomainName: acme.lun
objectClass: dNSZone
objectClass: top
dn: relativeDomainName=@,zoneName=acme.lun,ou=DNS,dc=acme,dc=lun
objectClass: top
objectClass: dNSZone
zoneName: acme.lun
relativeDomainName: @
dNSTTL: 86400
dNSClass: IN
sOARecord: ns1.acme.lun. root.acme.lun. 2010083102 604800 86400 2419200 604800
nSRecord: ns1.
dn: relativeDomainName=ns1,zoneName=acme.lun,ou=DNS,dc=acme,dc=lun
zoneName: acme.lun
relativeDomainName: ns1
dNSTTL: 86400
dNSClass: IN
objectClass: dNSZone
objectClass: top
aRecord: 10.1.1.2
dn: relativeDomainName=www,zoneName=acme.lun,ou=DNS,dc=acme,dc=lun
zoneName: acme.lun
relativeDomainName: www
dNSTTL: 604800
dNSClass: IN
objectClass: dNSZone
objectClass: top
cNAMERecord: www.acme.lun
aRecord: 10.1.1.3
dn: relativeDomainName=cacti,zoneName=acme.lun,ou=DNS,dc=acme,dc=lun
objectClass: top
objectClass: dNSZone
zoneName: acme.lun
relativeDomainName: cacti
dNSTTL: 604800
dNSClass: IN
cNAMERecord: cacti.acme.lun.
ARecord: 10.1.1.5
Exemplo de zona reversa em ldap:
dn: zoneName=1.1.10.in-addr.arpa,ou=DNS,dc=acme,dc=lun
zoneName: 1.1.10.in-addr.arpa
relativeDomainName: 1.1.10.in-addr.arpa
objectClass: dNSZone
objectClass: top
dn: relativeDomainName=@,zoneName=1.1.10.in-addr.arpa,ou=DNS,dc=acme,dc=lun
zoneName: 1.1.10.in-addr.arpa
relativeDomainName: @
dNSTTL: 3600
dNSClass: IN
objectClass: dNSZone
objectClass: top
dn: relativeDomainName=2,zoneName=1.1.10.in-addr.arpa,ou=DNS,dc=acme,dc=lun
zoneName: 1.1.10.in-addr.arpa
relativeDomainName: 2
dNSTTL: 3600
dNSClass: IN
objectClass: dNSZone
objectClass: top
pTRRecord: ns1.acme.lun.
dn: relativeDomainName=3,zoneName=1.1.10.in-addr.arpa,ou=DNS,dc=acme,dc=lun
zoneName: 1.1.10.in-addr.arpa
relativeDomainName: 3
dNSTTL: 3600
dNSClass: IN
objectClass: dNSZone
objectClass: top
pTRRecord: www.acme.lun.
dn: relativeDomainName=5,zoneName=1.1.10.in-addr.arpa,ou=DNS,dc=acme,dc=lun
zoneName: 1.1.10.in-addr.arpa
relativeDomainName: 5
dNSTTL: 3600
dNSClass: IN
objectClass: dNSZone
objectClass: top
pTRRecord: cacti.acme.lun.
Configure seus arquivos seguindo estes como modelo, para inclu-los para dentro da base ldap salve-os como .ldif
e use o slapadd, por exemplo:
# slapadd -l acme.ldif
Agora que temos as zonas prontas no servidor ldap, vamos fazer os apontamentos, edite o arquivo
/chroot/named.conf e adicione as seguintes linhas com as devidas alteraes de acordo com suas zonas:
# zona acme.lun
zone "acme.lun" {
type master;
database "ldap ldap://10.1.1.28/ou=DNS,dc=acme,dc=lun 10800";
notify yes;
};
# reverso acme.lun
zone "1.1.10.in-addr.arpa" {
type master;
database "ldap ldap://10.1.1.28/ou=DNS,dc=acme,dc=lun 10800";
notify yes;
};
Agora s iniciarmos o servio e acompanhar nos logs para identificar possveis erros.
Os logs ficam em /var/log/messages.
)estando
Para testarmos o funcionamento do nosso servidor de DNS gosto da maneira clssica com a dupla dinmica
nslookup e dig.
Concluso
Sempre gosto de lembrar a ideia de centralizao, o que nos possibilita grandes vantagens, principalmente quando
temos um cenrio misto em servios.
Vale ressaltar tambm em nossa integrao ldap+dns que podemos considerar alguns itens como performance,
que ser um pouco prejudicada pois a consulta DNS no est sendo mais local, o que envolve vrios outros
fatores.
Mas asseguro-lhes que este tipo de desvantagem poder ser levando em considerao quando temos um servio
extremamente estressado com uma taxa de acesso realmente grande.
Espero que aproveitem o artigo!

You might also like