ノードでユーザーのIPアドレスを確認する方法


349

コントローラ内から特定のリクエストのIPアドレスを確認するにはどうすればよいですか?例(エクスプレス):

app.post('/get/ip/address', function (req, res) {
    // need access to IP address here
})

22
Expressを使用している場合は、source-expressjs.comreq.ip
en

これを試してください:github.com/indutny/node-ip
Stephen Last

16
localhost私のように働いている人にとっては、以下のすべての答え(ほぼすべての答えがうまくいく)の結果が出るかもしれません::1。これは私をしばらく混乱させました。後で、それ::1が実際のIPアドレスでありIPV6、localhostの表記であることがわかりました。 Hope this helps someone
Pramesh Bajracharya 2018

回答:


452

あなたにはrequest、オブジェクトと呼ばれるプロパティがありconnectionあり、net.Socketオブジェクトが。net.SocketオブジェクトにはプロパティremoteAddressがあるため、次の呼び出しでIPを取得できるはずです。

request.connection.remoteAddress

httpおよびnetのドキュメントを参照してください

編集

@juandがコメントで指摘しているように、サーバーがプロキシの背後にある場合、リモートIPを取得する正しい方法は次のとおりです。 request.headers['x-forwarded-for']


6
これにより、whatismyip.comが提供するものとは異なるIPアドレスが得られます。なぜでしょうか?
Shamoon

3
APIサービスをno.deインスタンスにインストールしてます。私は自分のコンピュータからアクセスしようとすると私の本当の世界IPは「67.250.AAA.BBB」であるのに対し、私は「10.2.XXX.YYY」のIPアドレスを取得
Shamoon

7
それはrequest.headers ['X-Forwarded-For']
0x6A75616E

4
net.Streamがnet.Socketになり、ドキュメントはここにあります:nodejs.org/api/net.html#net_class_net_socket
monsur

4
:その興味を持って、Herokuのためのそれはだ誰のため request.headers['x-forwarded-for']
FueledPublishing

407
var ip = req.headers['x-forwarded-for'] || 
     req.connection.remoteAddress || 
     req.socket.remoteAddress ||
     (req.connection.socket ? req.connection.socket.remoteAddress : null);

で複数のIPアドレスを取得できる場合があることに注意してくださいreq.headers['x-forwarded-for']。また、x-forwarded-forヘッダーが常に設定されるとは限らないため、エラーがスローされる可能性があります。

フィールドの一般的な形式は次のとおりです。

x-forwarded-for: client, proxy1, proxy2, proxy3

ここで、値はコンマ+スペースで区切られたIPアドレスのリストで、左端が元のクライアント、リクエストを受け取った連続した各プロキシがリクエストを受け取ったIPアドレスを追加します。この例では、要求が通過proxy1proxy2その後、とproxy3proxy3リクエストのリモートアドレスとして表示されます。

これは、が設定されていない場合のコメントについて、Martinが以下で提案した修正を加えたArnav Guptaによって提案されたソリューションです。x-forwarded-for

var ip = (req.headers['x-forwarded-for'] || '').split(',').pop().trim() || 
         req.connection.remoteAddress || 
         req.socket.remoteAddress || 
         req.connection.socket.remoteAddress

9
これらのヘッダーのなりすましを防ぐ方法は?
ドミ2014年

8
これは通常はうまく機能しますが、何らかの理由で最近、「undefinedのプロパティ 'remoteAddress'を読み取れません」というエラーが発生しましたreq.connection.socket。なぜ/どのような状況が原因であるかはわかりませんreq.connection.socketが、これが発生した場合にサーバーがクラッシュしないように存在を確認することをお勧めします。
Matt Browne

9
最終行req.connection.socket.remoteAddressスローエラー。慎重に。
yAnTar 2014

11
返されるIPアドレスは:: 1です。どうして?
Bagusflyer 2016

3
pop()の動作を見ると、クライアントではなく、最後のプロキシを取得しようとしているようです。私が間違っている?
ミシェル


31

DRYのままで、IPv4IPv6の両方をサポートするノードIPウェアを使用できます

インストール:

npm install ipware

app.jsまたはミドルウェア:

var getIP = require('ipware')().get_ip;
app.use(function(req, res, next) {
    var ipInfo = getIP(req);
    console.log(ipInfo);
    // { clientIp: '127.0.0.1', clientIpRoutable: false }
    next();
});

ユーザーのIPアドレスを取得するために最善の試みを行うか、ユーザーのIPアドレスを127.0.0.1特定できなかったことを示すために戻ります。詳細オプションについては、READMEファイルを参照してください。


