【Express + nginx】IPアドレスが「::ffff:127.0.0.1」しか取得できない!?

こんにちは。フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、Express開発を進めてきてはや数カ月が経ち、いくつも「できない → 解決」を体験してきました。

そしてそんな中でも、「うっ、、言われてみれば当たり前ですよね・・・」という内容があったのでここで備忘録的に記事をつくっておきたいと思います。

その内容は、というと・・・

ExpressでIPアドレスが 「::ffff:127.0.0.1」しか取得できない😫

というものです。

これは、Express + nginxで運用する場合のちょっとした罠(笑)のようなものなのですが、メインの開発を長年PHPでやってきた私は、きっちりこの罠にハマってしまいました。。

ということで、今回は皆さんが私のように罠にハマらないよう、Express + nginxでIPアドレスを取得する方法をご紹介します。

ぜひ皆さんのお役に立てると嬉しいです😊✨

※解決法に急ぐ場合 → 実際に解決する方法

開発環境: Node 8、Express 4.1、Ubuntu 18.04

何が原因なのか??

あるドメインでExpressを運用する場合、以下のようになっていると思います。

  1. ブラウザからアクセス
  2. nginx を中継
  3. Expressにアクセス

これは、Expressだけで起動すると、

http://localhost:5000

というURLになるので、ドメインを使う場合は、以下のようにExpressへ「転送」する処理が必要になってくるためです。

server {
    listen 80;
    server_name express.test;
    location / {
        proxy_pass http://localhost:5000;
     }
}

しかし、IPアドレスがうまく取得できない問題点はまさにここにあります。

つまり、PHPの場合はnginxが直接ウェブサーバーになりますが、Expressの場合は代理人としてアクセスするため、のままだとnginxのIPアドレスが取得されてしまうというわけです。

つまり、::ffff:127.0.0.1は、nginx(自分のサーバー)のことだったわけですね。

問題を解決する方法論

これまでは、nginxが代理人だったのでIPアドレスは「::ffff:127.0.0.1」で固定でしたが、nginxにはIPアドレスを変数として使える機能があります。

そのため、この変数を特定のヘッダーに追加することで、あたかもIPアドレスを「水バケツリレー」することができるわけです。

  1. ブラウザからアクセス
  2. nginx を中継(IPアドレスをヘッダーに追加)
  3. Express内で、そのヘッダーからIPアドレスを取得する

では、次からは実際の作業をご紹介します!

実際に解決する方法

ここからは実際にアクセスした人のIPアドレスを取得する方法をご説明します。

※私の環境はUbuntu 18.04ですが、CentOSなどを使っている場合はファイルのパスを適宜変更してください。

nginxのコンフィグを変更する

まず以下のコマンドでnginxの設定を変更します。

sudo vi /etc/nginx/sites-available/default

そして、「X-Forwarded-For」にIPアドレスをセットします。

server {
    listen 80;
    server_name express.test;
    location / {
        proxy_pass http://localhost:5000;
        proxy_set_header X-Forwarded-For $remote_addr;
     }
}

そして:wq!などで保存したら、以下のコマンドでnginxを再起動しましょう。

sudo systemctl restart nginx

これでnginx側の作業は完了です。

nginxから送信されたIPアドレスを取得する

続いてExpress側のコードです。

といっても、reqからヘッダー情報を取得するだけでOKです。

app.get('/ip', (req, res) => {

  const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
  res.send(ip);

});

なお、req.connection.remoteAddressは「x-forwarded-for」が存在しない(つまり、ドメイン以外でアクセスされた)場合の保険のようなものです。

そして、ドメイン以外のアクセスの場合、req.headers['x-forwarded-for']からIPアドレスを取得しようとしてもundefinedが返ってきます。

開発のご依頼お待ちしております
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします! by 九保すこひ

おわりに

ということで、今回は「Express + nginx」でIPアドレスが固定されてしまう場合の解決法をお届けしました。

冒頭でも書きましたが、nginxが間にはさまっているので、IPアドレスがうまく取得できないのも当然の話ですよね。やっぱり固定概念で動こうとすると罠にハマってしまいやすいです💦

私の場合、これのせいで数時間無駄にしてしまいましたが、この記事で皆さんの時間をショートカットさせることができたら嬉しいです。

ではでは〜!

このエントリーをはてなブックマークに追加       follow us in feedly