Linuxのセミナーに参加してSELinuxとOpenSSH、https化を勉強しました

LPI 主催の Linux セキュリティに関するセミナーへ参加しました。

LPIC level2 も合格し、ある程度サーバーの構築ができるようになったので、次はセキュリティと SSL 証明書関連をマスターしようという思惑があります。

セミナーは 2 時間程度の座学でしたが、家で実際に作業してみましたので、その内容をまとめます。

セミナーの内訳

  • SELinux の設定方法
  • OpenSSH の設定方法
  • Web サーバーの SSL 設定方法

SELinux の設定方法と実際の挙動。OpenSSH の鍵認証の設定方法、SSL/TLS を当てて https 化する方法を学びました。

以下、記載したコマンドは CentOS7 で私が投入したものになります。Ubuntu など他の OS でも流れは同じですが、適宜自分の環境に置き換えて実行してください。

30 分で分かった気になれる SELinux

SELinux は Security-Enhanced Linux の略称で、Linux のカーネルに組み込まれているアクセス制御を行うためのモジュールです。有効にすると強固な壁を作ってくれます。ユーザーはその壁に穴を通すように、「このアプリケーションのこの動作を許可する。この動作は許可しない。」と言った具合に細かく挙動を制御することで、必要な動作のみ許可するような環境を構築できます。頑張れば root 権限でも回避できない強制的なアクセス制御も実現可能です。

SELinux の有効化

/etc/selinux/config 上記 config ファイルの「SELINUX=xxx」の項目を下記のように編集します。

SELINUX=enforcing or SELINUX=permissive

編集後は SELINUX を再起動します。

getenforce コマンドでステータスを確認できます。

SELinux を有効にするといくつかのコマンドの出力結果にコンテキストが付与されます。試しに下記コマンドを実行してみます。 ls -laZ, id, ps -axZ

ls では system_u:ob~~~ id では context=hogehoge ps では LABEL のカラムに変化が見られます。

semanage コマンドの利用

SELinux を設定するには「semanage」コマンドを利用します。semanage は policycoreutils-python の一部なので、それをインストールします。

sudo yum -y install policycoreutils-python

インストール後、semanage コマンドで実際に設定されているセキュリティ項目のブーリアン値をみてみます。例えば、Apache のセキュリティ項目で許可されている項目を見たい時。

sudo semanage boolean -l | grep httpd | grep Allow

ブーリアン値をオン/オフ(許可/不許可)することでアクセス制御を設定するようです。

OpenSSH でエレガントに ssh してみた

OpenSSH は SSH 接続を行うための Linux のソフトウェアです。SSH は全ての通信を暗号化しつつ、リモートのクライアントからサーバへアクセスする仕組みのこと。暗号化しているので、誰かに通信が盗聴された場合でも、複合するためのパスワードを知らない限り、盗聴者には通信内容がバレません。これで安心してリモート作業を行えます。

公開鍵認証

公開鍵と秘密鍵のペアを作成し、公開鍵で通信を暗号化、秘密鍵で複合します。公開鍵で暗号化された情報は秘密鍵でしか複合できません。秘密鍵を失くすと接続できなくなるので管理には気をつけます。

公開鍵認証の設定

ssh を公開鍵認証で接続できるように設定します。クライアント側で公開鍵と秘密鍵のペアを作成し、SSH 接続したいサーバーに、作成した公開鍵のコピーを置きます。

前準備

私は Vagrant で構築した仮想環境で試験しました。vagrant と virtualbox をインストールし、仮想マシンを二つ作成。各マシンの vagrantfile に下記1文を追記し、お互い疎通できる状態にしておきます。

ホスト A config.vm.network “private_network”, ip: “192.168.33.15”, virtualbox__intnet: “intnet”

ホスト B config.vm.network “private_network”, ip: “192.168.33.19”, virtualbox__intnet: “intnet”

クライアント側の設定

