Na segunda parte, demonstramos dicas e ajustes importantes para otimizar a capacidade do servidor em lidar com um volume de tráfego mais intenso. Hoje, veremos como configurar o servidor para negociar diferentes mecanismos de autenticação. Demonstraremos regras de acesso básicas, direcionadas apenas ao controle de sessões de usuários, pois o controle de navegação (permissões de acesso) será tratado na parte 4 (última).

No Squid, existem quatro esquemas (schemes) de autenticação, conhecidos como Basic, NTLM, Digest e Negotiate, e são apresentados aos clientes na ordem definida no arquivo de configuração (em squid.conf). Portanto, a ordem deve ser estabelecida em função do nível de segurança ou da “compatibilidade com o navegador ou aplicações“.

Neste artigo, não abordarei o esquema digest.

O Basic é o esquema mais simples e menos seguro (sem criptografia), com uma única codificação base64 (fácil ser quebrada). Logo, costuma ser a implementação mais simples e rápida, compatível com inúmeras aplicações ou navegadores. Apesar dos aspectos negativos, sua presença é importante para oferecer alternativas de autenticação para aplicações mais específicas. Em função do fraco nível de segurança, deve ser definido como último recurso disponível, para que esquemas mais seguros (como Negotiate ou NTLM) sejam testados antes. Normalmente, o “chaveamento” entre os esquemas é feito automaticamente pelos navegadores web.

Já o esquema NTLM oferece um nível de segurança mais elevado, centralizado (validando credenciais de contas de um “Domínio Windows”) e é baseado no protocolo NTLM – trata-se de um protocolo de autenticação de desafio-resposta, desenvolvido pela Microsoft. No entanto, apesar de oferecer um nível de segurança maior, o protocolo NTLMv1 (primeira versão) apresenta vulnerabilidade conhecida e deve ser mantido desabilitado (é padrão nas versões mais novas do Samba).

O Negotiate é, atualmente, o esquema que oferece o nível mais forte de criptografia e segurança, permitindo a autenticação baseada no protocolo Kerberos. É a opção preferencial para integração com o AD. Vale lembrar que os sistemas operacionais Windows Server, mais recentes, implementam o protocolo de autenticação Kerberos versão 5 e extensões para autenticação de chave pública, transporte de dados de autorização e delegação. Portanto, costuma ser o primeiro esquema oferecido aos clientes.

Para compreender detalhadamente as etapas de comunicação, confiram este guia (no final):
http://wiki.squid-cache.org/ConfigExamples/Authenticate/Kerberos

O suporte de autenticação nativo no Squid é modular e, por razões já explicadas, não é compatível com o modo transparente. Existem duas implementações extremamente simples, uma baseada no modulo ncsa_auth (base local, via htpasswd) e outra no pam_auth (contas de usuário do sistema, via integração PAM), ambas são baseadas no esquema Basic.

Liste o conteúdo do diretório /usr/lib/squid para saber quais módulos estão disponíveis:

root@proxysrv:~# ls /usr/lib/squid/
basic_db_auth                 basic_pop3_auth    cert_valid.pl                ext_wbinfo_group_acl          ntlm_fake_auth
basic_fake_auth               basic_radius_auth  diskd                        helper-mux.pl                 ntlm_smb_lm_auth
basic_getpwnam_auth           basic_smb_auth     ext_delayer_acl              log_db_daemon                 storeid_file_rewrite
basic_msnt_auth               basic_smb_auth.sh  ext_file_userip_acl          log_file_daemon               unlinkd
basic_msnt_multi_domain_auth  basic_smb_lm_auth  ext_kerberos_ldap_group_acl  negotiate_kerberos_auth       url_fake_rewrite
basic_ncsa_auth               cachemgr.cgi       ext_sql_session_acl          negotiate_kerberos_auth_test  url_fake_rewrite.sh
basic_nis_auth                cert_tool          ext_unix_group_acl           negotiate_wrapper_auth

Para habilitar a autenticação de usuários, primeiro o administrador precisa escolher o tipo de autenticação desejada e, em seguida, os módulos envolvidos e políticas de acesso.

Como forma de padronização, visando facilitar o processo de administração, costumamos subdividir a configuração do Squid em arquivos separados (a partir de /etc/squid/acl), estabelecendo uma lógica de “configuração modular”. Ou seja, a base de configuração é feita em /etc/squid/squid.conf e os recursos adicionais e mais específicos, como autenticação e controles de acesso, são separados em arquivos que serão carregados através da opção “include“.

Por exemplo:

## Utilização do cache em memória
cache_mem 512 MB

