首先感恩廖大讚歎廖大(chianan_liao)的分享私人筆記才有這篇騙吃騙喝的文章
現況 
有一台該死的Microsoft AD(Active Directory) 但我離不開她 (其實用 samba 的偽 AD 也可以) 我的無線網路環境有一堆人要用,不想用單一密碼,我需要 802.1x 做無線網路驗證,讓每個人打自己的 AD 帳密連線 架構 
本文就是要弄出右上角這台 RADIUS Server
網域: alexw.net 網域簡寫: ALEXW 原本就有的 AD Server 本文要建立的 FreeRADIUS + samba 本文測試環境: Debian 10  / Windows Server 2019
前置作業 
裝好一台 debian,設置 hosts 對應
debian 會設置 127.0.1.1 對應本機,這個註解掉改為 host ip
/etc/hosts
127.0.0.1   localhost
# 127.0.1.1 rad.alexw.net  rad
192.168.1.3    rad.alexw.net rad 
設置 DNS server (設為兼任 dns 的 AD server)
/etc/resolv.conf
nameserver 192.168.1.2
domain alexw.net
search alexw.net 
安裝套件 
安裝 freeradius 和 samba 等相關套件
apt install freeradius samba-common winbind krb5-config libpam-winbind libnss-winbind -y 
設定 krb5 
/etc/krb5.conf
[libdefaults]
    dns_lookup_realm = false
    dns_lookup_kdc = true
    default_realm = ALEXW.NET
    
[realms]
    ALEXW.NET = {
        kdc = ads.alexw.net
        admin_server = ads.alexw.net
    }
[domain_realm]
    .alexw.net = ALEXW.NET
     alexw.net = ALEXW.NET 
設定 samba 
/etc/samba/smb.conf
* * security = ADS  這行的 ADS 不是 ads.alexw.net 的 server name 而是真的要打 “ADS” * *
[global]
    security = ADS
    workgroup = ALEXW
    ntlm auth = Yes
    realm = ALEXW.NET
    client NTLMv2 auth = YES
    log file = /var/log/samba/log.%m
    max log size = 1000
    logging = file
    log level = 1
    password server = ads.alexw.net
    winbind use default domain = true
    winbind offline logon = false
    template homedir = /home/%U
    template shell = /bin/bash
    idmap config * : backend = tdb
    idmap config * : range = 10000-20000 
/etc/nsswitch.conf
passwd:         compat winbind
group:            compat winbind
shadow:         compat winbind
gshadow:       files
hosts:             files dns
networks:      files
protocols:      db files
services:         db files
ethers:            db files
rpc:                  db files
netgroup:       nis 
加入網域 
把這台機器加入 AD 網域,當個快樂的 AD 成員(使用 administrator 帳號,理論上非 administrator 也可以)
net ads join -U administrator 
下面這錯誤可以忽略 這是動態更新 DNS 失敗(因為伺服器都設置 static dns 不做 dynamic)
Enter administrator's password:
Using short domain name -- ALEXW
Joined 'RAD' to dns domain 'alexw.net'
DNS Update for rad.alexw.net failed: ERROR_DNS_UPDATE_FAILED
DNS update failed: NT_STATUS_UNSUCCESSFUL 
備註:以後如果機器撤掉要退網域則使用 (現在不要打這行指令啦啊啊啊)
## 這是退網域用的指令 
重啟 winbind
systemctl restart winbind 
測試是否能讀取 AD 使用者和群組的資料
wbinfo -u 
測試帳號登入
ntlm_auth --username={AD_USER_ACCOUNT} --password={AD_USER_PASSWORD} 
正確會出現
NT_STATUS_OK: The operation completed successfully. (0x0) 
設定FreeRADIUS 
把 freerad 帳號加入 winbindd_priv 群組
usermod -a -G winbindd_priv freerad 
重啟 winbind
systemctl restart winbind 
編輯 FreeRADIUS 設定
/etc/freeradius/3.0/radiusd.conf 不需更改
編輯用戶端設定
/etc/freeradius/3.0/clients.conf
secret 後面接的是 radius 用的 secret key (自行設定)
client localhost {
    ipaddr = 127.0.0.1
    secret   = AAA@AAA
}
client localhost_ipv6 {
    ipv6addr = ::1
    secret   = AAA@AAA
}
client private-network-1 {
    ipaddr  = 192.168.0.0/16
    secret  = AAA@AAA
} 
修改 mschap
/etc/freeradius/3.0/mods-available/mschap
mschap {
    use_mppe=yes
    require_encryption = yes
    require_strong = yes
    with_ntdomain_hack = yes
    winbind_username = "%{mschap:User-Name}"
    winbind_domain = "ALEXW"
   ntlm_auth = "/usr/bin/ntlm_auth --allow-mschapv2 --request-nt-key --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --challenge=%{%{mschap:Challenge}:-00} --nt-response=%{%{mschap:NT-Response}:-00}"
} 
修改 /etc/freeradius/3.0/mods-available/ntlm_auth
修改裡面的 path 和 domain
exec ntlm_auth {
    wait = yes
    program = "/usr/bin/ntlm_auth --request-nt-key --domain=ALEXW --username=%{mschap:User-Name} --password=%{User-Password}"
} 
測試 RADIUS 連線 
停止服務並改用啟動偵錯模式 freeradius -X
systemctl stop freeradius 
然後用另一個 console 測試連線測試本地端 (本地開 18120,如果是遠端則是 1812)
radtest -t mschap {USER} "{USER_PASSWORD}" localhost:18120 0 AAA@AAA 
成功會得到這樣的訊息
Sent Access-Request Id 12 from 0.0.0.0:57999 to 127.0.0.1:18120 length 132
        User-Name = "{USER}"
        MS-CHAP-Password = "{USER_PASSWORD}"
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 0
        Message-Authenticator = 0x00
        Cleartext-Password = "{USER_PASSWORD}"
        MS-CHAP-Challenge = 0x3a6a904d7a1c7d7b
        MS-CHAP-Response = 0x0001000000000000000000000000000000000000000000000000beb439542bf97174619a4b7a7360141633ba32b8719a5de4
