2016/08/16

シェルスクリプトでCentOS6.x/7.xの初期設定をする

CentOSでサーバを立てたときに、まず最初に必ずやっておきたい初期設定がある。
その作業の一覧が以下のとおり。
  • パッケージを最新化する
  • 新規ユーザを作成する
  • suコマンドを制限する
    • suコマンドを実行可能なユーザ・グループを限定する
    • 特定のグループ以外suコマンドでrootに昇格できないように制限する
    • パスワード入力なしでsudoコマンドを利用できるようにする
  • ssh接続を制限する
    • rootユーザのsshログインを禁止する
    • sshで公開鍵認証のみ接続を許可する
    • sshでパスワード認証を禁止する
    • 公開鍵をサーバに登録する
  • sshdサービスを再起動する
  • iptablesまたはfirewalldの設定 ←今回はやらない

Webアプリケーションをつくりたくて、WebサーバとAPサーバを用意しようと思ったが、毎回この初期設定をするのが超絶メンドそう...。

ということで、自動化するために初期設定をしてくれるシェルスクリプトをつくったので、その詳細な説明と「なぜ設定が必要なのか」をまとめていく。



初期設定をするシェルスクリプト


とあるキャンペーンで2万円クーポンをもらってから「さくらのクラウド」を利用しているので、さくらのクラウドのスタートアップスクリプトとしてつくった。
もちろん値の入力部分さえ修正すれば、普通のシェルスクリプトとして使える。
#! /bin/bash

# @sacloud-once
#
# @sacloud-require-archive distro-centos distro-ver-7.*
# @sacloud-require-archive distro-centos distro-ver-6.*
#
# @sacloud-desc-begin
#    Initial setup script for CentOS7.x or CentOS6.x on Sacloud
# @sacloud-desc-end
#
#
# @sacloud-text required shellarg maxlen=60 user_name "新規追加するユーザ名"
# @sacloud-password required shellarg maxlen=60 user_pass "新規追加するユーザのパスワード"
# @sacloud-textarea required shellarg maxlen=512 public_key "利用する公開鍵"
# @sacloud-radios-begin default=7 centos_version "CentOSのバージョン"
#   7 "CentOS7.x系"
#   6 "CentOS6.x系"
# @sacloud-radios-end

USER=@@@user_name@@@
PW=@@@user_pass@@@
PUBKEY=@@@public_key@@@
CENTOS_VERSION=@@@centos_version@@@

# disable SELinux temporarily
setenforce 0


# package update
yum -y update


# create user
useradd $USER
echo $PW | passwd --stdin $USER
gpasswd -a $USER wheel


# allow only members of the wheel group to use 'su'
cp /etc/pam.d/su /etc/pam.d/su.bak
## uncomment 'auth required pam_wheel.so use_uid'
tac /etc/pam.d/su > /etc/pam.d/su.tmp
cat << EOS >> /etc/pam.d/su.tmp 2>&1
auth required pam_wheel.so use_uid
EOS
tac /etc/pam.d/su.tmp > /etc/pam.d/su
rm -rf /etc/pam.d/su.tmp

## restrict the use of 'su' command
cp /etc/login.defs /etc/login.defs.bak
cat << EOS >> /etc/login.defs
SU_WHEEL_ONLY yes
EOS

## 'sudo' command without password
cp /etc/sudoers /etc/sudoers.bak
cat << EOS >> /etc/sudoers 2>&1
%wheel ALL=(ALL) NOPASSWD: ALL
EOS


# disallow SSH login and add public_key
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
cat << EOS >> /etc/ssh/sshd_config 2>&1
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
EOS

#AuthorizedKeysFile     .ssh/authorized_keys <--必要に応じて追加

mkdir /home/$USER/.ssh/
chmod go-w /home/$USER/.ssh/
touch /home/$USER/.ssh/authorized_keys
cat << EOS >> /home/$USER/.ssh/authorized_keys 2>&1
$PUBKEY
EOS
chmod 600 /home/$USER/.ssh/authorized_keys
chown -R $USER:$USER /home/$USER/.ssh/


# sshd service restart
if [ $CENTOS_VERSION -eq 7 ]; then
  systemctl restart sshd
elif [ $CENTOS_VERSION -eq 6 ]; then
  /etc/rc.d/init.d/sshd restart
