終電23時15分って早くね?

都内のIT企業で働くカラオケ大好きエンジニアの雑記

【自宅サーバ構築記録】サーバを外部にさらすまえに…セキュリティ!

ちょっと間が空きましたが、今回はサーバのセキュリティ設定を行っていきますよと!

え、セキュリティとかいいから早くApacheとかPHPとか入れてプログラムを動かしたい??


セキュリティ対策しないで外部にサーバ公開「ダメ。ゼッタイ。


まてまて、と。そんなに焦らずコツコツやりましょう!


まだあわてるような時間じゃない」by 仙道


ちょろっとサーバを外部からアクセスできるようにするだけで、
結構な攻撃を受けちゃいますし、サーバのセキュリティを突破された日には、
もう立ち直れません(経験談 笑)

なので、ローカルの環境で動かしている状態のうちに、
セキュリティの確保をば行いたいと存じます次第です。


【大事】とりあえず最低限のセキュリティの確保をしておきましょう!【大事】


ただし、ここで行う設定は、、
絶対にセキュリティを突破されないことを保障するものではないので、
あくまでも自己責任でお願いしますm(__)m(決まり文句)

「もっとこれもやったほうがいいし!」とか「それ逆にヤバくね?」とか、
お気づきの点がございました場合はご教授いただければ幸いです。。


ということで、かなり長いですが、
大事なサーバを守るため!
じゃんじゃか設定していきます。


ログイン用ユーザーの作成

まずはログイン用のユーザを作成します。

rootは制限なくなんでも出来てしまうので、

・基本的に一般ユーザでログインする。
・root権限が必要な操作を行う場合のみ、suコマンドでrootになる。

というのをルールとして運用することにします。

新たに centos というユーザを作成する。
※ユーザ名は任意で変えてくださいね。

[root@luffy ~]# useradd centos
[root@luffy ~]# passwd centos
ユーザー centos のパスワードを変更。
新しいパスワード:
新しいパスワードを再入力してください:
passwd: 全ての認証トークンが正しく更新できました。

これで新しいユーザの作成は完了です。


rootになれるユーザを限定する

Linuxのシステム上には、
wheelグループというグループがあり、
このグループに所属するユーザーのみが、
rootになれるよう設定します。

[root@luffy ~]# usermod -G wheel centos

[root@luffy ~]# vi /etc/pam.d/su
#auth           required        pam_wheel.so use_uid
↓
auth           required        pam_wheel.so use_uid

以降、rootになれるユーザを追加する場合は、
wheelグループに所属させてあげましょう。

rootでのログインを禁止する

ここまでで、rootになれるユーザは限定しましたが、
そもそもrootのユーザがログインできてしまうという状態は、
セキュリティ的にはだいぶよろしくないです。

rootというユーザ名が分かっているので、
後はパスワードさえ分かれば、rootアカウントが乗っ取られてしまうリスクがあがりますね。

ですので、まだ外部にサーバを公開していない状態で、
rootでのログインを禁止してあげると良いと思います。

※「いつやるの?」⇒「今でしょ!」※

[root@luffy ~]# vi /etc/ssh/sshd_config

#PermitRootLogin yes
↓
PermitRootLogin no

#PermitEmptyPasswords no
↓
PermitEmptyPasswords no


ファイル改竄検知システム導入(Tripwire)

Tripwireはファイルの改竄(かいざん)などを検出してくれるツールです。

たとえば・・・
悪意のあるユーザにログインされてしまった。

何かファイルを書き換えられてしまった。

Tripwireがその変更を検知。

メールなどで自分に教えてくれる。

というような動きをしてくれます。

ただ、Tripwireは「ファイルが変更された」というのをチェックしてくれるものなので、
実際、自分で変更した部分もお知らせしてくれる形ではあります。

なので変更が検知されたからといって、誰かにセキュリティを破られているということにはなりませんのでご安心を。

[root@luffy ~]# yum -y install tripwire
[root@luffy ~]# tripwire-setup-keyfiles

----------------------------------------------
The Tripwire site and local passphrases are used to sign a  variety  of
files, such as the configuration, policy, and database files.

