Controle de acesso ao servidor SAMBA

Este capítulo documenta o controle de acesso ao servidor samba e restrições.

Nível de acesso de usuários conectados ao SAMBA

Quando acessa um compartilhamento, o usuário do samba é mapeado com o UID respectivo de usuário do sistema ou o usuário guest (especificado pela opção "guest account") no caso de um acesso público. Quando isto ocorre, um processo filho do smbd é executado sobre o UID e GID deste usuário. Isto significa que em nenhuma ocasião o SAMBA dará mais permissões que as necessárias para o usuário (com excessão de quando é usado o parâmetro admin users, veja “Criando uma conta de administrador de domínio”).

Restringindo o acesso por IP/rede

Esta restrição pode ser feita pelos parâmetros allow hosts e deny hosts tanto em serviços individuais ou em todo o servidor. Os parâmetros hosts allow e hosts deny são equivalentes a estes acima. O allow hosts permite o acesso a máquina especificadas como argumento. São permitidos os seguintes métodos para permitir o acesso a uma máquina/rede:

  • 192.168.1.1 - IP da máquina

  • servidor - Nome da máquina

  • 192.168.1.0/255.255.255.0 - IP com máscara de rede

  • 192.168.1.0/24 - IP com máscara de rede octal

  • 192.168.1. - Porção de rede sem o host (como no hosts.allow e hosts.deny.

  • @nome - Pesquisa por máquinas no grupo NIS.

É permitido usar mais de um endereço IP separando-os por vírgulas ou espaços. A palavra chave EXCEPT pode ser usada para fazer excessão de um ou mais endereços IPs, por exemplo:

hosts allow = 192.168.1. EXCEPT 192.168.1.20

Que permite o acesso a toda as máquinas da faixa de rede 192.168.1.0/24 exceto para a 192.168.1.20.

O deny hosts possui a mesma sintaxe do allow hosts mas bloqueia o acesso das máquinas especificadas como argumento. Quando o allow hosts e deny hosts são usados juntos, as máquinas em allow hosts terão prioridade (processa primeiro as diretivas em allow hosts e depois em deny hosts).

OBS: O endereço de loopback (127.0.0.1) nunca é bloqueado pelas diretivas de acesso. Provavelmente deve ter notado porque o endereço de loopback não pode ser bloqueado e as conseqüências disto para o SAMBA.

Se você está executando o SAMBA via inetd, os arquivos hosts.allow e hosts.deny são verificados antes do controle e acesso allow hosts e deny hosts para controle de acesso ao smbd. Caso estiver usando o SAMBA viainetd e deseja restringir o acesso usando TCP Wrappers, veja “O mecanismo de controle de acessos tcpd”.

OBS: Lembre-se de usar o testparm para verificar a sintaxe do arquivo smb.conf sempre que desconfiar de problemas (veja “Buscando problemas na configuração”).

Testando a restrição de Acesso por IP/Redes

Um método interessante e útil para testar se a nossa configuração vai bloquear o acesso a serviços é usando o testparm da seguinte forma:

testparm /etc/samba/smb.conf IP/host

Você precisará dizer para o testparm qual é o arquivo de configuração que está usando e o endereço IP/nome de host que fará a simulação de acesso. Este método não falsifica o endereço IP para testes, apenas usa os valores em allow hosts e deny hosts para checagem. Por exemplo, para verificar o acesso vindo do IP 192.168.1.50:

testparm /etc/samba/smb.conf 192.168.1.50
Load smb config files from /etc/samba/smb.conf
Processing section "[homes]"
Processing section "[printers]"
Processing section "[tmp]"
Processing section "[cdrom]"
Loaded services file OK.
Allow connection from /etc/samba/smb.conf (focalinux) to homes
Allow connection from /etc/samba/smb.conf (focalinux) to printers
Allow connection from /etc/samba/smb.conf (focalinux) to tmp
Allow connection from /etc/samba/smb.conf (focalinux) to cdrom

Restringindo o acesso por interface de rede

Esta restrição de acesso permite que façamos o SAMBA responder requisições somente para a interfaces indicadas. O método de segurança descrito em “Restringindo o acesso por IP/rede” serão analisadas logo após esta checagem.

Para restringir o serviço SAMBA a interfaces, primeiro será necessário ativar o parâmetro bind interfaces only usando 1, yes ou true (o padrão é desativado). Depois, definir que interfaces serão servidas pelo samba com o parâmetro interfaces. Os seguintes formatos de interfaces são permitidos:

  • eth0, sl0, plip0, etc - Um nome de interface local. É permitido o uso de * para fazer o SAMBA monitorar todas as interfaces que iniciam com aquele nome (por exemplo, eth*).

  • 192.168.1.1, 192.168.1.2, etc - Um endereço IP de interface local.

  • 192.168.1.2/24, 192.168.1.2/255.255.255.0 - Um par de endereço/máscara de rede.

Mais de uma interface pode ser usada separando-as com vírgula ou espaços. A escolha do uso de nome da interface ou do IP é feita de acordo com a configuração da máquina. Em uma máquina DHCP por exemplo, é recomendado o uso do nome da interface. Quando bind interfaces only estiver ativado, o padrão é esperar conexões em todas as interfaces que permitem broadcast exceto a loopback.

Exemplo:

bind interfaces only = 1
interfaces = loopback eth0

Permite o recebimento de requisições de acesso ao SAMBA somente da interface loopback (desnecessário, pois como notou durante a leitura, sempre é permitida a conexão) e eth0.

Restringindo o acesso por usuários

Permite que você controle quem poderá ou não acessar o compartilhamento da máquina. Este controle é feito pelos parâmetros valid users e invalid users.

O invalid users lista de usuário que NÃO terão acesso ao compartilhamento. Se o nome for iniciado por "+" o parâmetro será tratado como um nome de grupo UNIX (/etc/group). O caracter "&" faz ele pesquisar o nome de grupo no banco de dados NIS. O caracter "@" permite fazer a busca do grupo primeiro no banco de dados NIS e caso ele não seja encontrado, no arquivo de grupos do sistema (/etc/group).

É possível usar a combinação de caracteres "+&" e "&+" para alternar a ordem de busca enter o /etc/group e o NIS.

Exemplos:

invalid users = junior, marcio, +badusers

Não permite que os usuários especificados e os usuários do grupo +badusers tenham acesso ao compartilhamento.

invalid users = &;semacesso

Bloqueia o acesso de todos os usuários NIS que pertençam ao grupo semacesso.

invalid users = bruno, henrique, +@users,

Bloqueia o acesso dos usuários bruno, henrique e de todos os usuários que pertençam ao grupo users. A pesquisa de grupo é feita primeiro no /etc/group e em seguida no NIS.

invalid users = @semacesso

Bloqueia o acesso dos usuários que pertencem ao grupo "semacesso". A pesquisa é feita primeiro no NIS e depois no /etc/group (equivalente ao uso de "&+").

O valid users possui a mesma sintaxe de funcionamento do invalid users, mas permite somente o acesso para os usuários/grupos listados. Caso a opção valid users não seja especificada ou a lista esteja vazia, o acesso é permitido. Se um mesmo nome de usuário estiver na lista valid users e invalid users, o padrão é ser mais restritivo, negando o acesso.

 valid users = gleydson, michelle, geo

A segurança deste método de acesso depende muito da forma de autenticação dos nomes antes de passar o controle para o SAMBA, pois uma autenticação fraca põe em risco a segurança da sua máquina.

Evite o uso do parâmetro hosts equiv!

Este parâmetro permite que máquinas tenham acesso sem senha a um servidor. Isto pode se tornar um *ENORME* buraco na segurança do seu sistema, pois mesmo usando uma senha inválida, a máquina poderá ter acesso a todos os recursos do compartilhamento e não é complicado fazer um ataque usando DNS spoofing.

Se realmente deseja fazer isto, tenha em mente os dados que poderão ser acessados daquela máquina, se realmente não existe nenhuma outra forma de disponibilizar o acesso de forma que mantenha o controle de restrições (usando todos os outros métodos), restrinja o acesso usando MAC Address com o iptables ou o arp (veja “Restrições por MAC Address/IP”). O padrão é não usar nenhum arquivo hosts.equiv.

Evite o uso de senhas em branco!

O parâmetro null passwords é usado na seção [global] permitindo que contas de usuários sem senha tenham acesso permitido ao servidor. ISTO É TOTALMENTE INSEGURO e deve ser sempre evitado. Caso você tenha feito uma bela restrição em sua máquina e deseja que o seu shell script de cópia de arquivos funcione usando este método, você está jogando toda a segurança do seu sistema por ralo abaixo.

Não existe motivo para usar senhas em branco em um controle de acesso por usuário, a não ser que precise testar algo realmente temporário e que depurando algo no SAMBA.

Criando um compartilhamento para acesso sem senha

Em algumas situações (mesmo em instalações seguras) é preciso tornar um compartilhamento acessível publicamente, exemplos disto incluem um diretório que contém drivers de impressoras, arquivos comuns, um diretório temporário, etc.

Para configurar um acesso público utilizamos a opção public = yes ou guest ok = yes (que é um sinônimo para o último comando). O UID utilizado no acesso público é especificado pelo parâmetro guest account, portanto ele deverá ser um usuário válido do sistema. Caso você queira somente definir acesso guest a um compartilhamento, especifique a opção guest only para o serviço, desta forma, mesmo que o usuário tenha acesso, ele será mapeado para o usuário guest.

Uma boa medida de segurança é usar o usuário nobody pois a maioria das distribuições de Linux seguras adotam-o como padrão como usuário que não é dono de quaisquer arquivos/diretórios no sistema, não possui login, senha ou sequer um diretório home.

Veja um exemplo disponibilizando o compartilhamento [download] para acesso público com acesso a gravação:

[global] 
guest account = nobody
..
..

[download]
 path = /downloads
 comment = Espaço público para abrigar downloads de Usuários
 guest ok = yes (aqui poderá ser também "public = yes").
 writable = yes
 follow symlinks = false

O parâmetro guest account também poderá ser especificado no compartilhamento, isto é útil quando não quiser que o usuário que acesse o compartilhamento não seja o mesmo usado na diretiva [global].

Caso seu servidor somente disponibiliza compartilhamentos para acesso público, é mais recomendado utilizar o nível security = share pra diminuir a carga máquina, pois o usuário guest será o primeiro a ser checado pelas regras de acesso (ao contrário do nível user, onde o acesso guest é o último checado).

OBS: Lembre-se que o compartilhamento funciona de modo recursivo, ou seja, todos os arquivos e subdiretórios dentro do diretório que compartilhou serão disponibilizados, portanto tenha certeza da importância dos dados que existem no diretório, verifique se existem links simbólicos que apontam para ele, etc. Recomendo dar uma olhada rápida em “Considerações de segurança com o uso do parâmetro "public = yes"”.

Criando um compartilhamento com acesso somente leitura

Esta proteção é útil quando não desejamos que pessoas alterem o conteúdo de um compartilhamento. Isto pode ser feito de duas formas: negando o acesso de gravação para todo o compartilhamento ou permitindo leitura somente para algumas pessoas. O parâmetro usado para fazer a restrição de acesso somente leitura é o read only = yes ou seu antônimo writable = no. Abaixo seguem os dois exemplos comentados:

[teste]
 comment = Acesso a leitura para todos
 path = /tmp
 read only = yes
 public = yes

No exemplo acima, o diretório /tmp (path = /tmp) foi compartilhado com o nome teste ([teste]), de forma pública (acesso sem senha - public = yes), e todos podem apenas ler seu conteúdo read only = yes).