fi
※サービスの再起動がCent6.x系と7.x系では違うので注意
※さくらのクラウドの特殊タグや変数については触れないので、公式サイトをご確認ください
※ さくらのクラウドではサーバ作成後にスタートアップスクリプトが実行されるので、作成後5〜10分待ってからアクセスするようにしてください。途中でアクセスするとスクリプトが止まるのかうまく設定が完了しませんでした


まず上記のスタートアップスクリプトを登録する

次に、登録したスタートアップスクリプトを使ってサーバ作成を行う。

これでサーバ作成すれば、すでに初期設定が完了した状態で使えるようになる。便利!!


次に「なぜ」このような設定が必要なのかについてまとめていく。



パッケージを最新化する


# yum -y update
すでにインストールされているパッケージを最新のモノにアップデートするコマンド。
Windows Update的なものだと思えば理解しやすいだろう。

-yオプションをつけることで「インストールしますか?」のような問い合わせにすべて「yes」で応えることができる。
これをつけないとスクリプトが途中で止まってしまうので注意。



新規ユーザを作成する


rootユーザは全権限を持っている管理者的なユーザなので、第三者にログインされてしまうとサーバを乗っ取られてしまう。
そこで別の新しいユーザ(作業用のユーザ)を作成し、そのユーザでログインできるようにする。

変数$USERという名前のユーザを作成する

# useradd $USER
作成すると /home/$USER/ というユーザのディレクトリが作成される。
 

ユーザのパスワードを設定する

# echo $PW | passwd --stdin $USER
本来なら passswd $USER というコマンドを使用する。
しかし、シェルスクリプトではインタラクティブ性な設定できないので、パイプを使い標準入力としてパスワードを指定する。
 

wheelグループに所属させる

# gpasswd -a $USER wheel
wheelとはrootに昇格できるユーザが属するグループの名称。いわば特別なグループが最初から用意されているので、そのグループに所属させればOKというわけだ。
usermod –G wheel $USER とも書けるが、usermodだとグループ情報に上書きgpasswdだと追記となるので後者を使った。



suコマンドを制限する


作業用ユーザがパッケージのインストールなど、システムに影響を与えるような作業をすることがある。しかしそのままでは権限不足により操作が制限されてしまう。
しかしsuコマンドを使えば、作業用ユーザがrootユーザになることができる。

なので、好き勝手 suコマンド を使われないように制限する必要がある。

ちなみにsuとは substitute user(代理ユーザ)の略。

suコマンドを実行可能なユーザ・グループを制限する

# cp /etc/pam.d/su /etc/pam.d/su.bak
# tac /etc/pam.d/su > /etc/pam.d/su.tmp
# cat << EOS >> /etc/pam.d/su.tmp 2>&1
# auth required pam_wheel.so use_uid
# EOS
# tac /etc/pam.d/su.tmp > /etc/pam.d/su
# rm -rf /etc/pam.d/su.tmp
/etc/pam.d/su の「auth required pam_wheel.so use_uid」がコメントアウトされているので、それを解除する。
スクリプトではファイルの一番上に「auth required pam_wheel.so use_uid」を追記しているが、普通は「vi /etc/pam.d/su」で修正するだけでよい。

特定のグループ以外suコマンドでrootに昇格できないように制限する

# cp /etc/login.defs /etc/login.defs.bak
# cat << EOS >> /etc/login.defs
# SU_WHEEL_ONLY yes
# EOS
/etc/login.defs に「SU_WHEEL_ONLY yes」を追記する。
普通は「vi /etc/login.defs」で末尾に追記するだけで良い。

パスワード入力なしでsudoコマンドを利用できるようにする

# cp /etc/sudoers /etc/sudoers.bak
# cat << EOS >> /etc/sudoers 2>&1
# %wheel ALL=(ALL) NOPASSWD: ALL
# EOS
スクリプトやプログラムからsudoコマンドを利用しようとしたときに、パスワードを求められると処理がとまってしまう。そのためパスワードなしでsudoコマンドを利用できるようにする。
/etc/sudoers に「%wheel ALL=(ALL) NOPASSWD: ALL」を追記する。

普通は直接sudoersを弄らずに visudoコマンド を利用して修正する。こうすることで修正内容が間違っているときに警告をだしてくれたりする。



ssh接続を制限する


パスワード認証を許可している場合、たとえばユーザを「root」に固定して、総当たり攻撃(Brute-Force Attack)で不正ログインを仕掛けてくる悪意を持った人たちがいる。
そうした人たちからの攻撃を防ぐために、rootユーザのsshログインを禁止したり、パスワード認証を禁止したりする対策がとられる。

