2011/02/24(木)これぐらいやっとけ ~Linuxサーバのセキュリティ設定~
管理中のサーバで行っているセキュリティ設定を公開します。本当はこういうことを公開するのはよろしくないのですが、脆弱サーバが氾濫している現状そこが踏み台となってsshアタックされるのも迷惑極まりないので、最低限やっとけという内容でまとめました。*1
起動サービスと概要
- Apache (www)
- sshd
- smtp/pop
- bind (DNS)
- ntpd
いくつかの注意点。
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
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 の設定」を参照。
まとめ
これだけやれば完璧というわけではありませんし、セキュリティ設定に完璧なんてありませんが、最低限これぐらいはという部分でまとめました。
あとはマメなアップデートを心がけてください。Debianならば次のコマンドです。
# apt-get update # apt-get upgrade