Freeradius + Google Autheticator + LDAP + Fortigate

E se você quiser uma autenticação de dois fatores e doer, mas não houver dinheiro para tokens de hardware e, em geral, eles oferecem para ficar de bom humor.



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).



All Articles