Co jeśli uwierzytelnianie dwuskładnikowe jest zarówno pożądane, jak i kłujące, ale nie ma pieniędzy na tokeny sprzętowe i ogólnie oferują pozostanie w dobrym nastroju.
To rozwiązanie nie jest czymś super oryginalnym, a raczej mieszanką różnych rozwiązań znalezionych w Internecie.
Tak podane
Домен Active Directory.
Użytkownicy domeny pracujący przez VPN, jak wielu dzisiaj.
Działa jako brama VPN fortygować.
Zapisywanie hasła do klienta VPN jest zabronione przez politykę bezpieczeństwa.
Polityka Fortinet w odniesieniu do własnych tokenów nie można tego nazwać mniej niż zhlob - jest aż 10 darmowych tokenów, reszta - w bardzo niekoszernej cenie. Nie brałem pod uwagę RSASecureID, Duo i tym podobnych, ponieważ chcę open source.
Wymagania wstępne: host *nic z ustalonym freeradius, SSD - wpisany do domeny, użytkownicy domeny mogą łatwo się na nim uwierzytelniać.
Dodatkowe pakiety: Pudełko Shelliny, figleta, freeradius-ldap, czcionka bunt.tlf z repozytorium
W moim przykładzie - CentOS 7.8.
Logika pracy ma być następująca: łącząc się z VPN, użytkownik zamiast hasła musi podać login domeny i OTP.
Konfiguracja usług
В /etc/raddb/radiusd.conf tylko użytkownik i grupa, w imieniu której się uruchamia freeradius, od usługi promień powinien mieć możliwość odczytu plików we wszystkich podkatalogach /Dom/.
user = root
group = root
Aby móc korzystać z grup w ustawieniach fortygować, należy przesłać Atrybut specyficzny dla dostawcy. Aby to zrobić, w katalogu raddb/policy.d Tworzę plik o następującej treści:
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
}
}
Po instalacji freeradius-ldap w katalogu raddb/mods-dostępne tworzony jest plik ldap.
Musisz utworzyć dowiązanie symboliczne do katalogu raddb/obsługa modów.
ln -s /etc/raddb/mods-available/ldap /etc/raddb/mods-enabled/ldap
Doprowadzam jego zawartość do tej postaci:
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'
}
}
w plikach raddb/witryny włączone/domyślne и raddb/obsługa witryn/tunel-wewnętrzny w sekcji autoryzować Dodaję nazwę polityki, która ma być używana - group_authorization. Ważna uwaga - nazwa polityki nie jest określana przez nazwę pliku w katalogu polityka.d, ale przez dyrektywę wewnątrz pliku przed nawiasami klamrowymi.
W dziale uwierzytelniać w tych samych plikach musisz odkomentować linię pam.
W pliku klienci.konf określić parametry, z którymi będzie się łączyć fortygować:
client fortigate {
ipaddr = 192.168.1.200
secret = testing123
require_message_authenticator = no
nas_type = other
}
Konfiguracja modułu 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
Domyślne opcje implementacji pakietu freeradius с uwierzytelnianie google wymagać od użytkownika wprowadzenia poświadczeń w formacie: Nazwa użytkownika Hasło+OTP.
Wyobrażając sobie liczbę klątw, które spadną na głowę, w przypadku korzystania z domyślnego pakietu freeradius с Google Authenticator, zdecydowano się na wykorzystanie konfiguracji modułu pam aby można było sprawdzić tylko token Google Authenticator.
Gdy użytkownik się łączy, dzieje się co następuje:
- Freeradius sprawdza, czy użytkownik jest w domenie i określonej grupie, a jeśli się powiedzie, sprawdza token OTP.
Wszystko wyglądało wystarczająco dobrze, aż do momentu, kiedy pomyślałem „Jak mogę zarejestrować OTP dla ponad 300 użytkowników?”
Użytkownik musi zalogować się na serwerze za pomocą freeradius i spod swojego konta i uruchom aplikację Wystawca uwierzytelnienia Google, który wygeneruje dla użytkownika kod QR dla aplikacji. Tu przychodzi pomoc. Pudełko Shelliny w połączeniu z .bash_profil.
[root@freeradius ~]# yum install -y shellinabox
Plik konfiguracyjny demona znajduje się pod adresem /etc/sysconfig/shellinabox.
Określam tam port 443 i możesz określić swój certyfikat.
[root@freeradius ~]#systemctl enable --now shellinaboxd
Użytkownik musi tylko kliknąć link, wprowadzić kredyty domeny i otrzymać kod QR dla aplikacji.
Algorytm wygląda następująco:
- Użytkownik loguje się do urządzenia przez przeglądarkę.
- Czy użytkownik domeny jest zaznaczony. Jeśli nie, nie podejmuje się żadnych działań.
- Jeśli użytkownik jest użytkownikiem domeny, sprawdzane jest członkostwo w grupie Administratorzy.
- Jeśli nie jest administratorem, sprawdza, czy jest skonfigurowany Google Authenticator. Jeśli nie, generowany jest kod QR i wylogowanie użytkownika.
- Jeśli nie jest to administrator, a Google Authenticator jest skonfigurowany, po prostu się wyloguj.
- Jeśli jesteś administratorem, sprawdź ponownie Google Authenticator. Jeśli nie jest skonfigurowany, generowany jest kod QR.
Cała logika odbywa się za pomocą /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
Konfiguracja Fortigate:
- Tworzymy Promień-serwer
- Tworzymy niezbędne grupy, jeśli to konieczne, kontrolę dostępu według grup. Nazwa grupy włączona fortygować musi pasować do przekazanej grupy Atrybut specyficzny dla dostawcy Nazwa-grupy-Fortinet.
- Edycja niezbędnych SSL-portale.
- Dodawanie grup do zasad.
Zalety tego rozwiązania:
- Możliwe jest uwierzytelnienie przez OTP na fortygować rozwiązanie open source.
- Użytkownik nie wprowadza hasła do domeny podczas łączenia przez VPN, co nieco upraszcza proces łączenia. 6-cyfrowe hasło jest łatwiejsze do wprowadzenia niż to, które zapewnia polityka bezpieczeństwa. W efekcie spada liczba zgłoszeń z tematem: „Nie mogę połączyć się z VPN”.
PS Planujemy uaktualnienie tego rozwiązania do pełnoprawnego uwierzytelniania dwuskładnikowego z funkcją challenge-response.
aktualizacja:
Zgodnie z obietnicą dostosowałem go do opcji wyzwanie-odpowiedź.
Tak więc:
W pliku /etc/raddb/sites-enabled/default Sekcja autoryzować wygląda tak:
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
}
sekcja uwierzytelniać teraz wygląda tak:
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
}
Teraz weryfikacja użytkownika odbywa się zgodnie z następującym algorytmem:
- Użytkownik wprowadza kredyty domeny w kliencie VPN.
- Freeradius sprawdza ważność konta i hasła
- Jeśli hasło jest poprawne, wysyłana jest prośba o token.
- Token jest weryfikowany.
- zysk).
Źródło: www.habr.com