[teste]
 comment = Acesso a gravação para todos com excessões
 path = /tmp
 read only = no
 read list = @users, gleydson
 invalid users = root

Neste, o mesmo compartilhamento teste ([teste]) foi definido como acesso leitura/gravação para todos (read only = no), mas os usuários do grupo @users e o usuário gleydson terão sempre acesso leitura (read list = @users, gleydson). Adicionalmente foi colocada uma proteção para que o superusuário não tenha acesso a ele (invalid users = root). Esta forma de restrição é explicada melhor em “Excessão de acesso na permissão padrão de compartilhamento”).

Criando um compartilhamento com acesso leitura/gravação

Esta forma de compartilhamento permite a alteração do conteúdo do compartilhamento dos usuários que possuem as permissões de acesso apropriadas. Este controle pode ser feito de duas formas: Acesso total de gravação para os usuários e acesso de gravação apenas para determinados usuários. Este controle é feito pela opção read only = no e seu antônimo equivalente writable = yes. Abaixo dois exemplos:

[teste]
 comment = Acesso de gravação para todos.
 path = /tmp
 writable = yes
 public = yes

No exemplo acima, o diretório /tmp (path = /tmp) foi compartilhado com o nome teste ([teste]), de forma pública (acesso sem senha - public = yes) e todos podem ler/gravar dentro dele (writable = yes).