rootユーザのsshログインを禁止する
sshで公開鍵認証のみ接続を許可する
sshでパスワード認証を禁止する

# cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak# 
# cat << EOS >> /etc/ssh/sshd_config 2>&1
# PermitRootLogin no
# PubkeyAuthentication yes
# PasswordAuthentication no
# EOS
/etc/ssh/sshd_config に以下の3つを追記する。
  • PermitRootLogin no  … rootユーザのsshログインを禁止
  • PubkeyAuthentication yes  … 公開鍵認証の許可
  • PasswordAuthentication no  … パスワード認証の禁止


公開鍵をサーバに登録する


ローカル環境で認証用の秘密鍵と公開鍵を作成する
(Windowsの場合は、git for windows についてくるgit-bashを使うとCYGWINとか入れなくてもbashが使えるのでオススメ)
$ ssh-keygen -t rsa

作成した鍵をサーバに登録することで、公開鍵認証でのssh接続が可能になる
# mkdir /home/$USER/.ssh/
# chmod go-w /home/$USER/.ssh/
# touch /home/$USER/.ssh/authorized_keys
# cat << EOS >> /home/$USER/.ssh/authorized_keys 2>&1
# $PUBKEY
# EOS
# chmod 600 /home/$USER/.ssh/authorized_keys
# chown -R $USER:$USER /home/$USER/.ssh/
/home/$USER/.ssh ディレクトリを作成し、その中に authorized_keysという認証可能な公開鍵を登録しておくファイルをつくる。
そして、ローカル環境でつくった公開鍵を登録(追記)する。

authorized_keysファイルは各ユーザが触れてしまうと改ざんされる可能性がでてくるので、パーミッションを変更しておく。(rootユーザのみ読み書き可能にする)
最後にファイルの所有者を$USERに変える。

これで公開鍵でssh接続できるようになった。



sshdサービスを再起動する


ひととおり初期設定が終わったので、SSHDのサービスを再起動し、今までに行った設定を有効化させる。

CentOS6.x

# /etc/rc.d/init.d/sshd restart

CentOS7.x

# systemctl restart sshd


これで初期設定の説明がひととおり終わった。
スタートアップスクリプトを使うことで、こういったことをサーバ作成と同時にできるので楽になるだろう。


ちなみにCentOS6.xならiptables、CentOS7.0ならfirewalldについては、設定が難しいので、さくらのクラウドにあるパケットフィルタ機能を使うと便利。



さいごに


いままでずっとアプリケーションエンジニアとして働いていたので、こういったサーバ関連の設定は初めてだった。
実際設定を手動でやってみたり、シェルスクリプトを書いてみたりして、なぜサーバレスアーキテクチャ(AWS LambdaやFirebaseなど)が流行っているのかがわかった。

でもフロントエンドエンジニアだからといって「サーバ・インフラの知識が必要ない」なんてことはないので、これからちょっとずつ勉強していこうと思う。



参考サイト

 

いろいろ参考にさせていただきました、ありがとうございました!

CentOSについて

シェルスクリプトやコマンドについて

さくらのクラウドについて





追記: 2016/08/19 13:00
個人利用だけならこれら設定をしなくても「rootユーザのパスワード認証を禁止し、鍵認証のみにする」だけでも良いかもしれない。(勉強不足でどちらの設定が良いかはわかりません)

ちなみにさくらのクラウドなら、サーバ作成時に「公開鍵認証以外でのSSHログインを禁止する」という機能があるので利用すると一発で設定完了になる。

追記: 2016/08/19 15:30
「2016/08/19 13:00」で気になったことを、会社のLinuxおじさん先輩に聞いてみた。


初期設定をするのも、rootユーザで鍵認証のみを許可するのも結果的には同じになるけど、 rootで直接操作させない運用ポリシーを使いたいときに使うよ。
sudosuであれば、誰がいつroot権限でコマンドを実行したか記録できるからね。
たとえば「この時間帯にログインしていて、コマンドを実行したのは誰だ!」というのを調べるときとかに役立つ。

ひとりでサーバ運用するのであればあまり関係ないけど、複数人で運用する場合は有用だよ。

なるほど…。
たしかに、全員がrootユーザにログインしてしまうと、誰が実行したのがわからないけど、それぞれのユーザでログインしてsudoなりsuなりを実行すれば「誰が(どのユーザが)実行したか」がわかる。




以上

written by @bc_rikko

0 件のコメント :

コメントを投稿