How to Get Request's Ip

How to determine a user's IP address in node

In your request object there is a property called socket, which is a net.Socket object. The net.Socket object has a property remoteAddress, therefore you should be able to get the IP with this call:

request.socket.remoteAddress

(if your node version is below 13, use the deprecated now request.connection.remoteAddress)

EDIT

As @juand points out in the comments, the correct method to get the remote IP, if the server is behind a proxy, is request.headers['x-forwarded-for']

EDIT 2

When using express with Node.js:

If you set app.set('trust proxy', true), req.ip will return the real IP address even if behind proxy. Check the documentation for further information

How do I get the IP address from a http request using the requests library?

It turns out that it's rather involved.

Here's a monkey-patch while using requests version 1.2.3:

Wrapping the _make_request method on HTTPConnectionPool to store the response from socket.getpeername() on the HTTPResponse instance.

For me on python 2.7.3, this instance was available on response.raw._original_response.

from requests.packages.urllib3.connectionpool import HTTPConnectionPool

def _make_request(self,conn,method,url,**kwargs):
response = self._old_make_request(conn,method,url,**kwargs)
sock = getattr(conn,'sock',False)
if sock:
setattr(response,'peer',sock.getpeername())
else:
setattr(response,'peer',None)
return response

HTTPConnectionPool._old_make_request = HTTPConnectionPool._make_request
HTTPConnectionPool._make_request = _make_request

import requests

r = requests.get('http://www.google.com')
print r.raw._original_response.peer

Yields:

('2a00:1450:4009:809::1017', 80, 0, 0)

Ah, if there's a proxy involved or the response is chunked, the HTTPConnectionPool._make_request isn't called.

So here's a new version patching httplib.getresponse instead:

import httplib

def getresponse(self,*args,**kwargs):
response = self._old_getresponse(*args,**kwargs)
if self.sock:
response.peer = self.sock.getpeername()
else:
response.peer = None
return response

httplib.HTTPConnection._old_getresponse = httplib.HTTPConnection.getresponse
httplib.HTTPConnection.getresponse = getresponse

import requests

def check_peer(resp):
orig_resp = resp.raw._original_response
if hasattr(orig_resp,'peer'):
return getattr(orig_resp,'peer')

Running:

>>> r1 = requests.get('http://www.google.com')
>>> check_peer(r1)
('2a00:1450:4009:808::101f', 80, 0, 0)
>>> r2 = requests.get('https://www.google.com')
>>> check_peer(r2)
('2a00:1450:4009:808::101f', 443, 0, 0)
>>> r3 = requests.get('http://wheezyweb.readthedocs.org/en/latest/tutorial.html#what-you-ll-build')
>>> check_peer(r3)
('162.209.99.68', 80)

Also checked running with proxies set; proxy address is returned.


Update 2016/01/19

est offers an alternative that doesn't need the monkey-patch:

rsp = requests.get('http://google.com', stream=True)
# grab the IP while you can, before you consume the body!!!!!!!!
print rsp.raw._fp.fp._sock.getpeername()
# consume the body, which calls the read(), after that fileno is no longer available.
print rsp.content

Update 2016/05/19

From the comments, copying here for visibility, Richard Kenneth Niescior offers the following that is confirmed working with requests 2.10.0 and Python 3.

rsp=requests.get(..., stream=True)
rsp.raw._connection.sock.getpeername()

Update 2019/02/22

Python3 with requests version 2.19.1.

resp=requests.get(..., stream=True)
resp.raw._connection.sock.socket.getsockname()

Update 2020/01/31

Python3.8 with requests 2.22.0

resp = requests.get('https://www.google.com', stream=True)
resp.raw._connection.sock.getsockname()

Correct way of getting Client's IP Addresses from http.Request

Looking at http.Request you can find the following member variables:

// HTTP defines that header names are case-insensitive.
// The request parser implements this by canonicalizing the
// name, making the first character and any characters
// following a hyphen uppercase and the rest lowercase.
//
// For client requests certain headers are automatically
// added and may override values in Header.
//
// See the documentation for the Request.Write method.
Header Header

// RemoteAddr allows HTTP servers and other software to record
// the network address that sent the request, usually for
// logging. This field is not filled in by ReadRequest and
// has no defined format. The HTTP server in this package
// sets RemoteAddr to an "IP:port" address before invoking a
// handler.
// This field is ignored by the HTTP client.
RemoteAddr string

You can use RemoteAddr to get the remote client's IP address and port (the format is "IP:port"), which is the address of the original requestor or the last proxy (for example a load balancer which lives in front of your server).

