Esta solução não é algo super original, mas sim uma mistura de diferentes soluções encontradas na Internet.
Então, dado
Domínio do Active Directory .
Usuários de domínio usando VPN, como muitos hoje. Fortigate
atua como um gateway VPN . Salvar a senha do cliente VPN é proibido pela política de segurança. A política da Fortinet em relação aos seus próprios tokens não pode ser menos do que redneck - já existem 10 tokens grátis, o resto está a um preço muito diferente do kosher. RSASecureID, Duo e similares não foram considerados, porque eu quero código aberto. Pré-requisitos: * host nix com freeradius instalado , sssd - inserido no domínio, os usuários do domínio podem se autenticar facilmente nele. Pacotes adicionais:
shellinabox , figlet , freeeradius-ldap , fonte rebel.tlf do repositório https://github.com/xero/figlet-fonts .
No meu exemplo, CentOS 7.8.
A lógica de trabalho é a seguinte: ao se conectar a uma VPN, um usuário deve inserir um login de domínio e OTP em vez de uma senha.
Configurando serviços
Em /etc/raddb/radiusd.conf, apenas o usuário e grupo sob o qual o freeradius é iniciado é alterado , uma vez que o serviço radiusd deve ser capaz de ler arquivos em todos os subdiretórios de / home / .
user = root
group = root
Para poder usar grupos nas configurações do Fortigate , você precisa passar o Atributo específico do fornecedor . Para fazer isso, no diretório raddb / policy.d, crie um arquivo com o seguinte conteúdo:
group_authorization {
if (&LDAP-Group[*] == "CN=vpn_admins,OU=vpn-groups,DC=domain,DC=local") {
update reply {
&Fortinet-Group-Name = "vpn_admins" }
update control {
&Auth-Type := PAM
&Reply-Message := "Welcome Admin"
}
}
else {
update reply {
&Reply-Message := "Not authorized for vpn"
}
reject
}
}
Após instalar o freeradius-ldap no diretório raddb / mods-available, o arquivo ldap é criado .
Você precisa criar um link simbólico para o diretório habilitado para raddb / mods .
ln -s /etc/raddb/mods-available/ldap /etc/raddb/mods-enabled/ldap
Eu trago seu conteúdo para este formulário:
ldap {
server = 'domain.local'
identity = 'CN=freerad_user,OU=users,DC=domain,DC=local'
password = "SupeSecretP@ssword"
base_dn = 'dc=domain,dc=local'
sasl {
}
user {
base_dn = "${..base_dn}"
filter = "(sAMAccountname=%{%{Stripped-User-Name}:-%{User-Name}})"
sasl {
}
scope = 'sub'
}
group {
base_dn = "${..base_dn}"
filter = '(objectClass=Group)'
scope = 'sub'
name_attribute = cn
membership_filter = "(|(member=%{control:Ldap-UserDn})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))"
membership_attribute = 'memberOf'
}
}
Nos arquivos raddb / sites-enabled / default e raddb / sites-enabled / inner-tunnel na seção de autorização , adiciono o nome da política que será usada - group_authorization. Um ponto importante - o nome da política é determinado não pelo nome do arquivo no diretório policy.d , mas pela diretiva dentro do arquivo antes das chaves.
Na seção de autenticação dos mesmos arquivos, descomente o pam .
No arquivo clients.conf, escreva os parâmetros com os quais o Fortigate se conectará :
client fortigate {
ipaddr = 192.168.1.200
secret = testing123
require_message_authenticator = no
nas_type = other
}
Configuração do módulo Pam.d / radiusd :
#%PAM-1.0
auth sufficient pam_google_authenticator.so
auth include password-auth
account required pam_nologin.so
account include password-auth
password include password-auth
session include password-auth
As opções padrão para implementar o pacote freeradius com o autenticador Google envolvem o usuário inserir credenciais no formato: nome de usuário / senha + OTP .
Tendo apresentado o número de maldições que cairão em sua cabeça, no caso de usar o pacote padrão freeradius com Google Authenticator , decidiu-se usar a configuração do módulo pam para verificar apenas o token Google Authenticator .
Quando um usuário se conecta, acontece o seguinte:
- O Freeradius verifica a presença do usuário no domínio e em um grupo específico e, se for bem-sucedido, verifica o token OTP.
Tudo parecia bom o suficiente até que pensei: "Como posso registrar OTP para mais de 300 usuários?"
O usuário deve fazer login no servidor com o freeradius e em sua conta e executar o aplicativo autenticador do Google , que irá gerar um código QR do aplicativo para o usuário. É aqui que o shellinabox se torna útil em combinação com .bash_profile .
[root@freeradius ~]# yum install -y shellinabox
O arquivo de configuração do daemon está localizado em / etc / sysconfig / shellinabox .
Eu indico a porta 443 lá e você pode especificar seu certificado.
[root@freeradius ~]#systemctl enable --now shellinaboxd
O usuário só precisa seguir o link, inserir os créditos do domínio e receber o código QR do aplicativo.
O algoritmo é o seguinte:
- O usuário efetua login na máquina por meio de um navegador.
- O usuário do domínio é verificado. Caso contrário, nenhuma ação será realizada.
- Se o usuário for um usuário de domínio, a associação ao grupo Administradores será verificada.
- Se não for administrador, ele verifica se o Google Autheticator está configurado. Caso contrário, um código QR e o logout do usuário são gerados.
- Se não for um administrador e o Google Authenticator estiver configurado, basta fazer logout.
- Se for o administrador, verifique novamente o Google Authenticator. Se não for configurado, um código QR será gerado.
Toda a lógica é feita usando /etc/skel/.bash_profile .
cat /etc/skel/.bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
# Make several commands available from user shell
if [[ -z $(id $USER | grep "admins") || -z $(cat /etc/passwd | grep $USER) ]]
then
[[ ! -d $HOME/bin ]] && mkdir $HOME/bin
[[ ! -f $HOME/bin/id ]] && ln -s /usr/bin/id $HOME/bin/id
[[ ! -f $HOME/bin/google-auth ]] && ln -s /usr/bin/google-authenticator $HOME/bin/google-auth
[[ ! -f $HOME/bin/grep ]] && ln -s /usr/bin/grep $HOME/bin/grep
[[ ! -f $HOME/bin/figlet ]] && ln -s /usr/bin/figlet $HOME/bin/figlet
[[ ! -f $HOME/bin/rebel.tlf ]] && ln -s /usr/share/figlet/rebel.tlf $HOME/bin/rebel.tlf
[[ ! -f $HOME/bin/sleep ]] && ln -s /usr/bin/sleep $HOME/bin/sleep
# Set PATH env to <home user directory>/bin
PATH=$HOME/bin
export PATH
else
PATH=PATH=$PATH:$HOME/.local/bin:$HOME/bin
export PATH
fi
if [[ -n $(id $USER | grep "domain users") ]]
then
if [[ ! -e $HOME/.google_authenticator ]]
then
if [[ -n $(id $USER | grep "admins") ]]
then
figlet -t -f $HOME/bin/rebel.tlf "Welcome to Company GAuth setup portal"
sleep 1.5
echo "Please, run any of these software on your device, where you would like to setup OTP:
Google Autheticator:
AppStore - https://apps.apple.com/us/app/google-authenticator/id388497605
Play Market - https://play.google.com/stor/apps/details?id=com.google.android.apps.authenticator2&hl=en
FreeOTP:
AppStore - https://apps.apple.com/us/app/freeotp-authenticator/id872559395
Play Market - https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp&hl=en
And prepare to scan QR code.
"
sleep 5
google-auth -f -t -w 3 -r 3 -R 30 -d -e 1
echo "Congratulations, now you can use an OTP token from application as a password connecting to VPN."
else
figlet -t -f $HOME/bin/rebel.tlf "Welcome to Company GAuth setup portal"
sleep 1.5
echo "Please, run any of these software on your device, where you would like to setup OTP:
Google Autheticator:
AppStore - https://apps.apple.com/us/app/google-authenticator/id388497605
Play Market - https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en
FreeOTP:
AppStore - https://apps.apple.com/us/app/freeotp-authenticator/id872559395
Play Market - https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp&hl=en
And prepare to scan QR code.
"
sleep 5
google-auth -f -t -w 3 -r 3 -R 30 -d -e 1
echo "Congratulations, now you can use an OTP token from application as a password to VPN."
logout
fi
else
echo "You have already setup a Google Authenticator"
if [[ -z $(id $USER | grep "admins") ]]
then
logout
fi
fi
else
echo "You don't need to set up a Google Authenticator"
fi
Configuração de fortificação:
- Crie um servidor Radius