[teste]
 comment = Acesso a leitura para todos com excessões
 path = /tmp
 writable = no
 write list = @users, gleydson

Neste, o mesmo compartilhamento teste ([teste]) foi definido como acesso de leitura para todos (writable = no), mas os usuários do grupo @users e o usuário gleydson serão os únicos que terão também acesso a gravação (write list = @users, gleydson). Esta forma de restrição é explicada melhor em “Excessão de acesso na permissão padrão de compartilhamento”).

Excessão de acesso na permissão padrão de compartilhamento

É possível alterar o nível de acesso para determinados usuários/grupos em um compartilhamento, para entender melhor: Caso tenha criado um compartilhamento somente leitura e queira permitir que apenas alguns usuários ou grupos tenham acesso a gravação, isto é possível e será explicado nesta seção. Este comportamento é controlado por duas opções: read list e write list. Veja alguns exemplos:

[temporario] 
 comment = Diretório temporário
 path = /tmp
 writable = yes
 read list = gleydson, root
 browseable = no
 available = yes

Neste exemplo, disponibilizamos o diretório /tmp (path = /tmp) como compartilhamento de nome temporario ([temporario]), seu acesso padrão é leitura/gravação para todos (writable = yes), exceto para os usuários root e gleydson (read list = root, gleydson). Em adição, tornamos o compartilhamento invisível (veja “Criando um compartilhamento invisível”) no "Ambiente de Rede" do Windows (browseable = no) e ele será lido e disponibilizado pelo SAMBA (available = yes).

