サーバーを本格的に運用するようになったらやること・守ること
- 作成日時:
- 最終更新日時:
- Categories: インフラ
- Tags: スタートアップシリーズ システム管理 セキュリティ
圧倒的に人手不足な組織でありがちなのが、『開発とデプロイができるならサーバー管理もできるだろう』と言わんばかりに経験も無いのにサーバー管理まで任されること。
そんな時に一通りチェックしておくと良いものを列挙する。
事前対策編【予防・抑止】
OSにインストールされているパッケージのアップデート(更新)
OSにインストールされているパッケージは問題がなければ定期的にアップデートしておく。
sudo apt update && sudo apt -y upgrade && sudo apt -y autoremove
ただし、起動してすぐに上記コマンドを実行しようとしても、受け付けてくれない。パッケージ管理ツールAPTよりも低レベルで動作するdpkgのアップデートが行われているためである。
一部のqiitaにはdpkgを止めてaptコマンドを実行するなどと誤った解説がされているが、普通に起動してしばらく待っていればaptコマンドを受け付けてくれる。不用意に低レベルな階層に手動で介入をしていると取り返しの付かないことになるので十分注意する。
また、一部のパッケージには更新に問題がある場合も少なからずあるので、予めパッケージの公式サイトあるいはGitHubなどから評判をチェックした上で、アップデートを行うと尚良いだろう。
ちなみに、ウェブアプリケーションフレームワークやライブラリなどは仮想環境を使用している場合(PythonであればVirtualenvなど)、それらはOSとは隔離されているので上記コマンドではアップデートされない。それぞれ手動でアップデートしていく。
不要なソフトは削除・解放するポートは最小限
当然のことだが、使用しないソフトやポートがそのままの状態になっている場合、そのソフトに何らかの脆弱性が発見された時、悪用されてしまう。
不要なソフトは予め削除しておく。Ubuntuであればapt purgeコマンドで削除できる。
sudo apt purge nginx
公共の場所、管理されていない端末、公衆無線LANなどからリモートログインしない
公共の場所、公衆無線LANやネットカフェからのリモートログインは言語道断である。
- ネットカフェのPC内にうっかりSSHの秘密鍵をおいたまま帰宅したら?
- 急に催して、ログインしたままトイレに駆け込んでしまったら?
- 管理されていない端末にキーロガーが仕込まれていたら?
- 公共の場でショルダーハッキングされたら?
そういったリスクは枚挙に暇がない。
ボットによるアクセスの規制
ボットのアクセスを許可するだけで、無駄にサーバーの負担が増えてしまう。
最近ではプログラマでなくても簡単にスクレイピングツールが作れる。悪質なものは並列化されていたり、待ち時間が設定されていないものもあるため、ボットのアクセス許可(対策なし)は百害あって一利なしだ。
このDDos攻撃まがいでサーバーが応答不能に陥るだけでなく、ログのオーバーフローという問題もある。サーバーのログをきちんと保管していたとしても、ボットによる大量アクセスでセキュリティ攻撃の痕跡を見つかりにくくさせよう、保存領域から消してしまおうという魂胆。
他にも、ボットを使用してアカウントを大量作成され、そのアカウントをハックした旨を管理者に通知し、金銭を脅し取る、ソーシャルエンジニアリングも存在する。
この対策として、Recaptchaを使用してボットによるアクセスを完全シャットアウトするか、一定時間内に一定以上のアクセスを記録したIPに対して一時的にサーバーにアクセスが集中している旨を表示して時間をおいてアクセスするように促す。
プロキシサーバー、Torを経由したアクセスの拒否
プロキシサーバーとボットによるアクセスと合わせて使うことで、送信元をどこかわからなくさせる手法がある。適当なプロキシサーバーを隠れ蓑にして攻撃を仕掛けるので、事案が起こっても法的措置を取ることは出来ない。
そして、厄介なのはプロキシサーバーによるアクセスは100%規制できるわけではないということ。一応、Torを使用したアクセスは拒否できるので、やっておきたい。
ウェブサーバーの公開ディレクトリに関係のないファイルを置かない
当たり前だが、/var/www/html/
の中に何かファイルを置くと、クライアント側からファイル名を直接指定してしまえば簡単にDLできる。
確かにウェブサイト上には、手動で置いたファイルのURLは公開されていないので、URL直入力しない限り見られることは無いが、ウェブサーバーにディレクトリリスティングの問題がある場合、簡単に見られてしまう。
そうでなくても総当りでそれっぽいURLにアクセスする悪質な攻撃者もいるので、関係のないファイルは置かない。
この問題は自分から公開しており、犯罪として成立しない(少なくとも不正アクセスには当たらない)ので、十分注意する。
事後対策編【修復・復旧】
ログを取る
ログを取るのはサーバー管理の基本中の基本。
事案が発生した時、問題行動を起こした端末を特定し、事態の早期解決ができるだけでなく、外部による犯行であれば法的措置を取ることができるだろう。問題が起こったURIも分かればコード修正作業も楽。
ただ、ログのオーバーフローと、プロキシサーバーを使ったものには注意。事前にある程度の対策が必要。
ログの保存領域(ストレージ)はなるべく多めに確保しておくと良い。ログが増えすぎてどれが問題のアクセスかわからない場合はgrepコマンドなどを使う。
事案が発生した時の管理者への通知方法を予め決めておく
自動化されたソフトで通知する場合、エンドユーザーが通知する場合、いずれも管理者への通知方法を予め決めておくことが重要。
専用のメールアドレスなどを用意しておくと良いだろう。事案以外のメールに埋もれてしまう問題を防ぐことができる。
ただし、ソーシャルエンジニアリングに十分注意する。
- 即対応を迫る・緊急を装ったメール
- 管理者へ圧力をかけるような物言い
- 立場が上の人の意見
- 管理者が忙しいとき
- やることはすぐにできる簡単なことだとアピール(『〇〇するだけ』等の文言)
上記は、犯罪者がサーバー管理者を巧みに騙して機密情報を奪取しようと考えている場合がある。近年ではAIを使って音声を合成し、本人になりすますなどの手法も流行している。
これらのソーシャルエンジニアリングの対策として、直接話をするか、偽装工作が難しい固定電話・携帯電話などで本人に確認を取るなどがある。
物理的に切り離したバックアップとリストア
できれば、バックアップするのであればデータはサーバーから物理的に切り離したい。
サーバーが感染した場合、サーバーと繋がっているバックアップのディスクに影響が及んでいるかチェックするのが大変だからだ。チェックも完全とは言い難い。
しかし、物理的に切り離されていれば感染のリスクはゼロだ。サーバーのネットワークの切り離しとクリーンインストールを行った後、安心してリストアできる。
また、ランサムウェア等の要求には基本的に応じないようにすることが重要。そのためにもバックアップが鍵になる。
効率運用編
証明書やドメインの更新などは自動化を
crontabを定期実行する必要のあるものは定期実行しておく。Let’Encryptを使用している場合はcrontabで自動生成。
ドメインの更新作業はドメインのホスティングサイトにて自動更新を有効化しておく。
また、crontabを使ってアンチウイルスソフトを起動しておくなどの対策も重要かと思われる。特にクライアントからファイルを受け付けるタイプのウェブアプリであれば、アンチウイルスソフトを常駐、もしくは定期的にスキャンするのは必須。
代表的なアンチウイルスソフトとしてClamTKなどがある。
aliasで複雑なコマンドを省略する
複雑なコマンドを予め省略しておけば、管理が必要になった時に1秒でも早く対処できる。
例えば、cdコマンドなどは、いつも作業を行うファイルパスが非常に長い場合、毎度毎度入力していると手間取る。そこで、~/.bashrc
に下記を入力する。
alias cdjango='cd ~/Document/programming/django/'
この入力を行った後、下記コマンドを実行して、bashの設定を再読込。
source ~/.bashrc
先の設定であれば、cdjango
と入力すれば、対応するcdコマンドが実行される。他にも、メール送信をワンライナーで実行できるようにするなども良いだろう。
下記はコマンド実行時に引数として件名と本文を指定できる。送信先はハードコードされていて、やや冗長ではあるがコピペですぐに使える。
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import sendgrid
import os
from sendgrid.helpers.mail import *
MAIL_FROM = ""
FROM_PASS = ""
MAIL_TO = ""
def send_mail(args):
try:
sg = sendgrid.SendGridAPIClient(api_key=FROM_PASS)
from_email = Email(MAIL_FROM)
to_email = To(MAIL_TO)
subject = args[1]
content = Content("text/plain", args[2])
mail = Mail(from_email, to_email, subject, content)
response = sg.client.mail.send.post(request_body=mail.get())
print("メールを送信しました。")
return True
except:
print("メール送信に失敗しました。")
return False
def main(args):
if len(args) < 3:
for i in range(3-len(args)):
args.append("null")
send_mail(args)
if __name__ == "__main__":
try:
main(sys.argv)
except KeyboardInterrupt:
print("\nprogram was ended.\n")
sys.exit()
結論
このサーバー運用、システム管理関係の話は、応用情報技術者試験、情報処理安全確保支援士試験(前、情報セキュリティスペシャリスト試験)に含まれているため、予め勉強しておくと良いだろう。