LDAPとSSH認証について

# LDAP
- **「Lightweight Directory Access Protocol」の略**で、ディレクトリデータベースへアクセスするためのプロトコルのこと
- LDAPにより、後述する、「LDAP認証」や「LDAP連携」といった仕組みが実現される
- また、LDAPのオープンソースソフトウェアをOpenLDAPという
- LDAPはLDAPクライアント(認証される側)とLDAPサーバー(認証する)で構成され、LDAPサーバーを複数台で構成することで負荷分散及び冗長化構成をとることもできる

## ディレクトリサービスとは
- **ネットワークを利用するユーザ名やマシン名等、様々な情報を管理するためのサービス**のこと
- ユーザ名等のキー値から様々な情報を検索することが可能
- 主な特徴としては以下
    - 読み取りが高速
    - 分散型の情報格納モデル
    - 高度な検索機能を持つ
    - テーブル構造ではなく木構造
    - 主にテキストベースの情報を扱う
    - 基本的な設定項目が最初から定義されている（氏名・電話番号など）

## LDAPの主な機能
### Linuxのシステムアカウント情報の一元化
- 多数のLinuxクライアントがある場合、1台1台にIDパスワード情報を入れることなく、LDAPサーバ1台だけ登録すれば、どのLinuxクライアントからも同じIDパスワードでログインできる

### Linuxサーバの各種アプリでのIDパスワード統一化
- ログインが必要なWebアプリサーバのIDパスワード情報を統一化することができる
- さらにこの発展形として、シングルサインオン（1つのサーバで認証すれば、他のサーバは認証無しでログインできる仕組み）も実装することができる

### 社員情報の共有
- LDAPサーバに氏名やメールアドレス等の情報を格納し、別のLinuxサーバにCybozu等のグループウェアサーバをインストールし利用することで共有することができる
- また、グループウェアサーバー側にアカウント設定を行うことなく、LDAPサーバーに登録するのみでアカウントの生成等も行うことができる

## LDAPとRDBの違い
- RDBは複雑なテーブル構造の更新処理に適している反面、LDAPの機能としては無駄な処理が走り負荷が大きくなる
- LDAPはデータベースのような複雑な構造は取れないが、簡単なツリー構造になっているため比較して負荷が軽くすることができる

## LDAPとAD（Active Directory）との違い
- Active Directoryとは、アカウントの管理を行うディレクトリ・サービス・システムで、ドメイン単位で管理する範囲を定義することができる
- Active Directoryのドメインコントローラは内部でLDAP（RFC4511に準拠したもの）を利用している

## LDAPの具体的な機能と仕組み
LDAPを用いることで、クライアントはLDAPサーバに接続を行い属性（個人名や部署名）で構成するエントリ（関連属性のまとまり）の検索、追加、削除の操作を行うことができる

- DIT(Directory Information Tree)というツリー構造のデータ形式で情報を管理されている
- ツリーにはエントリという単位で情報が登録され、一つのエントリにはLDAP識別名が一意に定められている
- エントリには複数の属性で構成されており、特に「objectClass」属性（スキーマ）ではエントリに登録されるべき属性を定義できる

### LDAP識別名
- ディレクトリサービスにアクセスを行うには、LDAP識別名（識別名 : DN（Distinguished Name））を用いる
- LDAP識別名は、複数のLDAP相対識別名（RDN（Relative Distinguished Name））をカンマ区切りで並べたもの
    - 例えば、ドメイン「kamihork.com」のコンテナ「Users」に配置したユーザー「hori」は`cn=hori, cn=Users, dc=kamihork, dc=com`となる
    - LDAP相対識別名（RDN）は「属性値=値」という構文で定義するが、具体的な定義はディレクトリサービスのソフトウェアにより異なる

Active Directoryで使用できるLDAP属性値

| LDAPの属性値 | 属性表示名 | オブジェクトタイプ |
|:--|:--|:--|
| cn | Common-Name | 　ユーザー名、グループ名、コンピュータ名、コンテナ名 |
| ou | Organizational-Unit-Name | 　組織単位（OU） |
| dc | Domain-Component | 　ドメイン |

# SSH
Secure Shellの略。SSHとは、**暗号や認証の技術を利用して、安全にリモートコンピュータと通信するためのプロトコル**のこと

- SSHの主要な認証方式としてはパスワード認証方式と公開鍵認証方式がある
- パスワード認証方式
    - デフォルトの認証方式で、ユーザー名とパスワードでログインする方式
    - ユーザー名とパスワードは接続先OSのユーザーアカウントの情報が利用
- 公開鍵認証方式
    - 公開鍵認証方式は公開鍵と秘密鍵の２つの鍵(キーペア)を使用した接続方式
    - サーバーに公開鍵を、クライアントに秘密鍵を置いて利用
    - また、公開鍵認証を使うとパスワード入力なしでログインする事が可能