maximum_object_size_in_memory 256 KB
maximum_object_size 200 MB
minimum_object_size 0 KB
cache_swap_low 85
cache_swap_high 90
...
## 1. Definição dos módulos de autenticação
include /etc/squid/acl/buildauth/authmodule

## 2. Opções globais de autenticação
include /etc/squid/acl/buildauth/options

# Example rule allowing access from your local networks.
# Adapt to list your (internal) IP networks from where browsing
# should be allowed
acl localnet dst 10.0.0.0/8     # RFC1918 possible internal network
acl localnet dst 172.16.0.0/12  # RFC1918 possible internal network
acl localnet dst 192.168.0.0/16 # RFC1918 possible internal network
...
## Lista negra
http_access deny to_localhost
http_access deny domain_blacklist

## 3. Políticas de acesso (usuários)
include /etc/squid/acl/buildauth/authpolicy
...

Desta forma, a base de configuração será sempre a mesma. É possível mover a estrutura inteira para qualquer servidor e depois ajustar apenas os arquivos necessários. Se, por exemplo, a autenticação não for desejada em determinado servidor, basta esvaziar o conteúdo dos arquivos exibidos anteriormente (em negrito).

 

1. Módulos de autenticação (/etc/squid/acl/buildauth/authmodule)

A primeira configuração define o helper de autenticação utilizado (programas externos) e suas respectivas opções (para dimensionamento de carga, por exemplo).

– Opções globais

auth_param [esquema_de_autenticação] program [chamada_do_módulo]
auth_param [esquema_de_autenticação] children [limite_máximo_de_filhos] startup=[filhos_disponíveis_ao_iniciar] idle=[filhos_ociosos]
auth_param [esquema_de_autenticação] [opções_do_esquema]

– Identificação do servidor no esquema Basic

auth_param basic realm [identificação_do_proxy]

A configuração para o helper basic_ncsa_auth pode ser feita da seguinte maneira:

auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/acl/buildauth/.ncsa_passwd
auth_param basic children 150 startup=10 idle=10
auth_param basic credentialsttl 2 hours
auth_param basic casesensitive off

auth_param basic realm "Squid Proxy"

Antes de demonstrar como os usuários serão cadastrados (via htpasswd), veremos a forma como os processos são alocados…

O número de processos que atenderá às solicitações dos usuários, simultaneamente, é definido pela opção children (filhos). Para realizar ajustes granulares, podemos modificar a alocação dos filhos através da opção startup (número de filhos instanciados imediatamente, quando o serviço iniciar) e idle (número de processos ociosos).

Não existe um cálculo exato para este dimensionamento. Por padrão, o Squid trabalha com um limite máximo de 5 filhos. Para redes de médio ou grande porte, este limite é pequeno e problemas de autenticação serão certos. Os desenvolvedores consideram que 20 é um limite interessante para demandas de acesso mais expressivas. Porém, a Internet vem oferecendo uma gama de opções que podem apresentar características de conexão irregular, deixando alguns filhos pendentes por um intervalo de tempo. Por esta razão, tenho adotado um limite máximo de 150 e ajusto a escala de alocação (startup e idle) até atingir este limite, que seria o pior caso.

Não abuse no valor de idle, pois ele também define a quantidade de filhos instanciados sob demanda. Se a demanda de acesso for superior a 10 filhos, o servidor alocará mais 10 (idle) – ou seja, depois da próxima alocação, serão 20 filhos (e assim sucessivamente). Isto pode ser custoso para o servidor. Por esta razão costumo configurar até 10.

Para verificar se o servidor está bem dimensionado, utilize os comandos:

squidclient -l 127.0.0.1 -p 8080 -m mgr:negotiateauthenticator | more
squidclient -l 127.0.0.1 -p 8080 -m mgr:ntlmauthenticator | more
squidclient -l 127.0.0.1 -p 8080 -m mgr:basicauthenticator | more

Por exemplo (helper negotiate_wrapper_auth):

squidclient -l 127.0.0.1 -p 8080 -m mgr:negotiateauthenticator

HTTP/1.1 200 OK
Server: squid
Mime-Version: 1.0
...
Connection: close

by kid1 {
Negotiate Authenticator Statistics:
program: /usr/lib/squid/negotiate_wrapper_auth
number active: 5 of 200 (1 shutting down)
requests sent: 2468245
replies received: 2468245
queue length: 0
avg service time: 0 msec

      #      FD     PID  # Requests       # Replies      Flags     Time  Offset Request
      2      12   24561         221             221       RS      0.000       0 (none)
      1     152   10250       15517           15517               0.003       0 (none)
      2     167   10261         196             196               0.003       0 (none)
      3     177   10267          11              11               0.004       0 (none)
      4     185   10286           3               3               0.007       0 (none)
      5     193   10299           0               0               0.000       0 (none)

Flags key:

   B = BUSY
   C = CLOSING
   R = RESERVED
   S = SHUTDOWN PENDING
   P = PLACEHOLDER
} by kid1