Passphrases should be at least 8 characters in length and contain  both
letters and numbers.

See the Tripwire manual for more information.

----------------------------------------------
Creating key files...

(When selecting a passphrase, keep in mind that good passphrases typically
have upper and lower case letters, digits and punctuation marks, and are
at least 8 characters in length.)

Enter the site keyfile passphrase: ← 任意のサイトパスフレーズを入力
Verify the site keyfile passphrase: ← 任意のサイトパスフレーズを入力(確認)

Enter the local keyfile passphrase: ← 任意のローカルパスフレーズを入力
Verify the local keyfile passphrase: ← 任意のローカルパスフレーズを入力(確認)

Signing configuration file...
Please enter your site passphrase: ← サイトパスフレーズを入力

Signing policy file...
Please enter your site passphrase: ← サイトパスフレーズを入力


[root@luffy ~]# vi /etc/tripwire/twcfg.txt
LOOSEDIRECTORYCHECKING =true ← ファイル変更時に所属ディレクトリの変更を通知しないようにする

EMAILREPORTLEVEL       =4 ← リポートレベルを変更する
REPORTLEVEL            =4 ← リポートレベルを変更する


[root@luffy ~]# twadmin -m F -c /etc/tripwire/tw.cfg -S /etc/tripwire/site.key /etc/tripwire/twcfg.txt ← Tripwire設定ファイルの暗号化
Please enter your site passphrase: ← サイトパスフレーズを入力
Wrote configuration file: /etc/tripwire/tw.cfg

[root@luffy ~]# rm -f /etc/tripwire/twcfg.txt ← Tripwire設定ファイル(テキスト版)削除

[root@luffy ~]# vi /etc/tripwire/twpolmake.pl ← ポリシーファイル最適化スクリプト作成
#!/usr/bin/perl
# Tripwire Policy File customize tool
# ----------------------------------------------------------------
# Copyright (C) 2003 Hiroaki Izumi
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
# ----------------------------------------------------------------
# Usage:
#    perl twpolmake.pl {Pol file}
# ----------------------------------------------------------------
#
$POLFILE=$ARGV[0];

open(POL,"$POLFILE") or die "open error: $POLFILE" ;
my($myhost,$thost) ;
my($sharp,$tpath,$cond) ;
my($INRULE) = 0 ;

