VirtualBox に CentOS 7.3.1611 を minimal でインストールした初期状態で検証した。
locale
-bash: 警告: setlocale: LC_CTYPE: ロケールを変更できません (UTF-8): そのようなファイルやディレクトリはありません
-bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
macOS のクライアントの場合、ログイン時に上記のような警告が出るようになった。
echo 'LC_ALL="ja_JP.utf-8"' >> /etc/environment
/etc/environment
に LC_ALL
を指定すると出なくなる。
あるいは Terminal や iTerm2 の設定画面で Set locale variables automatically
のチェックを外して再起動すると表示されなくなる。
時刻の同期
date && chronyc -a makestep && date
クローンした仮想マシンの時刻が大幅にずれている場合などにログの時刻がおかしくなるので、インストール状況に応じて強制的に時刻を同期しておく。詳細は「NTP クライアント Chrony」を参照。
etckeeper による /etc 配下のバージョン管理
yum -y install epel-release git && yum -y install etckeeper && $_ init && etckeeper commit ":hatching_chick: Initial commit"
バックアップファイルを作成するのはナンセンスなので /etc 配下のファイルを git でバージョン管理する。詳細は「/etc をバージョン管理する etckeeper」を参照。
コマンド履歴
history
日時記録設定
cat << "_EOF_" > /etc/profile.d/history.sh && source /etc/profile.d/history.sh
# history initialization
HISTTIMEFORMAT='%F %T '
HISTSIZE=100000
HISTFILESIZE=100000
HISTIGNORE='history:w:top:df'
HISTCONTROL=ignoreboth
PROMPT_COMMAND='history -a; history -c; history -r'
_EOF_
etckeeper commit ":new: Add a history setting shell script"
デフォルトではコマンド履歴に実行日時が残らないので残るように設定。詳しくは「history コマンドに日時を付与する」を参照。
i-search の有効化
echo '[ -t 0 ] && stty -ixon' > /etc/profile.d/stty.sh && source /etc/profile.d/stty.sh
etckeeper commit ":new: Add a disabling XON/XOFF flow control (enabling i-search) shell script"
Ctrl+r でコマンド履歴検索モード (reverse-i-search) になるが、デフォルトでは戻りすぎた場合に逆方向に再検索することが出来ない。
Ctrl+s に割り当てられた端末ロックの stop を無効にすることで順検索 (i-search) が機能するようになる。
stty -ixon
の代わりに stty stop undef
を実行しても同様。
scp などで標準入力を受け付けていないのに stty しようとすると stty: 標準入力: 無効な引数です
または stty: standard input: Invalid argument
というエラーが発生するので [ -t 0 ]
で標準入力かどうかを確認する。 1
script
mkdir /var/log/script && chmod 777 $_
cat << "_EOF_" > /etc/profile.d/script.sh && source /etc/profile.d/script.sh
# output operation log
P_PROC=`ps aux | grep $PPID | grep sshd | awk '{ print $11 }'`
if [ "$P_PROC" = sshd: ]; then
script -q /var/log/script/`whoami`_`date '+%F_%H%M%S'`.log
exit
fi
_EOF_
history や psacct では実行結果が記録されないので script で履歴を残す。
上記のシェルスクリプトでは SFTP 接続がうまくいかないので要検討。
Audit システム
`auditctl -a always,exit -F arch=b64 -S execve`
echo "-a exit,always -F arch=b64 -S execve" >> /etc/audit/rules.d/audit.rules
デフォルトで起動している auditd サービスによるコマンド履歴の保存。
デフォルトでは /var/log/audit/audit.log に保存される。ログはテキストなので直接参照可能だが aureport
コマンドや ausearch
コマンドで参照すると見やすくなる。
実行ユーザーや実行ディレクトリ、オプションなども記録される。
pwd
コマンドや cd
コマンドなどは実行自体が記録されなかった。
https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sec-Defining_Audit_Rules_and_Controls.html
プロセスアカウンティング (psacct)
yum -y install psacct && systemctl start $_ && systemctl enable $_
etckeeper commit ":new: Install and enable process accounting (psacct)"
lastcomm
コマンドでどのユーザーがどのコマンドをいつ実行したのかを確認できる。
非常に見づらいが、他のコマンド履歴と比べ改竄が難しいため監査証跡として有用。
HIDS による改ざん検知
ホスト型侵入検知システムの導入により改竄を検知する。OSSEC または AIDE などを利用する。
OSSEC HIDS
yum install -y epel-release wget && curl -s http://www.atomicorp.com/installers/atomic | sh && yum install -y ossec-hids-server
/var/ossec/bin/ossec-configure
sed -i.org '/directories check_all/s/"yes"/"yes" realtime="yes"/' /var/ossec/etc/ossec.conf
systemctl start ossec-hids && systemctl enable $_
etckeeper commit ":new: Install and enable OSSEC HIDS"
inotify によるリアルタイム検知が可能だが atomic リポジトリの導入が必要。詳細は「ファイル改ざん検知ツール OSSEC」を参照。
AIDE
yum -y install aide && $_ --init && mv /var/lib/aide/aide.db{.new,}.gz
curl -sL https://github.com/duritong/puppet-aide/raw/master/files/CentOS/{aide.cron} -o /etc/cron.daily/#1 && chmod +x /etc/cron.daily/aide.cron
etckeeper commit ":new: Install and enable AIDE"
inotify 未対応で古いが base リポジトリのみで導入可能。詳細は「ファイル改ざん検知ツール AIDE」参照。
Lynis や OpenSCAP などでインストールを要求される。
アップデート
yum clean all && yum -y update
Yum のキャッシュをクリアしてから、各パッケージを最新バージョンにアップデートする。
Kernel のバージョンアップがあった場合は reboot
コマンドで再起動する。
パスワードなしでのログインの禁止
sed -i 's/\<nullok\>//g' /etc/pam.d/system-auth
etckeeper commit ":lock: Prohibit login without password"
su / sudo の設定
sed -i.org '/NOPASSWD/ s/^# //' /etc/sudoers
sed -i.org '/use_uid/ s/^#//' /etc/pam.d/su
etckeeper commit ":unlock: Enable su/sudo settings"
パスワードなし sudo 実行
# %wheel ALL=(ALL) NOPASSWD: ALL
上記コメントアウトを解除することで、sudo の実行をパスワードなしで行えるようになる。
パスワードなし root 切り替え
#auth sufficient pam_wheel.so trust use_uid
上記コメントアウトを解除することで、root への切り替えをパスワードなしで行えるようになる。
su 許可ユーザーの制限
#auth required pam_wheel.so use_uid
上記コメントアウトを解除することで、wheel グループに所属するアカウントのみ su できるようになる。
管理ユーザーの追加
useradd joe && passwd $_ && usermod -G wheel $_ && getent group wheel
sudo -u joe echo 'joe@example.com' > ~/.forward
sed -i /etc/aliases -e '/root:/ s/^#//' -e '/root:/ s/marc/joe/' && newaliases
echo "Test mail" | sendmail root
etckeeper commit ":email: Set a mail alias for root user"
ユーザーの作成後にパスワードを設定、 wheel グループに追加し、 wheel グループに所属するアカウントを確認する。
外部のメールアドレスに転送したい場合に .forward ファイルに設定する。
root 宛てメールをユーザー marc に転送する設定が /etc/aliases にコメントで記載されているので、アンコメントしてユーザー名を差し替える。
テストメールを送信する場合 CentOS 7 の minimal では mail
コマンドや mailx
コマンドはインストールされていないので、デフォルトでインストールされている Postfix の sendmail 互換コマンドを利用する。
ホスト名の変更
hostnamectl set-hostname server1.example.com
IPアドレスの変更
nmcli device && nmcli connection show enp0s8 | grep IP
nmcli connection modify enp0s8 ipv4.method manual ipv4.addresses 192.168.56.201/24
nmcli connection down enp0s8 && nmcli connection up $_
SSH 接続している場合は上記実行後に切断される。
NTP サーバーの変更
sed -i 's/centos/jp/' /etc/chrony.conf
systemctl restart chronyd
etckeeper commit ":: Change the addresses of NTP servers to better ones"
server 0.centos.pool.ntp.org iburst
~ server 3.centos.pool.ntp.org iburst
を server 0.jp.pool.ntp.org iburst
~ server 3.jp.pool.ntp.org iburst
に変更。意味があるかは不明。ping の時間は3倍くらい速い。
他の NTP サーバーは「公開 NTP サーバー」を参照。
ローカル PC での操作
ネットワーク設定が完了後、ローカル PC から公開鍵を登録する。
認証鍵の生成
ssh-keygen -t ed25519 -C "joe@example.com $(date +'%Y-%M-%dT%T%z')" -f ~/.ssh/id_ed25519_server1.example.com
ssh-id-copy
が ls -t ${HOME}/.ssh/id*.pub
でファイルを探すので、それに合わせてファイル名を指定する。
鍵種別は ed25519 が望ましい。
コメントはサーバーの鍵の管理者が連絡を取れるように使用者のメールアドレスを記載することが望ましい。鍵の生成日も記載すると参考になるかもしれない。
生成した認証鍵の確認
ls -t ${HOME}/.ssh/id*.pub
ssh-keygen -l -f `!!`
ssh-add
ssh-add ~/.ssh/id_ed25519_server1.example.com
ssh-add -l
サーバーへの公開鍵の登録 (ssh-copy-id)
ssh-copy-id -i ~/.ssh/id_ed25519_server1.example.com.pub example@192.168.56.201
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/Users/Example/.ssh/id_ed25519_server1.example.com.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
example@192.168.56.201's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'example@192.168.56.201'"
and check to make sure that only the key(s) you wanted were added.
ローカル PC の公開鍵をサーバーに自動で登録する。
ssh
ssh example@192.168.56.201
パスワードなしで接続可能になる。
ssh-keygen -R
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Please contact your system administrator.
Add correct host key in /Users/Example/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /Users/Example/.ssh/known_hosts:21
ECDSA host key for 192.168.56.201 has changed and you have requested strict checking.
Host key verification failed.
ssh-keygen -R 192.168.56.201
ローカル PC の known_hosts に重複するサーバー情報が残っているとエラーが出て接続できないので、その際は上記のコマンドで削除する。
.ssh/config
cat << "_EOF_" > ~/.ssh/config
Host heros
User example
HostName 192.168.56.201
IdentityFile ~/.ssh/id_ed25519_server1.example.com
Port 10022
_EOF_
shopt
bashの”秘められた真のチカラ”を開放する。2
cat << "_EOF_" >> ~/.bashrc
shopt -s autocd
shopt -s cdspell
shopt -s dotglob
shopt -s extglob
shopt -s globstar
shopt -s nocaseglob
_EOF_
bash-completion
yum -y install epel-release && yum -y install bash-completion{,-extras}
Tab キーでファイルパス以外も色々補完してくれるようになる。
例
[root@localhost ~]# systemctl s
set-default set-environment set-property show
show-environment snapshot start status
stop suspend switch-root
[root@localhost ~]# ssh
::1 localhost localhost.localdomain
localhost4 localhost4.localdomain4 localhost6
localhost6.localdomain6
[root@localhost ~]# man z
zcat zcmp zdiff zforce zgrep zipcmp
zipdetails zipmerge ziptorrent zless zmore znew
zsoelim zts-php zts-phpize
Less
cat << '_EOF_' >> ~/.bashrc
export VISUAL=vim
export LESS="-M"
_EOF_
less コマンドの設定。
-M
オプションはファイル名、行数、進行率を常時表示する。
Vim
cat << '_EOF_' >> ~/.vimrc && mkdir -p ~/.vim/tmp
set encoding=utf-8
set directory=~/.vim/tmp
set backupdir=~/.vim/tmp
set undodir=~/.vim/tmp
_EOF_
.swp
などの一時ファイルの保存場所を変更する。
MySQL
cat << '_EOF_' > ~/.my.cnf
[mysql]
auto-rehash
pager = less -S -n -i -F -X
_EOF_
不足パッケージのインストール
Yum プラグイン
yum -y install epel-release && yum -y install yum-{axelget,changelog,cron,plugin-{ps,remove-with-leaves,rpm-warm-cache,show-leaves},utils}
パッケージ | 説明 |
---|---|
yum-axelget | axel を利用してダウンロードを高速化する Yum プラグイン |
yum-changelog | 更新の前後でパッケージ変更ログの表示を可能にする --changelog オプションを追加する Yum プラグイン |
yum-cron | yum update を Cron で実行する Yum プラグイン |
yum-plugin-ps |
yum ps で旧バージョンで稼働しているプロセスを一覧化する Yum プラグイン |
yum-plugin-remove-with-leaves | 依存関係のない孤立パッケージを削除する --remove-leaves オプションを追加する Yum プラグイン |
yum-plugin-rpm-warm-cache | rpmdb に直接アクセスする前に rpmdb ファイルをシステムキャッシュに読み込む Yum プラグイン |
yum-plugin-show-leaves | トランザクション後に依存関係のない孤立パッケージを表示する Yum プラグイン |
yum-utils | Yum を便利で強力にするためのユーティリティとサンプルのコレクション |
ユーティリティ
minimal ではインストールされていないコマンドなどが多いので、よく使うものは事前にインストールしておく。
yum -y install bind-utils net-tools policycoreutils-python psmisc rlwrap traceroute tree vim-enhanced wget
パッケージ | 説明 |
---|---|
bind-utils |
dig host nslookup nsupdate
|
net-tools | 代替コマンドがあるが互換性維持のため。netstat arp ether-wake ifconfig ipmaddr iptunnel mii-diag mii-tool nameif plipconfig route slattach
|
policycoreutils-python | SELinux の管理コマンドが含まれる。audit2allow audit2why chcat sandbox semodule_package semanage
|
psmisc |
killall pstree fuser peekfd prtstat
|
rlwrap | |
traceroute | |
tree | |
vim-enhanced | |
wget | 基本的に curl を使えば問題がないが、時折 wget が必須のスクリプトがある。 |
圧縮・解凍
yum -y install epel-release && yum -y install pigz {,p,l}bzip2 pxz {,un}zip
パッケージ | 説明 |
---|---|
unzip | zip 形式のみで圧縮されていることが意外に多い。 |
bzip2 | .tar.bz2 形式のファイルを展開するときに必要。 |
lbzip2 |
tar コマンドに -I lbzip2 を指定すると bzip2 を並列処理で時間短縮できる。 |
pbzip2 |
tar コマンドに -I pbzip2 を指定すると bzip2 を並列処理で時間短縮できる。 |
pigz |
tar コマンドに -I pigz を指定すると gzip を並列処理で時間短縮できる。 |
pxz |
tar コマンドに -I pxz を指定すると xz を並列処理で時間短縮できる。 |
モニターツールのインストール
yum -y install epel-release
yum -y install {a,apache,dns,h,if,io,inno,my,pg_}top iptraf-ng goaccess ncdu
yum -y --enablerepo=epel-testing install glances jnettop
GSSAPIAuthentication の無効化
sed -i '/GSSAPIAuthentication / s/yes/no/' /etc/ssh/sshd_config
etckeeper commit ":new: Disable the GSS API Authentication"
デフォルトで GSSAPIAuthentication が有効になっているが SSH ログイン時にもたつく模様。
カーネルの古いパッケージ保持数の上限を減らす 3
sed -e '/installonly_limit/ s/5/2/' -i /etc/yum.conf
セキュリティ設定
Lynis
sed -i.org '/mail_version/a smtpd_banner = $myhostname ESMTP' /etc/postfix/main.cf
sed -i.org /etc/login.defs -e '/PASS_MIN_DAYS/ s/0/1/' -e '/PASS_MAX_DAYS/ s/99999/3650/'
sed -i /etc/profile -e 's/umask 002/umask 027/' -e 's/umask 022/umask 027/'
cat << "_EOF_" > /etc/modprobe.d/blacklist.conf
blacklist usb-storage
blacklist firewire_core
blacklist firewire_ohci
_EOF_
for i in $(find /lib/modules/`uname -r`/kernel/drivers/net/wireless -name "*.ko" -type f) ; do echo blacklist $i >> /etc/modprobe.d/blacklist-wireless ; done
iptables --flush
firewall-cmd --reload
sed -i.org 's/#AllowTcpForwarding yes/AllowTcpForwarding no/' /etc/ssh/sshd_config
sed -i 's/#ClientAliveCountMax 3/ClientAliveCountMax 2/' /etc/ssh/sshd_config
sed -i 's/#Compression delayed/Compression no/' /etc/ssh/sshd_config
sed -i 's/#LogLevel INFO/LogLevel VERBOSE/' /etc/ssh/sshd_config
sed -i 's/#MaxAuthTries 6/MaxAuthTries 2/' /etc/ssh/sshd_config
sed -i 's/#MaxSessions 10/MaxSessions 2/' /etc/ssh/sshd_config
#sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
#sed -i 's/#Port 22/Port 10022/' /etc/ssh/sshd_config
sed -i 's/#TCPKeepAlive yes/TCPKeepAlive no/' /etc/ssh/sshd_config
sed -i 's/#UseDNS yes/UseDNS no/' /etc/ssh/sshd_config
sed -i 's/X11Forwarding yes/X11Forwarding no/' /etc/ssh/sshd_config
sed -i 's/#AllowAgentForwarding yes/AllowAgentForwarding no/' /etc/ssh/sshd_config
(echo; echo "Unauthorized access to this machine is prohibited."; echo "Disconnect now if you are not an authorized user."; echo) > /etc/issue
(echo; echo "Unauthorized access to this machine is prohibited."; echo "Disconnect now if you are not an authorized user."; echo) > /etc/issue.net
cat << "_EOF_" >> /etc/sysctl.conf
kernel.kptr_restrict=2
kernel.sysrq=0
net.ipv4.conf.all.accept_redirects=0
net.ipv4.conf.all.log_martians=1
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.default.accept_redirects=0
net.ipv4.conf.default.log_martians=1
net.ipv4.tcp_timestamps=0
net.ipv6.conf.all.accept_redirects=0
net.ipv6.conf.default.accept_redirects=0
_EOF_
sysctl -p
chmod 700 /usr/bin/as
yum install aide arpwatch psacct sysstat yum-utils
systemctl start arpwatch psacct && systemctl enable $_
詳細は「HowTos/OS Protection - CentOS Wiki」「Linuxセキュリティ監査ツール Lynis」「OpenSCAP」「脆弱性スキャナー Nikto」「脆弱性スキャナー OpenVAS」などを参照。
Fail2ban
yum -y install epel-release && yum -y install fail2ban{,-systemd}
cat << "_EOF_" > /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 192.168.0.0/24
[sshd]
enabled = true
_EOF_
etckeeper commit ":new: Add a Fail2ban setting file"
fail2ban-client -d
systemctl start fail2ban && systemctl enable $_
fail2ban-client status
fail2ban-client status sshd
詳細は「ブルートフォース攻撃対策 Fail2ban」を参照。
フールプルーフ(誤操作対策)
あくまでフールプルーフのための設定であり、これらに頼った運用や操作はしない。
やれ過保護だの慣れると他環境で失敗するだの言う人は宗教が異なりますのでお引き取りください。
リダイレクションによるファイル上書き禁止
set -o noclobber
interactive オプション
cat << "_EOF_" > /etc/profile.d/alias.sh
alias crontab='crontab -i'
alias cp='cp -i'
alias mv='mv -i'
alias rm='rm -i'
_EOF_
etckeeper commit ":new: Add a shell script of adding interactive option"
crontab
crontab -e
を実行しようとして r キーが e キーの隣にあるので、間違って crontab -r
を実行してしまう可能性が考えられる。万が一そのような事態が生じても大丈夫なように -i
オプションを指定しておくと -r
オプション指定時に Y/N
で確認を求めてくれるようになる。
cp/mv/rm
root ユーザーは /root/.bashrc で指定されているが、その他のユーザーでは指定がないので一律に指定する。
なお、この指定を無視したい場合は \mv source dist
のように先頭にバックスラッシュを付加することで対応できる。
yum
echo "exclude=kernel* centos*" >> /etc/yum.conf
echo "alias yum='yum --disableexcludes=all'" >> /etc/profile.d/yum.sh
etckeeper commit ":new: Add excluding kernel setting from yum updating"
無防備に kenerl をアップデートして kernel パニックが発生すると慣れない作業で復旧に手間取るので、通常のアップデート時は除外して、kernel のアップデートは独立して作業を行うようにする。 4
なお、exclude
を指定すると yum info
などでも除外されるので注意。
yum update --disableexcludes=all
yum.conf で指定した exclude を無効にするには --disableexcludes
オプションに all
または main
を指定する。
通常の yum update
では kernel のバージョンアップの有無を含めて確認できなくなるため、 alias で --disableexcludes
オプションを指定してこれを回避する。