クライアント側で下記コマンドを投入し、公開鍵と秘密鍵を作成します。

ssh-keygen -t dsa

id_dsa が秘密鍵、id_dsa.pub が公開鍵です。ユーザーディレクトリの.ssh ディレクトリ内に置かれます。

SSH 接続先の設定

ssh 接続先のサーバーに潜り、クライアント側で作成した公開鍵を~/.ssh/authorized_keys に追加します。.ssh フォルダが無い場合は作成します。作成する場合は root 権限でしか操作できないようにパーミッションを設定します。

mkdir ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

authorized_keys に id_dsa.pub の内容を追記します。スマートなやり方ではないですが、vim で開いて最終行にコピペしました。

vim ~/.ssh/authorized_keys

クライアントからサーバーへ ssh

ssh してみます。 ssh hostname

ユーザー指定して ssh ssh user@hostname

OpenSSH サーバーの設定

PermitRootLogin の設定をして root でのログインを制限したり PasswordAuthentication の設定をしてパスワード認証の制限しました。

セキュアな ssh 接続を行うなら、root でのログインは No。パスワード認証も No にするべき。 さらに Google Authenticator を使ってワンタイムパスワード認証の設定もすれば、ガッチガチに強固な接続にできます。

Web サーバーの SSL 設定〜頑張って https 化してみた

SSL を介した http を https と呼びます。通信が暗号化されるので、ユーザーはより安心してサイトを閲覧できます。Chrome や Firefox では、https 化されていない Web サイトにアクセスしたユーザーに対し、下記のようなメッセージを表示するようになりました。https 化はすでに当たり前の時代が到来しています。

https の 3 つの役割

https 化すると、主に下記の 3 つのメリットがあります。

1)サーバーのなりすまし防止 2)送受信されるデータの盗聴防止 3)データの改ざん防止

1)について 認証局が電子署名したサーバー証明書でサーバー自体の信頼性を保証

2)について 共通鍵暗号で通信内容を暗号化

3)について メッセージ認証コードでデータが改ざんされていないことを確認

https 化に必要なもの

・Web サーバーに Apache を利用する場合は Apache の SSL モジュール ・サーバーの公開鍵(CSR)と秘密鍵(Key) ・認証局(CA)が電子署名したサイト証明書(CRT)

通常、信頼のおける認証局にて署名してもらう必要がありますが、今回、認証局を自分で構築しました。

セミナーで配布された資料の方法では Chrome58 に対応しておらず、うまく https 化できなかったため、下記ページを参考に証明書を発行しました。

Fixing Chrome 58+ [missing_subjectAltName] with openssl when using self signed certificates

前準備:Apache と OpenSSL のインストール、hosts の設定

下記コマンドで Apache と ssl モジュールをインストールします。OpenSSL がない場合はそれもインストールします。

yum -y install httpd mod_ssl
yum -y install openssl

証明書のコモンネームに任意のドメインを使用する場合は、/etc/hosts ファイルの設定も済ませておきます。

サーバー秘密鍵(Key)の作成

mkdir ~/crt/
openssl genrsa -aes128 -out ~/crt/server.key 2048

genrsa RSA 形式の秘密鍵を作成するサブコマンド。

-aes128 128 ビット AES 暗号方式で暗号化する。

-out 秘密鍵ファイル名 秘密鍵のファイル名を指定する。

2048 2048 ビットの秘密鍵にする。ビット数は最後に書く。

コマンドを実行するとパスフレーズの入力を求められるので、任意のパスフレーズを入力します。

CSR (Certificate Signing Request)の作成

CSR ファイルは証明書を発行するために必要な情報を記述します。このファイルの内容を基に、認証局は証明書を発行することができます。

openssl req -new -key ~/crt/server.key -sha256 -out ~/crt/server.csr

req CSR ファイルを作成する。

-new 新規に CSR を作成する。

-key 秘密鍵ファイル 秘密鍵のファイル名を指定する。