This is all you have for sure.

Then you can investigate the headers, which are case-insensitive (per documentation above), meaning all of your examples will work and yield the same result:

req.Header.Get("X-Forwarded-For") // capitalisation
req.Header.Get("x-forwarded-for") // doesn't
req.Header.Get("X-FORWARDED-FOR") // matter

This is because internally http.Header.Get will normalise the key for you. (If you want to access header map directly, and not through Get, you would need to use http.CanonicalHeaderKey first.)

Finally, "X-Forwarded-For" is probably the field you want to take a look at in order to grab more information about client's IP. This greatly depends on the HTTP software used on the remote side though, as client can put anything in there if it wishes to. Also, note the expected format of this field is the comma+space separated list of IP addresses. You will need to parse it a little bit to get a single IP of your choice (probably the first one in the list), for example:

// Assuming format is as expected
ips := strings.Split("10.0.0.1, 10.0.0.2, 10.0.0.3", ", ")
for _, ip := range ips {
fmt.Println(ip)
}

will produce:

10.0.0.1
10.0.0.2
10.0.0.3

How to get the client's ip from the request?

The request object contains a property called socket, which is actually a net.Socket object. This object has a remoteAddress property which holds the IP address of the call.

request.socket.remoteAddress

Please also note, that if the server is behind a proxy, you should be using the request headers request.headers['x-forwarded-for']

what is the right way to get request's ip

The answer is complicated.

  • If your servlet is running on a webserver that is behind a reverse proxy or load balancer, then that web proxy can be configured to inject a request header that gives the IP address that the request came from. Different reverse proxies will inject different headers. Consult the documentation for your (front-end) server.

  • If your client uses a (forward) proxy, then it might insert headers to say what the client IP address is ... or it might not. And the IP address it insert might be incorrect.

  • The value you get by calling request.getRemoteAddr() is going to be the IP address of the immediate upstream source of the request.

None of the headers that you listed is standard, but "x-forwarded-for" is reputed to be a defacto standard; i.e. it is the one that is most likely to be inserted by a proxy, etc ... if anything is injected.

Finally, even if you did get an IP address, it wouldn't necessarily help you. For instance, if the client sits on a private network and connects to the internet via a NAT gateway, then the IP address in HTTP request will be an address of the NAT server ... not the actual client IP.


So what does this all mean? Well basically, it means that in general you cannot reliably find out the IP address of the system that the request originated from.

How to form GET HTTP Request with IP Address

The parameter for GET should be just the resource path by itself, and the Host header should be the domain/host of the machine that the request is being sent to, as specified by the original URL.

To request http://www.wwe.com/index.php, the GET request would look like this:

GET /index.php HTTP/1.1
Host: www.wwe.com
...

To request http://54.236.192.188/index.php, the GET request would look like this:

GET /index.php HTTP/1.1
Host: 54.236.192.188
...

However, if the server runs multiple websites on the same IP address, you can't provide an IP address in the rquest. The Host header tells the server which specific website to access.

Unless needed, HTTP/1.1 should be used instead of HTTP/1.0. For example, Keep-Alive isn't supported by HTTP/1.0 by default. And the Host header is required for HTTP 1.1.

How to get client IP address in Laravel 5+

Looking at the Laravel API:

Request::ip();

Internally, it uses the getClientIps method from the Symfony Request Object:

public function getClientIps()
{
$clientIps = array();
$ip = $this->server->get('REMOTE_ADDR');
if (!$this->isFromTrustedProxy()) {
return array($ip);
}
if (self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) {
$forwardedHeader = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]);
preg_match_all('{(for)=("?\[?)([a-z0-9\.:_\-/]*)}', $forwardedHeader, $matches);
$clientIps = $matches[3];
} elseif (self::$trustedHeaders[self::HEADER_CLIENT_IP] && $this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) {
$clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
}
$clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from
$ip = $clientIps[0]; // Fallback to this when the client IP falls into the range of trusted proxies
foreach ($clientIps as $key => $clientIp) {
// Remove port (unfortunately, it does happen)
if (preg_match('{((?:\d+\.){3}\d+)\:\d+}', $clientIp, $match)) {
$clientIps[$key] = $clientIp = $match[1];
}
if (IpUtils::checkIp($clientIp, self::$trustedProxies)) {
unset($clientIps[$key]);
}
}
// Now the IP chain contains only untrusted proxies and the client IP
return $clientIps ? array_reverse($clientIps) : array($ip);
}


Related Topics



Leave a reply



Submit