## sshとsshdの違い
- ssh(SSH client) : 他のサーバにsshで接続する設定
- sshd(OpenSSH Daemon) : 他のサーバからsshで接続されるときの設定であり、これが動作していないとsshでログインできない

## Open SSH
**LinuxでのデファクトスタンダードであるSSHプロトコルを使用（実現）する為のソフトウェア**であり、SSHクライアントとSSHサーバーの両方が含まれている

- sshコマンド
    - SSHでリモートホストに接続して各種コマンドを実行
    - `$ ssh [ユーザー名@]ホストネーム [実行コマンド]`で実行
        - ユーザー名を省略するとクライアントの現在のユーザーが利用
        - コマンドを指定すると、リモートホストに接続し指定のコマンドだけ実行してログアウトすることができる
        - ログアウト時は`$ exit`
    - オプション
        - i : 公開鍵認証で使用する秘密鍵ファイルを指定
        - F : 設定ファイルを指定
        - p : ポート番号を指定
- scpコマンド
    - SSHを使用してリモートホストとの間でファイルを転送を行う
    - クライアント側のファイルをリモートホストへコピー
        - `$ scp 転送ファイル [ユーザー名@]ホストネーム[:ディレクトリ名]`
    - リモートホストのファイルをクライアント側へコピー
        - `$ scp [ユーザー名@]ホストネーム:転送ファイル ディレクトリ名`
- ssh-keygen
    - 公開鍵認証方式で使用するキーペアを生成
    - オプション
        - b : 鍵の長さを指定する（最低値は768bit、初期値は2048bit）
        - C : 秘密鍵のコメントを新規作成
        - c : 秘密鍵ファイルおよび公開鍵ファイルのコメントを変更
        - f（T） : 鍵ファイル名を指定
        - i : 鍵ファイルの情報を表示
        - P : 秘密鍵のパスフレーズを変更
        - t : 暗号タイプを指定

| 暗号タイプ | 特徴 |
|:--|:--|
| RSA1 | SSH１で使えるが、SSH脆弱性がある |
| DSA | SSH2で使えるが、鍵長が1024bitと短め |
| RSA | 鍵長が最長4096bitと長め |

- ssh-copy-id
    - 公開鍵をリモートホストに登録するコマンド
    - リモートホスト指定ユーザーの`~/.ssh/authorized_keys`に公開鍵が追加される

### `~/.ssh/`内のファイル
Open SSHでは、~/.ssh/内のファイルがモード600(ユーザーのみ読み書き可能)でないと使用できないので注意

 - authorized_keys : 接続を許可する公開鍵を登録するサーバー側のファイル
 - config : SSH接続の情報を定義できるファイル
    - sshコマンドのオプションを省略したり、コマンドラインオプションでは指定できない情報も設定可能
    - 特に踏み台サーバー（SSHゲートウェイ/SSHプロキシ経由での多段SSH接続）の接続設定をする際に便利
 - id_rsa : ssh-keygenで生成した秘密鍵
 - id_rsa.pub : ssh-keygenで生成した公開鍵
 - known_hosts : 過去に接続したことがあるサーバー情報が格納されるファイル

## 公開鍵認証方式での接続
- 公開鍵認証で使用するキーペアはssh-keygenコマンドで生成を行う
- パスフレーズ（秘密鍵を暗号化するためのもの）を設定できるが、これを入力にするとパスワード/パスフレーズの接続毎に入力が必須になるので注意
- randomart image
    - 鍵を、人間がみやすいように記号絵図にすることによって、鍵内容の変化を判別しやすくするためのもの

### 公開鍵をサーバーに登録する
- ssh-copy-idコマンドによる追加、またはscpコマンド等を利用して公開鍵を追加する
    - なお、`~/.ssh/authorized_keys`は複数の公開鍵を登録するファイルなので、既存の情報を消さないように注意

### サーバー側での公開鍵とユーザーの結びつけ
- 1. ユーザーの作成
    - `$ adduser ユーザー名`でユーザーの作成後、`$ password ユーザー名`でパスワードを入力
- 2. 作成したユーザーにsudo権限を付与
    - `/etc/sudoers`を開き、`ユーザー名 ALL=(ALL) ALL`を追記
- 3. サーバー側に渡した鍵をユーザー配下に配置
    - `$ cd /home/ユーザー名`
    - `$ mkdir .ssh`
    - `$ mv /home/ec2-user/公開鍵.pub /home/ユーザー名/.ssh/authorized_keys`
- 4. オーナーグループの変更とパーミッションの変更
    - `$ chown ユーザー名 /home/ユーザー名/.ssh/authorized_keys`
    - `$ chgrp ユーザー名 /home/ユーザー名/.ssh/authorized_keys`
    - `$ chmod 600 /home/ユーザー名/.ssh/authorized_keys`
    - `$ chmod 700 /home/ユーザー名/.ssh`

