Amazon EC2でDoS/DDoS攻撃をブロックする – iptables –
サーバーへの攻撃とは
ファイアウォールで公開しているポートに対して攻撃を受けたかどうか、みなさんはどのように判断していますでしょうか?実際のところ、たまにログを目視チェックしていれば良い方だと思います。実際のところ、攻撃されたことにも気付かず。。。そこで、今回は、連続して攻撃を受け"そうに"なった場合に、アクセス自体をブロックする方法をご紹介します。
DoS/DDoS攻撃とは
DoS(Denial of Service:サービス妨害)攻撃は、正常なサービスの運営を妨害する攻撃です。F5キーを押し続けて大量のリクエストをし続けてサーバーをパンクさせるとか、考えられる全てのパスワードをチャレンジする総当り攻撃などとても怖いです。また、単一のクライアントからの攻撃だけでなく、トロイの木馬で感染させられた大量の端末を用いて総攻撃を掛けるDDoS(Distributed Denial of Service:分散サービス妨害)攻撃は、十分と思われる対策が施された大手Webサイトもパンクするような攻撃力を持っています。
iptablesとは
iptablesは、パケットフィルタリングやNATを行うコマンドです。フィルタリングを行うテーブルと、どのタイミングで処理するかチェインによって構成されています。今回は、外部からのアクセスに対してフィルタしますので、filterテーブルのINPUTチェインにて記述をします。
パケットフィルタリングの例
Wikipediaの丸パクリですが、分かりやすいのでご紹介します。
$ sudo iptables -t filter -I INPUT -p tcp -s 123.123.123.123 --dport 80 -j DROP
- -t filter でfilterテーブルを操作
- -I INPUT でINPUTチェインに追加(-Iでチェイン内ルールの先頭に、-Aで末尾に)
- -p tcp でTCPプロトコル限定
- -s 123.123.123.123 で送信元IPアドレスを指定
- --dport 80 で 80番ポート(80/tcp = http)を指定
- 上記ルールにマッチしたパケットを-j DROPで破棄
まとめるとfilterテーブルのINPUTチェインの先頭に以下のルールを追加:IP 123.123.123.123から80/tcp(http)に入ろうとしているパケットは送信元(123.123.123.123)に通知することなく破棄(DROP)ということになります。
SSHへの総当り攻撃をブロックする
まず始めに、Amazon EC2は、SSH接続する際にパスワードによる認証を行っていませんので、総当り攻撃を食らっても突破されるには現状難しいと思います。SSHの部分をFTP等でパスワード認証で公開しているサービスに置き換えて頂いても構いません。総当り攻撃の判断ですが、「一定時間内に連続して接続をトライして失敗した接続元」と定義します。例えば、5分で10回の接続失敗等です。
それでは、「1分間に5回しか接続トライをできないようにする」シナリオで進めてみます。
$ sudo iptables -A INPUT -p tcp --syn --dport 22 -m recent --name ssh_attack --set $ sudo iptables -A INPUT -p tcp --syn --dport 22 -m recent --name ssh_attack --rcheck --seconds 60 --hitcount 5 -j LOG --log-prefix 'SSH attack: ' $ sudo iptables -A INPUT -p tcp --syn --dport 22 -m recent --name ssh_attack --rcheck --seconds 60 --hitcount 5 -j REJECT
設定を保存してiptablesを再起動します。
$ sudo service iptables save $ sudo service iptables restart
これで1分間以内に連続接続5回失敗すると6回目から接続自体を拒否します。ここで注意が必要です。REJECTではなくDROPを指定してしまうと、SSHクライアント側が再接続を繰り返すのでログが大量に残ります。REJECTして拒否を確定しましょう。接続拒否のログを見てみます。
$ sudo tail /var/log/messages Mar 21 17:13:59 ip-10-146-58-XXX kernel: [324156.136295] SSH attack: IN=eth0 OUT= MAC=12:31:50:00:39:a7:fe:ff:ff:ff:ff:ff:08:00 SRC=210.20.91.XXX DST=10.146.58.XXX LEN=48 TOS=0x00 PREC=0x00 TTL=52 ID=4878 DF PROTO=TCP SPT=52141 DPT=22 WINDOW=65535 RES=0x00 SYN URGP=0 Mar 21 17:14:16 ip-10-146-58-XXX kernel: [324172.659590] SSH attack: IN=eth0 OUT= MAC=12:31:50:00:39:a7:fe:ff:ff:ff:ff:ff:08:00 SRC=210.20.91.XXX DST=10.146.58.XXX LEN=48 TOS=0x00 PREC=0x00 TTL=52 ID=16997 DF PROTO=TCP SPT=52141 DPT=22 WINDOW=65535 RES=0x00 SYN URGP=0 Mar 21 17:15:31 ip-10-146-58-XXX kernel: [324248.328989] ip_tables: (C) 2000-2006 Netfilter Core Team Mar 21 17:16:11 ip-10-146-58-XXX kernel: [324287.695710] SSH attack: IN=eth0 OUT= MAC=12:31:50:00:39:a7:fe:ff:ff:ff:ff:ff:08:00 SRC=210.20.91.XXX DST=10.146.58.XXX LEN=64 TOS=0x00 PREC=0x00 TTL=53 ID=25633 DF PROTO=TCP SPT=52159 DPT=22 WINDOW=65535 RES=0x00 SYN URGP=0 Mar 21 17:16:20 ip-10-146-58-XXX kernel: [324296.344494] SSH attack: IN=eth0 OUT= MAC=12:31:50:00:39:a7:fe:ff:ff:ff:ff:ff:08:00 SRC=210.20.91.XXX DST=10.146.58.XXX LEN=64 TOS=0x00 PREC=0x00 TTL=52 ID=62724 DF PROTO=TCP SPT=52160 DPT=22 WINDOW=65535 RES=0x00 SYN URGP=0
messagesはsyslogの様々なメッセージが入ってきますので、iptablesのログを分けたいと思います。Amazon Linuxのログはrsyslogです。
$ sudo vi /etc/rsyslog.conf
iptables用の出力設定を追記します。以下のようにしてみてください。
# Save iptables messages to iptables.log kern.debug /var/log/iptables.log
rsyslogサービスを再起動します。ちゃんとログが分かれました!
$ sudo service rsyslog restart
Webサーバーへの総当り攻撃をブロックする
パスワードを入力する画面に対して総当り攻撃を行い突破する方法は最もポピュラーな攻撃です。これらの攻撃に対処するためにOWASP(The Open Web Application Security Project)では、いくつかの方法を紹介しています。様々な仕掛けでサーバーを守る必要がありますね。AWSが行っているセキュリティ施策がお手本だと思います。
- CAPTCHASを使ってプログラムによる自動ログイン/自動登録をさせないようにする。
- パスワード認証時にレスポンスに時間を掛ける。
- 同じIPからの繰り返し認証失敗時に接続拒否をする。
- 何回か連続してパスワード認証に失敗するとアカウントをロックする。
- ログインしたらそのセッションでは同じIPアドレスからのみ受け付ける。
- ランダムなシークレット質問に回答する。
- ユーザー毎にユニークなログインURLを用意する
WebサーバーへのHashdos攻撃をブロックする
今年に入って、Webサーバへの新たなDoS攻撃手法が出てきました。Hashdos攻撃というものです。HttpRequestにあるパケットを大量に送り続けることによりWebサーバーが数分程度高負荷になってしまう攻撃です。かなり簡単にDoS攻撃できてしまいます。PHPやTomcatでも最新バージョンのパッチでは対策が施されているようですが、運用中のアプリ環境を変えるのは気が引けます。そこで、WAFでどうにかしちゃいましょう。ModSecurityがインストール済みということで進めます。
$ sudo vi /etc/httpd/modsecurity.d/modsecurity_crs_10_config.conf
最後の行あたりのSecRuleEngine Onの次に追記します。
#for Hashdos SecRequestBodyAccess On SecResponseBodyAccess Off SecRequestBodyLimit 5242880 SecRequestBodyNoFilesLimit 51200 SecRequestBodyNoFilesLimit 51200 SecAuditEngine RelevantOnly SecAuditLogRelevantStatus "^(?:5|4(?!04))" SecAuditLogType Serial SecAuditLog /var/log/httpd/modsec_audit.log SecAuditLogParts "ABIFHKZ" SecDebugLog /var/log/httpd/modsec_debug.log SecDebugLogLevel 3 SecDataDir /var/modsecurity/data/ SecTmpDir /var/modsecurity/tmp/ SecUploadDir /var/modsecurity/upload/
httpdが読み込むModSecurityに関する設定ファイルを編集します。
$ sudo vi /etc/httpd/conf.d/mod_security.conf
CoreRuleSetをインクルードします。
Include modsecurity.d/modsecurity_crs_10_config.conf
最後にhttpdサービスを再起動します。
$ sudo service httpd restart
まとめ
iptablesによってパケットレベルの制御を行い、総当り攻撃を防ぐ事が出来ました。WAFによってHashdos攻撃を防ぐ事ができました。日曜プログラマな私も気がつけばパケットの流れやHTTPの中身を制御する番人になっていました。やればできる。いつやる?いまだよ。以上、CM進ハイスクールでしたw。今日から君もパケットの番人だ!
参照資料
iptables の ipt_recent で ssh の brute force attack 対策