第3回 サーバセキュリティの基礎を見直す

みなさんこんにちは。teratail開発チームの出川幾夫です。

近年では攻撃方法が多様化・複雑化しており,サーバのセキュリティ要件は年々高まっています。セキュリティリスクは目に見えにくく,問題が表面化するまでは他の作業よりも後回しにされがちです。

そこで今回はサーバセキュリティの基礎をテーマに,普段当たり前にやっているセキュリティの手法について,その意味や効果について振り返りたいと思います。

本記事はCentOS 6.6で確認した内容を元に記述していますので,他の環境の方は適宜読み替えていただければと思います。

SSHの設定

サーバを立ち上げてまず立ち上げるサービスの一つがSSHです。サーバを構築したときからセキュリティを万全にしておく必要があります。

SSHの設定ファイルは主要なLinux OSでは/etc/ssh/sshd_configとして設置されています。まずSSHのポート番号をwell-known-portでないポート番号(1025~65535)に変更します。ログインして任意の動作ができるサービスでもっとも標的になりやすく,22番以外に変更することで攻撃される頻度を大きく減らすことができます。

以下の例ではポート番号を47382番に変更しています。

これも当然ですがrootでのSSHログインは絶対に許可してはいけません。もし万が一不正にログインされた場合そのログインされたサーバ内の全てのデータや設定の破棄を余儀なくされてしまうからです。当然外部からのrootでログインを試みる攻撃の頻度も高いです。

パスワードログインを不許可にし,鍵認証ログインのみにすることも必須です。パスワード認証では,暗号化されているとはいえパスワードをネットワークに流すことになります。また個人用の鍵ペアを生成する際にパスフレーズも設定すると,万が一その秘密鍵の入ったPCが不正に操作されても不正ログインをされる確率を下げることができます。

PasswordAuthentication no
参考:公開鍵暗号方式で秘密鍵を配布するのはダメなんでしょうか?
https://teratail.com/questions/7220

また特定のIPアドレス以外からのSSHログインを受け付けないのも非常に効果的です。

人災を防ぐ

サーバの不具合は多くの場合,開発者や管理者の誰かがサーバに何らかの変更を加えたあとに発生します。人の運用によるトラブルを防ぐのも,

サーバやサービスの安全性・安定性を向上する点において重要なセキュリティ施策です。

人災を防ぐ最もよい方法は,そもそも人がSSHでログインする回数を減らし,管理を自動化することです。ChefやAnsibleなどのサーバ構成管理ツールを用いて,事前に他のサーバでテストしたcookbookやplaybookの状態に定期的に収束させるようにすると,サービスの動いているサーバに日常的に直接SSHする必要はなくなります。またサーバの要件を記述したcookbookやplaybookはコードレビューを受けてテストし本番反映するという,普段の開発の流れと同様にサーバを手順もとれるため,毎回の変更の正確性も増し変更ミスが減ります。

誤ってファイルの削除や名称変更をしてしまわないように,alias rm=rm -ialias mv=mv -i/etc/profile等に記述して全てのユーザーに対してこのエイリアスを適用するとよいでしょう。

参考:Linuxの全ユーザーに向けて,まとめてパスを通したい
https://teratail.com/questions/1048

またcrontab -eも手動で打ち込むのは大変危険なコマンドです。erとキーの位置が近く,誤ってcrontab -rを叩いてしまうとcronの内容が確認なく全て消去されてしまうからです。編集する際はジョブを記録したファイルをcrontabコマンドで読み込むか,/etc/cron.dailyなどのディレクトリ内でcronを管理するようにしましょう。

1つのユーザーアカウントを複数の人がログインしている運用にするとパスワードを共有することになるため,パスワードの管理が困難になり漏洩の際の被害も大きくなります。アカウントを共有してコマンド履歴が共通になると操作した人を区別できなくなり,不具合が発生した際に原因の特定が遅れることになります。またsudo権限を与えた場合もそのアカウントにログインしているすべての開発者が持つことになります。このため必ず開発者一人一人に1つずつアカウントを発行し,個々がパスワードを管理する体制にする必要があります。sudoersの設定も必ずvisudoコマンドを利用してユーザーもしくはグループごとに設定を必ず行いましょう。

iptables

iptablesは最も有名なファイアウォールソフトウェアです。Red Hat系LinuxをはじめとしてさまざまなLinuxディストリビューションに対応していて,デフォルトで動作するようになっていることも多いです。

iptablesでパケットフィルタリングを設定する前に,まず必要のないサービスを立ち上げていないことを確認しましょう。またここでもIPアドレス制限を行うのが基本です。

以下の例ではWebサーバのために80番ポートを開放しています。

-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT

また以下の例では特定のIPアドレス"***.***.***.***"からのみ,上で設定したSSHの47382番ポートへのアクセスを許可しています。

-A INPUT -m state --state NEW -m tcp -p tcp -s ***.***.***.*** --dport 47382 -j ACCEPT

ここで紹介した以外にもiptablesにはあまり知られていない機能が多くあります。NATを設定できたり,簡単なロードバランサーのような動作をさせることもできるなど非常に多機能です。

参考:
MySQLサーバのiptables
https://teratail.com/questions/8233
VPS上で iptables -F するとフリーズする
https://teratail.com/questions/4536
CentOS に Apacheをインストールし起動したがブラウザからアクセスすると「このページは表示できません」となる
https://teratail.com/questions/3062

サーバ外のセキュリティ

意外に軽視されがちなのがサーバ外のセキュリティです。これは実はサーバセキュリティ以前にまず整っていなければならない部分で,怠るとサーバで行ったセキュリティ対策の効果が半減します。またそもそもサーバに到達させないという意味でも,非常に重要です。

大きく分けると物理的なセキュリティ,ネットワークのセキュリティの2つがあります。

サーバの物理的なセキュリティとは,サーバマシンをサーバ管理者以外に触らせないということです。社内に置くサーバは必ずサーバルームを作り,鍵は限られた人のみが持つようにします。万が一社内に外部の人間が不当に侵入することがあっても,サーバマシンに被害が及ぶ確率を減らすことができます。

またサーバを配置するネットワークに外部から不正アクセスされないような工夫も必要です。社内ネットワークのみなど限られた範囲に公開するサーバでも,そのネットワークの穴が攻撃へのきっかけになることも多くあります。

社内向けサービスと社外向けサービスの2つがある場合は,必ず役割ごとにルーターのポートフォワーディングやDMZでネットワークをわけましょう。

VPSやクラウドサーバを利用しているは基本的に気にかける必要はありませんが,どのようなネットワーク構成になっているかは確認しておく必要があります。またAWSなどではセキュリティグループやネットワークを細かく設定できますので,必ず確認しておきましょう。

参考:ネットワークの基礎知識をつけたい
https://teratail.com/questions/7679

最後に

本稿では,サーバセキュリティの基礎について,最も基本的な部分を解説しました。

ウェブに公開するサービスを行っている限りセキュリティの問題は常につきまといます。teratailではプログラミングの質問だけでなくネットワークやセキュリティに関する質問も多く投稿されていますので,疑問点ができたらどんどん質問してみるとよいと思います。