### SSHコマンド実行時の内部処理
0. SSHコマンドを実行
1. サーバー側で公開鍵と生成する乱数で暗号とハッシュ値を作成し、暗号をクライアント側に渡す。
2. クライアント側で暗号を受け取ると、パスフレーズで秘密鍵と暗号を復号。
3. クライアント側で復号された秘密鍵と乱数から、サーバー側で生成したハッシュ値を生成し、known_hostsに保存。
4. クライアント側で生成したハッシュ値をサーバー側へ送る
5. クライアントから送られてきたハッシュ値と、サーバー側のknown_hosts格納のハッシュ値が一致したら認証成功。

## SSHを自由に繋がせない理由
- サイバー犯罪者やマルウェアによるsshの悪用
- ファイルの改ざんやシステムファイルの改ざん
- 機密情報の漏えいやマルウェアの感染
- 踏み台にされて他のリモートホストへ接続し悪用
    - [IoTサーバーを踏み台としたDDos攻撃](http://www.itmedia.co.jp/enterprise/articles/1610/17/news040_2.html)

等、不正に接続されると開発者だけでなく第三者への被害にも繋がる可能性がある

## SSHのセキュリティを高める方法
- 標準ポートの変更
    - 一般的なポートの場合botなどから攻撃がされる危険があるため、標準のTCP22番ポートから変更する
    - `/etc/ssh/sshd_config`のPort項目を修正
- ssh経由でのrootにログイン規制とログイン可能ユーザーの限定
    - rootログインは基本的に不要であり、通常ユーザーのログインよりもリスクが高い
    - rootはどのサーバーにもあるアカウントなので総当り攻撃される危険があるため、ssh経由でrootにログインできないようにする
    - `/etc/ssh/sshd_config`のPermitRootLogin項目をNoに修正し、AllowUsersを追加
- パスワード認証を切る
    - 辞書攻撃(dictionary attack)される危険があるため、 公開鍵方式の認証のみを利用する
    - `/etc/ssh/sshd_config`のPasswordAuthentication項目, ChallengeResponseAuthentication項目をNoに修正
- sshdのプロトコルを2にする
    - sshdのプロトコル1は脆弱性があるため、プロトコル2を利用する
    - `/etc/ssh/sshd_config`のProtocol項目を2に修正
- 認証時の試行回数や時間を制限する
    - `/etc/ssh/sshd_config`のLoginGraceTime項目, MaxAuthTries項目を修正
- 総当たり攻撃を検知できるsshguardやfail2banの導入
- SSHの接続メッセージを変更する
    - SSHサービスへ接続してきたユーザーに対して見せるための固定のメッセージをカスタマイズする
    - `/etc/ssh/sshd_config`の`#Banner /etc/issue.net`項目を任意のテキストファイルのパスに変更
- TCP wrappersやiptablesを利用した特定のホストからの接続だけの許可
- iptablesによる一定時間内のSSHアクセス数を制限

# 参考
- [LDAPとは何をするもの？](https://thinkit.co.jp/free/tech/18/1/1.html)
- [【図解】初心者にも分かるLDAP入門～仕組みや認証/連携の具体例、ADやデータベースとの違い～](https://milestone-of-se.nesuke.com/l7protocol/ldap/ldap-summary/)
- [LDAP Authentication](https://www.infraexpert.com/study/security19.html)
- [OpenLDAPでユーザー認証までやってみる](https://qiita.com/toshihirock/items/fc6ba5b6be8040e69ac9)
- [インフラエンジニアじゃなくても押さえておきたいSSHの基礎知識](https://qiita.com/tag1216/items/5d06bad7468f731f590e)
- [SSHなるものをよくわからずに使っている人のための手引書](https://qiita.com/kenju/items/b09199c4b3e7203a2867)
- [【ssh-keygen】Linuxで秘密鍵・公開鍵を生成するコマンド](https://uxmilk.jp/52740)
- [SSHの仕組み!ぼんやりとした理解だったものをすっきりさせようの会](http://nigohiroki.hatenablog.com/entry/2013/08/18/221434)
- [システム管理で“御用達”ツールの「ssh」　攻撃者も利用する実態は？ (1/3)](http://www.itmedia.co.jp/enterprise/articles/1611/22/news009.html)
- [そこそこセキュアなlinuxサーバーを作る](https://qiita.com/cocuh/items/e7c305ccffb6841d109c#5-%E4%BD%BF%E3%82%8F%E3%81%AA%E3%81%84%E3%83%9D%E3%83%BC%E3%83%88%E3%82%92%E9%96%89%E3%81%98%E3%82%8B)
- [SSHのセキュリティを高めるためのハウツー](http://www.itmedia.co.jp/enterprise/articles/0704/05/news010.html)