110.2 レッスン 1
Certificate: |
LPIC-1 |
---|---|
Version: |
5.0 |
Topic: |
110 セキュリティ |
Objective: |
110.2 ホストセキュリティの設定 |
Lesson: |
1 of 1 |
はじめに
この章では、ホストのセキュリティを高める4つの基本的な手段を説明します。
-
シャドウパスワードを使って認証のセキュリティを高める
-
受信ネットワーク接続を待ち受けるスーパーデーモンを利用する
-
使用していないネットワークサービスを無効にする
-
ファイアウォールとしてTCPラッパーを用いる
シャドウパスワードを使って認証のセキュリティを高める
ユーザーアカウントの基本的な情報は、/etc/passwd
ファイルに保存されます。このファイルには、ログイン名、パスワード代わりの文字、ユーザーID、グループID、コメント(GECOSとも呼ばれます)、ホームディレクトリのパス、デフォルトシェルの、7つのフィールドが含まれています。この順番を覚えるには、ログインの時に何が起きるかを考えるのが簡単です。まず、ログイン名とパスワード(passwdファイルの中では x
になっているのが普通です)を入力します。システムはそれらをユーザーID(UID)とグループID(GID)に対応付けます。コメントないしGECOSがあって、それからユーザーのホームディレクトリに移動して、デフォルトのシェルを起動します。
最近のシステムでは、/etc/passwd
ファイルにパスワードが保存されず、パスワードフィールドには小文字の x
だけが記載されています。/etc/passwd
ファイルはすべてのユーザーが読み取り可能ですから、そこにパスワードを保存すべきではないのです。/etc/passwd
ファイルのパスワードフィールドに記載された小文字の x
は、暗号化された(ハッシュ化された)パスワードが /etc/shadow
ファイルに保存されていることを示します。/etc/shadow
ファイルは、すべてのユーザーが読み取り可能にはなっていません。
passwd
コマンドと chage
コマンドでパスワードに関する属性を設定できます。これらのコマンドは、/etc/shadow
ファイル内のエントリを変更します。ユーザー emma
のパスワードを設定するには、root権限で次のコマンドを実行します。
$ sudo passwd emma New password: Retype new password: passwd: password updated successfully
確認のため新しいパスワードを2回入力することを求められます。
ユーザー emma
のパスワードの有効期間その他の設定を表示するには、次のコマンドを実行します。
$ sudo chage -l emma Last password change : Apr 27, 2020 Password expires : never Password inactive : never Account expires : never Minimum number of days between password change : 0 Maximum number of days between password change : 99999 Number of days of warning before password expires : 7
ユーザーアカウントを無効化して emma
がシステムにログインできないようにするには、root権限で、アカウントが無効になる日付に現在よりも昔の日付を設定します。例えば、今日が2020年3月27日だとしたら、次のように、アカウントが無効になる日付に2020年3月26日を設定します。
$ sudo chage -E 2020-03-26 emma
ユーザー emma
のパスワードをロックするには、root権限で次のコマンドを実行します。
$ sudo passwd -l emma
-l
オプションを指定して passwd
コマンドを実行すると、パスワードをロックします。
(sudo chage -E 2020-03-26 emma
のようなコマンドを実行して)ユーザーアカウントを無効化したらどうなるかを、emma
としてログインしてみて確認します。
$ sudo login emma Password: Your account has expired; please contact your system administrator Authentication failure
rootユーザー以外のすべてのユーザーがシステムにログインできないようにするには、root権限で /etc/nologin
という名前のファイルを作成します。このファイルには、例えば「システムメンテナンス中」のように、ログインできない理由を知らせるメッセージを含められます。詳細は man 5 nologin
を参照してください。
ユーザーのデフォルトのシェルに nologin
コマンドを設定することで、そのユーザーがログインできないようにするという方法もあります。emma
にそうするなら、次のコマンドを実行します。
$ sudo usermod -s /sbin/nologin emma
詳細については man 8 nologin
を参照してください。
受信ネットワーク接続を待ち受けるスーパーデーモンを利用する
ウェブサーバー、メールサーバー、プリントサーバーなどのネットワークサービスは、専用のポートで接続を待ち受けるスタンドアロンのサービスであることが一般的です。こうしたスタンドアロンのネットワークサービスは、独立して並列的に動いています。サービスを管理するには、昔ながらのSysVinitに基づいたシステムでは service
コマンドを、最近のsystemdに基づいたシステムでは systemctl
コマンドを使います。
かつてはコンピューターリソースが非常に貧弱だったので、たくさんのサービスを並行してスタンドアローンモードで実行することには難がありました。そこで、スーパーデーモンが受信ネットワーク接続の待ち受けを一手に引き受け、要求に応じてそれぞれのネットワークサービスを開始していました。この方法ではネットワーク接続に少し余計な時間がかかります。よく知られているスーパーデーモンは inetd
と xinetd
です。systemdに基づく最近のシステムでは、systemd.socket
ユニットをこの目的で使えます。この節では、xinetd
が接続を待ち受けて要求に応じて sshd
デーモンを開始するという例を示してから、それと同等のsystemdソケットユニットの例を示します。
xinetd
の設定に入る前に、いくつかの準備をします。Debian系でもRed Hat系でも違いはありません。ここでの説明はDebian/GNU Linux 9.9で試したものですが、systemdに基づく最近のシステムであれば同じように実行できるはずです。
まず、openssh-server
と xinetd
がインストールされていることを確認します。(訳注:デフォルトで xinetd
がインストールされているディストリビューションはかなり減っています。インストールされていない場合は、xinetd
パッケージをインストルーしてください。)次に、以下のコマンドを実行して、SSHサービスが稼働していることを確かめます。
$ systemctl status sshd ● ssh.service - OpenBSD Secure Shell server Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2020-04-27 09:33:48 EDT; 3h 11min ago Docs: man:sshd(8) man:sshd_config(5) Process: 430 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS) Main PID: 460 (sshd) Tasks: 1 (limit: 1119) Memory: 5.3M CGroup: /system.slice/ssh.service └─460 /usr/sbin/sshd -D
以下のコマンドを実行して、SSHサービスがポート22番で接続を待ち受けていることを確認します。
$ sudo lsof -i :22 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 1194 root 3u IPv4 16053268 0t0 TCP *:ssh (LISTEN) sshd 1194 root 4u IPv6 16053270 0t0 TCP *:ssh (LISTEN)
sshd
ではなく xinetd
が接続を待ち受けるようにするために、以下のコマンドを実行してSSHサービスを止めます。
$ sudo systemctl stop sshd.service
再起動した後もSSHサービスを止めておくなら、systemctl disable sshd.service
を実行します。
ここからxinedの設定に入ります。以下の内容を記載した /etc/xinetd.d/ssh
ファイルを作成します。
service ssh { disable = no socket_type = stream protocol = tcp wait = no user = root server = /usr/sbin/sshd server_args = -i flags = IPv4 interface = 192.168.178.1 }
以下のコマンドを実行してxinetdを再起動します。
$ sudo systemctl restart xinetd.service
SSH接続の受信をどのサービスが待ち受けているかを確認します。
$ sudo lsof -i :22 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME xinetd 24098 root 5u IPv4 7345141 0t0 TCP 192.168.178.1:ssh (LISTEN)
xinetdサービスがポート22番で接続を待ち受けていることがわかります。
xinetd
の設定の詳細を説明します。設定ファイルは /etc/xinetd.conf
です。
# Simple configuration file for xinetd # # Some defaults, and include /etc/xinetd.d/ defaults { # Please note that you need a log_type line to be able to use log_on_success # and log_on_failure. The default is the following : # log_type = SYSLOG daemon info } includedir /etc/xinetd.d
デフォルトを設定する部分(defaults { }
)を除くと、ディレクトリを読み込むディレクティブ(includedir /etc/xinetd.d
)だけがあります。このディレクトリ /etc/xinetd.d
内に、xinetd
が扱うサービスごとに設定ファイルを作成していきます。先ほどの例では、SSHサービスの設定ファイルを /etc/xinetd.d/ssh
という名前で作成しました。.
(ドット)が含まれておらず ~
(チルダ)で終わらない限りファイル名は何でもよいのですが、設定するサービス名をファイル名にするのが一般的です。
ディレクトリ /etc/xinetd.d
内に、最初から作られている設定ファイルがあります。
$ ls -l /etc/xinetd.d total 52 -rw-r--r-- 1 root root 640 Feb 5 2018 chargen -rw-r--r-- 1 root root 313 Feb 5 2018 chargen-udp -rw-r--r-- 1 root root 502 Apr 11 10:18 daytime -rw-r--r-- 1 root root 313 Feb 5 2018 daytime-udp -rw-r--r-- 1 root root 391 Feb 5 2018 discard -rw-r--r-- 1 root root 312 Feb 5 2018 discard-udp -rw-r--r-- 1 root root 422 Feb 5 2018 echo -rw-r--r-- 1 root root 304 Feb 5 2018 echo-udp -rw-r--r-- 1 root root 312 Feb 5 2018 servers -rw-r--r-- 1 root root 314 Feb 5 2018 services -rw-r--r-- 1 root root 569 Feb 5 2018 time -rw-r--r-- 1 root root 313 Feb 5 2018 time-udp
あまりないとは思いますが、daytime
(時刻を同期するために大昔に使っていたサーバーです)などの古いサービスを使用する場合には、これらのファイルをテンプレートとして使えます。これらのテンプレートファイルには、disable = yes
というディレクティブが含まれていますから、yes
を no
に変更すると有効になります。
先のsshの例で /etc/xinetd.d/ssh
に記載したディレクティブについて、少し詳しく見てみましょう。
service ssh { disable = no socket_type = stream protocol = tcp wait = no user = root server = /usr/sbin/sshd server_args = -i flags = IPv4 interface = 192.168.178.1 }
service
-
xinetdが制御するサービスを記載します。22のようにポート番号を記載してもよいですし、
ssh
のように/etc/services
でポート番号と対応づけられているサービス名を記載してもよいです。 {
-
中括弧内に詳細設定を記載します。
disable
-
no
にすると設定が有効になります。設定を無効にしたいときはyes
にします。 socket_type
-
TCPソケットでは
stream
に、UDPソケットではdgram
にします。 protocol
-
TCPまたはUDPのいずれかを記載します。
wait
-
TCP接続の場合は通常
no
に設定します。 user
-
開始するサービスの所有者を記載します。
server
-
xinetd
が開始するサービスのフルパスを指定します。 server_args
-
サービス(コマンド)のオプションを追加します。スーパーデーモンからの起動を指示するオプションを指定します。SSHなら
-i
オプションです。 flags
-
IPv4やIPv6などのオプション。通常は指定する必要がありません。
interface
-
xinetd
が待ち受けるネットワークインターフェイス名、ないしはIPアドレスを記載します。bind
ディレクティブも同じ意味です。 }
-
中括弧を閉じるのを忘れないようにしてください。
systemdを使用するシステムでは、xinetd
ではなく、systemdソケットユニットを使用するのが普通です。SSHサービスがインストールされていれば、そのsystemdソケットユニットが既に存在しますから、設定ファイルの作成は必要ありません。通常は、systemdソケットユニットではなくssh(ないしsshd)サービスユニットが起動しているはずですから、まずそれを停止します。xinetd
も停止していることを確かめてください。(訳注:sudo lsof -i :22
を実行して何も表示されなければ、sshd
も xinetd
も起動していないことがわかります。)
以下のコマンドを実行してSSHソケットユニットを開始します。
$ sudo systemctl start ssh.socket
もう一度 lsof
を実行して、今はどのサービスがポート22番を待ち受けているかを確認してみましょう。ここでは -P
オプションを指定して、サービス名ではなくポート番号を表示します。
$ sudo lsof -i :22 -P COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME systemd 1 root 57u IPv6 14730112 0t0 TCP *:22 (LISTEN)
この節の締めくくりとして、好みのSSHクライアントでログインしてみてください。sshdプロセスが起動していることをpsコマンドで確認してみましょう。
Tip
|
|
使用していないネットワークサービスを無効にする
システムリソースとセキュリティの観点から、どのサービスが実行中かを把握しておくことは重要です。使われていない不要なサービスは無効にすべきです。例えば、ウェブページを提供する必要がないのであれば、Apacheやnginxといったウェブサーバーを実行する必要はありません。
SysVinitに基づいたシステムでは、次のコマンドを実行するとサービスの状況を確認できます。
$ sudo service --status-all
このコマンドを実行して出力されるサービスの一覧を確認して、不要なサービスを無効にします。Debian系のシステムでは次のコマンドを実行します。
$ sudo update-rc.d サービス名 remove
Red Hat系のシステムでは次のコマンドを実行します。
$ sudo chkconfig サービス名 off
最近主流のsystemdに基づいたシステムでは、次のコマンドを実行すると、すべての実行中のサービスを表示します。
$ systemctl list-units --state active --type service
次のコマンドを実行して不要なサービスユニットを無効にします。
$ sudo systemctl disable ユニット --now
このコマンドは、指定したユニットのサービスを停止して、有効なサービスのリストから削除します。そのため、次回以降の起動時には自動実行されなくなります。
さらに、接続を待ち受けているネットワークサービスの調査も行います。古いシステムでは、netstat
コマンド(net-tools
パッケージをインストールすると使えるようになります)を実行します。
$ netstat -ltu Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:ssh 0.0.0.0:* LISTEN tcp 0 0 localhost:mysql 0.0.0.0:* LISTEN tcp6 0 0 [::]:http [::]:* LISTEN tcp6 0 0 [::]:ssh [::]:* LISTEN udp 0 0 0.0.0.0:bootpc 0.0.0.0:*
新しいシステムでは、ss
(Socket Services)コマンドを実行します。
$ ss -ltu Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port udp UNCONN 0 0 0.0.0.0:bootpc 0.0.0.0:* tcp LISTEN 0 128 0.0.0.0:ssh 0.0.0.0:* tcp LISTEN 0 80 127.0.0.1:mysql 0.0.0.0:* tcp LISTEN 0 128 *:http *:* tcp LISTEN 0 128 [::]:ssh [::]:*
ファイアウォールとしてTCPラッパーを用いる
Linuxでファイアウォールが使えなかった時代には、TCPラッパーをホストのネットワーク接続のセキュリティを高めるために使っていました。現在では、TCPラッパーに対応していないプログラムがほとんどです。Fedora 29などのRed Had系のディストリビューションではTCPラッパーがサポートされなくなりました。それでも、古いシステムではTCPラッパーが用いられていることがありますから、基本的な事柄を知っておくことは有用です。(訳注:インストールされていない場合は、tcpd
パッケージをインストールします。)
ここでもSSHサービスを例に取ります。ローカルネットワークからしかSSH接続できないようにします。まず、SSHデーモンが、TCPラッパーをサポートする libwrap
ライブラリを使っているかを確認します。
$ ldd /usr/sbin/sshd | grep "libwrap" libwrap.so.0 => /lib/x86_64-linux-gnu/libwrap.so.0 (0x00007f91dbec0000)
次に、/etc/hosts.deny
ファイルに以下の行を追記します。
sshd: ALL
最後に、/etc/hosts.allow
ファイルに、ローカルネットワークからのSSH接続を例外的に許容するために、以下の行を追記します。
sshd: LOCAL
この変更は即座に反映されます。サービスを再起動する必要はありません。ローカルネットワーク以外から ssh
クライアントで接続して確かめてみてください。
演習
-
ロックされている
emma
のパスワードを解除(アンロック)してください。 -
ユーザーアカウント
emma
の有効期間を無期限(いつまでもアカウントが無効にならない)に設定してください。 -
印刷ジョブを処理するCUPSプリントサービスを無効にしてください。そして、CUPSプリントサービスで使われるポートで接続を待ち受けていないことを確かめてください。(CUPSプリントサービスを利用しているシステムで実施する場合には注意してください。)
-
インストールしたnginxウェブサーバーがTCPラッパーをサポートしているかどうかを調べてください。
発展演習
-
/etc/nologin
ファイルが存在すると、ユーザーroot
もログインできなくなるでしょうか? -
/etc/nologin
ファイルが存在すると、パスワードを使用しないSSH鍵によるログインもできなくなるでしょうか? -
login currently is not possible
とだけ記載された/etc/nologin
ファイルが存在すると、ログイン時にどうなりますか? -
一般ユーザーである
emma
は、grep root /etc/passwd
コマンドを実行して/etc/passwd
の中の ユーザーroot
の情報を見ることができますか? -
一般ユーザーである
emma
は、grep -i emma /etc/shadow
コマンドを実行して/etc/shadow
の中の自分のハッシュ化されたパスワードを見ることができますか? -
時刻を同期するために大昔に使っていたdaytimeサービスを、xinetdで利用するためにはどうすればよいでしょうか?(これはあくまでも説明のための演習です。本番環境では実行しないでください。)
まとめ
このレッスンでは、以下の事柄を学びました:
-
パスワードとその有効期間などの設定が保存されているファイル
-
xinetd
スーパーデーモンの目的とxinetd
がsshd
サービスを開始する仕組み -
実行中のネットワークサービスの確認と不要なサービスの無効化
-
シンプルなファイアウォールとしてのTCPラッパー
以下のコマンドを取り上げました。
chage
-
パスワードの有効期間などを変更します。
chkconfig
-
Red Hat系のシステムで、サービスを自動起動するかどうかを設定します。(古いコマンド)
netstat
-
ネットワークポートにアクセスするサービスの状態を表示する古いユーティリティです(
net-tools
パッケージに含まれています)。 nologin
-
ユーザーのシェルとして設定すると、そのユーザーがログインできなくなります。
passwd
-
ユーザーのパスワードをセットないし変更します。
service
-
サービスの停止や開始など、デーモンの状態を制御する古いコマンドです。
ss
-
ソケットの詳細状態を表示する、現在主流のコマンドです。(古いコマンドは
netstat
)。 systemctl
-
systemdを採用しているシステムでサービスやソケットなどを制御します。
update-rc.d
-
Debian系のシステムで、サービスを自動起動するかどうかを設定します。(古いコマンド)
xinetd
-
要求に応じてネットワークサービスを起動して、そこに接続させるスーパーデーモンです。それぞれのサービスは
xinetd
から呼び出されて起動します。
演習の解答
-
ロックされている
emma
のパスワードを解除(アンロック)してください。root権限で
passwd -u emma
を実行します。 -
ユーザーアカウント
emma
の有効期間を無期限(いつまでもアカウントが無効にならない)に設定してください。root権限で
chage -E -1 emma
を実行します(-E
オプションに数値-1
を指定)。chage -l emma
を実行すると設定を確認できます。 -
印刷ジョブを処理するCUPSプリントサービスを無効にしてください。そして、CUPSプリントサービスで使われるポートで接続を待ち受けていないことを確かめてください。(CUPSプリントサービスを利用しているシステムで実施する場合には注意してください。)
root権限で次のコマンドを実行します。
systemctl disable cups.service --now
次のいずれかのコマンドで接続を待ち受けていないことを確かめます。
netstat -l | grep ":ipp "
または
ss -l | grep ":ipp "
-
インストールしたnginxウェブサーバーがTCPラッパーをサポートしているかどうかを調べてください。
次のコマンドを実行します。
ldd /usr/sbin/nginx | grep "libwrap"
nginxがTCPラッパーをサポートしている場合、エントリが表示されます。
発展演習の解答
-
/etc/nologin
ファイルが存在すると、ユーザーroot
もログインできなくなるでしょうか?ユーザー
root
はログインできます。 -
/etc/nologin
ファイルが存在すると、パスワードを使用しないSSH鍵によるログインもできなくなるでしょうか?パスワードを使用しないログインもできなくなります。
-
login currently is not possible
とだけ記載された/etc/nologin
ファイルが存在すると、ログイン時にどうなりますか?login currently is not possible
というメッセージが表示され、ログインはできません。 -
一般ユーザーである
emma
は、grep root /etc/passwd
コマンドを実行して/etc/passwd
の中の ユーザーroot
の情報を見ることができますか?/etc/passwd
ファイルは誰でも読み取り可能ですからから、ユーザーroot
の情報を見ることができます。 -
一般ユーザーである
emma
は、grep -i emma /etc/shadow
コマンドを実行して/etc/shadow
の中の自分のハッシュ化されたパスワードを見ることができますか?一般ユーザーには
/etc/shadow
ファイルの読み取りパーミッションがありませんから、自分のハッシュ化されたパスワードを見ることができません。 -
時刻を同期するために大昔に使っていたdaytimeサービスを、xinetdで利用するためにはどうすればよいでしょうか?(これはあくまでも説明のための演習です。本番環境では実行しないでください。)
まず、
/etc/xinetd.d/daytime
ファイルのdisable
ディレクティブをdisable = no
に変更します。次に、systemctl restart xinetd.service
(SysVinitに基づいたシステムではservice xinetd restart
)コマンドを実行してxinetdサービスを再起動します。nc localhost daytime
(netcat localhost daytime
)コマンドを実行すると、daytimeサービスが動いているかどうかを確かめられます。