How to find the hostname of the original API caller

I have multiple internal servers calling the API gateway and I need to know which internal server is making the API call. I have the IP address of the original forwarded service (via proxy.client.ip and an XFF header) but I actually need the hostname for various reasons. It would be ideal to look up the hostname via reverse DNS, but there doesn't seem to be a way to do that without creating some other service to do the reverse DNS for me. External reverse DNS services wont work since it's an internal hostname.

My question is, what's the best way of getting the hostname of the original API caller?

Solved Solved
0 5 1,815
1 ACCEPTED SOLUTION

If you're doing this in a controlled, API Centric environment, then... you won't be concerned with the hostname of the caller.

Just issue multiple different credentials to the different caller apps, and then with VerifyApiKey or VerifyAccessToken you will be able to identify the client, irrespective of the hostname.

But maybe you need the hostname anyway. (I can't imagine why, but I guess it's possible)

There is no magic to discovering the hostname of the caller without doing a reverse DNS lookup. It is possible for you to design the API interface to require the client to pass a hostname, for example in an X-client-hostname header. But, this will be a "voluntary compliance" thing and a client could pass anything it likes. If you control the clients, then it's just a matter of making sure the client apps do the right thing.

If you don't control the clients, then ... you have to persuade the developers of those outside clients to pass something valid.

One way you might "enforce" a valid hostname is to, again, rely on Apigee app credentials. Require client devs to register a list of max 3 hostnames that might be used for their client systems, and store that as a custom attribute on the credential. And then at runtime,

  • VerifyApiKey or VerifyAccessToken
  • retrieve custom attributes for the credential
  • compare x-client-hostname header against the set of registered valid hostnames
    • Send 403 if the hostname is not valid

What do you need the hostname for anyway?

View solution in original post

5 REPLIES 5

you can use http referrer, I think that should be sufficient.

If you're doing this in a controlled, API Centric environment, then... you won't be concerned with the hostname of the caller.

Just issue multiple different credentials to the different caller apps, and then with VerifyApiKey or VerifyAccessToken you will be able to identify the client, irrespective of the hostname.

But maybe you need the hostname anyway. (I can't imagine why, but I guess it's possible)

There is no magic to discovering the hostname of the caller without doing a reverse DNS lookup. It is possible for you to design the API interface to require the client to pass a hostname, for example in an X-client-hostname header. But, this will be a "voluntary compliance" thing and a client could pass anything it likes. If you control the clients, then it's just a matter of making sure the client apps do the right thing.

If you don't control the clients, then ... you have to persuade the developers of those outside clients to pass something valid.

One way you might "enforce" a valid hostname is to, again, rely on Apigee app credentials. Require client devs to register a list of max 3 hostnames that might be used for their client systems, and store that as a custom attribute on the credential. And then at runtime,

  • VerifyApiKey or VerifyAccessToken
  • retrieve custom attributes for the credential
  • compare x-client-hostname header against the set of registered valid hostnames
    • Send 403 if the hostname is not valid

What do you need the hostname for anyway?

Perhaps this speaks to the problem of the architecture of our environments more than anything.

Essentially, we have dozens of teams that spin up testing environments in their own VMs. Each team may spin them up on demand for testing features and tear them back down again. They may have a number of these VMs at a time.

On each of these VMs, there are hundreds of APIs that we want to proxy through a single, internal API gateway to apply policies and make it more production-like, but we didn't want to create an Apigee environment for each VM since that would be managing a hundred different dynamic environments - all of which should have the same policies applied. So the design was to route all the APIs through the same gateway (and Apigee environment) and have the gateway determine who the ultimate target should be depending on the source of the request.

For example, if on server 1, service A made a service call through the gateway intending to call service B, the gateway should route to service B on the same server that originated the call, server 1 in this example.

The problem of the hostname comes from the fact that the VMs run IIS and bind to hostnames and not IPs in order to serve the APIs. So calling the services in each VM requires there be a hostname bound to the IIS application.

So we have a bit of a strange setup for now, but the proposed idea of just resolving the hostname and having the gateway route to that target is really a quick and dirty stop-gap solution until we get a more reasonable testing architecture in place.

I see. that makes sense.

With the information I provided previously, can you make progress?

I think I can make some progress, yes. Bottom line is that there isn't an out-of-the-box way to do what I'm asking. The ideas about identifying the caller via apikey could be useful in the future though.

FYI, I created a NodeJS App proxy to do the reverse lookup and used the native DNS library to try and do the reverse lookup to no avail. Every call responds with EINVAL response, even when I pass a hard-coded valid IP. The same NodeJS script works fine when running locally or on another server, even using an older version of Node. It just fails within Apigee. No idea why.

The other alternative for the reverse lookup was to deploy an extremely simple service and call an endpoint that does the reverse lookup. Basically /dns?ip=10.100.x.x and the hostname is returned. This way I can call it via a policy in a shared flow and cache the result for some time. This seems to be the best option for now.

Thanks for the help.