やーまんぶろぐ

気が向いた時にだけ書くブログ

SendGridでメール受信するときにドメイン名でアクセス制限する方法 Nginx lua編

以前、SendGridのメール受信方法について書きました。
yamano3201.hatenablog.jp

AWSのSecurityGroupではIP単位でしかアクセス制限できないので、SendGridなどクライアントのIPがアクセスのたびに変わるようなサービスの場合アクセス制限ができません。

SendGridのクライアントのIPをいくつか逆引きすると、ドメイン名に規則性があることがわかりますので、ドメイン名でアクセス制限できないか調べることにしました。

最初は、reverse DNS を使おうと思いましたが、luaで書きました。

Nginx lua

Nginx luaの構築は割愛します。

SendGridはメールの内容をHTTPで受信することになるので、Nginxの設定でパスを用意します。

location /mail {
  access_by_lua_file /etc/nginx/conf/scripts/lib/mail.lua;
}

続いてluaファイルを用意します。ここでドメイン名でのアクセス制限を行います。
ここではロジックの部分しか書いてないので、ドメイン名が異なる場合の処理やレスポンスなどは別途考えましょう。

conf/scripts/lib/mail.lua

if ngx.re.match(ngx.var.uri, "/mail") then
   client_ip = ngx.var.remote_addr
   local handle = io.popen("dig -x " ..client_ip .." +short | tr -d '\n'")
   local domain_name = handle:read("*a")
   handle:close()

   if string.match(domain_name, "mail.sendgrid.net.$") then
      local handle2 = io.popen("dig " ..domain_name .." +short | tr -d '\n'")
      local check_ip = handle2:read("*a")
      handle2:close()

      if string.match(client_ip, check_ip) then
         ngx.say("OK")
      end
   end
end

luaの復習

luaは2, 3年ぶりに触ったので、文法から調べながら書きました。
とりあえず使った分だけメモしておきます。

ngx.var

ngx.var でnginx.confの中でsetされた値にアクセスすることができます。
ここではuriには/mailが、remote_addrにはクライアントのIPが入っています。
qiita.com

io.popen

io.popenでlinuxコマンドを実行して、結果を取得することができます。
qiita.com

string.match

文字列の比較ができます。正規表現で書けます。
aoikujira.com

テーブルから文字列変換

上のコードには書いていませんが、テーブルから文字列変換がデバッグのときに役立ちました。
http://www.lifeaether.com/overtaker/blog/?p=883www.lifeaether.com

最後に

これでドメイン名でのアクセス制限ができました。SendGridだけじゃなくクライアントのIPが変わるときは使えるのかなと思います。

別記事で書いた、Let's Encryptのドメイン認証のときにも使えそうです。
yamano3201.hatenablog.jp

実際にメールを受け取ったあとの処理もluaで書いてみようと思います。
その前にluaの復習からですね。

Programming in Lua プログラミング言語Lua公式解説書

Programming in Lua プログラミング言語Lua公式解説書


気が向いたら、また書きます。