2018 年度 OSS リテラシー 3 : 第 4 回 セキュリティ対策
不要なポートを閉じる
まず, 開いているポートを確認するには, netstat コマンドや nmap コマンドを用いる. なお, nmap コマンドはクラッキングの前段階として行われることが多いので, 無用の誤解を与えないために localhost 以外のホストに対して実行しないこと.
netstat -ntl コマンドを実行する. 以下の例では, 22 番ポート (SSH) が全ての IP アドレス (0.0.0.0) に対して開いており, 25 番ポート (SMTP) が自分 (127.0.0.1) に対してのみ 開かれていることがわかる. また IPv6 で 22 番ポート (SSH) が全ての IP アドレス (0.0.0.0) に対して開かれていることがわかる.
$ netstat -ntl 稼働中のインターネット接続 (サーバのみ) Proto 受信-Q 送信-Q 内部アドレス 外部アドレス 状態 tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN tcp6 0 0 :::10050 :::* LISTEN tcp6 0 0 :::22 :::* LISTEN
ここで 10050 ポートも開いていることがわかる. このポート番号に対するサービスは /etc/services を確認することで把握できる.
$ grep 10050 /etc/services zabbix-agent 10050/tcp # Zabbix Agent zabbix-agent 10050/udp
上記コマンドで, 10050 ポートは zabbix-agent であることがわかる. zabbix-agent は授業の後半で使うが現在は必要ない. ポートを閉める (サービスを止める) には以下のようにする. /etc/init.d 以下にサービスをスタート/ストップするためのスクリプトが置かれている.
$ sudo /etc/init.d/zabbix-agent stop [ ok ] Stopping zabbix-agent (via systemctl): zabbix-agent.service.
改めて netstat コマンドを実行すると, 10050 ポートが閉まった (= 10050 ポートを使う zabbix-agent が停止した) ことがわかる.
$ netstat -ntl 稼働中のインターネット接続 (サーバのみ) Proto 受信-Q 送信-Q 内部アドレス 外部アドレス 状態 tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN tcp6 0 0 :::22 :::* LISTEN
次に nmap を使って開いているポートを確認する. nmap はすでにインストールされている. localhost (127.0.0.1) と無線 LAN の IP アドレスに対して nmap を実行せよ. 前述の netstat コマンドと同様に, localhost では 22, 25 番ポート (SSH, SMTP) が, 無線 LAN の IP アドレス (ローカルホスト以外) に対しては 22 番ポート (SSH) のみが 公開されていることが確認できる.
$ nmap localhost (localhost (127.0.0.1) を指定) ...(中略)... PORT STATE SERVICE 22/tcp open ssh 25/tcp open smtp Nmap done: 1 IP address (1 host up) scanned in 0.30 seconds $ hostname -I (有線もしくは無線の IP アドレスを確認) XX.XX.XX.XX $ nmap XX.XX.XX.XX (有線もしくは無線の IP アドレスを指定) ...(中略)... PORT STATE SERVICE 22/tcp open ssh Nmap done: 1 IP address (1 host up) scanned in 0.30 seconds
もしも 25 番ポートが全てのホスト (0.0.0.0) に対して開いている場合は, 前回のメールサーバ設定が間違っている可能性が高い. 前回の資料を確認し, 設定内容を修正すること.
もしも 22, 25 番以外のポート番号が表示された場合は教員に相談すること. 誤って余計なパッケージをインストールしてしまった可能性が高い. 誤ってインストールしたパッケージを削除すればポートを閉めることができる.
ssh の設定の修正
前節で確認した通り, ラズパイでは外部に対して 22 番ポート (SSH) しか 開いていないが, さらにセキュリティを高める方法として, 以下の 2 つがある.
- パスワード認証を無効化し公開鍵認証のみにする
- SSH 接続が可能なホストを限定する
パスワード認証の無効化.
ssh でパスワードによる認証を無効にし, 公開鍵認証のみをサポートする.
$ sudo -s # vi /etc/ssh/sshd_config # To disable tunneled clear text passwords, change to no here! #PasswordAuthentication yes (変更前) PasswordAuthentication no (変更後, yes -> no にすること)
設定を変更したら ssh サーバを再起動する.
# /etc/init.d/ssh restart [ ok ] Restarting ssh (via systemctl): ssh.service. # exit $
確認を行う. サーバにログインしてからラズパイに対して ssh コマンドを実行する. もしもユーザ pi でログインできてしまう場合は, 前述のパスワード認証禁止がうまく設定されていない. 設定を見直すこと.
$ ssh -l jxxxx sky.epi.it.matsue-ct.jp ...(略)... sky$ ssh -l pi XX.XX.XX.XX (自分のラズパイの IP) Permission denied (publickey). (公開鍵を作っていないユーザ pi はログインできない) sky:~$ ssh -l hogehoge XX.XX.XX.XX (自分のラズパイのユーザ名と IP を使うこと) Enter passphrase for key '/home/jxxxx/.ssh/id_rsa': (パスフレーズ入力) ...(略)... $ (ラズパイに再度ログイン) $ exit (ラズパイからサーバへ) sky$ exit (サーバからラズパイへ) $
TCP Wrapper によるアクセス制限
TCP Wrapper を用いて ssh 接続を許可するホストを限定する. 設定ファイルは /etc/hosts.allow と /etc/hosts.deny の 2 つである. 動作としては /etc/hosts.allow に書かれたアクセスルールが最初に適用され, 次に /etc/hosts.deny に書かれたアクセスルールが適用される.
まず, /etc/hosts.allow において, サーバ sky.epi.it.matsue-ct.jp (10.100.100.1) のみに SSH アクセスの許可を出すことにする.
$ sudo -s # vi /etc/hosts.allow sshd: 10.100.100.1 (末尾に追記)
書式としては, コロンの前にデーモン名 (SSH ならば sshd (ssh daemon)),
コロンの後ろにホスト名である. ホスト名には .matsue-ct.jp のように,
matsue-ct.jp のドメインを持つ全てのホスト, という書き方もできる.
[注: 書式的にはドメインで書いても良いはずだが, IP で指定しないとうまく動かなかった]
次に, /etc/hosts.deny において, 全てのホストからの接続を禁止する 設定を行う. ALL: ALL とすると, 外部の全てのホストから, 全てのデーモン (ポート) へのアクセスを拒否することとなる.
# vi /etc/hosts.deny ALL: ALL (末尾に追記)
TCP wrapper は再起動は必要なく, 編集したファイルの内容は直ちに適用される.
以上の設定で, sky.epi.it.matsue-ct.jp 以外はラズパイのどのポートにも アクセスできなくなったはずである. 動作確認として, 友人のラズパイに SSH 接続してみよ. 正しく設定されていれば, 以下のように Connection がリセットされ, SSH 接続できないことがわかる.
$ ssh -l pi XX.XX.XX.XX (友人のラズパイの IP) ssh_exchange_identification: read: Connection reset by peer
さらに確認として, サーバからはラズパイに対して ssh 接続できることを確かめる.
$ ssh -l jxxxx sky.epi.it.matsue-ct.jp ...(略)... sky:~$ ssh -l hogehoge XX.XX.XX.XX (自分のラズパイの IP) Enter passphrase for key '/home/jxxxx/.ssh/id_rsa': (パスフレーズ入力) ...(略)... $ (ラズパイに再度ログイン) $ exit (ラズパイからサーバへ) sky$ exit (サーバからラズパイへ) $
フィルタリング : fail2ban (iptables)
本演習では iptables のフロントエンドとして実装されたソフトウェア fail2ban を用いる. iptables を直接設定するのは初心者には難しいためである.
fail2ban はログを監視し, 特定のパターンに引っかかる動作が記録されたらファイヤウォールに動的にルールを追加して, 通信をブロックする. 例えば ssh のブルトフォース攻撃 (パスワード総当たり攻撃) のように, 頻繁にアクセス & ログイン失敗を繰り返すホストからのアクセスを切断する.
まず, iptables の現在の設定を確認する. すでに fail2ban をインストールしているので, fail2ban のエントリも存在する.
$ sudo -s # iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain f2b-sshd (0 references) target prot opt source destination RETURN all -- anywhere anywhere
fail2ban の設定ファイルは /etc/fail2ban/jail.conf および /etc/fail2ban/jail.d/defaults-debian.conf である. 各ポートに対して /etc/fail2ban/filter.d/ 以下にフィルタが用意されている. デフォルトの設定では ssh のみ監視が有効にされている. 本演習のラズパイでは ssh 以外に外部からアクセス可能なポートを開けていないので, ssh 以外のフィルタを有効にする必要はない.
sshd が監視対象となっていることは, 以下のコマンドを実行すれば確かめられる.
# fail2ban-client status Status |- Number of jail: 1 `- Jail list: sshd
[参考] ban された時の動作
fail2ban をインストールしたので, ssh で何度もパスワード入力を誤ると ban される (以下のように ssh コネクションが切られる). デフォルトでは 10 分間接続不可となる.
sky$ ssh XX.XX.XX.XX ssh: connect to host 10.138.64.109 port 22: Connection refused
ラズパイで ssh アクセスで ban された IP を確認するためには以下のようにする.
# fail2ban-client status sshd Status for the jail: sshd |- filter | |- File list: /var/log/auth.log | |- Currently failed: 0 | `- Total failed: 6 `- action |- Currently banned: 1 | `- IP list: 10.164.1.197 `- Total banned: 1
ban された IP を解除するには以下のようにコマンドをうつ.
# fail2ban-client set sshd unbanip XX.XX.XX.XX (ban された IP)
不要なユーザのアカウントのロック
ユーザーアカウントをロックすると, そのアカウントは使用不可の状態になりログインすらできなくなる. ユーザ pi はもはや必要ないので, このアカウントをロックする.
$ sudo -s # passwd -l pi passwd: パスワード期限切れ情報を変更しました # exit $ su pi (ユーザ pi にスイッチ) パスワード: su: 認証失敗
なお, パスワードロックを外す場合は, $ passwd -u pi とすればよい.
課題
- 不要なユーザ pi をロックする前とロックした後で何が変わるか調べなさい. wbt のオンラインテキストで提出しなさい. (ヒント: パスワードが保管されているファイルは?)
- ユーザのパスワードに有効期限をつけるためのコマンドを調べ, wbt のオンラインテキストで提出しなさい.
- 次の単語の意味を調べて, wbt のオンラインテキストにまとめよ.
- ランレベル
- SUID
- SGID
- 教員がチェックスクリプトを実行する. そのチェックに必ず合格すること.