Samba4でWindows/Linuxの認証統合をしてみた。
次のような要件が背景にある
- WindowsとGNU/Linuxで共通のユーザー認証データベースを用いる
- Windowsホストはいろんなバージョンがある
- LinuxホストはUbuntu Trusty Tahr
- 予算がないのでWindows Serverをドメインコントローラーにするのは却下
- ホームディレクトリはネットワーク上に置いて各マシンで共通して用いる
- (本稿では扱わないが)できればSolarisとHP-UXとAIXとIrixとFreeBSDも統合したい
- いろんなOSで依存性を解決してSambaをビルドして回りたくないのでwinbind認証は却下
- SSOできるに越したことはない
要件を鑑みて、次のような構成にしてみた
- Samba4でActive Directoryドメインを構成する
- Windowsマシンはドメインメンバーにする
- LinuxマシンはSSHで入るときにKerberos GSSAPI + nss_ldap, またはlibpam_heimdal + nss_ldapで認証/ユーザー情報取得を行う
- ホームディレクトリはドメインコントローラからCIFSおよびNFSで提供する
- (本稿では扱わないが)将来は別途NASを用いて提供する
本稿では次の3つのマシンで説明する
- dc.ad.dev.yugui.jp
- ドメインコントローラ
- 192.168.50.11
- host1.ad.dev.yugui.jp
- Linuxホスト
- 192.168.50.12
- win7.ad.dev.yugui.jp
- Windowsホスト
- 192.168.50.13
ドメインコントローラのセットアップ
Ubuntu Trusty上にSamba4でドメインコントローラを構成する。
RealmはAD.DEV.YUGUI.JP
とした。
パッケージのインストール
$ hostname
dc
$ sudo aptitude install ntp samba nfs-server
Note: selecting "nfs-kernel-server" instead of the
virtual package "nfs-server"
The following NEW packages will be installed:
attr{a} libaio1{a} libavahi-client3{a} libavahi-common-data{a} libavahi-common3{a} libcups2{a} libfile-copy-recursive-perl{a} libhdb9-heimdal{a} libkdc2-heimdal{a} libldb1{a} libntdb1{a} libopts25{a}
libtalloc2{a} libtdb1{a} libtevent0{a} libwbclient0{a} nfs-kernel-server ntp python-dnspython{a} python-ldb{a} python-ntdb{a} python-samba{a} python-talloc{a} python-tdb{a} samba samba-common{a}
samba-common-bin{a} samba-dsdb-modules{a} samba-libs{a} samba-vfs-modules{a} tdb-tools{a} update-inetd{a}
0 packages upgraded, 32 newly installed, 0 to remove and 0 not upgraded.
Need to get 8545 kB of archives. After unpacking 46.8 MB will be used.
Do you want to continue? [Y/n/?] y
...
$ sudo rm /etc/samba/smb.conf
$ sudo samba-tool domain provision --use-rfc2307 --interactive
Realm: AD.DEV.YUGUI.JP
Domain [AD]:
Server Role (dc, member, standalone) [dc]:
DNS backend (SAMBA_INTERNAL, BIND9_FLATFILE, BIND9_DLZ, NONE) [SAMBA_INTERNAL]:
DNS forwarder IP address (write 'none' to disable forwarding) [10.0.2.3]:
Administrator password:
Retype password:
...
$ sudo shutdown -r now
-
/etc/ntp.conf
はそのままでも良いが、筆者は近場のNTP serverを設定した -
/etc/resolv.conf
が自分自身を指すようにする。
ただしUbuntuでは自動管理されているので/etc/network/interfaces
のほうをいじって再起動する
それから、作業を進める前にドメインレベルを上げておく
$ sudo samba-tool domain level raise --domain-level 2008_R2 --forest-level 2008_R2
ユーザーの作成
LDAP情報へのアクセス用ユーザーと統合認証でログインするユーザーを作成する
$ sudo samba-tool user add ldap-reader
New Password:
Retype Password:
$ sudo samba-tool user add yugui \
--use-username-as-cn \
--profile-path='\\dc\yugui\profile' \
--uid=yugui --uid-number 20000 \
--gid-number 20000 \
--home-drive=z \
--home-directory='\\dc\yugui' \
--login-shell=/bin/bash
New Password:
Retype Password:
...
unixHomeDirectoryなど、いくつかsamba-tool
での設定方法が分からなかった項目がある。仕方が無いのでこれはあとでwindowsからRemote Server Administration Toolsで設定する。
ホームディレクトリの作成
/etc/samba/smb.conf
にShareを追加する
[yugui]
path = /home/yugui
readonly = No
$ sudo mkdir /home/yugui
$ sudo chown 20000:20000 /home/yugui
次はNFSを設定する
-
/etc/exports
に/home/yugui 192.168.50.0/255.255.255.0(rw)
を足す sudo service nfs-kernel-server
ログイン対象ホストの設定 (Windows)
ドメイン参加
まずはActive Directoryドメインに参加する。
- ホストに管理ユーザーでログインする
- Control Panel -> System -> Advanced system settings -> Computer Nameタブを開く
- "Change"ボタンを押す
- "Domain"にチェックを入れてsambaに設定したREALM名を入力し、"OK"を押す
- sambaに設定したドメインの管理ユーザーとパスワードを入力し、"OK"を押す
ついでにRemote Server Administration Toolsをダウンロードして入れておく
なお、このプログラムはインストールしただけでは有効にならなくて明示的に有効化する必要があるらしい。
- Control Panel -> Programs and Features -> "Turn Windows features on or off"を開く
- Remote Server Administration Tools -> Role Administration Tools -> AD DS and AD LDS Tools -> AD DS Tools -> Active Directory Administrative CenterおよびServer for NIS Toolsを選択する
unix attributesの設定
次はためしにActive Directoryのユーザーでログインしてみる。それからさっき登録したユーザーのunix home directoryやなんかを設定する
- AD\Administratorとしてログインする。
- Start menu -> Active Directory Users and Computersを起動する
- ユーザーを選択してフィールドを埋める
ログイン対象ホストの設定 (Linux)
Samba4組み込みのKerberos実装はHeimdalなので、クライアント側もHeimdalを用いる。
ちなみにMIT Kerberosではenctypeが不一致でうまく認証できなかった。サーバーとクライアント両サイドを適切に設定すればいけるのかもしれないが、面倒なのでこのままHeimdalで行く。
なお、ここではlibnss-ldapを用いたが、@fumiyasさんよりlibnss-ldapdのほうが良い旨教えていただいたので、後日そちらも試してみた。それは節を分けて書いてある。
認証の設定
まずはログインできるところまで設定しよう。
$ hostname
host1
$ sudo aptitude install autofs heimdal-clients libpam-heimdal libnss-ldap
The following NEW packages will be installed:
auth-client-config{a} autofs heimdal-clients krb5-config{a} ldap-auth-client{a} ldap-auth-config{a} libhdb9-heimdal{a} libkadm5clnt7-heimdal{a} libkadm5srv8-heimdal{a} libkafs0-heimdal{a} libnss-ldap
libotp0-heimdal{a} libpam-heimdal libpam-ldap{a} libsl0-heimdal{a}
0 packages upgraded, 15 newly installed, 0 to remove and 0 not upgraded.
Need to get 934 kB of archives. After unpacking 4322 kB will be used.
Do you want to continue? [Y/n/?] y
...
途中、いくつかパラメータを訊かれるので設定する
- LDAP server Uniform Resource Identifier:
- ldap://dc.ad.dev.yugui.jp
- Distinguished name of the search base:
- cn=Users,dc=ad,dc=dev,dc=yugui,dc=jp
- LDAP version to use:
- 3
- Make local root Database admin:
- Yes
- Does the LDAP database require login?
- Yes
- LDAP account for root:
- cn=Administrator,cn=Users,dc=ad,dc=dev,dc=yugui,dc=jp
- LDAP root account password:
- 前に設定したAdministratorのパスワード
- Unprivileged database user;
- cn=ldap-reader,cn=Users,dc=ad,dc=dev,dc=yugui,dc=jp
- Password for database login account:
- 前に設定したldap-readerのパスワード
- Default Kerberos version 5 realm:
- AD.DEV.YUGUI.JP
以上で次のようなエントリが/etc/krb5.conf
に設定されている。
[libdefaults]
default_realm = AD.DEV.YUGUI.JP
これに次のエントリも加えておく。
[realms]
AD.DEV.YUGUI.JP = {
kdc = dc.ad.dev.yugui.jp:88
admin_server = dc.ad.dev.yugui.jp
}
同様に/etc/ldap.conf
に次のような設定がある。
uri ldap://dc.ad.dev.yugui.jp
ldap_version 3
binddn cn=ldap-reader,cn=Users,dc=ad,dc=dev,dc=yugui,dc=jp
bindpw XXXXX
rootbinddn cn=Administrator,cn=Users,dc=ad,dc=dev,dc=yugui,dc=jp
なぜかuri ldap://dc.ad.dev.yugui.jp
ではうまく動かないので、とりあえずhost dc.ad.dev.yugui.jp
に書き換えた。
これに加えて次のコメントアウトされている設定を有効にしておく
## RFC 2307 (AD) mappings
#nss_map_objectclass posixAccount user
#nss_map_objectclass shadowAccount user
#nss_map_attribute uid sAMAccountName
#nss_map_attribute homeDirectory unixHomeDirectory
#nss_map_attribute shadowLastChange pwdLastSet
#nss_map_objectclass posixGroup group
#nss_map_attribute uniqueMember member
#pam_login_attribute sAMAccountName
#pam_filter objectclass=User
#pam_password ad
/etc/nsswitch.conf
のpasswd, group, shadowの項目に"ldap"を足す
passwd: compat ldap
group: compat ldap
shadow: compat ldap
/etc/ssh/sshd_config
でGSSAPIを有効にする
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes
GSSAPIKeyExchange yes
GSSAPIStoreCredentialsOnRekey yes
次は、host1側のホスト名やDNSの逆引き/正引きがドメインコントローラ側と整合性がとれている必要があるので順に設定していく。
まず、ドメインコントローラの場合と同様にresolv.conf
でネームサーバーとしてドメインコントローラを使うようにする
次にhostnameを設定して/etc/hostname
も直しておく
$ sudo hostname host1.ad.dev.yugui.jp
それからDNSとSPNを設定する。ドメインコントローラに移って次のようにする。
$ sudo samba-tool dns add -U Administrator localhost ad.dev.yugui.jp host1 A 192.168.50.12
Password for [AD\Administrator]:
$ sudo samba-tool dns zonecreate -UAdministrator localhost 50.168.192.in-addr.arpa
$ sudo samba-tool dns add -U Administrator localhost 50.168.192.in-addr.arpa 12 PTR host1.ad.dev.yugui.jp
$ sudo service samba-ad-dc restart
$ sudo samba-tool user create --random-password host1.ad.dev.yugui.jp
$ sudo samba-tool user setexpiry --noexpiry host1.ad.dev.yugui.jp
$ sudo samba-tool spn add host/host1.ad.dev.yugui.jp host1.ad.dev.yugui.jp
$ sudo samba-tool domain exportkeytab host1.keytab --principal=host/host1.ad.dev.yugui.jp
これでhost1.keytab
というファイルが生成されるので、これをhost1の/etc/krb5.keytab
にコピーする
以上で一通り設定が終わりである。最後にhost1に戻ってSSHを再起動する
$ sudo service ssh restart
これで、Kerberos認証でSSHできるようになる。たとえばドメインコントローラーからSSHしてみる。
$ sudo aptitude install heimdal-clients
$ kinit yugui
yugui@AD.DEV.YUGUI.JP's Password:
$ klist
Credentials cache: FILE:/tmp/krb5cc_1000
Principal: yugui@AD.DEV.YUGUI.JP
Issued Expires Principal
Nov 3 10:11:11 2014 Nov 3 20:11:08 2014 krbtgt/AD.DEV.YUGUI.JP@AD.DEV.YUGUI.JP
$ ssh yugui@host1.ad.dev.yugui.jp
Welcome to Ubuntu 14.04.1 LTS (GNU/Linux 3.13.0-39-generic x86_64)
$
...
おまけとして、時刻ずれによる認証エラーを防ぐためにNTPでドメインコントローラに同期するようにcron jobも設定した。
ホームディレクトリの設定
現状ではホームディレクトリのNFSマウントが設定されていないので、SSHでログインすると/
にいる。そこで次はautofsを設定する。
/etc/auto.master
に次のエントリを足す。
/mnt/home /etc/auto.home
更に/etc/auto.home
を下記の内容で作る
* 192.168.50.11:/home/&
最後にautofsを再起動する
$ sudo service autofs restart
以上でauto mountの設定もできた。
$ hostname
dc.ad.dev.yugui.jp
$ ssh yugui@host1.ad.dev.yugui.jp
Welcome to Ubuntu 14.04.1 LTS (GNU/Linux 3.13.0-39-generic x86_64)
$ pwd
/mnt/home/yugui
ログイン対象ホストの設定(Linux, libnss-ldapd編)
@fumiyas さんにlibnss-ldapdのほうが良いと教えていただいたのでそちらも試した。
まずはlibnss-ldapd
をインストールする。既にlibnss-ldap
がインストール済みの場合はこれをアンインストールする必要もある。
$ sudo aptitude install libnss-ldapd
また途中でいくつかパラメータを訊かれる
- Name services to configure
- group
- passwd
- shadow
- LDAP server URI:
- ldap://dc.ad.dev.yugui.jp
- LDAP server search base:
- cn=Users,dc=ad,dc=dev,dc=yugui,dc=jp
これで/etc/nslcd.conf
が次のように設定されている
uid nslcd
gid nslcd
uri ldap://dc.ad.dev.yugui.jp/
base cn=Users,dc=ad,dc=dev,dc=yugui,dc=jp
これに加えて次の設定も足す。
なお、この段階でnslcdは既に起動しているが設定が中途半端なせいで正常にユーザー情報をリストできない状態である。このためsudo
するのに時間が掛かる。nslcdがtimeoutすれば正常にsudo
できるが、ちょっと待たされる。
もしかしたら、インストール時の"Name services to configure"では何もチェックせずにおいて、設定が終わってから手でnsswitch.conf
をいじった方が良いかもしれない。
binddn cn=ldap-reader,cn=Users,dc=ad,dc=dev,dc=yugui,dc=jp
bindpw 前に設定したldap-readerのパスワード
rootpwmoddn cn=Administrator,cn=Users,dc=ad,dc=dev,dc=yugui,dc=jp
rootpwmodpw 前に設定したAdministratorのパスワード
map passwd uid sAMAccountName
map passwd homeDirectory unixHomeDirectory
map passwd gecos displayName
map passwd gidNumber primaryGroupID
# map group uniqueMember member
これを保存するとnslcd
は勝手に再読み込みしてくれる。
ちなみに、参考にしたSambaのページにはuniqueMember
のマッピングが書いてあるが、手元の環境ではこれを書くとエラーになったのでコメントアウトしてある。
それからAdministratorのパスワードが書かれているのでこのファイルをchmod 0600
しておいた方が良い(とman pageに書いてある)。
他のDNS, SPN, krb5.conf
などの設定が前節と同様にできていれば、以上でsshできるようになっている。
トラブルシューティング
DNS, NTP, Kerberos, LDAP, NFSと多くのコンポーネントがあるので、設定ミスの際に切り分けが大変だった。
- Samba内のKerberosには期待通りにユーザーを設定できているか。
- → ドメインコントローラーでkinitしてみる。
- ホストの
krb5.conf
は正しいか。- → そのマシンでkinitしてみる
- DNSは正しいか
- → 次のものを引いてみる
dig SRV _kerberos._tcp.ad.dev.yugui.jp
dig SRV _kerberos._udp.ad.dev.yugui.jp
dig SRV _ldap._tcp.ad.dev.yugui.jp
dig dc.ad.dev.yugui.jp
dig -x 192.168.50.11
dig host1.ad.dev.yugui.jp
dig -x 192.168.50.12
- → 次のものを引いてみる
- 認証が通らない
ping
- kinitできるか
- 時刻は同期できているか
- ホストからldapで検索できるか
ldapsearch -H ldap://dc.ad.dev.yugui.jp -W -D cn=ldap-reader,cn=Users,dc=ad,dc=dev,dc=yugui,dc=jp -b cn=Users,dc=ad,dc=dev,dc=yugui,dc=jp1
-
/etc/pam.d/common-auth
のlibpam_krb5.so
にdebug
パラメータをつけて試して/var/log/auth.log
を見る -
/etc/ldap.conf
のdebug
のverbosityを挙げてsshのログ出力を見る - KerberosやLDAPのパケットをキャプチャしてldapsearchのときやなんかの場合と比べる
- ログイン時にホームディレクトリに行かない
- ホームディレクトリに直接cdしたときはauto mountされるか
- auto mountされない
- そのパラメータで直接mountできるか
sudo mount -t nfs 192.168.50.11:/home/yugui /mnt/yugui
- そのパラメータで直接mountできるか
- その他
- sshdをforegroundで走らせてログを見る
sudo /usr/sbin/sshd -d -d -d -D -p 2233
- (接続元から)
ssh -p 2233 host1.ad.dev.yugui.jp
- 更に
sudo strace /usr/sbin/sshd -d -d -d -D -p 2233
- straceとwiresharkは友達
- sshdをforegroundで走らせてログを見る