[temporario] 
 comment = Diretório temporário
 path = /tmp
 writable = no
 write list = gleydson, @operadores
 browseable = yes

Neste exemplo, disponibilizamos o diretório /tmp (path = /tmp) como compartilhamento de nome temporario ([temporario]), seu acesso padrão é apenas leitura para todos (writable = no), exceto para o usuário gleydson e usuários do grupo Unix operadores, que tem acesso a leitura/gravação (write list = gleydson, @operadores). Tornamos o compartilhamento visível no "Ambiente de Rede" do Windows (browseable = yes - que é o padrão).

Restringindo o IPC$ e ADMIN$

É seguro restringir os serviços IPC$ e ADMIN$ para acesso somente pelas faixas de rede de confiança. Isto pode ser feito através da mesma forma que a restrição em outros compartilhamentos. Os efeitos desta restrição serão que somente as redes autorizadas possam obter a lista de máquinas, se autenticar no domínio e realizar tarefas administrativas gerais:

[IPC$]
read only = yes
allow from 192.168.1.0/24

[ADMIN$]
read only = yes
allow from 192.168.1.0/24

O exemplo acima permite que os serviços IPC$ e ADMIN$ sejam acessados de qualquer máquina na faixa de rede 192.168.1.0/24. Para forçar a autenticação para acesso a estes serviços:

[IPC$]
invalid users = nobody
valid users = gleydson michelle
read only = yes
allow from 192.168.1.0/24

[ADMIN$]
invalid users = nobody
valid users = gleydson michelle
read only = yes
allow from 192.168.1.0/24

Os exemplos acima são similares ao de antes, mas o acesso a listagem dos compartilhamentos é restringida (invalid users = nobody), pois o usuário nobody (usado para mostrar o compartilhamento) tem o acesso negado. Somente os usuários gleydson e michelle (valid users = gleydson michelle) podem listar seu conteúdo.

OBS: Mesmo que estejam restritos, os serviços IPC$ e ADMIN$ sempre poderão ser acessados de 127.0.0.1, ou teríamos problemas com o funcionamento do SAMBA. Assim não é necessário colocar 127.0.0.1 na lista de IPs autorizados.

