How to get IP upon server request on Galaxy

I’m trying to check user’s IP from the server endpoint using WebApp. I’m assuming this is the most direct way?

WebApp.connectHandlers.use(async (req, res, next) => {
const xForwardedFor = req.headers[‘x-forwarded-for’];

}

This works most of the time, but not all. It’s inconsistent. Sometimes I see Galaxy’s server IP coming in instead.

I do see some very old posts about this that are 10+ years old but nothing recent. Ideas?

1 Like

My code is in a very different context – handling Apollo requests – but see if this is helpful in any way:

// https://forums.meteor.com/t/solved-check-ip-address-on-api-applications/55443
function parseIp(req) {
    let response =
    (typeof req?.headers['x-forwarded-for'] === 'string'
        && req?.headers['x-forwarded-for'].split(',').shift())
    || req?.connection?.remoteAddress
    || req?.socket?.remoteAddress
    || req?.connection?.socket?.remoteAddress;

    return response;
}

        [.....]
        let request = ctx?.req || ctx.extra.request;
        clientIp = request?.clientIp || parseIp(request) || request?.ip || request?.headers['x-forwarded-for'] || request?.connection?.remoteAddress  || ctx?.res?.req?.headers["x-forwarded-for"] || request?.client?.remoteAddress;
2 Likes

Thanks. My issue is basically that the x-forwarded-for header occasionally comes in not as the user’s IP but as one of Galaxy’s private IPs (10.0.x…x). I can pull my IP connecting from my network, but someone else on the same network(!) I can’t pull theirs, even when they switch browsers. Total mystery. I’ve tried using the rawConnectHandler with no change in behavior.

Ok, it is a little more complicated due to NAT-ing.
First, legal matters—the user needs to know you are trying to locate her. Privacy policy needs to include collection and retention of device IP addresses.

If I knew more of what you want to do, I could probably help you with more code. For instance, if you need analytics such as device type, location based on IP, I have those bits from a custom-made analytics platform that I maintain.

If you use Accounts, you can get this data at “startup” as this is only called on the first loading of a logged session:

 Accounts.onLogin(function (login) {
   // login has your IP data as login.connection?.clientAddress
}

Due to NATing through gateways, network balancers or reverse proxies, you may get various more or less internal IP addresses for a user, from different VPNs / VPCs.
Meteor has a global variable to help you deal with this problem.
HTTP_FORWARDED_COUNT: 2 - Environment Variables | Docs
I used empirical testing and found that 2 works for me. I host in AWS, on EC2s behind an Application Load Balancer.
Try with 1, 2, 3 and see the value that consistently gives you a public IP address.

2 Likes

Thanks. Very valuable info. In my circumstance, the app is a private, in-house application only used by a small group of employees. For security I have two levels on top: IP whitelisting and url obfuscation. Given that the url is an easy hit through casual discovery, either purposeful or accidental, I need a way to keep others off the sign-in page.

IPs aren’t saved on my end (except for the few whitelisted ones), although Galaxy’s server logs will for a time as they are consoled. They’re just used as checks.

Not using Meteor accounts. It’s a simple pw entry checked on the server. No cookies, but it does keep the user signed in for 3 days (just to make it a little friendlier).

For those who I can’t get IPs for, I’m resorting to bypassing the IP check and relying on obscuring the url with tokens.

Legal shouldn’t be an issue since the employees have given consent, and the whitelisted IPs are locked down and not public facing.

I have a few users whose IP shows as a 10.0.x.x address when grabbing the x-forwarded-for header. This, I’m quite sure is one of Galaxy’s. There’s a, what I would call, ‘health check’ ping every 10 seconds or so which has the same IP signature (10.0.x.x).

Anyway, we’re operating ok for now. Nothing super critical. Just wanted to reach out to the community. It always impresses me the level of knowledge here.

1 Like

Hey, indeed if this is an internal app, no worries about the collection of data.
I think you can then rely on HTTP_FORWARDED_COUNT to get the end user IP.

2 Likes

Update to the IP issue

After reaching out to the Galaxy team, they informed me that IPv6 support, which I did have switched on, can have issues with consistent IP retrieval. Switching that off and updating the CNAME record to point to the non-ipv6 Galaxy DNS solved it.

The HTTP_FORWARDED_COUNT didn’t help in my case because that header was coming in as a single IP, not multiple ones, so there was nothing to parse.

Hoping this may help others with the same issue.

1 Like

[SOLVED] How to get IP upon server request on Galaxy

1 Like