HTTPサーバのログ解析からアタックを検出する簡易ツールを作ってみた

Webサイトを運用しているとアタックや如何わしいアクセスを調べたいときがあります。簡単にHTTPサーバのアクセスログから短い間隔で大量にアクセスしているホストを、諸々のコマンドで操作するのは面倒なので、簡単に検出できるツールがあると便利です。 探してみたところ簡単に扱えそうなものがなかったので、Rubyベースで作ってみました。 Detect HTTP Attack https://github.com/tilfin/detect-http-attack Ruby 1.9 系で動きます。依存するライブラリはないので、直ぐにコマンドラインで実行できます。標準入出力で処理しているのシェルのパイプラインに組み合わせることができます。 準備 $ git clone https://github.com/tilfin/detect-http-attack.git $ cd detect-http-attack $ ./detect_http_attack.rb --help Usage: detect_http_attack [options] -ltsv Log type is LTSV -n notify when detecting attack -s COUNT Specify minimum sequential count -i SECONDS Specify maximum interval seconds -f CONFFILE Specify configuration file 対応するログフォーマット Apache, Nginx Combined Log (Common Logもそのまま無いフィールドが空になる) LTSV format (引数に -ltsv を付加) http://ltsv.org/ 使い方 引数で検出する最大のアクセス間隔(秒)と、その間隔で連続した回数を引数で渡すと、それに適合するアクセスを標準出力します。 例えば、2秒以内の間隔で5回以上連続でアクセスがあった場合を検出するときは次のようにします。(デフォルトは3秒以内の間隔で8回以上連続で検出) ./detect-http-attack.rb -s 2 -i 5 < /var/log/apache/access_log 10.128.192.255 7 Mozilla/3.0 (windows) 2012-12-20T08:25:28+09:00 200 /admin/phpmyadmin/scripts/setup.php - 2012-12-20T08:25:28+09:00 200 /wp-content/plugins/wp-phpmyadmin/phpmyadmin/scripts/setup.php - 2012-12-20T08:25:28+09:00 200 /mysql/scripts/setup.php - 2012-12-20T08:25:28+09:00 200 /phpmyadmin2/scripts/setup.php - 2012-12-20T08:25:28+09:00 200 /pma/scripts/setup.php - 2012-12-20T08:25:28+09:00 200 /phpmyadmin/scripts/setup.php - 2012-12-20T08:25:28+09:00 200 /myadmin/scripts/setup.php - 2012-12-20T08:25:28+09:00 200 /phpMyAdmin/scripts/setup.php - 通常は、ホストごとにブロックで出力しますが、-n フラグを付けると標準エラーに検出したアクセス毎に出力します。ターミナルで下記のように実行すれば、検出したアタックを適宜表示しつつ、まとめた結果をファイルに書き出すことができます。 ...

2013年2月12日 · Toshimitsu Takahashi

Ubuntu 12.04 に Redmine 2.0.3 を構築した時の Apache + Passenger の設定

Ruby 1.9 で Passenger を動かすために試行錯誤したのでメモしておく。基本的には、アップグレード — Redmine Guide 日本語訳 などを参考にする。 Passenger のインストール $ sudo apt-get install libcurl4-openssl-dev $ sudo apt-get install apache2-prefork-dev $ sudo gem1.9.1 install passenger $ cd /var/lib/gems/1.9.1/gems/passenger-3.0.13 $ sudo ./passenger-install-apache2-module Apache + Passenger の設定 /etc/apache2/mods-available/passenger.load LoadModule passenger_module /var/lib/gems/1.9.1/gems/passenger-3.0.13/ext/apache2/mod_passenger.so #LoadModule passenger_module /usr/lib/apache2/modules/mod_passenger.so /etc/apache2/mods-available/passenger.conf PassengerRoot /var/lib/gems/1.9.1/gems/passenger-3.0.13 PassengerRuby /usr/bin/ruby1.9.1 #PassengerRoot /usr #PassengerRuby /usr/bin/ruby PassengerDefaultUser www-data VirtualHostの設定 $ ln -s /web/example.local/redmine /web/redmine-2.0.3 上記のようにシンボリックリンクが張ってある。 <VirtualHost *:80> ServerName example.local DocumentRoot /web/example.local RailsBaseURI /redmine <Directory /web/example.local/redmine/public> PassengerAppRoot /web/redmine-2.0.3 ...

2012年8月3日 · Toshimitsu Takahashi

WordPress をフロント Nginx のリバースプロキシ下で運用する場合に 管理画面を SSL に強制する設定