Criando um compartilhamento invisível

Para não exibir um compartilhamento da lista de compartilhamentos das máquinas, utilize o parâmetro browseable = no. Por exemplo:

[teste]
 path = /tmp
 comment = Diretório temporário
 read only = yes
 browseable = no

Neste exemplo, o diretório /tmp (path = /tmp) foi compartilhado através de teste ([teste]) com acesso somente leitura (read only = yes) e ele não será mostrado na listagem de compartilhamentos do ambiente de rede do Windows (browseable = no).

Note que o compartilhamento continua disponível, porém ele poderá ser acessado da estação Windows, especificando a \\maquina\compartilhamento. Para acessar o compartilhamento do exemplo acima:

# Clique em Iniciar/Executar e digite:
\\nome_do_servidor_samba\teste

Ao contrário das máquinas Windows onde é necessário adicionar um "$" do nome de compartilhamento para criar um compartilhamento oculto (como teste$) o SAMBA cria um compartilhamento realmente oculto, não aparecendo mesmo na listagem do smbclient.

Executando comandos antes e após o acesso ao compartilhamento

Este recurso oferece uma infinidade de soluções que podem resolver desde problemas de praticidade até segurança usando as opções preexec e postexec. Por exemplo, imagine que esteja compartilhando 4 unidades de CD-Rom de um servidor na rede, e deseje que estes CDs estejam sempre disponíveis mesmo que algum operador engraçadinho tenha ejetado as gavetas de propósito, podemos fazer a seguinte configuração:

[cdrom]
 path = /cdrom
 comment = Unidade de CD-ROM 1
 read only = yes
 preexec = /bin/mount /cdrom
 preexec close = yes
 postexec = /bin/umount /cdrom

Na configuração acima, o CD-ROM será compartilhado como cdrom ([cdrom]), somente leitura (red only = yes), quando o usuário acessar o compartilhamento ele "fechará" a gaveta do CD (preexec = /bin/mount /cdrom) e desmontará o drive de CD assim que o compartilhamento for fechado (postexec = /bin/umount /cdrom). Adicionalmente, caso o comando mount da opção preexec tenha retornado um valor diferente de 0, a conexão do compartilhamento é fechada (preexec close = yes).

A UID do processo do preexec e postexec será o mesmo do usuário que está acessando o compartilhamento, por este motivo ele deverá ter permissões para montar/desmontar o CD-ROM no sistema. Caso precise executar comandos como usuário root, utilize a variante root preexec e root postexec. Apenas tenha consciência que os programas sendo executados são seguros o bastante para não comprometer o seu sistema.

Usando a mesma técnica, é possível que o sistema lhe envie e-mails alertando sobre acesso a compartilhamentos que em conjunto com um debug level 2 e logs configurados independentes por máquina, você possa ver o que a máquina tentou acessar (e foi negado) e o que ela conseguiu acesso.

Como bom administrador, você poderá criar scripts que façam uma checagem de segurança no compartilhamento e encerre automaticamente a conexão caso seja necessário, montar um "honney pot" para trojans, etc.

Como deve estar notando, as possibilidades do SAMBA se extendem além do simples compartilhamento de arquivos, se integrando com o potencial dos recursos do sistema UNIX.

Considerações de segurança com o uso do parâmetro "public = yes"

Este parâmetro permite que você acesso um compartilhamento sem fornecer uma senha, ou seja, que o usuário não esteja autenticado. NÃO utilize o parâmetro "public = yes" (ou um de seus sinônimos) no compartilhamento [homes], pois abrirá brechas para que possa acessar o diretório home de qualquer usuário e com acesso a gravação (que é o padrão adotado pelos administradores para permitir o acesso ao seu diretório home remoto).

Recomendo utilizar o parâmetro public = yes somente em compartilhamentos onde é realmente necessário, como o [netlogon] ou outras áreas de acesso público onde as permissões do sistema de arquivos local estejam devidamente restritas. Outra medida é não utilizar a opção follow symlinks, que poderá lhe causar problemas com usuários mal intencionados que tenham acesso shell.