40
「または127.0.0.1を返し、ユーザーのIPアドレスを特定できなかったことを示します。」127.0.0.1とunknownの間にはかなり大きな違いがあります
Nepoxx

4
:ffff:(not my IP address)Herokuからテストしたところ、奇妙な結果が返ってきました。@ edmar-miyakeの答えは私には適切に機能しています。
Nilloc、2015

「x-forwarded-for」の場合にright2leftルックアップを使用するとしたら、IPはどうなるのでしょうか。var ip_info = get_ip(req、right_most_proxy = True)。一部の設定では、クライアントIPが最も適切なIPである可能性があります。
un33k 2015

2
その方法はclientIp: '::1'私に戻ってきました。動作しないようです。
JamEngulfer

@JamEngulfer-ipwareは、IPアドレスがrequest.headers []を介してアプリに適切に渡された場合にのみ機能します。例:AWS LBSはIPアドレスを「x-forwarded-for」で送信しますが、カスタムNginXの多くは他の変数を使用します。ipwareは、IPアドレスを特定するために最善の試みを行いますが、IPがヘッダーに渡されている場合のみです。
un33k 2016年

19

あなたは使用することができ、要求-IPをユーザのIPアドレスを取得するために、。それはかなりの数の異なるエッジケースを処理し、そのいくつかは他の回答で言及されています。

開示:このモジュールを作成しました

インストール:

npm install request-ip

アプリで:

var requestIp = require('request-ip');

// inside middleware handler
var ipMiddleware = function(req, res, next) {
    var clientIp = requestIp.getClientIp(req); // on localhost > 127.0.0.1
    next();
};

お役に立てれば


2
github.com/pbojinov/request-ip/blob/master/index.jsでパッケージrequest-ipのソースコードをチェックします。AWSELBやCloudflareなどの一般的なロードバランサーのx-forwarded-forやその他のヘッダーをチェックします。 、アカマイ、nginx、Rackspace LB、およびRiverbedのスティングレイ
Giorgio

1
それはnull私のために戻ります。
S.M_Emamian

代わりに同じものを使用request.headers['x-forwarded-for']
Prathamesh More

19

request.headers['x-forwarded-for'] || request.connection.remoteAddress

x-forwarded-forヘッダーがある場合はそれを使用し、それ以外の場合は.remoteAddressプロパティを使用します。

x-forwarded-forヘッダ用に設定ロードバランサ(またはプロキシの他のタイプ)を通過する要求に追加されるHTTPまたはHTTPS(それにバランスするときの要求にこのヘッダーを追加することも可能だTCPの使用レベルプロキシプロトコル)。これはrequest.connection.remoteAddress、プロパティにクライアントのパブリックIPアドレスではなく、ロードバランサーのプライベートIPアドレスが含まれるためです。上記の順序でORステートメントを使用することにより、x-forwarded-forヘッダーの存在を確認し、存在する場合はそれを使用しrequest.connection.remoteAddressます。それ以外の場合はを使用します。


12

以下の機能は、すべてのケースをカバーしています。

var ip;
if (req.headers['x-forwarded-for']) {
    ip = req.headers['x-forwarded-for'].split(",")[0];
} else if (req.connection && req.connection.remoteAddress) {
    ip = req.connection.remoteAddress;
} else {
    ip = req.ip;
}console.log("client IP is *********************" + ip);

ipsは, 私にとっては間にあることに注意してください。
ThomasReggi 2016年

8

IPアドレスを取得するには2つの方法があります。

  1. let ip = req.ip

  2. let ip = req.connection.remoteAddress;

しかし、上記のアプローチには問題があります。

Nginxまたは任意のプロキシの背後でアプリを実行している場合、すべてのIPアドレスはになります127.0.0.1

したがって、ユーザーのIPアドレスを取得するための最良の解決策は次のとおりです。

let ip = req.header('x-forwarded-for') || req.connection.remoteAddress;

6

