2011/02/24(木)これぐらいやっとけ ~Linuxサーバのセキュリティ設定~

管理中のサーバで行っているセキュリティ設定を公開します。本当はこういうことを公開するのはよろしくないのですが、脆弱サーバが氾濫している現状そこが踏み台となってsshアタックされるのも迷惑極まりないので、最低限やっとけという内容でまとめました。*1

はてブさん #の切り分けやめてくれないかな……。

*1 : 国内サーバからもよくアタックがやってくる。会社のサーバとか「おたくクラックされてますよ」とメールしても返事すらないのが現状。

起動サービスと概要

  • Apache (www)
  • sshd
  • smtp/pop
  • bind (DNS)
  • ntpd

いくつかの注意点。

  • sftpで十分なのでftpdは使わないWinSCP等を使えばffftpに依存する必要はない。*2
  • sshで十分なのでtelnetdは間違っても使わない。
  • データベース等のサービスは外部公開する必要はないので、そもそもポート開けない。*3
  • ntpサービスを外に公開せず、外部ntpサーバに同期するのみならば、udp/ntpポート開放は不要。

*2 : それに、ffftpは光回線で小さいファイルを大量に転送すると不安定。

*3 : サーバ側の設定で、外向きIPをそもそもbindしない。

iptables/Firewallの設定

Debian系の場合は /etc/network/if-pre-up.d/iptables というスクリプトファイルを作成します。ディストリにより作成場所は色々ですが、面倒くさいので /etc にシンボリックリンクを張ります。

# ln -s /etc/network/if-pre-up.d/iptables /etc/iptables

ファイルを書き換えるたびに、このファイルを実行してください。

# /etc/iptables

iptablesの中身

#!/bin/sh

iptables -F
iptables -F -nat
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

#---------------------------------------------------------------------------
# コネクション済のパケットを通過させる
#---------------------------------------------------------------------------
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#---------------------------------------------------------------------------
# pingに応答させる。pingに応答させないならコメントアウト
#---------------------------------------------------------------------------
iptables -A INPUT -p icmp -j ACCEPT

#---------------------------------------------------------------------------
# ローカルネットワークからの接続を許可する
#---------------------------------------------------------------------------
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.0.0/16 -j ACCEPT
iptables -A INPUT -p udp -s 192.168.0.0/16 -j ACCEPT

#---------------------------------------------------------------------------
# 他の所有サーバや決まった出先など、
# 特別に許可するネットワークをIPで指定する
#---------------------------------------------------------------------------
iptables -A INPUT -p tcp -s 111.222.xxx.xxx -j ACCEPT

#---------------------------------------------------------------------------
# 過去にアタックしてきた等、既知の危険なホストを拒否する
#---------------------------------------------------------------------------
# 2009/02/07 DNS attack
iptables -A INPUT -s 89.149.221.182 -j DROP
# 2009/02/21 DNS attack
iptables -A INPUT -s 62.109.4.89 -j DROP

#---------------------------------------------------------------------------
# 外向きに公開するサービスのポートを空ける
# ここでは pop や ssh などのパスワード付サービスは開けない
#---------------------------------------------------------------------------
iptables -A INPUT -p udp --dport domain -j ACCEPT
iptables -A INPUT -p tcp --dport http -j ACCEPT
iptables -A INPUT -p tcp --dport https -j ACCEPT
iptables -A INPUT -p tcp --dport smtp -j ACCEPT
iptables -A INPUT -p tcp --dport submission -j ACCEPT

#---------------------------------------------------------------------------
# パスワード付サービスをアクセス回数制限付で空ける
# 以下は各IPごとに1時間に30回のアクセス制限
# (例)5/m:1分5回まで、10/h:1時間10回まで、30/d:1日30回まで
#---------------------------------------------------------------------------
iptables -A INPUT -p tcp --dport ssh  -m hashlimit --hashlimit-name ssh --hashlimit 30/h --hashlimit-burst 10 --hashlimit-mode srcip -j ACCEPT
iptables -A INPUT -p tcp --dport pop3 -m hashlimit --hashlimit-name pop --hashlimit 30/h --hashlimit-burst 10 --hashlimit-mode srcip -j ACCEPT
  • 無用なポートは絶対に開けない
  • 信頼できるIPからの接続は無条件許可する。
  • パスワード付サービスは時間あたりの接続数を制限する。

サーバを運営すると辞書およびブルートフォースアタック(総当り)により、有効なID/Passwordを探索するアタックが無数にやってきます。実際これによりあちこちのサーバがクラックされているのが現状です。最低でもsshにはlimit-burstによる接続回数制限をつけてください。

なお、IPだけの指定はIP偽装攻撃IP Spoofing/差出人を詐称)が成り立つため問題は残るのですが、やらないよりは大分マシです。

limit-burstについて

--limit 6/m --limit-burst 4

このように設定されていれば10秒に1回にアクセスを制限しますが、limit-burstにより連続4回までは10秒1回の制限を超えてアクセス可能になります。「limit-burst」に達したあとは10秒平均1回以下になるまで時間が経たないとアクセスできなくなります。

