linuxのログオン認証を active direcotryにする方法

書いとかないと忘れるのでメモっとく。
winbind + krb5 (+ pam) により、linux の認証を active directoryにアウトソースできる。

マシン名 mymachine
マシンIP 192.168.50.128
ドメイン rti7743.local 必然的に RTI7743 がワークグループに
ADサーバ ad.rti7743.local
ADサーバIP 192.168.50.2

A1.必要なソフトウェアのインストール

yum install samba pam_krb5 krb5-workstation krb5-libs ntp

なぜか、samba4 aplha14を activedirectoryに設定した際、 samba3x パッケージでないと、No logon servers というエラーが発生して、ログイン出来ませんでした。
rootからAD上の一般ユーザに su することはできても、 AD上の一般ユーザから AD上野一般ユーザに su すると、 No logon servers エラーが発生し、ログイン出来ない状態になってしまいました。
うーむ。


samba3x を入れる場合はいかのようにするといい(たぶん)

yum remove samba samba-common
yum install samba3x-winbind

B1.マシン名をちゃんとキメる。

マシンにちゃんとした名前を与えます。localhosts とかやめる。

vi /etc/sysconfig/network
--内容--------------------------------
HOSTNAME=mymachine
-------------------------------------

名前を変更したら reboot してください。

B2.ADサーバと自分の名前サーバ名がフルネームで引けるようにする。

hosts.conf に以下の行を追加します。

vi /etc/hosts
--内容------------------------------------------
192.168.50.2     ad.rti7743.local
192.168.50.123   mymachine.rti7743.local
-----------------------------------------------

C1 sambaの設定

/etc/samba/smb.conf を変更します。

vi /etc/samba/smb.conf
---内容------------------------------
[global]
workgroup = RTI7743                    #ドメインの前の部分を大文字で
realm = RTI7743.LOCAL                  #ドメイン名を大文字で
netbios name = mymachine               #自分のマシン名
security = ADS
allow trusted domains = No
obey pam restrictions = Yes
password server = ad.rti7743.local     #ADサーバの名前を小文字で
idmap backend = rid:HOGE=10000-19999
idmap uid = 10000-19999
idmap gid = 10000-19999
template homedir = /home/%U
template shell = /bin/bash
winbind separator = !
winbind use default domain = Yes
------------------------------------

D1 krb5の設定

krb5 を全部消して、以下の内容をコピペします。

vi /etc/krb5.conf
--内容---------------------------------
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = RTI7743.LOCAL          #ドメイン名を大文字で
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 forwardable = yes

[realms]
 RTI7734.LOCAL = {                      #ドメイン名を大文字で
 kdc = rti7743.local                    #ドメイン名を小文字で
 admin_server = rti7743.local           #ドメイン名を小文字で
 default_domain = rti7743.local         #ドメイン名を小文字で
 }

[domain_realm]
 .rti7743.local = RTI7743.LOCAL        #ドメイン名をそれぞれ入力
 rti7743.local = RTI7743.LOCAL         #ドメイン名をそれぞれ入力

[appdefaults]
 pam = {
  debug = false
  ticket_lifetime = 36000
  renew_lifetime = 36000
  forwardable = true
  krb4_convert = false
 }
-------------------------------------

E1 resolve の設定

resolv.conf の先頭に以下の行を追加します。

vi /etc/resolv.conf
---内容---------------------------------------
search     rti7743.local     #ドメイン名を小文字で
nameserver 192.168.50.2      #ADサーバをIPで書く.
----------------------------------------------

F1 winbindの再起動

winbind を起動します。

/etc/init.d/winbind start


以後、自動で起動するようにします。

chkconfig winbind on

G1. ドメイン参加!!

このコンピュータを AD に参加させます。
ユーザ権限でも参加できますが、たぶん他の人のデータを引けませんので、administrator で参加を推奨します。

net ads join -U administrator

パスワードを聞かれるので、ADサーバの administrator のパスワードを入れてください。

G2. ドメインに参加できていることを確認する.

以下の2つのコマンドが正常に通るか確認して下さい。

net ads info
net ads testjoin

以上で、AD参加は終わりです。

うまくいかない場合。

うまくいかない場合。
以下のファイルの内容が間違っていないか確認してください。
大文字小文字が入り混じっているので、意外とミスがあります。

vi /etc/samba/smb.conf
vi /etc/krb5.conf
vi /etc/resolve.conf
vi /etc/hosts

それと、設定を変えたら、 winbind を再起動したほうがいいです。