Para validar esquema o basic (basic_ncsa_auth), altere mgr para mgr:basicauthenticator”

Ao optar pelo helper basic_ncsa_auth, trabalharemos com uma base local. De acordo com o exemplo anterior, as contas serão armazenadas no arquivo .ncsa_passwd (em /etc/squid/acl/buildauth) e gerenciadas via htpasswd.

Para instalar a ferramenta htpasswd, utilize o comando:

apt install apache2-utils

Para criar o arquivo, durante o cadastro da primeira conta, adicione a opção “-c”. No entanto, não informe esta opção para as demais.

htpasswd -c /etc/squid/acl/buildauth/.ncsa_passwd user1
htpasswd /etc/squid/acl/buildauth/.ncsa_passwd user2
htpasswd /etc/squid/acl/buildauth/.ncsa_passwd usern

Outros exemplos:
http://www.hardware.com.br/livros/servidores-linux/proxy-com-autenticacao.html

 

2. Opções globais (/etc/squid/acl/buildauth/options)

Neste arquivo, através das opções authenticate_ttl e authenticate_ip_ttl, determinamos o tempo de duração do cache das credenciais de usuário e o intervalo de tempo em que o Squid mantém o mapeamento de usuários por IP (utilizado em conjunto com uma ACL do tipo max_user_ip).

authenticate_ttl 2 hour
authenticate_ip_ttl 900 seconds
authenticate_cache_garbage_interval 1 hour

acl UserInfoControlChar urllogin [[:cntrl:]]
http_access deny UserInfoControlChar

A ACL UserInfoControlChar foi utilizada como prevenção contra um bug no MSIE:
http://www.squid-cache.org/Advisories/SQUID-2004_1.txt

 

3. Políticas de acesso (/etc/squid/acl/buildauth/authpolicy)

Em authpolicy, podemos evitar que as contas de usuários sejam compartilhadas, definindo max_user_ip como 1, e também forçar a autenticação para qualquer requisição de acesso.

## Política de acesso
acl max_users max_user_ip -s 1
acl all_users proxy_auth REQUIRED
acl shared_users proxy_auth -i "/etc/squid/acl/user_shared"

http_access deny !all_users
http_access deny max_users !shared_users all


## Lista negra e lista branca
acl user_blacklist proxy_auth_regex -i "/etc/squid/acl/user_blacklist"
http_access deny user_blacklist all

acl user_whitelist proxy_auth_regex -i "/etc/squid/acl/user_whitelist"
http_access allow user_whitelist

O controle de acesso é feito a partir de regras http_access. A primeira obriga a identificação do usuário e a segunda inibe o compartilhamento de contas. A opção all, no final das regras, é uma garantia de que o acesso será bloqueado sem que o proxy envie uma nova solicitação de autenticação. Em alguns casos, pode ser desejado impedir o acesso para o usuário corrente, porém possibilitando a validação de outra credencial. Os principais controles costumam ser feitos com a opção all para evitar que os usuários sejam incomodados, constantemente, com caixas de autenticação.

A ACL all_users (REQUIRED) foi definida para forçar a identificação prévia dos usuários, antes de submeter aos demais controles. Vale lembrar que cada ACL identifica uma condição de acesso, mas o controle efetivo é feito pelas regras http_access.

Já a ACL max_users foi utilizada para garantir que as contas de usuários não sejam compartilhadas, pois permitirá apenas 1 endereço IP por usuário simultâneamente. Caso o limite de max_user_ip seja excedido, ambos os endereços serão bloqueados pelo intervalo de tempo configurado no arquivo options (vide authenticate_ip_ttl). Ou seja, o bloqueio durará 15 minutos (900 segundos).

 

Integrando com o Active Directory

A lógica essencial e básica foi apresentada. Veremos agora um exemplo, mais avançado, de configuração com autenticação integrada ao AD. Trabalharemos com os três esquemas de autenticação (negotiate, ntlm e basic), oferecendo suporte à autenticação Kerberos e NTLM. Conforme exposto inicialmente, o navegador selecionará o método mais adequado.

Vale lembrar que, para ingressar o servidor corretamente ao domínio, os mapeamentos de DNS são fundamentais (na autenticação Kerberos são OBRIGATÓRIOS), sejam registros do tipo A como PTR (precisa do reverso também) – as referências ao servidor proxy, em configurações manuais ou WPAD, serão feitas pelo nome FQDN. É recomendável conferir o mapeamento local, com a identificação do servidor no arquivo /etc/hosts, também.