while (<POL>) {
    chomp;
    if (($thost) = /^HOSTNAME\s*=\s*(.*)\s*;/) {
        $myhost = `hostname` ; chomp($myhost) ;
        if ($thost ne $myhost) {
            $_="HOSTNAME=\"$myhost\";" ;
        }
    }
    elsif ( /^{/ ) {
        $INRULE=1 ;
    }
    elsif ( /^}/ ) {
        $INRULE=0 ;
    }
    elsif ($INRULE == 1 and ($sharp,$tpath,$cond) = /^(\s*\#?\s*)(\/\S+)\b(\s+->\s+.+)$/) {
        $ret = ($sharp =~ s/\#//g) ;
        if ($tpath eq '/sbin/e2fsadm' ) {
            $cond =~ s/;\s+(tune2fs.*)$/; \#$1/ ;
        }
        if (! -s $tpath) {
            $_ = "$sharp#$tpath$cond" if ($ret == 0) ;
        }
        else {
            $_ = "$sharp$tpath$cond" ;
        }
    }
    print "$_\n" ;
}
close(POL) ;

[root@luffy ~]# perl /etc/tripwire/twpolmake.pl /etc/tripwire/twpol.txt > /etc/tripwire/twpol.txt.new ← ポリシーファイル最適化
[root@luffy ~]# twadmin -m P -c /etc/tripwire/tw.cfg -p /etc/tripwire/tw.pol -S /etc/tripwire/site.key /etc/tripwire/twpol.txt.new
 ← 最適化済ポリシーファイルを元にポリシーファイル(暗号署名版)作成
Please enter your site passphrase: ← サイトパスフレーズを入力
Wrote policy file: /etc/tripwire/tw.pol

[root@luffy ~]# rm -f /etc/tripwire/twpol.txt* ← ポリシーファイル(テキスト版)削除

[root@luffy ~]# tripwire -m i -s -c /etc/tripwire/tw.cfg ← Tripwireデータベース作成
Please enter your local passphrase: ← ローカルパスフレーズ応答


[root@luffy ~]# tripwire --check ← Tripwireチェック実行

[root@luffy ~]# vi tripwire.sh ← Tripwire定期自動実行スクリプト作成
#!/bin/bash

PATH=/usr/sbin:/usr/bin:/bin:/usr/local/tripwire/sbin

# パスフレーズ設定
LOCALPASS=xxxxxxxx # ローカルパスフレーズ
SITEPASS=xxxxxxxx  # サイトパスフレーズ

cd /etc/tripwire

# Tripwireチェック実行
tripwire -m c -s -c tw.cfg|mail -s "Tripwire(R) Integrity Check Report in `hostname`" root

# ポリシーファイル最新化
twadmin -m p -c tw.cfg -p tw.pol -S site.key > twpol.txt
perl twpolmake.pl twpol.txt > twpol.txt.new
twadmin -m P -c tw.cfg -p tw.pol -S site.key -Q $SITEPASS twpol.txt.new > /dev/null
rm -f twpol.txt* *.bak

# データベース最新化
rm -f /usr/local/tripwire/lib/tripwire/*.twd*
tripwire -m i -s -c tw.cfg -P $LOCALPASS

[root@luffy ~]# chmod 700 tripwire.sh

[root@luffy ~]# crontab -e
# 毎日03:00にtripwire(ファイル改竄検知)を行う
00 03 * * * /root/tripwire.sh

【参考サイト】
■はじめての自宅サーバ構築 - Fedora/CentOS - ファイル改竄検知システムの導入(Tripwire)
http://kajuhome.com/tripwire.shtml


rootkit検知ツール導入(chkrootkit)

まず、rootkitとは・・・?
http://e-words.jp/w/rootkit.html

サーバに悪意のある第3者に侵入された場合に、
その痕跡を消したり、再度アクセスできるようにしたり、
といったクラッカーの手助けをするツールrootkitです。

そのrootkitを検出してくれるのがこのツールです。

まぁrootkitが検知されてしまったら、
おそらく何かしら悪さをされているであろう状況だと思うので、
早急な被害拡大の防止の対応ができる。
というような二次災害を食い止めるツールというような考え方でよいのかな?と思っています。

[root@luffy ~]# yum -y install chkrootkit

chkrootkit定期自動実行設定
[root@luffy ~]# vi chkrootkit.sh

[root@luffy ~]# chmod 700 chkrootkit.sh

[root@luffy ~]# crontab -e
# 毎日02:00にchkrootkit(rootkit検知)を行う
00 02 * * * /root/tripwire.sh


Clam AntiVirusインストール

Clam AntiVirusは無料で使えるアンチウイルスソフトウェアです。
(当初はUNIX用だったようですが、現在はいろんなプラットフォームで使えるようです。)

Windowsにウイルス○スターとかカス○ルスキーとか入れるのと同じですね 笑

[root@luffy ~]# yum -y install clamd

[root@luffy ~]# freshclam ← ウィルス定義ファイルの更新

[root@luffy ~]# service clamd start

[root@luffy ~]# sed -i 's/Example/#Example/g' /etc/freshclam.conf ← ウィルス定義ファイル更新機能の有効化

[root@luffy ~]# vi virusscan.sh ← ウィルススキャン実行スクリプト作成

[root@luffy ~]# chmod 700 virusscan.sh

#!/bin/bash

PATH=/usr/bin:/bin

# clamd update
yum -y update clamd > /dev/null 2>&1

# excludeopt setup
excludelist=/root/clamscan.exclude
if [ -s $excludelist ]; then
    for i in `cat $excludelist`
    do
        if [ $(echo "$i"|grep \/$) ]; then
            i=`echo $i|sed -e 's/^\([^ ]*\)\/$/\1/p' -e d`
            excludeopt="${excludeopt} --exclude-dir=^$i"
        else
            excludeopt="${excludeopt} --exclude=^$i"
        fi
    done
fi

# virus scan
CLAMSCANTMP=`mktemp`
clamscan --recursive --remove ${excludeopt} / > $CLAMSCANTMP 2>&1
[ ! -z "$(grep FOUND$ $CLAMSCANTMP)" ] && \

# report mail send
grep FOUND$ $CLAMSCANTMP | mail -s "Virus Found in `hostname`" root
rm -f $CLAMSCANTMP

[root@luffy ~]# chmod 700 virusscan.sh

[root@luffy ~]# crontab -e
# 毎日04:00にclamd(ウィルススキャン)を行う
00 04 * * * /root/virusscan.sh


不必要なサービスの停止

[root@luffy ~]# service --status-all

無駄に動いているサービスはとめてしまいましょう。というお話。

サーバのリソース消費を抑えたり、脆弱性が露見する可能性を低くするために、
不必要なサービスは停止してしまいます。

[root@luffy ~]# service haldaemon status
hald (pid  7984) を実行中...
[root@luffy ~]# service haldaemon stop
HAL デーモンを停止中:                                      [  OK  ]
[root@luffy ~]# chkconfig haldaemon off

[root@luffy ~]# service abrtd status
abrtd (pid  8153) を実行中...
[root@luffy ~]# service abrtd stop
abrt デーモンを停止中:                                     [  OK  ]
[root@luffy ~]# chkconfig abrtd off

[root@luffy ~]# service auditd status
auditd (pid  8368) を実行中...
[root@luffy ~]# service auditd stop
auditd を停止中:                                           [  OK  ]
[root@luffy ~]# chkconfig auditd off

[root@luffy ~]# service messagebus status
messagebus (pid  7946) を実行中...
[root@luffy ~]# service messagebus stop
システムメッセージバスを停止中:                            [  OK  ]
[root@luffy ~]# chkconfig messagebus off

[root@luffy ~]# service kdump status
Kdump is operational
[root@luffy ~]# service kdump stop
Stopping kdump:                                            [  OK  ]
[root@luffy ~]# chkconfig kdump off

【参考サイト】
■◇不要デーモンの停止(CentOS6)◇初心者のためのLinuxサーバー構築講座(CentOS 自宅サーバー対応)☆お便利サーバー.com☆
http://www.obenri.com/_minset_cent6/daemon_cent6.html


バッファオーバーフロー対策(Exec-Shield)

Exec-ShieldはCentOSに標準でインストールされている機能で、
バッファオーバーフローを防いでくれるものですが、
デフォルトでは無効になっているので、有効にしておきます。

[root@luffy ~]# cat /proc/sys/kernel/exec-shield
1
[root@luffy ~]# echo 2 > /proc/sys/kernel/exec-shield

[root@luffy ~]# cat /proc/sys/kernel/exec-shield
2


不要なポートへのアクセス制御(iptables)

不要なポートは閉じる!進入経路を減らす!

公開するポートは、
22(ssh)と80(http)と443(https)だけの想定で設定しています。

[root@luffy ~]# vi iptables.sh

#!/bin/bash

#---------------------------------------#
# 設定開始                              #
#---------------------------------------#

# インタフェース名定義
LAN=eth0

#---------------------------------------#
# 設定終了                              #
#---------------------------------------#

# 内部ネットワークのネットマスク取得
LOCALNET_MASK=`ifconfig $LAN|sed -e 's/^.*Mask:\([^ ]*\)$/\1/p' -e d`

# 内部ネットワークアドレス取得
LOCALNET_ADDR=`netstat -rn|grep $LAN|grep $LOCALNET_MASK|cut -f1 -d' '`
LOCALNET=$LOCALNET_ADDR/$LOCALNET_MASK

# ファイアウォール停止(すべてのルールをクリア)
/etc/rc.d/init.d/iptables stop

# デフォルトルール(以降のルールにマッチしなかった場合に適用するルール)設定
iptables -P INPUT   DROP   # 受信はすべて破棄
iptables -P OUTPUT  ACCEPT # 送信はすべて許可
iptables -P FORWARD DROP   # 通過はすべて破棄

# 自ホストからのアクセスをすべて許可
iptables -A INPUT -i lo -j ACCEPT

# 内部からのアクセスをすべて許可
iptables -A INPUT -s $LOCALNET -j ACCEPT

# 内部から行ったアクセスに対する外部からの返答アクセスを許可
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# SYN Cookiesを有効にする
# ※TCP SYN Flood攻撃対策
sysctl -w net.ipv4.tcp_syncookies=1 > /dev/null
sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf
echo "net.ipv4.tcp_syncookies=1" >> /etc/sysctl.conf

# ブロードキャストアドレス宛pingには応答しない
# ※Smurf攻撃対策
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1 > /dev/null
sed -i '/net.ipv4.icmp_echo_ignore_broadcasts/d' /etc/sysctl.conf
echo "net.ipv4.icmp_echo_ignore_broadcasts=1" >> /etc/sysctl.conf

# ICMP Redirectパケットは拒否
sed -i '/net.ipv4.conf.*.accept_redirects/d' /etc/sysctl.conf
for dev in `ls /proc/sys/net/ipv4/conf/`
do
    sysctl -w net.ipv4.conf.$dev.accept_redirects=0 > /dev/null
    echo "net.ipv4.conf.$dev.accept_redirects=0" >> /etc/sysctl.conf
done

# Source Routedパケットは拒否
sed -i '/net.ipv4.conf.*.accept_source_route/d' /etc/sysctl.conf
for dev in `ls /proc/sys/net/ipv4/conf/`
do
    sysctl -w net.ipv4.conf.$dev.accept_source_route=0 > /dev/null
    echo "net.ipv4.conf.$dev.accept_source_route=0" >> /etc/sysctl.conf
done

# フラグメント化されたパケットはログを記録して破棄
iptables -A INPUT -f -j LOG --log-prefix '[IPTABLES FRAGMENT] : '
iptables -A INPUT -f -j DROP

# 外部とのNetBIOS関連のアクセスはログを記録せずに破棄
# ※不要ログ記録防止
iptables -A INPUT ! -s $LOCALNET -p tcp -m multiport --dports 135,137,138,139,445 -j DROP
iptables -A INPUT ! -s $LOCALNET -p udp -m multiport --dports 135,137,138,139,445 -j DROP
iptables -A OUTPUT ! -d $LOCALNET -p tcp -m multiport --sports 135,137,138,139,445 -j DROP
iptables -A OUTPUT ! -d $LOCALNET -p udp -m multiport --sports 135,137,138,139,445 -j DROP

# 1秒間に4回を超えるpingはログを記録して破棄
# ※Ping of Death攻撃対策
iptables -N LOG_PINGDEATH
iptables -A LOG_PINGDEATH -m limit --limit 1/s --limit-burst 4 -j ACCEPT
iptables -A LOG_PINGDEATH -j LOG --log-prefix '[IPTABLES PINGDEATH] : '
iptables -A LOG_PINGDEATH -j DROP
iptables -A INPUT -p icmp --icmp-type echo-request -j LOG_PINGDEATH

# 全ホスト(ブロードキャストアドレス、マルチキャストアドレス)宛パケットはログを記録せずに破棄
# ※不要ログ記録防止
iptables -A INPUT -d 255.255.255.255 -j DROP
iptables -A INPUT -d 224.0.0.1 -j DROP

# 113番ポート(IDENT)へのアクセスには拒否応答
# ※メールサーバ等のレスポンス低下防止
iptables -A INPUT -p tcp --dport 113 -j REJECT --reject-with tcp-reset

# ACCEPT_COUNTRY_MAKE関数定義
# 指定された国のIPアドレスからのアクセスを許可するユーザ定義チェイン作成
ACCEPT_COUNTRY_MAKE(){
    for addr in `cat /tmp/cidr.txt|grep ^$1|awk '{print $2}'`
    do
        iptables -A ACCEPT_COUNTRY -s $addr -j ACCEPT
    done
}

# DROP_COUNTRY_MAKE関数定義
# 指定された国のIPアドレスからのアクセスを破棄するユーザ定義チェイン作成
DROP_COUNTRY_MAKE(){
    for addr in `cat /tmp/cidr.txt|grep ^$1|awk '{print $2}'`
    do
        iptables -A DROP_COUNTRY -s $addr -m limit --limit 1/s -j LOG --log-prefix '[IPTABLES DENY_COUNTRY] : '
        iptables -A DROP_COUNTRY -s $addr -j DROP
    done
}

# IPアドレスリスト取得
. /root/iptables_functions
IPLISTGET

# 日本からのアクセスを許可するユーザ定義チェインACCEPT_COUNTRY作成
iptables -N ACCEPT_COUNTRY
ACCEPT_COUNTRY_MAKE JP
# 以降,日本からのみアクセスを許可したい場合はACCEPTのかわりにACCEPT_COUNTRYを指定する

# 中国・台湾・ロシア※からのアクセスをログを記録して破棄
# ※全国警察施設への攻撃元上位3カ国(日本・アメリカを除く)
# http://www.cyberpolice.go.jp/detect/observation.htmlより
iptables -N DROP_COUNTRY
DROP_COUNTRY_MAKE CN
DROP_COUNTRY_MAKE TW
DROP_COUNTRY_MAKE RU
iptables -A INPUT -j DROP_COUNTRY

#----------------------------------------------------------#
# 各種サービスを公開する場合の設定(ここから)               #
#----------------------------------------------------------#

# 外部からのTCP22番ポート(SSH)へのアクセスを日本からのみ許可
# ※SSHサーバーを公開する場合のみ
iptables -A INPUT -p tcp --dport 22 -j ACCEPT_COUNTRY

# 外部からのTCP80番ポート(HTTP)へのアクセスを許可
# ※Webサーバーを公開する場合のみ
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# 外部からのTCP443番ポート(HTTPS)へのアクセスを許可
# ※Webサーバーを公開する場合のみ
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

#----------------------------------------------------------#
# 各種サービスを公開する場合の設定(ここまで)               #
#----------------------------------------------------------#

# 拒否IPアドレスからのアクセスはログを記録せずに破棄
# ※拒否IPアドレスは/root/deny_ipに1行ごとに記述しておくこと
# (/root/deny_ipがなければなにもしない)
if [ -s /root/deny_ip ]; then
    for ip in `cat /root/deny_ip`
    do
        iptables -I INPUT -s $ip -j DROP
    done
fi

# 上記のルールにマッチしなかったアクセスはログを記録して破棄
iptables -A INPUT -m limit --limit 1/s -j LOG --log-prefix '[IPTABLES INPUT] : '
iptables -A INPUT -j DROP
iptables -A FORWARD -m limit --limit 1/s -j LOG --log-prefix '[IPTABLES FORWARD] : '
iptables -A FORWARD -j DROP

# サーバー再起動時にも上記設定が有効となるようにルールを保存
/etc/rc.d/init.d/iptables save

# ファイアウォール起動
/etc/rc.d/init.d/iptables start

[root@luffy ~]# vi iptables_functions

# IPアドレスリスト取得関数定義
IPLISTGET(){
    # http://nami.jp/ipv4bycc/から最新版IPアドレスリストを取得する
    wget -q http://nami.jp/ipv4bycc/cidr.txt.gz
    gunzip cidr.txt.gz
    # 最新版IPアドレスリストが取得できなかった場合
    if [ ! -f cidr.txt ]; then
        if [ -f /tmp/cidr.txt ]; then
            # バックアップがある場合はその旨をroot宛にメール通知して処理を打ち切る
            echo cidr.txt was read from the backup! | mail -s $0 root
            return
        else
            # バックアップがない場合はその旨をroot宛にメール通知して処理を打ち切る
            echo cidr.txt not found!|mail -s $0 root
            exit 1
        fi
    fi
    # 最新版IPアドレスリストを /tmpへバックアップする
    /bin/mv cidr.txt /tmp/cidr.txt
}

[root@luffy ~]# vi /etc/cron.daily/iplist_check.sh ← IPアドレスリストチェックスクリプト作成
#!/bin/bash

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# 新旧IPLIST差分チェック件数(0を指定するとチェックしない)
# ※新旧IPLIST差分がSABUN_CHKで指定した件数を越える場合はiptables設定スクリプトを実行しない
# ※新旧IPLIST差分チェック理由はhttp://centossrv.com/bbshtml/webpatio/1592.shtmlを参照
SABUN_CHK=9999
[ $# -ne 0 ] && SABUN_CHK=${1}

# チェック国コード
COUNTRY_CODE='JP CN TW RU'

# iptables設定スクリプトパス
IPTABLES=/root/iptables.sh

# iptables設定スクリプト外部関数取り込み
. /root/iptables_functions

# IPアドレスリスト最新化
rm -f IPLIST.new
IPLISTGET
for country in $COUNTRY_CODE
do
    if [ -f /tmp/cidr.txt ]; then
        grep ^$country /tmp/cidr.txt >> IPLIST.new
    else
        grep ^$country /tmp/IPLIST >> IPLIST.new
    fi
done
[ ! -f /tmp/IPLIST ] && cp IPLIST.new /tmp/IPLIST

# IPアドレスリスト更新チェック
diff -q /tmp/IPLIST IPLIST.new > /dev/null 2>&1
if [ $? -ne 0 ]; then
    if [ ${SABUN_CHK} -ne 0 ]; then
        if [ $(diff /tmp/IPLIST IPLIST.new | egrep -c '<|>') -gt ${SABUN_CHK} ]; then
            (
             diff /tmp/IPLIST IPLIST.new
             echo
             echo "$IPTABLES not executed."
            ) | mail -s 'IPLIST UPDATE' root
            rm -f IPLIST.new
            exit
        fi
    fi
    /bin/mv IPLIST.new /tmp/IPLIST
    sh $IPTABLES > /dev/null
else
    rm -f IPLIST.new
fi

[root@luffy ~]# chmod 700 /etc/cron.daily/iplist_check.sh

[root@luffy ~]# sh iptables.sh

[root@luffy ~]# chkconfig iptables on

【参考】
ファイアウォール構築(iptables) - CentOS自宅サーバー構築
http://centossrv.com/iptables.shtml


SSHのポート番号を変更

ポート番号を変えておいたほうが、
よりクラッカーからは敬遠されやすいはず!

[root@luffy ~]# vi /etc/ssh/sshd_config

#Port 22
↓
Port 10000 ← 任意のポート番号

[root@luffy ~]# service sshd restart

上で設定した開放するポート番号も変更します。

[root@luffy ~]# vi iptables.sh

# 外部からのTCP22番ポート(SSH)へのアクセスを日本からのみ許可
# ※SSHサーバーを公開する場合のみ
iptables -A INPUT -p tcp --dport 22 -j ACCEPT_COUNTRY
↓
iptables -A INPUT -p tcp --dport 10000 -j ACCEPT_COUNTRY

[root@luffy ~]# sh iptables.sh


パスワードでの認証を禁止し、公開鍵認証方式にする

パスワード認証と公開鍵認証のメリット・デメリットについては、
下記サイト様に非常に分かりやすくまとめられていました!

■[OpenSSH] SSHの2つの認証方式の違い - Life with IT
http://l-w-i.net/t/openssh/auth_001.txt

パスワード認証方式では、ID・PASSが分かればログインできてしまいますが、
公開鍵認証方式では、事前に秘密鍵・公開鍵のセットを発行しておく必要があり、
ひと手間かかる部分ですがセキュリティ的には強固になりますね!
秘密鍵の取り扱いは要注意ですが。。)

さて、まずは、公開鍵認証の設定をします。

公開鍵と秘密鍵の作成

最初のころーにダウンロードした、

PuTTY ごった煮版
http://yebisuya.dip.jp/Software/PuTTY/

に「puttygen.exe」がありますのでこちらを実行します。

f:id:blue_goheimochi:20130731233200j:plain

1.[SSH-2 RSA]を選択
2.[生成する鍵のビット数(B):] に [2048] を指定
3.[生成]をクリック

f:id:blue_goheimochi:20130731233214j:plain

4.[鍵] と表示されている何も書いてない部分で、緑のバーが溜まるまでマウスをぐりぐり動かす。

f:id:blue_goheimochi:20130731233223j:plain

5.[鍵のパスフレーズ] と「パスフレーズの確認」を入力する。
後でログインする際に使うので忘れないように!
→これは現状のサーバへのログインパスワードではないので、任意のものを設定でOKです。
6.[公開鍵の保存]をクリックして、任意の場所に公開鍵を「public-key.pub」という名前で保存する。
7.[秘密鍵の保存]をクリックして、任意の場所に秘密鍵を「scecret-key.pub」という名前で保存する。


サーバに公開鍵の設定をする

先ほど保存した「public-key.pub」のファイルをWinSCP等で、
サーバに転送します。
( /home/centos/public-key.pub に配置した想定で進めます。 )

以下のコマンドを実行。

[centos@luffy ~]$ mkdir -p .ssh

[centos@luffy ~]$ chmod 700 .ssh

[centos@luffy ~]$ ssh-keygen -i -f public-key.pub >> .ssh/authorized_keys

[centos@luffy ~]$ chmod 600 .ssh/authorized_keys

rootユーザに戻って、sshの設定を変更

[root@luffy ~]# vi /etc/ssh/sshd_config

#RSAAuthentication yes
#PubkeyAuthentication yes
#AuthorizedKeysFile     .ssh/authorized_keys

↓各コメントアウトをはずす

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile     .ssh/authorized_keys

PasswordAuthentication yes
↓パスワード認証を禁止する設定
PasswordAuthentication no

また、私の環境におきましては、
ローカル環境からのアクセス(自宅LAN内からのアドレス)についてだけは、
パスワード認証を許可する設定をしております。

何らかが原因で公開鍵を紛失したとか接続したいPCが複数台あるとか、
ぶっちゃけ設定画面めんどくさいとか
もろもろの理由がございまして・・・笑

その際には、WiFiなどのネットワークにも気を配る必要がありますが。。

[root@luffy ~]# vi /etc/ssh/sshd_config

末尾に追記
↓
# 内部(192.168.1.0/24)からのアクセス時の設定
Match Address 192.168.1.0/24
PasswordAuthentication yes

Puttyの設定

Puttyにて先ほど作成した秘密鍵(scecret-key.ppk)を使ってログインする設定をします。
基本の設定は、こちらの記事を参照していただくとして、追加で下記設定をします。

f:id:blue_goheimochi:20130731233241j:plain

[接続]→[SSH]→[認証]に進み、
[認証パラメータ] の [認証のためのプライベートキーファイル] の [参照]をクリックして、
scecret-key.ppk を指定して[開く]をクリックします。

[セッション]に進み、現状の設定を [保存] したら、[開く]ボタンで開いてみましょう。

login as: centos ← centosを応答
Authenticating with public key "rsa-key-20130729"
Passphrase for key "rsa-key-20130729": ←上のほうでメモっておいたパスフレーズを応答

これで、公開鍵認証方式でのログインの設定は完了です。


おー疲れ様です!
長かったですねぇ、セキュリティ設定!
でもこれで敵がきても(たぶん)大丈夫!気持ち!

というのは嘘で、様々な書籍・Webを参考にまとめてみましたが、
冒頭でも申し上げたとおり、
「もっとこれもやったほうがいいし!」とか「それ逆にヤバくね?」とか、
お気づきの点がございました場合はご教授いただければ幸いです。。

きっとまだできることがあるはずだ!
ということで、ここのコンテンツは気がついた時点で随時増やしていきたいなと思います。

自分だけが被害を被るならまだしも、
踏み台にされたサーバから他人様に迷惑をかけてしまうようなことが無いよう、
セキュリティとは真剣に向き合わないとならないですね。

これにて、
「サーバを外部にさらすまえに…セキュリティ!」
は終了です!

次回、乞うご期待!