H1. pamの設定

これから、PAMの設定を行い、 AD のユーザでマシンにログインできるようにします。


nsswitch.conf の3つの箇所に winbind を追記してください。
!!このファイルをいい加減に変更するとログイン出来なくなるので注意してくださいね。!!

vi /etc/nsswitch.conf
--内容----------------------------
passwd:     files winbind
shadow:     files winbind
group:      files winbind
---------------------------------

H2. system-auth の設定

/etc/pam.d/system-auth を変更します。
!!このファイルをいい加減に変更するとログイン出来なくなるので注意してくださいね。!!

vi /etc/pam.d/system-auth
----内容------------------------------------------
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        sufficient    pam_winbind.so use_first_pass
auth        required      pam_deny.so

account     required      pam_unix.so
account     sufficient    pam_succeed_if.so uid < 500 quiet
account     required      pam_permit.so

password    requisite     pam_cracklib.so try_first_pass retry=3
password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok
password    sufficient    pam_winbind.so use_authtok
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
session     [success=1 default=ignore] pam_succeed_if.so service incrond quiet use_uid
session     required      pam_unix.so
session     required      pam_mkhomedir.so skel=/etc/skel umask=0022
--------------------------------------------------

I1. テスト!

準備ができました。
テストしてみましょう。
ユーザー administrator の情報が引けるはずです。

id administrator

I2. テスト その2 ssh

ssh rti@127.0.0.1

これで、うまく ADのユーザ名でログインできると正解です。

H1. ログインできるグループを制限する。

ただし、このままだと Active Directory にいるユーザは全員ログインできてしまうのであまりよくありません。
そこでグループ名で制限をかけてみることにします。


グループ linux_logon というグループを作り、このグループに所属しているユーザのみをログインできるようにしてみます。

注意:root から su で移動した場合はターゲットになりません。
一般ユーザから 一般ユーザへ su した場合や、 ssh でログインするなどの事情を防ぎます。

H2. グループを作るって、ユーザ rti2を所属させる

まず、linux_logon グループ作り、rti2 さんを参加させました。

アカウントの情報は id コマンドで見れます。
rti2 さんが、 linux_logon グループに所属しているのがわかります。

id rti2
uid=11107(rti2) gid=10513(domain users) 所属グループ=10513(domain users),11109(linux_logon)

id rti3
uid=11108(rti3) gid=10513(domain users) 所属グループ=10513(domain users)

H3. 制限をかける

次にシステムに制限をかけます。
変更するのは一行だけです。

vi /etc/pam.d/system-auth
---内容---------------------------------------------------------------
auth        sufficient    pam_winbind.so use_first_pass

↓以下のように変更↓

auth        sufficient    pam_winbind.so use_first_pass require_membership_of=linux_logon
----------------------------------------------------------------------

これで、 linux_logon グループに所属していない人はログオンできなくなりました。

H4. 制限かかってますか?

ためしにやってみましょう。
rootから su された場合は、この制限を受けません。rootぢゃない一般ユーザに降格してから試してくださいネ。

[nazonazo@samba3 ~]$su - rti3
パスワード:
su: パスワードが違います

[nazonazo@samba3 ~]$su - rti2
パスワード:
[rti2@samba3 ~]$

こんな感じになりました。
ちゃんと動いているみたいです。

H5. rti3もグループに入れる

次に、 Active Directory 側で、 ユーザrti3もグループに加えます。

本当に加わったか試してみます。

id rti3
uid=11108(rti3) gid=10513(domain users) 所属グループ=10513(domain users)

あれ、、?かわっていません。
どうやらキャッシュがあるみたいです。でも大丈夫。ログインできますヨ!

[nazonazo@samba3 ~]$su - rti3
パスワード:
[rti3@samba3 ~]$ 

[rti3@samba3 ~]$ id rti3
uid=11108(rti3) gid=10513(domain users) 所属グループ=10513(domain users),11109(!linux_logon)

うまくログインできました。
この状態で id の値を見るとちゃんとグループも追加されているのが変わります。


メモ:require_membership_of の値は、 id で表示されるグループ名を入れる。
実際のactive directoryでの表示名とidで表示されるグループ名が違うことがあるので注意。
必ず id コマンドでグループ名を確認する。

メモ:require_membership_of の引数には、空白を含むグループ名を入力できない。日本語は試していないけどたぶん・・・
そーゆー場合は SID で入力する必要がある。

H5. SID変換

