Kerberos 認証を理解する
はじめに
Kerberos 認証をちゃんと理解しないまま利用していたため、とある環境構築の案件でとてもハマってしまいました。次に同じ失敗をしないためにも、基礎を学ぶことが大切だと思うので、お勉強してみることにしました。
この記事でやること
- Kerberos 認証に関する知識の整理
- Kerberos 認証のデモ環境を構築
- Kerberos 認証でサーバーに接続するために必要な作業の説明
Kerberos 認証に関する知識の整理
Kerberos とは?
Kerberos は、ネットワーク認証プロトコルのひとつであり、これによりネットワーク内のクライアントとサーバー間で安全な通信を実現することが可能になります。
クライアント、サーバー、および KDC(Key Distribution Server)の3つから構成され、KDC から発行されるチケットにより、安全な通信とシングルサインオン(SSO)を実現することができます。
Kerberos 認証の流れ
Kerberos 認証では、上図の流れで認証プロセスを進めます。
その際、2種類のチケットを使います。
- TGT(Ticket Granting Ticket): ユーザーがログインするときに取得するチケット。他のサービスにアクセスするためのチケットを取得する際に使われる。
- Service Ticket: ユーザーが特定のサービスにアクセスするために必要なチケット。
Kerberos 認証の構成要素と用語
Realm
Realm は認証管理ドメインを示します。Realm は Kerberos サーバー(KDC) によって管理されます。
ユーザー/サービスは、その Realm の認証サーバーと secret (password/key) を共有する場合のみ、その Realm に属します。
Realm の主な役割は以下です。
- 認証ドメインの定義: ユーザーやサービスがどの KDC によって管理されるかを示す。
- 信頼関係(トラスト)の設定: 異なる Realm 間で信頼関係(トラスト)が設定されている場合、ユーザーは自分の Realm 外のリソースにアクセスできる。
Principal
Principal は、Kerberos がチケットを割り当てることができる一意の ID です。
この記事を書いてる段階で主要バージョンである Kerberos V5 での Principal の形式は以下のとおりです。
primary/instance@REALM
- primary: ユーザーの場合、ユーザ名。nfs などのサービスになることもある。host という単語になることもある。
- instance: instance は、user principal の場合は optional になるが、service principal の場合は必須。service principal の場合、instance に指定する hostname は FQDN で指定する必要がある。
- REALM: Realm のとこで説明した内容と同じ。慣習的には大文字で書く。
有効な Principal Name は以下のようなものがあります。
jdoe
jdoe/admin
jdoe/admin@CORP.EXAMPLE.COM
nfs/host.corp.example.com@CORP.EXAMPLE.COM
host/corp.example.com@CORP.EXAMPLE.COM
Kerberos 認証のデモ環境の構築
実際に手を動かしたほうが理解が早いので、Kerberos 認証を試せるデモ環境を構築して、基本的な操作方法を試してみたいと思います。
ここでは、クライアントからサーバーへ Kerberos 認証を使った接続ができるようになるまでに必要な手順を記録しています。
Docker のインストール
好きな方法で Docker をインストールします。
Docker Container を立ち上げる
https://github.com/rea9r/demo-kerberos-auth にデモ環境を用意しました。
以下のコマンドを実行して、必要なコンテナを全て立ち上げます。
docker-compose up --build
KDC でやること
kadmin で Principal のリストを出力
KDC のコンテナに接続して bash を実行します。
docker exec -it kerberos-kdc /bin/bash
kadmin を使って、Kerberos Database 内に存在する全ての Principal のリストを確認してみます。
kadmin.local -q "listprincs"
[root@kerberos-kdc /]# kadmin.local -q "listprincs"
Authenticating as principal root/admin@EXAMPLE.COM with password.
K/M@EXAMPLE.COM
kadmin/admin@EXAMPLE.COM
kadmin/changepw@EXAMPLE.COM
kadmin/kerberos-kdc@EXAMPLE.COM
kiprop/kerberos-kdc@EXAMPLE.COM
krbtgt/EXAMPLE.COM@EXAMPLE.COM
noPermissions@EXAMPLE.COM
kadmin は Kerberos V5 管理システムへのコマンドラインインターフェースです。kadmin.local
とすることで、Kerberos Database に直接アクセスします。
kadmin で Principal を新しく追加
kadmin.local -q "addprinc -randkey host/service-server@EXAMPLE.COM"
[root@kerberos-kdc /]# kadmin.local -q "addprinc -randkey host/service-server@EXAMPLE.COM"
Authenticating as principal root/admin@EXAMPLE.COM with password.
WARNING: no policy specified for host/service-server@EXAMPLE.COM; defaulting to no policy
Principal "host/service-server@EXAMPLE.COM" created.
kadmin で Service Principal と keytab を作成
次に、 service-server
のコンテナにデプロイする必要がある Service Principal の keytab ファイルを作成します。
kadmin.local -q "ktadd -k /service.keytab host/service-server@EXAMPLE.COM"
[root@kerberos-kdc /]# kadmin.local -q "ktadd -k /service.keytab host/service-server@EXAMPLE.COM"
Authenticating as principal root/admin@EXAMPLE.COM with password.
Entry for principal host/service-server@EXAMPLE.COM with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/service.keytab.
Entry for principal host/service-server@EXAMPLE.COM with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/service.keytab.
Entry for principal host/service-server@EXAMPLE.COM with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/service.keytab.
Entry for principal host/service-server@EXAMPLE.COM with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/service.keytab.
Entry for principal host/service-server@EXAMPLE.COM with kvno 2, encryption type camellia256-cts-cmac added to keytab WRFILE:/service.keytab.
Entry for principal host/service-server@EXAMPLE.COM with kvno 2, encryption type camellia128-cts-cmac added to keytab WRFILE:/service.keytab.
Entry for principal host/service-server@EXAMPLE.COM with kvno 2, encryption type des-hmac-sha1 added to keytab WRFILE:/service.keytab.
Entry for principal host/service-server@EXAMPLE.COM with kvno 2, encryption type des-cbc-md5 added to keytab WRFILE:/service.keytab.
kadmin で User Principal と keytab を作成
次に、service-server 上で利用する User Principal を追加します。
ここでのユーザー名は、service-server のコンテナ上のユーザー名と同じである必要があります。
ここでは、ユーザー名として krb5user
を使用します。
kadmin.local -q "addprinc -randkey krb5user"
[root@kerberos-kdc /]# kadmin.local -q "addprinc -randkey krb5user"
Authenticating as principal root/admin@EXAMPLE.COM with password.
WARNING: no policy specified for krb5user@EXAMPLE.COM; defaulting to no policy
Principal "krb5user@EXAMPLE.COM" created.
Principal 追加後の listprincs も確認しておく
[root@kerberos-kdc /]# kadmin.local -q "listprincs"
Authenticating as principal root/admin@EXAMPLE.COM with password.
K/M@EXAMPLE.COM
host/service-server@EXAMPLE.COM
kadmin/admin@EXAMPLE.COM
kadmin/changepw@EXAMPLE.COM
kadmin/kerberos-kdc@EXAMPLE.COM
kiprop/kerberos-kdc@EXAMPLE.COM
krbtgt/EXAMPLE.COM@EXAMPLE.COM
krb5user@EXAMPLE.COM
noPermissions@EXAMPLE.COM
kadmin.local -q "ktadd -k /krb5user.keytab krb5user@EXAMPLE.COM"
[root@kerberos-kdc /]# kadmin.local -q "ktadd -k /krb5user.keytab krb5user@EXAMPLE.COM"
Authenticating as principal root/admin@EXAMPLE.COM with password.
Entry for principal krb5user@EXAMPLE.COM with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/krb5user.keytab.
Entry for principal krb5user@EXAMPLE.COM with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/krb5user.keytab.
Entry for principal krb5user@EXAMPLE.COM with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/krb5user.keytab.
Entry for principal krb5user@EXAMPLE.COM with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/krb5user.keytab.
Entry for principal krb5user@EXAMPLE.COM with kvno 2, encryption type camellia256-cts-cmac added to keytab WRFILE:/krb5user.keytab.
Entry for principal krb5user@EXAMPLE.COM with kvno 2, encryption type camellia128-cts-cmac added to keytab WRFILE:/krb5user.keytab.
Entry for principal krb5user@EXAMPLE.COM with kvno 2, encryption type des-hmac-sha1 added to keytab WRFILE:/krb5user.keytab.
Entry for principal krb5user@EXAMPLE.COM with kvno 2, encryption type des-cbc-md5 added to keytab WRFILE:/krb5user.keytab.
keytab ファイルを各コンテナにコピー
Service Principal と User Principal の追加ができたら、keytab ファイルを各コンテナにコピーします。
docker cp kerberos-kdc:/service.keytab ./service.keytab
docker cp ./service.keytab service-server:/etc/krb5.keytab
docker cp kerberos-kdc:/krb5user.keytab ./krb5user.keytab
docker cp ./krb5user.keytab client-server:/etc/krb5.keytab
KDC の /etc/hosts の修正
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' service-server
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' client-server
172.18.0.2 kerberos-kdc
# 以下を追記
172.18.0.3 client-server
172.18.0.4 service-server
service-server での設定
コンテナに接続
docker exec -it service-server /bin/bash
/etc/ssh/sshd_config の修正
service-server が SSH の認証で Kerberos チケットを受け入れられるようにするには、/etc/ssh/sshd_config
で次の構成を有効にする必要があります。
# GSSAPI を使用した認証を有効にする
GSSAPIAuthentication yes
# セッション終了時に GSSAPI クレデンシャルをクリーンアップする
GSSAPICleanupCredentials yes
- GSSAPI 認証は、Kerberos のようなセキュアな認証メカニズムを提供するために使用されます。これを有効にすることで、クライアントは GSSAPI ベースの認証プロトコル(例えば Kerberos)を使用して SSH で接続できるようになります。
- これでパスワードを送信することなく、チケットベースのセキュアな認証を行うことができます。
/etc/krb5.conf の修正
/etc/krb5.conf
を修正して、KDC の接続先などを指定します。
[libdefaults]
default_realm = EXAMPLE.COM
forwardable = TRUE
[realms]
EXAMPLE.COM = {
kdc_ports = 88
kadmind_port = 749
kdc = host.docker.internal
admin_server = host.docker.internal
}
[domain_realm]
host.docker.internal = EXAMPLE.COM
krb5user の作成
adduser krb5user
これで service-server は krb5user の Kerberos チケットベースのログインを受け入れる準備が整いました。
client-server での設定
コンテナに接続
docker exec -it client-server /bin/bash
/etc/hosts の修正
client から接続したい server の情報を /etc/hosts
に追記します。
# 以下を追記
172.18.0.4 service-server
/etc/ssh/ssh_config の修正
client 側が SSH の認証で Kerberos チケットを利用できるようにするために/etc/ssh/ssh_config
で次の構成を有効にします。
# GSSAPI を使用した認証を有効にする
GSSAPIAuthentication yes
/etc/krb5.conf の修正
client 側も /etc/krb5.conf
を修正して、KDC の接続先などを指定します。
[libdefaults]
default_realm = EXAMPLE.COM
forwardable = TRUE
[realms]
EXAMPLE.COM = {
kdc_ports = 88
kadmind_port = 749
kdc = host.docker.internal
admin_server = host.docker.internal
}
[domain_realm]
host.docker.internal = EXAMPLE.COM
Client から色々試してみる
kinit で Kerberos チケットの初期化
これで kinit
を使用して Kerberos チケットを初期化できるようになりました。
kinit krb5user -k -t /etc/krb5user.keytab
kinit
コマンドがエラー無しで返された場合、クライアント側は krb5.conf
に基づいて KDC に正常にアクセスできたことを意味します。User Principal の TGT チケットを初期化できた状態になります。
klist で keytab ファイルの内容を確認
klist
を使用できるかを確認してみます。
klist -kte
[root@client-server /]# klist -kte
Keytab name: FILE:/etc/krb5.keytab
KVNO Timestamp Principal
---- ------------------- ------------------------------------------------------
2 06/19/2024 12:56:28 krb5user@EXAMPLE.COM (aes256-cts-hmac-sha1-96)
2 06/19/2024 12:56:28 krb5user@EXAMPLE.COM (aes128-cts-hmac-sha1-96)
2 06/19/2024 12:56:28 krb5user@EXAMPLE.COM (des3-cbc-sha1)
2 06/19/2024 12:56:28 krb5user@EXAMPLE.COM (arcfour-hmac)
2 06/19/2024 12:56:28 krb5user@EXAMPLE.COM (camellia256-cts-cmac)
2 06/19/2024 12:56:28 krb5user@EXAMPLE.COM (camellia128-cts-cmac)
2 06/19/2024 12:56:28 krb5user@EXAMPLE.COM (des-hmac-sha1)
2 06/19/2024 12:56:28 krb5user@EXAMPLE.COM (des-cbc-md5)
Kerberos チケットを使用して SSH 接続
Kerberos チケットを使用して、パスワードを必要とせずに SSH 接続できることを確認します。
ssh krb5user@service-server
[root@client-server /]# ssh krb5user@service-server
The authenticity of host 'service-server (172.18.0.4)' can't be established.
ECDSA key fingerprint is SHA256:t+yaqZfgauI2ZMAWd3gF3bzHhoLyJU55wI/X/ePJ630.
ECDSA key fingerprint is MD5:c6:a4:cb:15:3f:34:03:de:da:73:07:36:ad:58:7e:f9.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'service-server,172.18.0.4' (ECDSA) to the list of known hosts.
Last login: Thu Jun 20 11:33:03 2024 from client-server.demo-kerberos-auth_default
[krb5user@service-server ~]$
これで Kerberos 認証を利用したサーバーへの接続が確認できました。
Discussion