Nginx をフロントにおいて高速化するのは常套手段ですが、そのときに WordPress の wp-admin(管理画面)は SSL を有効にしたいときの設定方法です。 Nginx の設定 # HTTP server # server { listen 80; location / { proxy_redirect off; proxy\_set\_header Host $host; proxy\_set\_header X-Real-IP $remote_addr; proxy\_set\_header X-Forwarded-Host $host; proxy\_set\_header X-Forwarded-Server $host; proxy\_set\_header X-Forwarded-For $proxy\_add\_x\_forwarded\_for; proxy_pass http://127.0.0.1:8080/; } } \# HTTPS server # server { listen 443; ssl on; ssl_certificate ssl/cert.pem; ssl\_certificate\_key ssl/cert.key; ssl\_session\_timeout 5m; ssl_protocols SSLv2 SSLv3 TLSv1; ssl_ciphers HIGH:!aNULL:!MD5; ssl\_prefer\_server_ciphers on; location / { proxy_redirect off; proxy\_set\_header Host $host; proxy\_set\_header X-Real-IP $remote_addr; proxy\_set\_header X-Forwarded-Proto https; proxy\_set\_header X-Forwarded-Host $host; proxy\_set\_header X-Forwarded-Server $host; proxy\_set\_header X-Forwarded-For $proxy\_add\_x\_forwarded\_for; proxy_pass http://127.0.0.1:8080/; } } 環境変数 HTTP_X_FORWARDED_PROTO を使って Nginx が受けたのは http か https かを後ろのサービスに伝えます。 ...

2012年5月7日 · Toshimitsu Takahashi

Ubuntu で Apache 2.2 でマルチドメイン SSL を設定するには

マルチドメインSSL証明書は本来IPアドレスごとに1FQDNだった SSL ホストを、1IPアドレスで複数のFQDNに対応させるものです。 要するにhttpsでも名前ベースのバーチャルホストが使えるようになります。 Apache 2.2.12 以降で SNI(Server Name Indication)という SSLプロトコルに対する拡張機能がサポートされ、そのモジュールが mod_gnutls になります。 ただ Server Name Indication - Wikipedia, the free encyclopedia にある通り、SNI は Windows XP の IE ではサポートされないなど、まだまだ一般的使うには早そうです。 今回、さくら VPS サーバの Ubuntu 上でセットアップしたのでまとめておきます。 mod_gnutls をインストール・適用 # apt-get install libapache2-mod-gnutls # a2enmod gnutls /etc/apache2/ports.conf を編集 mod_ssl は一応コメントアウト、mod_gnutil を有効にする。SSLStrictSNIVHostCheck はSNIに未対応のブラウザがデフォルトのCommon Nameを参照するように off にする。 #<IfModule mod_ssl.c> # # If you add NameVirtualHost *:443 here, you will also have to change # # the VirtualHost statement in /etc/apache2/sites-available/default-ssl # # to <VirtualHost *:443> # # Server Name Indication for SSL named virtual hosts is currently not # # supported by MSIE on Windows XP. # NameVirtualHost *:443 # Listen 443 #</IfModule> <IfModule mod_gnutls.c> Listen 443 NameVirtualHost *:443 SSLStrictSNIVHostCheck off </IfModule> サイトの設定 デフォルトを無効にして、それぞれのサイト定義ファイルを作りSSLの設定を各VirtualHost内に定義します。パスは共通の証明書なので同じなります。 ...

2011年2月24日 · Toshimitsu Takahashi

WordPress の wp-content に SELinux で httpd に書き込み生成権限を与えるには

WordPress のテーマファイルやプラグイン、アップロードしたファイルの置き場所は wp-content ディレクトリ以下になる。 ここに対して、httpd (Apache) で書き込み生成権限を付加する必要がある。その SELinux の設定についてのメモ。 権限の確認 httpd_t のエントリーを見てみると、タイプ httpd_cache_t がファイル、ディレクトリ、シンボリックリンクともに読み書き作成権限が付加されている。 # sesearch --allow -s httpd_t allow httpd_t httpd_cache_t : file { ioctl read write create getattr setattr lock append unlink link rename }; allow httpd_t httpd_cache_t : dir { ioctl read write create getattr setattr lock unlink link rename add_name remove_name reparent search rmdir }; allow httpd_t httpd_cache_t : lnk_file { read create getattr setattr unlink link rename }; コンテキストを変更 wp-content 以下に httpd_cache_t を設定する。 ...

2009年5月31日 · Toshimitsu Takahashi

Apache WebDAV + SVN で LDAP 認証を設定する

CentOS で LDAP 認証サービスを立ち上げたので、Subversion リポジトリの認証も LDAP で行うようにしたメモ。 LDAPサーバ: ldap.example.com 検索対象(ユーザーのOU): ou=People,dc=example,dc=com httpd.conf 下記のLimitExcept の部分が認証設定。 LoadModule dav\_svn\_module modules/mod\_dav\_svn.so LoadModule authz\_svn\_module modules/mod\_authz\_svn.so <Location /svn> DAV svn SVNParentPath /var/svn SVNListParentPath on <LimitExcept GET PROPFIND OPTIONS REPORT> AuthType Basic AuthBasicProvider ldap AuthName "SVN Repo Authentication" AuthzLDAPAuthoritative off AuthLDAPURL ldap://ldap.example.com/ou=People,dc=example,dc=com?uid Require valid-user </LimitExcept> </Location>