例えば「--limit-burst 1」と指定すれば、完全に10秒に1回しかアクセスできなくなります。

hashlimitについて

コメント欄で指摘いただいたのですが、limit-burstではあらゆるところからの接続を同一に扱うため、アタックを受けている最中は管理者でも接続不能となります。ですのでIPごとに接続回数をカウントする「hashlimit」を使用した例を掲示しています。

# limit-burst
iptables -A INPUT -p tcp --dport pop3 -m limit --limit 12/h --limit-burst 10 -j ACCEPT
# hashlimit-burst
iptables -A INPUT -p tcp --dport ssh  -m hashlimit --hashlimit-name ssh --hashlimit 12/h --hashlimit-burst 10 --hashlimit-mode srcip -j ACCEPT

基本的には limit が hashlimit に書き変わるだけですが「--hashlimit-name」として適当なハッシュテーブル名を付けることがポイントです。サービス名と同じで問題ないと思います。

2015/05/08追記。「--hashlimit-mode srcip」を必ず付けてください。接続元で区別するという指定です。これを付けないと「hashlimit」はほとんど「limit」と同じ動作をしてしまいます。

hosts.allow/hosts.deny(TCP Wrapper)の設定

iptables だけで済ませずTCP Wrapperも設定しておきます。iptablesがパケットレベルのフィルタであるのに対し、TCP Wrapperはサービスソフトウェア側の実装です。ですので、ApacheやpostfixやdovecotのようにTCP Wrapperに対応していないソフトでは設定しても意味がありません

なお書き換え後にサービスの再起動は不要です。書き換え後に新たにアクセスがあったときに新しい設定が参照されます。*4

# hosts.deny
ALL : ALL
# hosts.allow
ALL : 111.222.xxx.xxx 211.xxx.xxx.xxx
ALL : 192.168.1.

sshd : .jp EXCEPT 219.117.209.7 59.106.23.215

特別なIPに全アクセスを許可し、sshアタックを防ぐためsshdに対し .jp 以外からのアクセスを拒否しています。

EXCEPT より右側はスペース区切りで複数のホストやIPを書くことができます。.jpでありながら、過去にアタックしてきたホストを書くようにしていますが、通常はそこまでしなくてもいいでしょう。

.jp以外にアクセスするドメインがあるときは、それを個別に追加するほうが良いです。

sshd : .jp example.com example.net

ここまでするのは神経質と思われるかもしれませんが、毎日のように無数のsshアタックを受けていますのでやり過ぎということはありません。この中には国内サーバも多数あります。既にsshアタックにより攻略されたサーバが踏み台にされていると想像されます。

sshで入られるということはサーバ自体乗っ取られたのとほぼ等価です。大したデータがないし破壊もされてないから構わないと考えるアホ業者が結構いますが、そこが新たな汚染源となってネットに大量の迷惑をまき散らしていることを自覚してほしいものです。*5

*4 : 既にコネクションされているアクセスには何の効果もありません。

*5 : こういう脆弱サーバを平気で納品する業者が山のようにいるので本当に頭がいたい。

sshdの設定

sshdの設定で特に注意したいとことのみ抜粋。

# /etc/ssh/sshd_config
# ssh2のみ使用する
Protocol 2
# Rootログインを許可しない
PermitRootLogin no
# 空パスワードを許可しない
PermitEmptyPasswords no

本当はパスワードログインを不許可にし公開鍵ログインのみを許可するべきですが、よく分からない人は上の設定までで。

公開鍵ログインが分かる人は下も設定しましょう。

# 公開鍵ログインを許可する
PubkeyAuthentication Yes
# パスワードログインを許可しない
PasswordAuthentication no
# チャレンジレスポンスログインを許可しない
# (パスワードログインと似たようなもの)
ChallengeResponseAuthentication no

その他の設定

攻撃者に余計な情報を与えないため、Version情報などを秘匿します。もちろん隠したところで脆弱性があれば突かれるのですが、見た瞬間に攻略方法が分かるのではなく、調べないと攻略方法が分からないって程度になります。

Apacheの設定

# レスポンスヘッダにVersion等を表示しない
ServerTokens ProductOnly
# エラーページにApacheの情報を付けない
ServerSignature Off
# 下記参照
TraceEnable Off

TraceEnableはoffにしたほうがいいよとされています。詳しくはリンクを参照してください。

Postfixの設定

メールサーバにPostfixを使用している場合。

# /etc/postfix/main.cf
smtpd_banner = ESMTP unknown
disable_vrfy_command = yes

SMTPサーバ名や情報を表示しないようにします。

2行目は「ユーザーの存在問い合わせ」を無効にする設定です。*6

Dovecotの設定

popによるパスワードアタックを防ぐため、メールパスワードを独立に設定しています。詳しくは「Postfix/Dovecot on Ubuntu で SMTP Auth の設定」を参照。

*6 : コメント欄にて教えて頂きました。感謝します。

まとめ

これだけやれば完璧というわけではありませんし、セキュリティ設定に完璧なんてありませんが、最低限これぐらいはという部分でまとめました。

あとはマメなアップデートを心がけてください。Debianならば次のコマンドです。

# apt-get update
# apt-get upgrade