Expressバージョン3.x以降を使用している場合は、信頼プロキシ設定(http://expressjs.com/api.html#trust.proxy.options.table)を使用でき、アドレスのチェーンをたどります。 x-forwarded-forヘッダーを使用して、信頼済みプロキシとして構成していないチェーン内の最新のIPをreqオブジェクトのipプロパティに配置します。


6

function getCallerIP(request) {
    var ip = request.headers['x-forwarded-for'] ||
        request.connection.remoteAddress ||
        request.socket.remoteAddress ||
        request.connection.socket.remoteAddress;
    ip = ip.split(',')[0];
    ip = ip.split(':').slice(-1); //in case the ip returned in a format: "::ffff:146.xxx.xxx.xxx"
    return ip;
}


1
文字列としてipが必要な場合は、最後の行を次のように置き換えることができます。ip= ip.split( ':')。slice(-1)[0]
Ahmad Agbaryah

コードのみの回答はお勧めしません。この回答が以前の、よりよく説明された、そして(はるかに)賛成された回答よりも優れていることを説明できますか?
Dan Dascalescu

5

警告:

重要なレート制限のためにこれを盲目的に使用しないでください。

let ip = request.headers['x-forwarded-for'].split(',')[0];

なりすましは非常に簡単です。

curl --header "X-Forwarded-For: 1.2.3.4" "https://example.com"

その場合、ユーザーの実際のIPアドレスは次のようになります。

let ip = request.headers['x-forwarded-for'].split(',')[1];

他の回答でこれについて言及していないことに私は驚いています。


トップの答えはでこれを処理しpop()することができ、インデックス1にある要素を取得するよりも一般的である配列、からINGのだまさcurl --header "X-Forwarded-For: 1.2.3.4, 5.6.7.8" "https://example.com"
Dan Dascalescu

3

複数のIPを取得した場合、これは私にとってはうまくいきます:

var ipaddress = (req.headers['x-forwarded-for'] || 
req.connection.remoteAddress || 
req.socket.remoteAddress || 
req.connection.socket.remoteAddress).split(",")[0];


3

nodejsでリモートIPを取得するだけ:

var ip = req.header('x-forwarded-for') || req.connection.remoteAddress;

3

nginxの背後にあるノード10.14では、次のようにnginxヘッダーを介してリクエストすることで、IPを取得できます。

proxy_set_header X-Real-IP $remote_addr;

次にapp.jsで:

app.set('trust proxy', true);

その後、表示したい場所に:

var userIp = req.header('X-Real-IP') || req.connection.remoteAddress;

2

私はこれが死への答えになっていることを理解していますが、airbnbベースのeslint標準に従って私が書いた最新のES6バージョンを次に示します。

const getIpAddressFromRequest = (request) => {
  let ipAddr = request.connection.remoteAddress;

  if (request.headers && request.headers['x-forwarded-for']) {
    [ipAddr] = request.headers['x-forwarded-for'].split(',');
  }

  return ipAddr;
};

X-Forwarded-Forヘッダーには、プロキシIPのコンマ区切りリストを含めることができます。順序はclient、proxy1、proxy2、...、proxyNです。現実の世界では、人々はこのヘッダーに必要なものを何でも提供できるプロキシを実装しています。ロードバランサーなどの背後にいる場合、少なくともリストの最初のIPは、少なくとも何らかの要求が通過したプロキシであることを信頼できます。


1

Graphql-Yogaを使用している場合は、次の関数を使用できます。

const getRequestIpAddress = (request) => {
    const requestIpAddress = request.request.headers['X-Forwarded-For'] || request.request.connection.remoteAddress
    if (!requestIpAddress) return null

    const ipv4 = new RegExp("(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")

    const [ipAddress] = requestIpAddress.match(ipv4)

    return ipAddress
}


-7

同じ問題がありました... imもjavascriptで新しくなりましたが、req.connection.remoteAddressでこれを解決しました。これにより、IPアドレス(ただしipv6形式:: ffff.192.168.0.101)が与えられ、次に.sliceによって最初の7桁が削除されます。

var ip = req.connection.remoteAddress;

if (ip.length < 15) 
{   
   ip = ip;
}
else
{
   var nyIP = ip.slice(7);
   ip = nyIP;
}

ipv6は7桁+ IPv4だけではなく、完全に異なる場合があるため、これは良い方法ではありません。
Radek、2016年

@Radekは、アドレスの開始を検証すると、仕様に準拠します(en.wikipedia.org/wiki/IPv6_address ctrl-f search for "IPv4-mapped"を参照)ip= (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):undefined))は、上記のコードのif ...を置き換えます
非同期

個人的にnpm request-ipからgetClientIp()をラップしてfunction getClientIp4(req){ var ip=typeof req==='string'?req:getClientIp(req); return (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):undefined)); }、以前にフェッチされたIPまたは要求オブジェクトのいずれかを入力として受け入れ、結果としてIPまたは未定義を与える
非同期の
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.