架設Linux/Apache Single Sign On (Active Directory, mod_auth_kerb, Kerberos)
Tuesday, October 14th, 2008
目的:在Windows Domain(網域)內的Intranet(內聯網)使用者,用IE或Firefox瀏覽到這個架設在Linux/Apache的Website,無需再輸入密碼即可自動登入,達成SSO - Single Sign On。其中Linux需Join Domain並擁有該Domain下的Computer Account(電腦帳號)。
非目的:能用網域帳號登入Linux系統、認証之後的權限處理。
引言
若目標只是想認証網域內的Credential(一組使用者名稱和密碼),方法有很多。其中我先試過KB555092的就是其中一個方法,但這個基本上就是將Credential以Cleartext(純文字)傳過去,Web Server(網站伺服器)再直接拿著純文字版本向Domain Controller質問是否對的,如果用IE瀏覽過去,會清清楚楚看到相關警告,也不肯做SSO。對Client side(客戶端)來說,一來不安全,二來即使有SSL,也就是把密碼一乾二淨的拱手相讓給Web Server,所以KB555092實在沒有什麼用。我相如LDAP等也能做到相似效果。
KB555092當中關鍵是KrbMethodNegotiate是Off的,所以就不容許SSO的發生。但是並不是把它變成On就可以,後台還是有一大堆東西要幹的。
話說回來,我的環境是:
原理
簡單來說……
當Client訪問到可使用Kerberos作驗証Server的時候,就先將從KDC (Key Distribution Center,多數也是由管Active Directory的Server負責),拿一個以目標Server的Principal的Private Key(私鑰)加密的一個Ticket。之後Client會將這個Ticket傳過去該Server,該Server通過成功解密,也就能驗證到Client的身份。
因為KDC認識所有的人和物,也有所有人物的Secret,這樣就解決也Credential也流給Web Server的問題,其他設計細則也使得Server和Client可以互相信任。
攻略
假設設定
- Active Directory Full Qualified Domain Name (FQDN)
work.example.com - NETBIOS Short Domain Name
WORK - Linux box Hostname
penguin - …and hence the Linux FQDN will be
penguin.work.example.com - User that has rights to join computer to domain
jsmith
詳細步驟
大前提是Linux的IP是DHCP進來的,最少DNS是用上Domain Controller的一個。
以下步驟都是以root進行。
- 用aptitude將samba, apache2和mod-auth-kerb都裝上
- 修改/etc/krb5.conf
[libdefaults] default_realm = WORK.EXAMPLE.COM default_keytab_name = FILE:/etc/krb5.keytab- 由於正常的Active Directory setup,DNS已經載有KDC的相關數據,而dns_lookup_kdc默認是啟用的,所以整個[realm]的部份以及其他部份都可以刪除。
- 注意realm必需為大寫。
- 若然真的很想填寫[realm]部分的話,又不知到KDC的地址(大概因為公司大,AD Controller多的是),可以用”dig SRV _kerberos._tcp.work.example.com”,就能找到相關的KDC的FQDN。其實這個跟自動搜尋的原理一樣。
- 修改/etc/samba/smb.conf
[global] netbios name = penguin realm = FAREAST.CORP.MICROSOFT.COM security = ads encrypt passwords = yes workgroup = WORK use kerberos keytab = yes- 方間有些說法要用password server,有需要的話就貼KDC的IP地址或FQDN就可以,找地址的方法同上。
- 方間有些說法要用password server,有需要的話就貼KDC的IP地址或FQDN就可以,找地址的方法同上。
- 試試klist、kinit來測試Kerberos的設定
- klist
應返回”klist: No credentials cache found” - kinit jsmith
應會問一下你的密碼 “Password for jsmith@WORK.EXAMPLE.COM”,那輸入Domain Password即可。 - 再klist
應返回”Default principal: jsmith@WORK.EXAMPLE.COM”再加上krbtgt/的Ticket。
- klist
- 修改/etc/hosts
在127.0.0.1的一行後加上penguin.work.example.com,那ping penguin.work.example.com會resolve成127.0.0.1。 - 正式Join Domain
- net ads join -U jsmith
打過Password後應能順應Join Domain - net ads status -U jsmith
檢查一下剛建立的Computer Account
- net ads join -U jsmith
- 建立keytab
- net ads keytab create -U jsmith
會建立keytab到/etc/krb5.keytab - net ads keytab add HTTP -U
會將HTTP這個Service Principal Name加到AD上,也會更新keytab。其實這一步可有可無,不過慣例每個Service都會用自己的名。 - klist -ke
會列出/etc/krb5.keytab的內容,應該會有數個HTTP/, host/等等的Principal - 注意keytab必須好好保護,裏面載有等同於Computer Account密碼的資訊。
- net ads keytab create -U jsmith
- Copy一份keytab到某處,並chmod或chown到apache的user可以讀得到。
測試時可先chmod 666讓所有人都讀得到keytab - 通過.htaccess或Apache主Config的手段開啟Kerberos認証功能
AuthName "Kerberos Login" AuthType Kerberos Krb5Keytab /path/to/a/readable/keytab KrbMethodNegotiate On KrbMethodK5Passwd Off KrbSaveCredentials off KrbVerifyKDC On KrbAuthRealm WORK.EXAMPLE.COM KrbServiceName HTTP/penguin.work.example.com@WORK.EXAMPLE.COM Require valid-user- 當中KrbServiceName可考慮直接copy and paste之前klist -k的輸出,那就萬無一失。
很多網上的參考資料就是欠缺了這一句。單是KrbServiceName HTTP是不夠的,必需完整的把Pricinpal寫出來才成。
- 當中KrbServiceName可考慮直接copy and paste之前klist -k的輸出,那就萬無一失。
- 試著用IE瀏覽相關網頁,理應則大功告成!檢查/var/log/apache2/access.log,應該看到登入者的身份。若IE還是問你密碼,請參考下列的Q & A。Firefox的話也看Q & A。
- 後續步驟
- 把keytab的chmod和chown改回一個安全的設定,如chmod 600, chown www-data:www-data
- 用ktutil,用read_kt、delete_entry、write_kt把Website用的keytab當中的無關的Pricinpal(如host/*)刪除掉。(但自動生成的krb5.keytab則最好不要動)
Q & A
- Join Domain後也沒有自動新成penguin.work.example.com的DNS A紀錄,怎辦?
試試執行”net ads dns register -P”。長期來說可在/etc/dhcp3/dhclient-exit-hooks.d下加一個檔案把這一句放進去 - Firefox的設定方法為何?
在about:config,network.negotiate-auth.trusted-uris下把penguin.work.example.com (或penguin)加進去 - IE無法自動SSO,還是問密碼,不過也沒有出現說什麼”insecure”……
瀏覽到http://penguin.work.example.com/,之後在狀態列確認IE是否將之判定為”Local Intranet Zone” (局域網),因為SSO預設只在Local Intranet Zone下才啟用,解決辦法是將之強行加進Local Intranet Zone。
- 有些網站提到使用”kinit -k -t /etc/krb5.keytab HTTP/penguin.work.example.com@WORK.EXAMPLE.COM”來驗證keytab的可用性,但這個指命一直出錯”kinit(v5): Client not found in Kerberos database while getting initial credentials”,那是否代表有問題?
沒問題,最少我的Setup也是這樣的。據我了解,是因為servicePrincipalName是不可以用來Login,而一般建出來的Computer Account也沒有載有userPrincipalName,也就是說用這個來正正式式的Login (kinit)是不可能的。不過若klist -k沒問題的話,用來看Client証明自己的是認可的Service則綽綽有餘。 - 若有其他問題,應怎辦?
- Join Domain時確定penguin.work.example.com可以resolve成自己,自己的IP也好,是127.0.0.1也好。
- 確定所有電腦的時鐘都一致,最多只能誤差5分鐘。請用ntpdate同步。
- 把Apache的LogLevel提到debug,再檢查/var/log/apache2/error.log。
- Apache Error Log出現”gss_acquire_cred() failed: Unspecified GSS failure. Minor code may provide more information (No principal in keytab matches desired name)”
再三確定KrbServiceName的值是正確,是整整的一個Pricinpal copy and paste進去的。很多芳間的設定都沒有提到這一點。
LogLevel是Debug的話應該會看到”Acquiring creds for HTTP/penguin.work.example.com@WORK.EXAMPLE.COM”,若是長成”…HTTP@penguin”這樣或者是其他樣子的就會出問題。
總結
幾年間Windows和Samba分別都有很大的改善和進行,網上的資料很多時都過了時。經過一天的發掘,發現現在Samba對AD的支持比幾年前的都好多了,實現SSO也其實很容易。
































































中文
粵語
October 17th, 2008 at 14:45
勁!等我遲d試下~
November 19th, 2008 at 8:38
Okay, so I am confused. Being a neophyte cretin I always assume single sign on was for two applications requiring login that were running on the same server so that if you logged into one you were automatically loged into the other if needed. What I have been calling single sign on all this time is something totally different? Then what would I call what I am talking about?
an example: a Metadot Intranet Portal running along side an osCommerce shopping cart. User logs into Metadot to leave a message in a discussion group or to edit their page, decides he needs to purchase something in the shopping cart and he is automatically logged into his account on the shopping cart and can proceed to purchase without needing to enter his account id and password. The IDs are the same on both applications and his password is also the same. When he first registered for his account on the Intranet Portal it created the registration on the shopping cart.
thanks
November 19th, 2008 at 11:47
You are actually correct too.
The context here is - the 1st application is the Windows OS login. The 2nd application is the web application. The focus is to make an Linux/Apache accepting the credential information from the Windows Domain logon.