グループ名をSIDで指定する方法がマニュアルには推奨されています。
SIDって、ユーザ名やグループ名などのオブジェクトに降られているユニークな値らしいです。(たぶん)


問題はどうやって、所属しているグループ名のSIDを取得するかですが、一発でどかんとやる方法をみつけられませんでした。


たぶん、この方法が一番簡単だと思います。
まず、id コマンドを使って、自分が所属しているグループ名とgid(数字の部分)を取得します。
次に、gid を wbinfo にかけて SID に変換します。


ちょっとやってみましょう。

id rti2
uid=11107(rti2) gid=10513(domain users) 所属グループ=10513(domain users),11109(!linux_logon)

これで、 linux_logon グループは gid: 11109 にマッピングされていることがわかります。
この数字を wbinfo に食べさせるとSIDが求まります。

wbinfo --gid-to-sid 11109
S-1-5-21-2558067586-3132001088-1936578106-1109

linux_logon の SID は S-1-5-21-2558067586-3132001088-1936578106-1109 であることがわかりました。


さっそく制限を書き換えてみましょう。

H6. SID指定による制限

vi /etc/pam.d/system-auth
---内容---------------------------------------------------------------
auth        sufficient    pam_winbind.so use_first_pass require_membership_of=linux_logon

↓以下のように変更↓

auth        sufficient    pam_winbind.so use_first_pass require_membership_of=S-1-5-21-2558067586-3132001088-1936578106-1109
----------------------------------------------------------------------

これで、SIDでの制限がかかっていますので、ログインできるか試してみてください。

(おまけ) PHP AD認証

PHP での active directory 認証してみる。

php.net にサンプルが載っているので拝借〜

<?php
$username = "rti";
$password = "秘密!";
$ldap_url = 'ad.rti7743.local';
$ldap_domain = 'rti7743.local';
$ldap_dn = "dc=rti7743,dc=local";

$ds = ldap_connect( $ldap_url );
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);


