私の戦闘力は53万です

awsとgcpについて書きます

AWS WAF 海外IPを拒否しGoogleのクローラ(bot)は許可する設定

AWS WAF 海外IPを拒否しGoogleのクローラ(bot)は許可する設定」を
することがありましたので設定時のメモとして書きます。
 

Googleのクローラの条件

まずは通すべき条件を調べました。
色々と細かい条件はあるようです。今回の私の要件は
User-Agentヘッダに「Googlebot」が含まれていれば
Googleのクローラとして見なしてOKだったので
そちらをGoogleクローラの条件としました。
 

海外IPアクセスの条件

AWS WAFはIPを国別で判断して許可・拒否することが可能です。
こちらはデフォルトの機能を利用します。

AWS WAFを設定 

 まず1つ目のCondition作成として「string and regex match」を選択します

f:id:remmemento:20191130144740p:plain



「Googlebot」をuser-agentヘッダに含む場合の条件を作成します。

f:id:remmemento:20191130144036p:plain

 

 

f:id:remmemento:20191130144230p:plain

上記のように入力しAdd filterボタンを押します。

 

 

 

f:id:remmemento:20191130144241p:plain

Filterに追加されたらCreateボタンを押します。

 

 

 

条件作成2個目

2つ目の条件は国別の制限をします。Geo matchを選択します。

f:id:remmemento:20191130144918p:plain

 

日本を登録します 

f:id:remmemento:20191130145158p:plain

ルール作成

上記で作成した条件を元にルールを作成します

f:id:remmemento:20191130145316p:plain

 

上記で作成した条件を設定します。

この時、WAFのデフォルトルールを

Allowにしたかったので下記のようにルールを設定しています。

f:id:remmemento:20191130143352p:plain

上記の意味が少し分かりにくいと思いますので掘り下げます。

条件の整理

私は条件の組合せを考えるときは
頭の中が混乱するので、極力ド・モルガンの法則をベースに考えています。
もっと良い方法があれば知りたいのですが、
こんな方法あるよ!という方いたらぜひコメントください。
 
 
例えば下記のように考えます。
A=「User-agentにGooglebotを含む」
B=「日本からのアクセス」
上記のルールはを意味します。
 
=「User-agentにGooglebotを含まない」かつ「日本からのアクセスでない」
=「User-agentにGooglebotを含まない」かつ「海外アクセスである」
となります。 
 
デフォルトの設定がAllow/Denyにより設定内容が異なるのですが、
今回はデフォルトをAllow(許可)にしています。
 
上記設定は下記のように動作します。
  • 「User-agentにGooglebotを含まない」かつ「海外アクセスである」場合ブロック
  • それ以外はAllow(許可)

 ド・モルガン風に考える

Blockの挙動を否定と置き換えて考えると
の否定(Block)なので、
ド・モルガンの法則の両辺を否定してみます。
すると、f:id:remmemento:20191130150433p:plainの否定はとイコールであることが導かれます。
は「User-agentにGooglebotを含む」または「日本からのアクセス」
許可するを意味していますので、意図した設定であることが分かります。

検証してみる

上記で設定したWAFを適当なCloudFrontに設定してアクセス確認してみます。
#国内IP(xx.xx.xx.xx)からかつuser-agentにGooglebotが含まれないアクセス → アクセス成功
<!DOCTYPE html>
<html lang="ja">
・・・・・・・・・・・・
#国内IP(xx.xx.xx.xx)からかつuser-agentにGooglebotが含まれるアクセス → アクセス成功
<!DOCTYPE html>
<html lang="ja">
・・・・・・・・・・・・
 
 
#whois yy.yy.yy.yy |grep City
City:           Seattle
City:           Singapore
 
#海外IP(yy.yy.yy.yy)からかつuser-agentにGooglebotが含まないアクセス → アクセス失敗
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>403 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Request blocked.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: OLTvH3ay52g-1i32HRmRi-XBxlGINEvGdBF5HGgUHt14Qe62zYIb6A==
</PRE>
<ADDRESS>
</ADDRESS>
</BODY></HTML>
 
 
#海外IP(yy.yy.yy.yy)からかつuser-agentにGooglebotが含まれるアクセス → アクセス成功
<!DOCTYPE html>
<html lang="ja">
・・・・・・・・・・・・
 上記から、
「海外IP(yy.yy.yy.yy)から」かつ「user-agentにGooglebotが含まない」アクセスのみが
拒否されていることが確認できました。

注意点

User-Agentのヘッダは上記の検証で実施しているように
なりすましが可能です。
そのため、より厳密に設定したい場合は、
例えば下記のような設定が追加で必要になってくるのかと思いました。
 
  1. WAFログを定期的に解析しアクセス元IPをDNSリバースルックアップ[※1]を実施
  2. なりすましのアクセス元IPを判定する
  3. 2のIPをWAFのIP拒否リストに設定する
[※1]
 
機会があれば試してみたいと思います!