- Criamos os grupos necessários, se necessário diferenciamos o acesso por grupos. O nome do grupo em Fortigate deve corresponder ao grupo que é passado no Atributo específico do fornecedor Fortinet-Group-Name .

- Editando os portais SSL necessários .

- Adicione grupos às políticas.

As vantagens desta solução:
- Existe a possibilidade de autenticação OTP na solução de código aberto Fortigate .
- Isso exclui o usuário que insere a senha de domínio ao se conectar via VPN, o que simplifica um pouco o processo de conexão. A senha de 6 dígitos é mais fácil de inserir do que a política de segurança. Como resultado, o número de tíquetes com o assunto: "Não é possível conectar-se à VPN" diminui.
PS: Planejamos transformar essa solução em uma autorização completa de dois fatores com resposta de desafio.
Atualizar:
Como prometido, terminei até a opção desafio-resposta.
Portanto:
No arquivo / etc / raddb / sites-enabled / default , a seção de autorização tem a seguinte aparência:
authorize {
filter_username
preprocess
auth_log
chap
mschap
suffix
eap {
ok = return
}
files
-sql
#-ldap
expiration
logintime
if (!State) {
if (&User-Password) {
# If !State and User-Password (PAP), then force LDAP:
update control {
Ldap-UserDN := "%{User-Name}"
Auth-Type := LDAP
}
}
else {
reject
}
}
else {
# If State, then proxy request:
group_authorization
}
pap
}
A seção de autenticação agora se parece com isto:
authenticate {
Auth-Type PAP {
pap
}
Auth-Type CHAP {
chap
}
Auth-Type MS-CHAP {
mschap
}
mschap
digest
# Attempt authentication with a direct LDAP bind:
Auth-Type LDAP {
ldap
if (ok) {
update reply {
# Create a random State attribute:
State := "%{randstr:aaaaaaaaaaaaaaaa}"
Reply-Message := "Please enter OTP"
}
# Return Access-Challenge:
challenge
}
}
pam
eap
}
Agora o usuário é verificado de acordo com o seguinte algoritmo:
- O usuário insere créditos de domínio no cliente VPN.
- Freeradius verifica a validade da conta e senha
- Se a senha estiver correta, uma solicitação de token será enviada.
- O token é verificado.
- Lucro).