Cisco AnyConnect 經過FreeRADIUS集成域帳號+Google MFA認證

實驗目的:用戶使用Cisco AnyConnect撥號時,輸入AD帳號密碼和Google動態碼後經過認證,得到受權。Cisco ASA指向FreeRADIUS作認證,FreeRADIUS聯動AD和google_authenticator。python

1、環境介紹

  • 拓撲圖

【AnyConnect freeradius ad mfa】topo

  • 實驗環境CentOS8有兩塊網卡,一塊網卡用於訪問Internet,一塊網卡位於防火牆inside區域。
  • 這裏使用CentOS8(CentOS7也能夠)安裝FreeRADIUS和Google Authenticator。Windows Server 2016安裝AD服務,AD安裝過程這裏不作介紹。須要用戶在手機上安裝Google-Authenticator APP。
  • 用戶使用AnyConnect撥號,輸入用戶名和密碼,密碼框輸入密碼+動態碼,實現AD帳號+動態碼雙因素認證。

2、CentOS8 環境設置

  • 系統更新linux

    [root@centos8 ~]# yum update
  • 修改時區c++

    [root@centos8 /]# ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
  • 查看時間是否正確git

    [root@centos8 /]#ll /etc/localtime
  • 關閉SElinux,臨時關閉和永久關閉。github

    [root@centos8 ~]# setenforce 0
    [root@centos8 ~]# sed -i 's/=enforcing/=permissive/g' /etc/selinux/config
  • 查看SElinux狀態。web

    [root@centos8 ~]# getenforce
    Permissive
  • 關閉防火牆(可選),本次實驗未關閉防火牆。
    [root@centos8 ~]# systemctl stop firewalld.service
    [root@centos8 ~]# systemctl disable firewalld.service

3、FreeRADIUS 安裝及配置

3.1 FreeRADIUS安裝

  • 安裝FreeRADIUSbootstrap

    [root@centos8 ~]# yum install freeradius freeradius-utils
  • 啓動radius服務centos

    [root@centos8 ~]# systemctl enable --now radiusd.service
  • 防火牆放行radius
    [root@centos8 ~]# firewall-cmd --add-service=radius --permanent
    [root@centos8 ~]# firewall-cmd --reload

3.2 FreeRADIUS修改配置文件

  • 因爲FreeRadius必須有權訪問全部用戶目錄中的.google_authenticator令牌,所以它必須具備root權限。
[root@centos8 ~]# vi /etc/raddb/radiusd.conf

        #user = radiusd
        #group = radiusd
        user = root
        group = root
  • 取消pam的註釋,radius激活PAM(Pluggable Authentication Modules)可動態加載驗證模塊。
[root@centos8 ~]#  vi /etc/raddb/sites-enabled/default

        pam
  • 激活pam,radius pam模塊默認沒有激活。
[root@centos8 ~]#  ln -s /etc/raddb/mods-available/pam /etc/raddb/mods-enabled/pam
  • 編輯/etc/raddb/clients.conf配置文件,接受來Cisco ASAv的radius認證請求。在行末添加防火牆的與共享密鑰和ip地址。
[root@centos8 ~]# vi /etc/raddb/clients.conf

client 192.168.1.254 {
 secret = cisco
 shortname = CiscoASA
 nastype = cisco
}

3.3 FreeRADIUS 服務測試

  • 新建用戶組,若是你須要拒絕用戶訪問,能夠將用戶加入到這個組。
[root@centos8 ~]# groupadd radius-disabled
  • 編輯/etc/raddb/users將建立的「radius-disabled」組添加到「拒絕用戶組」部分。
[root@centos8 ~]# vi /etc/raddb/users

#DEFAULT        Group == "disabled", Auth-Type := Reject
#               Reply-Message = "Your account has been disabled."

DEFAULT         Group == "radius-disabled", Auth-Type := Reject
                Reply-Message = "Your account has been disabled."
DEFAULT         Auth-Type := PAM
  • CentOS新建本地帳號測試radius服務。
[root@centos8 ~]# useradd radlocal
[root@centos8 ~]# passwd radlocal
更改用戶 radlocal 的密碼 。
新的 密碼:radpassword
從新輸入新的 密碼:radpassword
passwd:全部的身份驗證令牌已經成功更新。
  • radius 開啓調式模式,這個命令很是有用,若是認證不成功,能夠根據報錯信息定位到錯誤發生的緣由。
[root@centos8 ~]# radiusd -X
  • 新建一個窗口,測試本地帳號radius驗證是否經過,注意Received Access-Accept表示認證經過。
[root@centos8 ~]# radtest radlocal radpassword localhost 18120 testing123
Sent Access-Request Id 9 from 0.0.0.0:41546 to 127.0.0.1:1812 length 78
        User-Name = "radlocal"
        User-Password = "radpassword"
        NAS-IP-Address = 172.20.29.110
        NAS-Port = 18120
        Message-Authenticator = 0x00
        Cleartext-Password = "radpassword"
Received Access-Accept Id 9 from 127.0.0.1:1812 to 127.0.0.1:41546 length 20
  • 開啓radius -X窗口顯示的輸出做爲參考。