Comece ingressando o servidor ao domínio:
http://linuxfirewall.com.br/linuxwp/autenticacao-integrada-com-o-ms-active-directory-ad/

Observação: “Para evitar exposição e consumo de recursos desnecessários, basta instalar e executar apenas o serviço winbind (responsável pela identificação dos usuários). Neste cenário, os demais serviços do Samba não são necessários – caso sejam instalados, desabilite os serviços smbd e nmbd (a instalação das dependências samba-common e samba-common-bin são suficientes). Como o nosso objetivo é prover a autenticação no Squid, a integração com NSS também é opcional (não requer a configuração do arquivo nsswitch.conf), mas seria necessária se houvesse integração com o PAM“.

Siga os passos descritos no link anterior. A cada alteração, reinicie o serviço winbind. Não há mistério, porém prossiga com a configuração do Squid apenas quando os testes de integração retornarem mensagem de sucesso (comandos net ads testjoin e wbinfo -t, por exemplo).

Em seguida, certifique-se da existência dos seguintes módulos:

root@proxysrv:~# ls /usr/lib/squid/* /usr/bin/ntlm_auth | grep "\(wrapper\|ntlm_auth\|kerberos_auth\b\)"
/usr/bin/ntlm_auth
/usr/lib/squid/negotiate_kerberos_auth
/usr/lib/squid/negotiate_wrapper_auth

Caso não encontre os dois últimos módulos exibidos em /usr/lib/squid, é provável que sua compilação não ofereça suporte ao Kerberos. Se este for o caso, instale as bibliotecas de desenvolvimento e recompile o Squid (vide parte 1). Para confirmar as opções de compilação, utilize o comando “squid -v“.

Se necessário (recompilação), instale as bibliotecas de desenvolvimento:

apt-get install krb5-user libkrb5-3 libkrb5-dev libsasl2-modules-gssapi-mit

Certifique-se também da existência do winbind. Não esqueça de ajustar a permissão do usuário proxy, incluindo no grupo winbindd_priv:

apt-get install winbind
chgrp winbindd_priv /var/lib/samba/winbindd_privileged
gpasswd -a proxy winbindd_priv

Neste caso, edite o arquivo de configuração e comente a opção cache_effective_group para evitar que o Squid fixe um único grupo como efetivo, ignorando o mapeamento de grupo alternativo. Do contrário, inviabilizará o mapeamento sugerido.

Com esta configuração, já é possível validar o módulo ntlm_auth sob os esquemas NTLM e Basic. Até este ponto é simples. Mas, a configuração do Kerberos tende ser um pouco mais trabalhosa e depende de uma atenção adicional. Volto a frisar, os mapeamentos de DNS são obrigatórios e devemos utilizar o nome FQDN do servidor na configuração dos navegadores.

Para incluir o suporte à autenticação Kerberos será necessária a inclusão de alguns registros LDAP, criação de um SPN para classe de serviço HTTP e geração do arquivo com a estrutura de chaves para HTTP/nome_fqdn_do_servidor (keytab).

O processo descrito acima pode ser feito, no servidor Linux, através da ferramenta msktutil.

 

1. Instalação da ferramenta msktutil

Opte, preferencialmente, pelo download no site oficial. Já encontrei dificuldade com o binário disponível nos repositórios do Ubuntu (algumas versões).

wget https://fuhm.net/software/msktutil/releases/msktutil_0.4-2_amd64.deb

ou

apt-get install msktutil

 

2. Geração do keytab para HTTP/nome_fqdn_do_servidor

Neste exemplo, estou supondo que o nome FQDN do servidor é proxysrv.local e o SPN será HTTP/proxysrv.local. Em computer-name informe o nome netbios (até o limite de 15 caracteres) – é um nome específico apenas para este propósito (diferente do nome mapeado com net join).

Antes de executar o comando msktutil, inicie uma sessão administrativa com kinit“.

kinit adminitrator@LOCAL
msktutil -c -s HTTP/proxysrv.local -k /etc/squid/PROXY.keytab --computer-name k-proxy --upn HTTP/proxysrv.local --server dc001.local --verbose --enctypes 28

chown proxy.proxy /etc/squid/PROXY.keytab
chmod 640 /etc/squid/PROXY.keytab

Altere o arquivo /etc/krb5.conf, incluindo a seguinte linha:

