29

When saving data to Firebase database with a Firebase cloud function, I'd like to also write the IP address where the request comes from.

However, req.connection.remoteAddress always returns ::ffff:0.0.0.0. Is there a way to get the actual IP address of the client that makes the request?

tuomassalo
  • 8,133
  • 5
  • 43
  • 49
  • 1
    It looks as if you can no longer rely on x-forwarded-for. Try reading the fastly-client-ip. The other ip addresses seem to be google internal IP's – jqualls Jul 25 '18 at 07:50
  • 4 years and Google still no publishing any official documentation about it. It's crazy. – Broda Noel Jan 12 '22 at 05:31

6 Answers6

22

The clients IP is in request.ip.

Example:

export const pay = functions.https.onRequest((request, response) => {
  console.log(`My IP is ${request.ip}`);
});
Luke
  • 2,463
  • 1
  • 14
  • 15
  • 17
    When using Callable Functions (`functions.https.onCall((data, context) => {...})`), it's `context.rawRequest.ip` – sceee Jun 18 '20 at 07:59
  • 1
    Is it safe to use considering that its undocumented and could potentially be changed? – eozzy Sep 26 '20 at 23:56
  • 1
    @eozzy the documentation is at https://expressjs.com/en/guide/behind-proxies.html – Luke Oct 07 '20 at 07:09
  • 1
    I'm seeing undefined for context.rawRequest.ip - has this already been deprecated? – Stefan Feb 25 '21 at 16:49
  • 1
    @Stefan since I was probably the only one notified I thought I should test my example. The example still worked. I haven't looked at the onCall method but since request.ip still works so I would assume there is still a way to access the IP. Even if the IP address was deprecated in Firebase I would still think the ip would return a value. – Luke Feb 26 '21 at 00:57
  • 2
    Thanks Luke, ok my bad (but then again is it?) - I was using the emulator which is errrrm meant to emulate stuff. Turns out it contains only a few of the expected properties. For future readers, don't test thus locally. If you have an https.onCall then use `functions.logger.log(context.rawRequest.headers);` to see the wares. – Stefan Feb 26 '21 at 18:22
17

The IP address seems to be available in req.headers["x-forwarded-for"].
See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For

Note that if there are proxies in between the interim ip addresses are concatenated towards the end:

X-Forwarded-For: <client_ip>, <proxy_1 : actual-ip-as-seen-by-google> ...

Ujjwal Singh
  • 4,760
  • 3
  • 35
  • 53
tuomassalo
  • 8,133
  • 5
  • 43
  • 49
16

If you are looking for the client ip thru firebase hosting you should use the header fastly-client-ip there will be the real client ip.

Fernando Cheong
  • 218
  • 2
  • 4
  • 2
    I actually thought this would be spam, but they changed it from `x-forwarded-for` to `fastly-client-ip`. Thanks for posting this update. – Robin Sep 18 '18 at 15:18
1

This worked for me:

const express = require('express');

const logIP = async (req : any, res : any, next : any) => {
    const clientIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.headers['fastly-client-ip'];
}

const logIPApp = express();
logIPApp.use(logIP);

exports.reportIP = functions.https.onRequest(logIPApp);
hellmit100
  • 73
  • 1
  • 7
  • 1
    Why is logIP constant just creating a new constant within its scope? and doing nothing with it? Sorry, Am I missing something? – Sylvester Das Sep 23 '21 at 16:22
0

If you are looking for ip address or headers in cloud callable function, then you can get information inside context object.

for ex:

    exports.testUser = async (data, context) => {
      console.log('------------------------::context::------------------');
      if(context.rawRequest && context.rawRequest.headers){
         console.log(context.rawRequest.headers);
      }
    }

In the headers you can get ip : header { 'x-appengine-user-ip' : 'xxip' } etc.

  • I've tried this in my auth function but there is no IP information in the headers. `exports.auth = functions.https.onCall(async ({ roomid, userid }, context => {...` – Stefan Feb 25 '21 at 16:48
  • Do you tried by `context.rawRequest.headers['x-appengine-user-ip']` this way? – Bhargav Suthar Feb 25 '21 at 17:49
  • Thanks, that gives me an undefined value but I just realised I was using the local emulator so this would most likely not work there. However the previous approach should still give an IP if present I think... I'll give this a try with a real firebase staging app. – Stefan Feb 26 '21 at 18:15
  • Yep, works if not running locally.... That emulator, shoot me now :-) – Stefan Feb 26 '21 at 18:23
0

This is what worked for me using Firebase Cloud Functions:

const clientIP = req.headers['x-appengine-user-ip'] || req.header['x-forwarded-for']

Note, that this doesn't work locally!

George Chalhoub
  • 12,037
  • 3
  • 35
  • 60