2009年5月9日 · Toshimitsu Takahashi

WordPress のフィード配信を 410 Gone にするには

WordPress の RSS, Atom フィードの URL は /feed/rss, /feed/atom/ など /feed/ 以下にある。 mod_rewrite で /feed/ 以下を 410 Gone にして、フィードが配信されなくなったことを知らせてみる。 .htaccess RewriteRule ^feed/.*$ - \[G,L\] ※きちんと解釈してくれるかどうかはその FeedFetcher による。

2009年3月6日 · Toshimitsu Takahashi

HTTP サーバのレスポンスヘッダは Firefox の Live HTTP headers よりも wget -S の方が詳しく取れる

#!/usr/bin/ruby print “Content-Type:application/xhtml+xml\r\n” print “Content-Type:text/plain\r\n\r\n” print «EOF Test for How to deal Content-Type EOF たとえば上記のようにわざと Content-Type を二重に出力してしまうと、Apache はバリデートで後者のみがクライアントに返されるが、lighttpd はそのまま二重定義で返してしまう。 これを確認するために、Firefox の Live HTTP headers を使ってレスポンスヘッダを見ても、下記のように Content-Type はどちらも1つしかない。lighttpd の前記の動作を確認することはできない。 Firefox Live HTTP headers Apache HTTP/1.x 200 OK Date: Fri, 12 Dec 2008 15:23:14 GMT Server: Apache/2.2.3 (CentOS) Content-Length: 34 Connection: close Content-Type: text/plain; charset=UTF-8 lighttpd HTTP/1.x 200 OK Transfer-Encoding: chunked Content-Type: text/plain Date: Fri, 12 Dec 2008 15:23:55 GMT Server: lighttpd/1.4.20 wget -S 今度は wget -S オプションで server response を見るようにしてみると、lighttpd の方は Content-Type がそのまま二重に出力されていることが確認できた。 ...

2008年12月12日 · Toshimitsu Takahashi

Apache 2.2 のロードバランスでセッション毎にワーカーのパーシステンスを図るには

mod_proxy_balancer では、単純に stickysession の値をマッピングをしてくれるわけではないことが http://www.res-system.com/weblog/item/618 をみてわかった。 そこで、 http://d.hatena.ne.jp/tagomoris/20070717/1184671767 を参考にして、とにかくルートを持つ値をクッキーにセットすることにした。 フロントエンド バランサ側の設定を下記のようにする。 ProxyRequests Off ProxyPass / balancer://cluster/ stickysession=RWORKER ProxyPassReverse / http://worker1:8081/ ProxyPassReverse / http://worker2:8081/ <Proxy balancer://cluster/> BalancerMember http://worker1:8081/ route=worker1 BalancerMember http://worker2:8081/ route=worker2 </Proxy> バックエンド リクエストヘッダに RWORKER があるかどうかを判別してなければ付加するようにバックエンド側の Apache 設定を worker1 では SetEnvIf Cookie “RWORKER=[^;]+” HAVA_RWORKER Header add Set-Cookie “RWORKER=route.worker1” env=!HAVA_RWORKER として、worker2 では SetEnvIf Cookie “RWORKER=[^;]+” HAVA_RWORKER Header add Set-Cookie “RWORKER=route.worker2” env=!HAVA_RWORKER とした。 stickysession は . 以降を route 値としてみる仕様なので、route.worker としている。 ちなみにバックエンドが Tomcat だったら jvmRoute でいけたらしい・・・。

2008年3月29日 · Toshimitsu Takahashi

mod_rewrite のメモ

Apache の Rewrite 機能で試してた設定をメモ書きしておく。 ある CGI から別の CGI を呼び出す /test/one.cgi?x=1&y=2… のようなリクエストを /another.cgi?x=1&y=2… と受けるには RewriteRule ^/test/one.cgi(.*)$ /another.cgi?$1 ではできない。URL引数はマッチ対象に含まれないためだ。%{QUERY_STRING} を渡せば良い。 RewriteEngine On RewriteRule ^/test/one.cgi$ /another.cgi?%{QUERY_STRING} とする。 CGI の引数を組み変えるには arg=xxxx,yyyy を user=xxxx&pass=yyyy としたい場合は RewriteEngine On RewriteCond %{QUERY_STRING} ^arg=(.),(.)$ RewriteRule ^/test/one.cgi$ /another.cgi?user=%1&pass=%2 とする。この場合は、arg=… という引数があるのが条件になっているので、付いていないとリライトは走らない。

2008年1月26日 · Toshimitsu Takahashi