-sha256 署名アルゴリズムとして SHA-2 を利用する。(SHA-1 にする場合は、このオプションを付けない。)

-out CSR ファイル名 作成する CSR のファイル名を指定する。

コマンド実行後、秘密鍵のパスフレーズを要求されます。続いて国や会社の情報、コモンネーム(ドメイン名)の設定をします。

認証局(CA : Certification Authority)の構築

認証局を構築し、認証局の証明書(公開鍵)を発行します。

mkdir ~/ssl/
openssl genrsa -des3 -out ~/ssl/rootCA.key 2048
openssl req -x509 -new -nodes -key ~/ssl/rootCA.key -sha256 -days 1024 -out ~/ssl/rootCA.pem

コマンドが長いので、シェルスクリプトにして実行すると楽かなと思います。

サイト証明書の発行

CSR を認証局に送りつけて、サーバー証明書を発行します。

sudo openssl req -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout server.key -config <( cat ~/crt/server.csr.cnf )
sudo openssl x509 -req -in ~/crt/server.csr -CA ~/ssl/rootCA.pem -CAkey ~/ssl/rootCA.key -CAcreateserial -out ~/crt/server.crt -days 500 -sha256 -extfile ~/crt/v3.ext

あらかじめ下記内容で openssl のコンフィグファイルを作っておき、上記 1 行目の openssl コマンドで参照します。

[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn

[dn]
C=JP
ST=Hodaland
L=Hodacity
O=Hodacaompany
OU=Testing Domain
emailAddress=hodaland@gmail.com
CN = mycentos

さらに v3.ext ファイルを用意します(2 行目のコマンドで参照)。v3.ext ファイルでは subjectAltName、通称 SANS と呼ばれる項目を設定しています。これが特に重要で、chrome58 以降は証明書に SANS が設定されていないとエラーが表示されます。

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = mycentos

このコマンドも非常に長いので、シェルスクリプトとして実行するのが楽です。下記は実行結果になりますが、いくつかエラーが発生しています。このエラーは無視しても問題ないですが、 こちらのページ(C.2. Creating an SSL Certificate) を参考に解消できるので、試してみると良いかと。

サーバー秘密鍵とサイト証明書設置

サーバー秘密鍵とサイト証明書を適当な場所へ設置し、パーミッションの設定をします。

sudo mkdir /etc/httpd/conf/ssl.key
sudo chmod 700 /etc/httpd/conf/ssl.key
sudo cp ~/crt/server.key /etc/httpd/conf/ssl.key
sudo chmod 600 /etc/httpd/conf/ssl.key
sudo mkdir /etc/httpd/conf/ssl.crt
sudo cp ~/crt/server.crt /etc/httpd/conf/ssl.crt/server.crt

Apache の設定と接続確認

ssl.conf を編集し、ドキュメントルートの設定をコメントインします。

sudo vim /etc/httpd/conf.d/ssl.conf

さらに下記文を追記し、もともと設定されていた行はコメントアウトします。 SSLCertificateFile /etc/httpd/conf/ssl.crt/server.crt SSLCertificateKeyFile /etc/httpd/conf/ssl.key/server.key

動作確認

これまでの設定が完了したら Apache を再起動してブラウザで確認します。

sudo systemctl restart httpd

正しく設定されていればパスフレーズの入力指示があります。

ブラウザで確認すると下図のようになります。

これは、自分で構築した認証局の情報が PC に登録されていないためです。認証局の公開鍵(ルート証明書 Root certificate)をインポートすると、下図のようにアドレス欄が緑色になり、正常にページが表示されます。

検証ツールで確認すると、正常に証明書が当てられていることを確認できます。

まとめ

SELinux と OpenSSH、https 化の基本的な設定方法を学びました。自己認証による https 化はかなり手こずりましたが、無事解決できて良かったです。証明書に関しては、今後は Let’s encrypt を利用して、実際に運営しているサイトに適用したいと考えています。

以上です。