PR

サイト構築 〜自宅サーバー公開に向けて セキュリティ設定 その4〜

セキュリティ

インターネット上にサーバーを公開すると、ローカル環境で使用していた時とは違い、たくさんの人がサーバーにアクセスできるようになります。大切なサーバーを守るためにセキュリティ対策は必ず実施するようにしましょう!!

色んな方のサイトの情報を基に調べたことをまとめておきます。ただし、ここにまとめた設定をすれば絶対にセキュリティを突破されない事を保障するものではありません。あくまで、自己責任でお願いします。

  1. 特権ユーザーに関する設定
  2. sshに関する設定
  3. サービスに関する設定
  4. ポートに関する設定
  5. ファイル改竄の検知
  6. アンチウィルス
  7. rootkit検出

今回は、4.ポートに関する設定についてです。

4.ポートに関する設定

4.1.不要なポートへのアクセス制御

不要なポートを閉じてしまうことで、侵入経路を減らすことができるという設定です。iptablesというLinuxに実装されているパケットフィルタリング型のファイアウォール機能で、パケットフィルタリングルールやアドレス変換ルールを適用することができます。

下記のように、コマンドを実行することで設定することができます。コマンドをシェルファイルにまとめて記述して実行して設定した方が間違いが少なくなりますし、設定作業が楽にできます。

 

iptablesコマンドの確認

iptables -h

 

設定されているルールの確認

iptables -L

 

設定されている個別ルールを全て削除

iptables -F

シェルファイルによる設定例

 

iptables設定シェルを作成する。

vi iptables_setup.sh

#!/bin/sh
#インターフェース名
LANIF=eth0 ←ご使用の環境に合わせてインターフェース名を設定して下さい。
#ネットマスク取得(内部ネットワーク)
LOCAL_NET_MASK='ifconfig $LANIF|sed -e 's/^.*Mask:\([^ ]*\)$/\1/p' -e d`
#ネットワークアドレス取得(内部ネットワーク)
LOCAL_NET_ADDR=`netstat -rn|grep $LANIF|grep $LOCAL_NET_MASK|cut -f1 -d' '`
LOCAL_NET=$LOCAL_NET_ADDR/$LOCAL_NET_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
# TCP SYN Flood攻撃対策
# SYN Cookies:有効
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
# Smurf攻撃対策
# ブロードキャストアドレス宛のping応答を拒否
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 $LOCAL_NET -p tcp -m multiport --dports 135,137,138,139,445 -j DROP
iptables -A INPUT ! -s $LOCAL_NET -p udp -m multiport --dports 135,137,138,139,445 -j DROP
iptables -A OUTPUT ! -d $LOCAL_NET -p tcp -m multiport --sports 135,137,138,139,445 -j DROP
iptables -A OUTPUT ! -d $LOCAL_NET -p udp -m multiport --sports 135,137,138,139,445 -j DROP
# Ping of Death攻撃対策
# 1秒間に4回を超えるpingをログに記録して破棄
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
# メールサーバ等のレスポンス低下防止
# IDENT(113番ポート)アクセス応答拒否
iptables -A INPUT -p tcp --dport 113 -j REJECT --reject-with tcp-reset
# 指定国のIPアドレスからのアクセス許可をするユーザー定義の作成
ACCEPT_COUNTRY(){
  for addr in `cat /tmp/cidr.txt|grep ^$1|awk '{print $2}'`
    do
      iptables -A ACCEPT_COUNTRY -s $addr -j ACCEPT
  done
}
# 指定国のIPアドレスからのアクセス破棄をするユーザー定義の作成
DROP_COUNTRY(){
  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_iplistget
IP_LIST_GET
# 日本からのアクセス許可をするユーザー定義の作成
iptables -N ACCEPT_COUNTRY
ACCEPT_COUNTRY_MAKE JP
# 以降、日本からのアクセスのみ許可したい場合、ACCEPT_COUNTRYを指定
# 攻撃元になることが多い中国、台湾、ロシアからのアクセスをログに記録して破棄
iptables -N DROP_COUNTRY
DROP_COUNTRY_MAKE CN
DROP_COUNTRY_MAKE TW
DROP_COUNTRY_MAKE RU
iptables -A INPUT -j DROP_COUNTRY
# 各種サービスを公開設定
# 外部からSSH(TCP22番ポート)アクセス:日本からのみ許可
iptables -A INPUT -p tcp --dport 22 -j ACCEPT_COUNTRY
# 外部からHTTP(TCP80番ポート)アクセス:許可
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# 外部からHTTPS(TCP443番ポート)アクセス:許可
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 拒否IPアドレスのアクセスはログに記録せず破棄
# 拒否IPアドレスは/root/deny_ipに1行ごとに記述
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

 

再起動時に設定が有効となるようにファイアウォールのルールを保存する。
iptables save

 

ファイアウォールを起動する。
iptables start

 

IPアドレスリスト取得関数を作成する。

vi iptables_iplistget

# IPアドレスリスト取得
IP_LIST_GET(){
  # 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 found backup!! | mail -s $0 root
      return
    else
      # バックアップがないことをroot宛にメール通知して処理終了
      echo cidr.txt not found!! |mail -s $0 root
      exit 1
    fi
  fi
  # 最新版のIPアドレスリストをバックアップ
  /bin/mv cidr.txt /tmp/cidr.txt
}

 

IPアドレスリストチェックシェルを作成する。

vi /etc/cron.daily/iplist_check.sh

#!/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# 新旧IPアドレスリストの差分チェック件数(0指定はチェックなし)
# 新旧IPアドレスリストの差分チェック件数がSABUNで指定した件数を越える場合iptables設定スクリプトを実行しない
SABUN=9999
[ $# -ne 0 ] && SABUN=${1}
# チェック国コード
COUNTRY_CODE='JP CN TW RU'
# iptables設定シェルパス
IP_TABLES_PATH=/root/iptables_setup.sh
# IPアドレス取得関数
. /root/iptables_iplistget
# IPアドレスリスト最新化
rm -f IP_LIST.new
IP_LIST_GET
for country in $COUNTRY_CODE
  do
    if [ -f /tmp/cidr.txt ]; then
      grep ^$country /tmp/cidr.txt >> IP_LIST.new
    else
      grep ^$country /tmp/IP_LIST >> IP_LIST.new
    fi
done
[ ! -f /tmp/IP_LIST ] && cp IP_LIST.new /tmp/IP_LIST
# IPアドレスリスト更新チェック
diff -q /tmp/IP_LIST IP_LIST.new > /dev/null 2>&1
if [ $? -ne 0 ]; then
  if [ ${SABUN} -ne 0 ]; then
    if [ $(diff /tmp/IP_LIST IP_LIST.new | egrep -c '<|>') -gt ${SABUN} ]; then
      (
      diff /tmp/IP_LIST IP_LIST.new
      echo
      echo "$IP_TABLES_PATH not executed."
      ) | mail -s 'IP_LIST UPDATE' root
      rm -f IP_LIST.new
     exit
    fi
  fi
  /bin/mv IP_LIST.new /tmp/IP_LIST
  sh $IP_TABLES_PATH > /dev/null
else
  rm -f IP_LIST.new
fi

 

IPアドレスリストチェックシェルに実行権限を付与する。

chmod 700 /etc/cron.daily/iplist_check.sh

 

iptables設定シェルを実行する。

sh iptables_setup.sh

 

ファイアウォールをシステム起動時に起動するサービスに登録する。

chkconfig iptables on

 

 

 

コメント