// now try a real login
$login = ldap_bind( $ds, "$username@$ldap_domain", $password );
echo '- Logged In Successfully<br/><br/>';
try{
       /*
       $attributes = array("displayname", "mail",
       "department",
       "title",
       "physicaldeliveryofficename",
       "manager");
       */
       $attributes= array("*");
       $filter = "(&(objectCategory=person)(sAMAccountName=$username))";

       $result = ldap_search($ds, $ldap_dn, $filter, $attributes);

       $entries = ldap_get_entries($ds, $result);

       if($entries["count"] > 0){
               echo print_r($entries[$i],1)."<br />";
       }
       catch(Exception $e){
               ldap_unbind($ds);
               return;
       }
       ldap_unbind($ds);
       echo '<br/><br/>- Logged Out';
?>

で、これを実行すると、いろいろ情報が画面に出力されます。
そのなかで、memberof という値に、所属グループが入っています。
この値を利用して、できるできないを作成します。

["memberof"]=>
array(5) {
 ["count"]=>
 int(4)
 [0]=>
 "CN=グループ1,CN=Users,DC=rti7743,DC=local"
 [1]=>
 "CN=グループ2,CN=Users,DC=rti7743,DC=local"
 [2]=>
 "CN=グループ3,CN=Users,DC=rti7743,DC=local"
}

もし、AD認証をガチで使う場合は、「〜できるグループ」のように名前をつけていけば結構平和になると思います。

"CN=管理ページにログインすることができるグループ,CN=Users,DC=rti7743,DC=local"


一応、日本語も、utf-8 で受け取れます。
ですが、あまり気持ちのいいものではないので、英数字にするのがおすすめかな。


この php を実行するには、 php-ldap モジュールが必要です。
ただし、ldapのバインドの是非をみているだけなのでパスワードが平文がネットワークに流れてしまうのがデメリットです。
ガチでケルベロス認証すればパスワードはネットに流れないのですが、 php からやるのは結構大変だと思うので・・・

linux で pptp サーバを active directoryと連携させよう。

linux で作った pptp サーバの認証を active directoryと連携させてみようという話です。


pptp には poptop (10年前ぐらいからある安心のブランドw)、 AD と連携する部分に winbind を利用します。

図解するとこんな感じ
pptp ---> winbind ----> Active Directory

A1.samba winbind の環境構築

samba winbind の環境を構築します。
http://d.hatena.ne.jp/rti7743/20110426/1303840756

A2.pptpd 導入。

残念ながら yum では入りません。なんでだろうw
しかし、親切な方が rpm を作られているので、そちらで入れることは可能です。
http://poptop.sourceforge.net/yum/beta/packages/

wget http://poptop.sourceforge.net/yum/beta/packages/ppp-2.4.5-8.1.rhel5.x86_64.rpm
wget http://poptop.sourceforge.net/yum/beta/packages/pptpd-1.3.4-2.rhel5.1.x86_64.rpm
rpm -Uvh pp*.rpm

10年ぐらい昔は、カーネルにパッチあてたりいろいろしないといけなかったよーなこともありましたが、それも遠い昔。ふつーに動作します。便利な世の中になったものですw。

A3. sysctl で ip_forward を有効にします。

このままだとpptpサーバまでしか接続できないので、
このpptpサーバをルータとして使い他のサーバにも行けるように設定します。

vi /etc/sysctrl.conf 
------------------------------
net.ipv4.ip_forward = 0
---↓変更---------------------
net.ipv4.ip_forward = 1
------------------------------


設定ファイルを再読込させます。

sysctl -p

設定が有効になったか確認します。
以下のコマンドの結果が 1 と表示されればOKです。

cat /proc/sys/net/ipv4/ip_forward

C1.pptpd の認証を winbind に委託します。

一番下に追記してください。

vi /etc/ppp/options.pptpd
--内容----------------------------------------------------------
plugin winbind.so
ntlm_auth-helper "/usr/bin/ntlm_auth --helper-protocol=ntlm-server-1"
----------------------------------------------------------------

これで終わりですw
あと pptpd を再起動すれば、それで完了です。
これだけで、 pptpd と active directory が連携できてしまうのです。
超絶楽ですね。
しかし、これでは割り当てするIPアドレスの指定などができていないのでもうちょっと調整します。

D1. 割り当てるIPアドレスなどを調整します

ファイルの一番下に追記してください。

vi /etc/pptpd.conf
--内容----------------------------------------------------------
localip   192.168.59.1
remoteip  192.168.59.100-200
----------------------------------------------------------------

E1.pptp起動。

できたので、 pptpd を起動します。

/etc/init.d/pptpd start


windows機から接続しています。
ADと連携しているので、ADにいるユーザーでログインします。
ただし、ドメインのところは空白でやります。

うまくつながるはず。

うまくいかんゾ

うまくつながらない場合、 message(めっさげと一部の人は呼ぶ)にログが出ているので確認してください。
pptpd または、 ppp と表示されている項目がヒントになると思います。

less /var/log/messages
--内容例-----------------------------------------------------------------------------------
Apr 27 03:05:20 samba3 pptpd[6454]: CTRL: Client 192.168.56.1 control connection started
Apr 27 03:05:20 samba3 pptpd[6454]: CTRL: Starting call (launching pppd, opening GRE)
Apr 27 03:05:20 samba3 pppd[6455]: Plugin winbind.so loaded.
Apr 27 03:05:20 samba3 pppd[6455]: WINBIND plugin initialized.
Apr 27 03:05:20 samba3 pppd[6455]: Plugin /usr/lib64/pptpd/pptpd-logwtmp.so loaded.
Apr 27 03:05:20 samba3 pppd[6455]: pppd 2.4.5 started by root, uid 0
Apr 27 03:05:20 samba3 pppd[6455]: Using interface ppp0
Apr 27 03:05:20 samba3 pppd[6455]: Connect: ppp0 <--> /dev/pts/1
Apr 27 03:05:23 samba3 pptpd[6454]: CTRL: Ignored a SET LINK INFO packet with real ACCMs!
Apr 27 03:05:23 samba3 pppd[6455]: MPPE 128-bit stateless compression enabled
Apr 27 03:05:25 samba3 pppd[6455]: Cannot determine ethernet address for proxy ARP
Apr 27 03:05:25 samba3 pppd[6455]: local  IP address 10.0.0.10
Apr 27 03:05:25 samba3 pppd[6455]: remote IP address 10.0.0.101
Apr 27 03:08:24 samba3 pppd[6455]: LCP terminated by peer (yl^JM-:^@<M-Mt^@^@^@^@)
Apr 27 03:08:24 samba3 pppd[6455]: Connect time 3.0 minutes.
Apr 27 03:08:24 samba3 pppd[6455]: Sent 0 bytes, received 39608 bytes.
Apr 27 03:08:24 samba3 pppd[6455]: Modem hangup
Apr 27 03:08:24 samba3 pppd[6455]: Connection terminated.
Apr 27 03:08:24 samba3 pppd[6455]: Exit.
---------------------------------------------------------------------------------------------

もっと詳細なエラーがみたい人は、 デバッグモードに切り替えることもできます。

vi /etc/pptpd.conf
--変更-------------------------------------------------------------
#debug

↓変更↓

debug
------------------------------------------------------------------

設定変更後、 pptpd を再起動します。

/etc/init.d/pptpd restart

MACOSXで繋がらない

iOS(iphone)やwindowsからだと繋がるのに、MACOSXからだけ繋がらない場合がありました。
mtuを直すと大丈夫です。

vi /etc/ppp/options.pptpd
--内容----------------------------------------------------------
mtu 1200
----------------------------------------------------------------

F1. グループで制限をかける

グループに制限をかけてみます。
vpn-allow というグループを作って、そのグループに所属している人だけが VPN できるようにします。

vpn-allowという文字列を SID 化して登録しました。
SIDの求め方の解説は、前回を参考にしてください

id rti2
uid=11107(rti2) gid=10513(domain users) 所属グループ=10513(domain users),11109(linux_logon),11110(vpn-allow)

wbinfo --gid-to-sid 11110
S-1-5-21-2558067586-3132001088-1936578106-1110


SIDによる制限を記述しました。

vi /etc/ppp/options.pptpd
--内容----------------------------------------------------------
plugin winbind.so
ntlm_auth-helper "/usr/bin/ntlm_auth --helper-protocol=ntlm-server-1 --require-membership-of=S-1-5-21-2558067586-3132001088-1936578106-1110"
----------------------------------------------------------------


試してみます。資格を持っていないユーザがアクセスすると接続エラーになり、以下のようにエラーが /var/log/messages に記録されました。
デバッグモードで動かしているのでログの量が多めです。

Apr 27 03:40:50 samba3 pppd[7201]: Connect: ppp0 <--> /dev/pts/1
Apr 27 03:40:53 samba3 pptpd[7200]: CTRL: Ignored a SET LINK INFO packet with real ACCMs!
Apr 27 03:40:53 samba3 pppd[7201]: Winbind has declined authentication for user!
Apr 27 03:40:53 samba3 pppd[7201]: Logon failure
Apr 27 03:40:53 samba3 pppd[7201]: Peer rti failed CHAP authentication
Apr 27 03:40:53 samba3 pppd[7201]: Connection terminated.
Apr 27 03:40:53 samba3 pppd[7201]: Exit.


次に資格を持っているユーザーでアクセスしてます。
こちらは、うまくいきました。

Apr 27 03:40:30 samba3 pppd[7155]: Connect: ppp0 <--> /dev/pts/1
Apr 27 03:40:30 samba3 pppd[7155]: MPPE 128-bit stateless compression enabled
Apr 27 03:40:30 samba3 pptpd[7154]: CTRL: Ignored a SET LINK INFO packet with real ACCMs!
Apr 27 03:40:32 samba3 pppd[7155]: Cannot determine ethernet address for proxy ARP
Apr 27 03:40:32 samba3 pppd[7155]: local  IP address 192.168.59.1
Apr 27 03:40:32 samba3 pppd[7155]: remote IP address 192.168.59.100


メモ:文字列グループ名で制限をかけるために require-membership-of=RTI7743+vpn-allow や require-membership-of=RTI7743/vpn-allow や require-membership-of=RTI7743\vpn-allow や require-membership-of=RTI7743\\vpn-allow などといろいろ指定してみたのですが、すべてエラーで弾かれてしまいました。
やはり、SID で指定するのが一番なようです。

文字列したときのエラーログ

Apr 27 03:27:07 samba3 pppd[6740]: Connect: ppp0 <--> /dev/pts/1
Apr 27 03:27:07 samba3 ntlm_auth: [2011/04/27 03:27:07.652344,  0] utils/ntlm_auth.c:274(get_require_membership_sid)
Apr 27 03:27:07 samba3 ntlm_auth:   Could not parse vpn-allow into seperate domain/name parts!
Apr 27 03:27:07 samba3 pppd[6740]: Winbind has declined authentication for user!
Apr 27 03:27:07 samba3 pppd[6740]: (null)
Apr 27 03:27:07 samba3 pppd[6740]: Peer rti failed CHAP authentication
Apr 27 03:27:07 samba3 pppd[6740]: Connection terminated.
Apr 27 03:27:07 samba3 pppd[6740]: Exit.