Received Access-Accept Id 12 from 127.0.0.1:18120 to 127.0.0.1:57999 length 84
        MS-CHAP-MPPE-Keys = 0x00000000000000004e09b29052bcb917ed0d2bc195ce801a
        MS-MPPE-Encryption-Policy = Encryption-Required
        MS-MPPE-Encryption-Types = 4 
測試成功後 ctrl-c 終止 freeradius -X 程序 啟用並設置每次開機啟動服務
systemctl start freeradius 
現在連線可以使用
Android 手機連線時選擇 PEAP / MSCHAPV2 / 不驗證
iOS 則無腦直連
以上就可以算完工了,不過對於 android 11 更新後會發現不能選不驗證,他一定要做驗證才能連線
只好繼續往下做
加入憑證 
這邊我們採用免費的 Let’s encrypt  的憑證來使用
let’s encrypt  是發行憑證的單位,但是我們會用第三方套件去申請和更新憑證,本文採用 certbot  這個套件來處理
記得以前都是用 apt 直裝,不過這次發現 certbot  是建議使用 snap 套件管理來安裝,那就來試試看)
那就先來安裝 snap 
apt install snapd -y 
安裝完之後要更新 snap core
snap install core 
使用 snap 安裝 certbot
snap install --classic certbot 
取得憑證 (需公用 ip 正反解 + 80 port 防火牆暢通)
/snap/bin/certbot certonly --standalone 
完成後金鑰會存放在 /etc/letsencrypt/live/{your_domain} 裡
測試自動更新
/snap/bin/certbot renew --dry-run 
在 free radius 目錄內建立 let’s encrypt 資料夾 將金鑰檔案複製過去並設置權限
mkdir -p /etc/freeradius/3.0/certs/letsencrypt
cp /etc/letsencrypt/live/rad.alexw.net/privkey.pem /etc/freeradius/3.0/certs/letsencrypt
cp /etc/letsencrypt/live/rad.alexw.net/fullchain.pem /etc/freeradius/3.0/certs/letsencrypt
chown freerad:freerad -R /etc/freeradius/3.0/certs/letsencrypt 
修改 /etc/freeradius/3.0/mods-enabled/eap
# private_key_file = /etc/ssl/private/ssl-cert-snakeoil.key 
private_key_file = /etc/freeradius/3.0/certs/letsencrypt/privkey.pem
# certificate_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
certificate_file = /etc/freeradius/3.0/certs/letsencrypt/fullchain.pem 
重啟 freeradius
systemctl restart freeradius 
android 手機連線的時候,驗證部分選使用系統憑證應該就可以通了
iOS 一樣無腦直連
搞定收工