Listening on auth address 127.0.0.1 port 18120 bound to server inner-tunnel
Listening on proxy address * port 43164
Listening on proxy address :: port 40551
Ready to process requests
(0) Received Access-Request Id 9 from 127.0.0.1:41546 to 127.0.0.1:1812 length 78
(0)   User-Name = "radlocal"
(0)   User-Password = "radpassword"
(0)   NAS-IP-Address = 172.20.29.110
(0)   NAS-Port = 18120
(0)   Message-Authenticator = 0xeba37c10c860860bd3dcc7bff2c5edf0
(0) # Executing section authorize from file /etc/raddb/sites-enabled/default
(0)   authorize {
(0)     policy filter_username {
(0)       if (&User-Name) {
(0)       if (&User-Name)  -> TRUE
(0)       if (&User-Name)  {
(0)         if (&User-Name =~ / /) {
(0)         if (&User-Name =~ / /)  -> FALSE
(0)         if (&User-Name =~ /@[^@]*@/ ) {
(0)         if (&User-Name =~ /@[^@]*@/ )  -> FALSE
(0)         if (&User-Name =~ /\.\./ ) {
(0)         if (&User-Name =~ /\.\./ )  -> FALSE
(0)         if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/))  {
(0)         if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/))   -> FALSE
(0)         if (&User-Name =~ /\.$/)  {
(0)         if (&User-Name =~ /\.$/)   -> FALSE
(0)         if (&User-Name =~ /@\./)  {
(0)         if (&User-Name =~ /@\./)   -> FALSE
(0)       } # if (&User-Name)  = notfound
(0)     } # policy filter_username = notfound
(0)     [preprocess] = ok
(0)     [chap] = noop
(0)     [mschap] = noop
(0)     [digest] = noop
(0) suffix: Checking for suffix after "@"
(0) suffix: No '@' in User-Name = "radlocal", looking up realm NULL
(0) suffix: No such realm "NULL"
(0)     [suffix] = noop
(0) eap: No EAP-Message, not doing EAP
(0)     [eap] = noop
(0) files: users: Matched entry DEFAULT at line 69
(0)     [files] = ok
(0)     [expiration] = noop
(0)     [logintime] = noop
(0) pap: WARNING: No "known good" password found for the user.  Not setting Auth-Type
(0) pap: WARNING: Authentication will fail unless a "known good" password is available
(0)     [pap] = noop
(0)   } # authorize = ok
(0) Found Auth-Type = pam
(0) # Executing group from file /etc/raddb/sites-enabled/default
(0)   authenticate {
(0) pam: Using pamauth string "radiusd" for pam.conf lookup
(0) pam: Authentication succeeded
(0)     [pam] = ok
(0)   } # authenticate = ok
(0) # Executing section post-auth from file /etc/raddb/sites-enabled/default
(0)   post-auth {
(0)     update {
(0)       No attributes updated
(0)     } # update = noop
(0)     [exec] = noop
(0)     policy remove_reply_message_if_eap {
(0)       if (&reply:EAP-Message && &reply:Reply-Message) {
(0)       if (&reply:EAP-Message && &reply:Reply-Message)  -> FALSE
(0)       else {
(0)         [noop] = noop
(0)       } # else = noop
(0)     } # policy remove_reply_message_if_eap = noop
(0)   } # post-auth = noop
(0) Sent Access-Accept Id 9 from 127.0.0.1:1812 to 127.0.0.1:41546 length 0
(0) Finished request
Waking up in 4.9 seconds.
(0) Cleaning up request packet ID 9 with +50
Ready to process requests

4、SSSD安裝配置

  • AD已經安裝和配置完成,下面是AD的一些配置信息。建立python.com域,DNS能解析公網地址,防止CentOS DNS指向AD以後沒法yum安裝軟件。

【AnyConnect freeradius ad mfa】ad-01.png

  • 建立mfatest的A記錄,CentOS作測試解析用途。

【AnyConnect freeradius ad mfa】ad-02.png

  • 安裝SSSD,CentOS8已經內建。
[root@centos8 ~]# yum install sssd realmd adcli
[root@centos8 ~]# yum install oddjob oddjob-mkhomedir sssd samba-commontools
  • 修改DNS,指向AD的IP地址。
[root@centos8 ~]# vi /etc/resolv.conf
nameserver 192.168.1.20
  • DNS連通性測試
[root@centos8 ~]# ping python.com
PING python.com (192.168.1.20) 56(84) bytes of data.
64 bytes from 192.168.1.20 (192.168.1.20): icmp_seq=1 ttl=128 time=0.205 ms
  • DNS解析測試
[root@centos8 ~]# nslookup
> mfatest.python.com
Server:         192.168.1.20
Address:        192.168.1.20#53

Name:   mfatest.python.com
Address: 1.1.1.1
  • CentOS加入python.com域,輸入管理員密碼。
[root@centos8 ~]# realm join python.com
Administrator 的密碼:
  • 能夠發現域信息。
[root@centos8 ~]# realm list
python.com
  type: kerberos
  realm-name: PYTHON.COM
  domain-name: python.com
  configured: kerberos-member
  server-software: active-directory
  client-software: sssd
  required-package: oddjob
  required-package: oddjob-mkhomedir
  required-package: sssd
  required-package: adcli
  required-package: samba-common-tools
  login-formats: %U@python.com
  login-policy: allow-permitted-logins
  permitted-logins:
  permitted-groups: ***users
  • AD查看CentOS8加入成功。

【AnyConnect freeradius ad mfa】ad-03.png

  • AD上建立測試用戶wintest

【AnyConnect freeradius ad mfa】ad-04.png

  • 在CentOS上使用AD的用戶名密碼登陸測試。
[root@centos8 ~]# ssh -l wintest@python.com localhost
The authenticity of host 'localhost (::1)' can't be established.
ECDSA key fingerprint is SHA256:JNzSM2I5llmwVPjZAmZa0n1TS9dAZJYTgB2Odpq5IWA.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
wintest@python.com@localhost's password:
Activate the web console with: systemctl enable --now cockpit.socket

[wintest@python.com@centos8 ~]$ exit
註銷
  • AD建立users組,建立user用戶

【AnyConnect freeradius ad mfa】ad-05.png

  • CentOS放行容許***users這個組的用戶在這臺機器上認證。這條命令容許全部域帳號認證:realm permit -all。這裏放行的認證,不僅放行了radius,還放行了ssh的認證,生產環境應該禁止這個組用戶登
    錄ssh。服務器

    [root@centos8 ~]# realm permit -g ***users
  • 開啓radius調試模式session

    [root@centos8 ~]#radius -X
  • 在新的窗口,使用AD帳號測試radius認證,認證經過。
[root@centos8 ~]# radtest ***user@python.com Cisc0123 localhost 18120 testing123
Sent Access-Request Id 16 from 0.0.0.0:38424 to 127.0.0.1:1812 length 88
        User-Name = "***user@python.com"
        User-Password = "Cisc0123"
        NAS-IP-Address = 172.20.29.110
        NAS-Port = 18120
        Message-Authenticator = 0x00
        Cleartext-Password = "Cisc0123"
Received Access-Accept Id 16 from 127.0.0.1:1812 to 127.0.0.1:38424 length 20
  • radius調試模式看到的日誌。
(2) Received Access-Request Id 16 from 127.0.0.1:38424 to 127.0.0.1:1812 length 88
(2)   User-Name = "***user@python.com"
(2)   User-Password = "Cisc0123"
(2)   NAS-IP-Address = 172.20.29.110
(2)   NAS-Port = 18120
(2)   Message-Authenticator = 0xd2adbf7920450d47617cc1c7128e437e
(2) # Executing section authorize from file /etc/raddb/sites-enabled/default
(2)   authorize {
(2)     policy filter_username {
(2)       if (&User-Name) {
(2)       if (&User-Name)  -> TRUE
(2)       if (&User-Name)  {
(2)         if (&User-Name =~ / /) {
(2)         if (&User-Name =~ / /)  -> FALSE
(2)         if (&User-Name =~ /@[^@]*@/ ) {
(2)         if (&User-Name =~ /@[^@]*@/ )  -> FALSE
(2)         if (&User-Name =~ /\.\./ ) {
(2)         if (&User-Name =~ /\.\./ )  -> FALSE
(2)         if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/))  {
(2)         if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/))   -> FALSE
(2)         if (&User-Name =~ /\.$/)  {
(2)         if (&User-Name =~ /\.$/)   -> FALSE
(2)         if (&User-Name =~ /@\./)  {
(2)         if (&User-Name =~ /@\./)   -> FALSE
(2)       } # if (&User-Name)  = notfound
(2)     } # policy filter_username = notfound
(2)     [preprocess] = ok
(2)     [chap] = noop
(2)     [mschap] = noop
(2)     [digest] = noop
(2) suffix: Checking for suffix after "@"
(2) suffix: Looking up realm "python.com" for User-Name = "***user@python.com"
(2) suffix: No such realm "python.com"
(2)     [suffix] = noop
(2) eap: No EAP-Message, not doing EAP
(2)     [eap] = noop
(2) files: users: Matched entry DEFAULT at line 69
(2)     [files] = ok
(2)     [expiration] = noop
(2)     [logintime] = noop
(2) pap: WARNING: No "known good" password found for the user.  Not setting Auth-Type
(2) pap: WARNING: Authentication will fail unless a "known good" password is available
(2)     [pap] = noop
(2)   } # authorize = ok
(2) Found Auth-Type = pam
(2) # Executing group from file /etc/raddb/sites-enabled/default
(2)   authenticate {
(2) pam: Using pamauth string "radiusd" for pam.conf lookup
(2) pam: Authentication succeeded
(2)     [pam] = ok
(2)   } # authenticate = ok
(2) # Executing section post-auth from file /etc/raddb/sites-enabled/default
(2)   post-auth {
(2)     update {
(2)       No attributes updated
(2)     } # update = noop
(2)     [exec] = noop
(2)     policy remove_reply_message_if_eap {
(2)       if (&reply:EAP-Message && &reply:Reply-Message) {
(2)       if (&reply:EAP-Message && &reply:Reply-Message)  -> FALSE
(2)       else {
(2)         [noop] = noop
(2)       } # else = noop
(2)     } # policy remove_reply_message_if_eap = noop
(2)   } # post-auth = noop
(2) Sent Access-Accept Id 16 from 127.0.0.1:1812 to 127.0.0.1:38424 length 0
(2) Finished request
Waking up in 4.9 seconds.
(2) Cleaning up request packet ID 16 with timestamp +6169
Ready to process requests
  • 使用戶不需用帶域名就能夠被識別,須要修改配置文件/etc/sssd/sssd.conf,將use_fully_qualified_names行的True值修改成False。
[root@centos8 ~]# vi /etc/sssd/sssd.conf

use_fully_qualified_names = False
  • 重啓sssd服務,從新列出域控信息,登陸格式能夠和以前對比。
[root@centos8 ~]# systemctl restart sssd

[root@centos8 ~]# realm list
python.com
  type: kerberos
  realm-name: PYTHON.COM
  domain-name: python.com
  configured: kerberos-member
  server-software: active-directory
  client-software: sssd
  required-package: oddjob
  required-package: oddjob-mkhomedir
  required-package: sssd
  required-package: adcli
  required-package: samba-common-tools
  login-formats: %U
  login-policy: allow-permitted-logins
  permitted-logins:
  permitted-groups: ***users
  • 如今不用加域信息也能識別用戶。
[root@centos8 ~]# id ***user
uid=363201109(***user) gid=363200513(domain users) 組=363200513(domain users),363201108(***users)

5、安裝和配置Google Authenticator PAM

5.1 安裝Google Authenticator

  • 準備PAM編譯環境
[root@centos8 ~]# yum install pam-devel make gcc-c++ git
[root@centos8 ~]# yum install automake autoconf libtool
  • 下載安裝文件,注意這裏目錄爲~
[root@centos8 ~]# git clone https://github.com/google/google-authenticator-libpam
  • 安裝google-authenticator
    [root@centos8 ~]# cd google-authenticator-libpam/
    [root@centos8 google-authenticator-libpam]# ./bootstrap.sh
    [root@centos8 google-authenticator-libpam]# ./configure
    [root@centos8 google-authenticator-libpam]# make
    [root@centos8 google-authenticator-libpam]# make install

5.2 帳號開啓雙因素認證

  • 切換到ad帳號
[root@centos8 ~]# su - ***user@python.com
  • 爲帳號開啓雙因素認證。
[***user@python.com@centos8 ~]$ google-authenticator

Do you want authentication tokens to be time-based (y/n) y
Warning: pasting the following URL into your browser exposes the OTP secret to Google:
  https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/***user@python.com@centos8%3Fsecret%3DOF2GUT37EUSG7Y2TYX57HKYRUY%26issuer%3Dcentos8
Failed to use libqrencode to show QR code visually for scanning.

若是安裝了`libqrencode`,屏幕會出現一個二維碼若是你的終端終端不支持顯示二維碼,能夠手動打開這個網頁連接(牆)來查看二維碼或者手動輸入後面的密鑰(secret key)來代替掃描二維碼,下面有5個緊
急救助碼(emergency scratch code),
緊急救助碼就是當你沒法獲取認證碼時(好比手機丟了),能夠當作認證碼來用,每用一個少一個,但其實能夠手動添加的,建議若是 root 帳戶使用 Google Authenticator 的話必定要把緊急救助碼另外保存一
份。

Consider typing the OTP secret into your app manually.
Your new secret key is: OF2GUT37EUSG7Y2TYX57HKYRUY
Enter code from app (-1 to skip): 198586
Code confirmed
Your emergency scratch codes are:
  82763900
  77203549
  34651872
  82841984
  93446389

Do you want me to update your "/home/***user@python.com/.google_authenticator" file? (y/n) y
是否更新用戶的 Google Authenticator 配置文件,選擇 y 才能使上面操做對當前用戶生效,其實就是在對應用戶的 Home 目錄下生成了一個 .google_authenticator 文件,
若是你想停用這個用戶的 Google Authenticator 驗證,只須要刪除這個用戶 Home 目錄下的 .google_authenticator 文件就能夠了。

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y
每次生成的認證碼是否同時只容許一我的使用?這裏選擇 y。

By default, a new token is generated every 30 seconds by the mobile app.
In order to compensate for possible time-skew between the client and the server,
we allow an extra token before and after the current time. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
Do you want to do so? (y/n) y
是否增長時間偏差?這裏選擇 n或者y都行。

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting? (y/n) y
是否啓用次數限制?
  • 上面的交互式的設置也可用經過參數一次性設置(推薦),先查看一下參數含義。
[***user@python.com@centos8 ~]$google-authenticator -h
google-authenticator [<options>]
 -h, --help                     Print this message
 -c, --counter-based            Set up counter-based (HOTP) verification
 -C, --no-confirm               Don't confirm code. For non-interactive setups
 -t, --time-based               Set up time-based (TOTP) verification
 -d, --disallow-reuse           Disallow reuse of previously used TOTP tokens
 -D, --allow-reuse              Allow reuse of previously used TOTP tokens
 -f, --force                    Write file without first confirming with user
 -l, --label=<label>            Override the default label in "otpauth://" URL
 -i, --issuer=<issuer>          Override the default issuer in "otpauth://" URL
 -q, --quiet                    Quiet mode
 -Q, --qr-mode={NONE,ANSI,UTF8} QRCode output mode
 -r, --rate-limit=N             Limit logins to N per every M seconds
 -R, --rate-time=M              Limit logins to N per every M seconds
 -u, --no-rate-limit            Disable rate-limiting
 -s, --secret=<file>            Specify a non-standard file location
 -S, --step-size=S              Set interval between token refreshes
 -w, --window-size=W            Set window of concurrently valid codes
 -W, --minimal-window           Disable window of concurrently valid codes
 -e, --emergency-codes=N        Number of emergency codes to generate
  • 這裏Cisco_是會在APP上顯示的令牌名標籤,user@centos8是APP上的主機名標籤。
[***user@python.com@centos8 ~]$ google-authenticator -t -f -d -l ***user@centos8 -i Cisco_*** -r 3 -R 30 -W
Warning: pasting the following URL into your browser exposes the OTP secret to Google:
  https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/lql@centos8%3Fsecret%3DJQ355PSUBG52KJBUMDJVBSMDLU%26issuer%3DLQL.ME

5.3 修改pam配置文件,並測試AD帳號加動態碼登陸radius。

  • 查找pam_google_authenticator.so所在目錄
[root@centos8 ~]# find / -name pam_google_authenticator.so
/usr/local/lib/security/pam_google_authenticator.so
  • 編輯/etc/pam.d/radiusd,告訴FreeRadius使用本地Unix密碼和Google Authenticator代碼對用戶進行身份驗證。
[root@centos8 ~]# vi /etc/pam.d/radiusd

#%PAM-1.0
#auth       include     password-auth
#account    required    pam_nologin.so
#account    include     password-auth
#password   include     password-auth
#session    include     password-auth

auth       requisite    /usr/local/lib/security/pam_google_authenticator.so forward_pass
auth       required     pam_sss.so use_first_pass
account    required     pam_nologin.so
account    include      password-auth
session    include      password-auth
  • 開啓radius調試模式

    [root@centos8 ~]#radius -X
  • 在新的窗口使用域帳號測試radius認證,這裏密碼構成是密碼+動態碼
[root@centos8 ~]# radtest ***user@python.com Cisc0123072009 localhost 18120 testing123
Sent Access-Request Id 119 from 0.0.0.0:49063 to 127.0.0.1:1812 length 88
        User-Name = "***user@python.com"
        User-Password = "Cisc0123072009"
        NAS-IP-Address = 172.20.29.110
        NAS-Port = 18120
        Message-Authenticator = 0x00
        Cleartext-Password = "Cisc0123072009"
Received Access-Accept Id 119 from 127.0.0.1:1812 to 127.0.0.1:49063 length 20
  • AD 結合動態碼測試日誌
(3) Received Access-Request Id 119 from 127.0.0.1:49063 to 127.0.0.1:1812 length 88
(3)   User-Name = "***user@python.com"
(3)   User-Password = "Cisc0123072009"
(3)   NAS-IP-Address = 172.20.29.110
(3)   NAS-Port = 18120
(3)   Message-Authenticator = 0x457cc852a7cb00f054b1cc168f75998e
(3) # Executing section authorize from file /etc/raddb/sites-enabled/default
(3)   authorize {
(3)     policy filter_username {
(3)       if (&User-Name) {
(3)       if (&User-Name)  -> TRUE
(3)       if (&User-Name)  {
(3)         if (&User-Name =~ / /) {
(3)         if (&User-Name =~ / /)  -> FALSE
(3)         if (&User-Name =~ /@[^@]*@/ ) {
(3)         if (&User-Name =~ /@[^@]*@/ )  -> FALSE
(3)         if (&User-Name =~ /\.\./ ) {
(3)         if (&User-Name =~ /\.\./ )  -> FALSE
(3)         if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/))  {
(3)         if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/))   -> FALSE
(3)         if (&User-Name =~ /\.$/)  {
(3)         if (&User-Name =~ /\.$/)   -> FALSE
(3)         if (&User-Name =~ /@\./)  {
(3)         if (&User-Name =~ /@\./)   -> FALSE
(3)       } # if (&User-Name)  = notfound
(3)     } # policy filter_username = notfound
(3)     [preprocess] = ok
(3)     [chap] = noop
(3)     [mschap] = noop
(3)     [digest] = noop
(3) suffix: Checking for suffix after "@"
(3) suffix: Looking up realm "python.com" for User-Name = "***user@python.com"
(3) suffix: No such realm "python.com"
(3)     [suffix] = noop
(3) eap: No EAP-Message, not doing EAP
(3)     [eap] = noop
(3) files: users: Matched entry DEFAULT at line 69
(3)     [files] = ok
(3)     [expiration] = noop
(3)     [logintime] = noop
(3) pap: WARNING: No "known good" password found for the user.  Not setting Auth-Type
(3) pap: WARNING: Authentication will fail unless a "known good" password is available
(3)     [pap] = noop
(3)   } # authorize = ok
(3) Found Auth-Type = pam
(3) # Executing group from file /etc/raddb/sites-enabled/default
(3)   authenticate {
(3) pam: Using pamauth string "radiusd" for pam.conf lookup
(3) pam: Authentication succeeded
(3)     [pam] = ok
(3)   } # authenticate = ok
(3) # Executing section post-auth from file /etc/raddb/sites-enabled/default
(3)   post-auth {
(3)     update {
(3)       No attributes updated
(3)     } # update = noop
(3)     [exec] = noop
(3)     policy remove_reply_message_if_eap {
(3)       if (&reply:EAP-Message && &reply:Reply-Message) {
(3)       if (&reply:EAP-Message && &reply:Reply-Message)  -> FALSE
(3)       else {
(3)         [noop] = noop
(3)       } # else = noop
(3)     } # policy remove_reply_message_if_eap = noop
(3)   } # post-auth = noop
(3) Sent Access-Accept Id 119 from 127.0.0.1:1812 to 127.0.0.1:49063 length 0
(3) Finished request
Waking up in 4.9 seconds.
(3) Cleaning up request packet ID 119 with timestamp +6972
Ready to process requests

6、ASAv AnyConnect 配置

6.1 ASAv初始化配置

  • ASAv接口初始化,這裏我經過防火牆mgmt接口ssh網管。
interface Management0/0
 nameif mgmt
 security-level 0
 ip address 192.168.100.100 255.255.255.0

ssh 0.0.0.0 0.0.0.0 mgmt

interface GigabitEthernet0/0
 nameif outside
 security-level 0
 ip address 202.100.1.254 255.255.255.0
!
interface GigabitEthernet0/1
 nameif inside
 security-level 100
 ip address 192.168.1.254 255.255.255.0

6.2 ASAv上傳AnyConnect鏡像

  • 開啓http服務,建立本地管理密碼,讓ASDM能夠順利鏈接。
http server enable 8000
http 0 0 mgmt
aaa authentication http console LOCAL
username admin password cisco privilege 15
  • ASDM上傳AnyConnect鏡像到ASAv本地。

【AnyConnect freeradius ad mfa】asdm-01
【AnyConnect freeradius ad mfa】asdm-02
【AnyConnect freeradius ad mfa】asdm-03
【AnyConnect freeradius ad mfa】asdm-04

  • 確認AnyConnect上傳成功
    MFA-ASAv# dir
    Directory of disk0:/
    94     -rwx  41077110     08:07:22 Mar 05 2020  anyconnect-win-4.6.00362-webdeploy-k9.pkg

6.3 Cisco ASAv AnyConnect本地認證配置。

  • 首先配置AnyConnect的本地認證,當本地認證測試經過以後,再將認證流量送到freeradius進行雙因素認證。
username ssluser password cisco

web***
 enable outside
 anyconnect image disk0:/anyconnect-win-4.6.00362-webdeploy-k9.pkg 1
 anyconnect enable
  • 這裏啓用了隧道分隔。
access-list anyconnect_split standard permit 192.168.1.0 255.255.255.0
access-list anyconnect_filter_acl extended permit ip any 192.168.1.0 255.255.255.0

ip local pool ssl***_pool 192.168.50.100-192.168.50.200

group-policy anyconnect_group_policy internal
group-policy anyconnect_group_policy attributes
 ***-filter value anyconnect_filter_acl
 ***-tunnel-protocol ssl-client ssl-clientless
 split-tunnel-policy tunnelspecified
 split-tunnel-network-list value anyconnect_split
 address-pools value ssl***_pool
 web***
  anyconnect profiles value anyconnect_profile type user

username ssluser attributes
 ***-group-policy anyconnect_group_policy
  • 默認anyconnect不容許經過RDP的方式登陸,這裏個人管理機器是經過RDP登陸的。因此須要修改anyconnect profile,讓RDP用戶能正常登陸。

【AnyConnect freeradius ad mfa】rdp-01

【AnyConnect freeradius ad mfa】rdp-02

  • 經過ASDM配置profile以後,經過命令行確認profile調用。
group-policy anyconnect_group_policy attributes
 web***
  anyconnect profiles value anyconnect_profile type user

6.4 AnyConnect本地帳號登陸測試

【AnyConnect freeradius ad mfa】login-01
【AnyConnect freeradius ad mfa】login-02
【AnyConnect freeradius ad mfa】login-03

6.5 freeradius配置和測試

  • 配置3A服務器指向freeradius。
aaa-server freeradius protocol radius
aaa-server freeradius (inside) host 192.168.1.10
 key cisco
 authentication-port 1812

tunnel-group DefaultWEB***Group general-attributes
 authentication-server-group freeradius
 default-group-policy anyconnect_group_policy
  • ASAv使用AD帳號測試radius服務,由於以前修改過SSSD配置文件,這裏是否添加python.com域名均可以。
MFA-ASAv# test aaa-server authentication freeradius host 192.168.1.10 username ***user password Cisc0123187977
INFO: Attempting Authentication test to IP address <192.168.1.10> (timeout: 12 seconds)
INFO: Authentication Successful
  • radius調試模式看到的日誌
Listening on acct address :: port 1813 bound to server default
Listening on auth address 127.0.0.1 port 18120 bound to server inner-tunnel
Listening on proxy address * port 54915
Listening on proxy address :: port 45190
Ready to process requests
(0) Received Access-Request Id 4 from 192.168.1.254:30861 to 192.168.1.10:1812 length 86
(0)   User-Name = "***user"
(0)   User-Password = "Cisc0123187977"
(0)   NAS-IP-Address = 192.168.1.254
(0)   NAS-Port = 4
(0)   NAS-Port-Type = Virtual
(0)   Cisco-AVPair = "coa-push=true"
(0) # Executing section authorize from file /etc/raddb/sites-enabled/default
(0)   authorize {
(0)     policy filter_username {
(0)       if (&User-Name) {
(0)       if (&User-Name)  -> TRUE
(0)       if (&User-Name)  {
(0)         if (&User-Name =~ / /) {
(0)         if (&User-Name =~ / /)  -> FALSE
(0)         if (&User-Name =~ /@[^@]*@/ ) {
(0)         if (&User-Name =~ /@[^@]*@/ )  -> FALSE
(0)         if (&User-Name =~ /\.\./ ) {
(0)         if (&User-Name =~ /\.\./ )  -> FALSE
(0)         if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/))  {
(0)         if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/))   -> FALSE
(0)         if (&User-Name =~ /\.$/)  {
(0)         if (&User-Name =~ /\.$/)   -> FALSE
(0)         if (&User-Name =~ /@\./)  {
(0)         if (&User-Name =~ /@\./)   -> FALSE
(0)       } # if (&User-Name)  = notfound
(0)     } # policy filter_username = notfound
(0)     [preprocess] = ok
(0)     [chap] = noop
(0)     [mschap] = noop
(0)     [digest] = noop
(0) suffix: Checking for suffix after "@"
(0) suffix: No '@' in User-Name = "***user", looking up realm NULL
(0) suffix: No such realm "NULL"
(0)     [suffix] = noop
(0) eap: No EAP-Message, not doing EAP
(0)     [eap] = noop
(0) files: users: Matched entry DEFAULT at line 69
(0)     [files] = ok
(0)     [expiration] = noop
(0)     [logintime] = noop
(0) pap: WARNING: No "known good" password found for the user.  Not setting Auth-Type
(0) pap: WARNING: Authentication will fail unless a "known good" password is available
(0)     [pap] = noop
(0)   } # authorize = ok
(0) Found Auth-Type = pam
(0) # Executing group from file /etc/raddb/sites-enabled/default
(0)   authenticate {
(0) pam: Using pamauth string "radiusd" for pam.conf lookup
(0) pam: Authentication succeeded
(0)     [pam] = ok
(0)   } # authenticate = ok
(0) # Executing section post-auth from file /etc/raddb/sites-enabled/default
(0)   post-auth {![login-ad](https://i.imgur.com/yltINYr.png)
(0)     update {
(0)       No attributes updated
(0)     } # update = noop
(0)     [exec] = noop
(0)     policy remove_reply_message_if_eap {
(0)       if (&reply:EAP-Message && &reply:Reply-Message) {
(0)       if (&reply:EAP-Message && &reply:Reply-Message)  -> FALSE
(0)       else {
(0)         [noop] = noop
(0)       } # else = noop
(0)     } # policy remove_reply_message_if_eap = noop
(0)   } # post-auth = noop
(0) Sent Access-Accept Id 4 from 192.168.1.10:1812 to 192.168.1.254:30861 length 0
(0) Finished request
Waking up in 4.9 seconds.
(0) Cleaning up request packet ID 4 with timestamp +11
Ready to process requests
  • 若是radius -X 沒法運行,而且報錯以下,通常是radius服務已經啓動,佔用了1812端口號致使的。
Failed binding to auth address * port 1812 bound to server default: Address already in use
/etc/raddb/sites-enabled/default[59]: Error binding to port for 0.0.0.0 port 1812
  • 查看UDP端口號使用。
[root@centos8 ~]# ss -ulnp
State  Recv-Q  Send-Q     Local Address:Port     Peer Address:Port
UNCONN 0       0              127.0.0.1:18120         0.0.0.0:*      users:(("radiusd",pid=15068,fd=14))
UNCONN 0       0                0.0.0.0:1812          0.0.0.0:*      users:(("radiusd",pid=15068,fd=10))
UNCONN 0       0                0.0.0.0:1813          0.0.0.0:*      users:(("radiusd",pid=15068,fd=11))
  • 可使用pkill命令結束radius全部進程。
[root@centos8 ~]# pkill radiusd

6.6 使用 AD帳號+動態碼 登陸AnyConnect

  • AnyConnect輸入密碼時,首先輸入AD密碼,而後輸入6位動態碼。例如這裏密碼是Cisc0123,動態碼是914714,那麼密碼框應該輸入Cisc0123914714

【AnyConnect freeradius ad mfa】login-01
【AnyConnect freeradius ad mfa】login-ad
【AnyConnect freeradius ad mfa】login-03

  • 動態碼

【AnyConnect freeradius ad mfa】code

  • AnyConnect登陸,radius 調試日誌。
(4) Received Access-Request Id 8 from 192.168.1.254:30861 to 192.168.1.10:1812 length 666
(4)   User-Name = "***user"
(4)   User-Password = "Cisc0123914714"
(4)   NAS-Port = 32768
(4)   Called-Station-Id = "202.100.1.254"
(4)   Calling-Station-Id = "202.100.1.10"
(4)   NAS-Port-Type = Virtual
(4)   Tunnel-Client-Endpoint:0 = "202.100.1.10"
(4)   Cisco-AVPair = "mdm-tlv=device-platform=win"
(4)   Cisco-AVPair = "mdm-tlv=device-mac=00-50-56-8e-14-a9"
(4)   Cisco-AVPair = "mdm-tlv=device-mac=00-50-56-8e-8a-ac"
(4)   Cisco-AVPair = "mdm-tlv=device-mac=00-50-56-8e-93-54"
(4)   Cisco-AVPair = "mdm-tlv=device-type=VMware, Inc. VMware7,1"
(4)   Cisco-AVPair = "mdm-tlv=device-platform-version=10.0.18362 "
(4)   Cisco-AVPair = "mdm-tlv=ac-user-agent=AnyConnect Windows 4.6.00362"
(4)   Cisco-AVPair = "mdm-tlv=device-uid=D7237D73128E45F4F2706858D0F4AC09129E5131839298ACB03D3999125B5FC1"
(4)   NAS-IP-Address = 192.168.1.254
(4)   Cisco-AVPair = "audit-session-id=c0a801fe000080005e60c235"
(4)   Cisco-AVPair = "ip:source-ip=202.100.1.10"
(4)   ASA-TunnelGroupName = "DefaultWEB***Group"
(4)   ASA-ClientType = AnyConnect-Client-SSL-***
(4)   Cisco-AVPair = "coa-push=true"
(4) # Executing section authorize from file /etc/raddb/sites-enabled/default
(4)   authorize {
(4)     policy filter_username {
(4)       if (&User-Name) {
(4)       if (&User-Name)  -> TRUE
(4)       if (&User-Name)  {
(4)         if (&User-Name =~ / /) {
(4)         if (&User-Name =~ / /)  -> FALSE
(4)         if (&User-Name =~ /@[^@]*@/ ) {
(4)         if (&User-Name =~ /@[^@]*@/ )  -> FALSE
(4)         if (&User-Name =~ /\.\./ ) {
(4)         if (&User-Name =~ /\.\./ )  -> FALSE
(4)         if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/))  {
(4)         if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/))   -> FALSE
(4)         if (&User-Name =~ /\.$/)  {
(4)         if (&User-Name =~ /\.$/)   -> FALSE
(4)         if (&User-Name =~ /@\./)  {
(4)         if (&User-Name =~ /@\./)   -> FALSE
(4)       } # if (&User-Name)  = notfound
(4)     } # policy filter_username = notfound
(4)     [preprocess] = ok
(4)     [chap] = noop
(4)     [mschap] = noop
(4)     [digest] = noop
(4) suffix: Checking for suffix after "@"
(4) suffix: No '@' in User-Name = "***user", looking up realm NULL
(4) suffix: No such realm "NULL"
(4)     [suffix] = noop
(4) eap: No EAP-Message, not doing EAP
(4)     [eap] = noop
(4) files: users: Matched entry DEFAULT at line 69
(4)     [files] = ok
(4)     [expiration] = noop
(4)     [logintime] = noop
(4) pap: WARNING: No "known good" password found for the user.  Not setting Auth-Type
(4) pap: WARNING: Authentication will fail unless a "known good" password is available
(4)     [pap] = noop
(4)   } # authorize = ok
(4) Found Auth-Type = pam
(4) # Executing group from file /etc/raddb/sites-enabled/default
(4)   authenticate {
(4) pam: Using pamauth string "radiusd" for pam.conf lookup
(4) pam: Authentication succeeded
(4)     [pam] = ok
(4)   } # authenticate = ok
(4) # Executing section post-auth from file /etc/raddb/sites-enabled/default
(4)   post-auth {
(4)     update {
(4)       No attributes updated
(4)     } # update = noop
(4)     [exec] = noop
(4)     policy remove_reply_message_if_eap {
(4)       if (&reply:EAP-Message && &reply:Reply-Message) {
(4)       if (&reply:EAP-Message && &reply:Reply-Message)  -> FALSE
(4)       else {
(4)         [noop] = noop
(4)       } # else = noop
(4)     } # policy remove_reply_message_if_eap = noop
(4)   } # post-auth = noop
(4) Sent Access-Accept Id 8 from 192.168.1.10:1812 to 192.168.1.254:30861 length 0
(4) Finished request
Waking up in 4.9 seconds.
(4) Cleaning up request packet ID 8 with timestamp +608
Ready to process requests

我的博客:https://cswk.work

~

相關文章
相關標籤/搜索