...
        ticket_lifetime = 24h
        default_keytab_name = /etc/squid/PROXY.keytab
        default_tkt_enctypes = rc4-hmac

        default_tgs_enctypes = aes256-cts-hmac-sha1-96 rc4-hmac des-cbc-crc des-cbc-md5
        permitted_enctypes = aes256-cts-hmac-sha1-96 rc4-hmac des-cbc-crc des-cbc-md5
...

 

Em seguida, edite o script de inicialização do serviço (em /etc/init.d/squid, por exemplo) e inclua as seguintes linhas:

KRB5_KTNAME=/etc/squid/PROXY.keytab
KRB5RCACHETYPE=none
export KRB5_KTNAME
export KRB5RCACHETYPE

A variável KRB5RCACHETYPE deve ser definida como none caso o cache comprometa o consumo de CPU – infelizmente, na maioria das vezes, compromete“.

 

Podemos validar o keytab abrindo uma nova sessão a partir do SPN criado anteriormente:

– Domínio local e realm LOCAL

root@proxysrv:~# kdestroy

root@proxysrv:~# klist -ek
Keytab name: FILE:/etc/squid/PROXY.keytab
KVNO Principal
---- --------------------------------------------------------------------------
...
   2 HTTP/proxysrv.local@LOCAL (arcfour-hmac) 
   2 HTTP/proxysrv.local@LOCAL (aes128-cts-hmac-sha1-96) 
   2 HTTP/proxysrv.local@LOCAL (aes256-cts-hmac-sha1-96) 
   2 host/proxysrv.local@LOCAL (arcfour-hmac) 
   2 host/proxysrv.local@LOCAL (aes128-cts-hmac-sha1-96) 
   2 host/proxysrv.local@LOCAL (aes256-cts-hmac-sha1-96) 


root@proxysrv:~# kinit -V -k -t /etc/squid/PROXY.keytab HTTP/proxysrv.local@LOCAL

root@proxysrv:~# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: HTTP/proxysrv.local@LOCAL

Valid starting       Expires              Service principal
04-06-2017 14:35:06  05-06-2017 00:35:06  krbtgt/LOCAL@LOCAL
        renew until 05-06-2017 14:35:06

root@proxysrv:~# kdestroy

 

3. Mantendo o keytab atualizado (em função da política de expiração de senhas): Agende uma tarefa diária no cron para executar o msktutil com a opção –auto-update.

– Inclua um novo agendamento, como root, com crontab -e

00 4 * * * msktutil --auto-update --verbose --computer-name k-proxy | logger -t msktutil

 

Para finalizar, basta alterar a configuração dos helpers (acl/buildauth/authmodule):

## Negotiate kerberos/NTLM module
auth_param negotiate program /usr/lib/squid/negotiate_wrapper_auth --ntlm /usr/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp --use-cached-creds --kerberos /usr/lib/squid/negotiate_kerberos_auth -s GSS_C_NO_NAME
auth_param negotiate children 200 startup=15 idle=5
auth_param negotiate keep_alive on

## NTLM Auth
auth_param ntlm program /usr/bin/ntlm_auth --use-cached-creds --helper-protocol=squid-2.5-ntlmssp
auth_param ntlm children 110 startup=5 idle=5
auth_param ntlm keep_alive on

## Basic NTLM plugin Auth
auth_param basic program /usr/bin/ntlm_auth --use-cached-creds --helper-protocol=squid-2.5-basic
auth_param basic children 110 startup=5 idle=5
auth_param basic credentialsttl 2 hours
auth_param basic casesensitive off

auth_param basic realm "Squid Proxy"

Reinicie o serviço para recarregar a configuração:

service squid stop
service squid start

ou

/etc/init.d/squid stop
/etc/init.d/squid start

Mais uma vez, o assunto prolongou um pouco mais do que imaginei. Ficou extenso porque procurei detalhar cada fase. O processo, em si, depois de compreendido, é muito simples.

Procurei organizar o texto de uma forma que facilite na compreensão das opções de configuração e técnicas de depuração. Já passei por inúmeras dificuldades e estas dicas me ajudaram bastante. A configuração com balanceamento de carga é um pouco mais complexa (precisa prever os nós de balanceamento também) e será tema de outro artigo no futuro.

– Confiram algumas referências de pesquisa:
http://wiki.bitbinary.com/index.php/Active_Directory_Integrated_Squid_Proxy
https://wiki.gentoo.org/wiki/Kerberos_Windows_Interoperability
https://www.safesquid.com/content-filtering/integrating-linux-host-windows-ad-kerberos-sso-authentication
https://fuhm.net/software/msktutil/manpage.html

– Outro link interessante, onde fiz uma pequena participação (comentando):
https://www.mundotibrasil.com.br/integrando-squid-com-grupos-do-active-directory/