OBS: Tenha em mente todas as considerações de segurança abordadas neste capítulo, bem como as permissões de acesso ao sistema Unix e como elas funcionam. A disponibilidade de arquivos em uma rede é simples, simples também pode ser o acesso indevido a eles caso não saiba o que está fazendo.

Senhas criptografadas ou em texto puro?

Como regra geral, prefira sempre utilizar senhas criptografadas. Aqui alguns motivos:

  • A senha é enviada de uma forma que dificulta sua captura por pessoas maliciosas.

  • O NT não permite que você navegue no ambiente de rede em um sistema SAMBA com nível de acesso por usuário autenticando usando senhas em texto plano.

  • Será solicitada sempre a senha para reconexão em cada compartilhamento da máquina.

  • Todas as versões de Windows NT 4 a partir SP3 e Windows 95 OSR/2 utilizam senhas criptografadas como padrão. É possível faze-lo utilizar senhas em texto plano modificando chaves no registro das máquinas clientes (veja “Ativando o suporte a senhas em texto plano” para detalhes).

As vantagens da utilização da autenticação usando texto plano:

  • A senha utilizada será a mesma do /etc/passwd (servindo para ftp, login, etc)

  • O servidor PDC pode ser usado para logon desde que os clientes estejam usando senhas em texto plano.

  • Elas não são armazenadas no disco da estação cliente.

  • Você não será perguntado por uma senha durante cada reconexão de recurso.

Antes de optar por utilizar um sistema de senhas em texto plano, leve em consideração estes pontos. Se você já utiliza telnet ou ftp, provavelmente a utilização de autenticação usando texto plano no SAMBA não trará problemas mais graves para você.

OBS: Caso seu NT ou versão derivada não navegue no ambiente de rede (só aceitando conexões especificando diretamente o "\\servidor\compartilhamento") modifique sua configuração do SAMBA para autenticar usando senhas criptografadas (veja “Ativando o suporte a senhas criptografadas”) para detalhes de como fazer isto.

Mapeamento de nomes de usuários

Este recurso faz a mapeamento (tradução) de nomes de usuários usados no momento do acesso para contas de acesso locais, bastante útil quando o nome de usuário enviado pela máquina não confere com NENHUMA conta local do sistema (um exemplo é quando o login do usuário no Windows é diferente de seu Login no Linux). Outro vantagem de seu uso é permitir que uma categoria de usuários utilizem um mesmo nível de acesso no sistema.

Seu formato é o seguinte: username map = arquivo.

As seguintes regras são usadas para construir o arquivo de mapeamento de nomes:

  • Um arquivo de múltiplas linhas onde o sinal de "=" separa os dois parâmetros principais. O arquivo é processado linha por linha da forma tradicional, a diferença é o que o processamento do arquivo continua mesmo que uma condição confira. Para que o processamento do resto do arquivo seja interrompido quando um mapeamento confira, coloque o sinal "!" na frente do nome local.

  • O parâmetro da esquerda é a conta Unix local que será usada para fazer acesso ao compartilhamento. Somente uma conta Unix poderá ser utilizada.

  • O parâmetro da direita do sinal de "=" pode conter um ou mais nomes de usuários separados por espaços que serão mapeados para a conta Unix local.

    O parâmetro "@grupo" permite que usuários pertencentes ao grupo Unix local sejam mapeados para a conta de usuário do lado esquerdo. Outro caracter especial é o "*" e indica que qualquer usuário será mapeado.

Você pode utilizar comentários na mesma forma que no arquivo de configuração smb.conf. Alguns exemplos:

# Mapeia o usuário "gleydson mazioli" com o usuário local gleydson
gleydson = gleydson mazioli

# Mapeia o usuário root e adm para o usuário nobody
nobody = root adm

# Mapeia qualquer nome de usuário que pertença ao grupo smb-users para o usuário
# samba. 
samba = @smb-users

# Utiliza todos os exemplos anteriores, se nenhum usuário conferir, ele será 
# mapeado para o usuário nobody (como o usuário root e adm já são mapeados
# para "nobody", este exemplo terá o mesmo efeito).
!gleydson = gleydson mazioli
!samba = @smb-users
nobody = *