Cách xác định địa chỉ IP của người dùng trong nút


349

Làm cách nào tôi có thể xác định địa chỉ IP của một yêu cầu đã cho từ trong bộ điều khiển? Ví dụ: (thể hiện):

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

22
Nếu bạn đang sử dụng Express, bạn có thể sử dụng req.ip nguồn - expressjs.com/en/api.html#req.ip
FrickeFresh

Hãy thử điều này: github.com/indutny/node-ip
Stephen

16
Đối với những người đang làm việc từ localhost- như tôi đã làm, kết quả cho tất cả các câu trả lời dưới đây (Gần như tất cả các câu trả lời hoạt động) có thể đến ::1. Điều này khiến tôi bối rối đôi khi. Sau đó phát hiện ra đó ::1là Địa chỉ IP thực và IPV6ký hiệu cho localhost. Hope this helps someone
Pramesh Bajracharya

Câu trả lời:


452

Trong requestđối tượng của bạn có một thuộc tính được gọi connection, đó là một net.Socketđối tượng. Đối tượng net.Socket có một thuộc tính remoteAddress, do đó bạn sẽ có thể nhận IP bằng cuộc gọi này:

request.connection.remoteAddress

Xem tài liệu cho httpnet

BIÊN TẬP

Như @juand chỉ ra trong các bình luận, phương pháp chính xác để lấy IP từ xa, nếu máy chủ đứng sau proxy, là request.headers['x-forwarded-for']


6
Điều này mang lại cho tôi một địa chỉ IP khác với những gì whatismyip.com mang lại cho tôi. Tại sao lại như vậy?
Shamoon

3
Tôi đã cài đặt dịch vụ API của mình trên một ví dụ no.de. Khi tôi cố gắng truy cập nó từ máy tính của mình, tôi nhận được địa chỉ IP là "10.2.XXX.YYY" trong khi IP thế giới thực của tôi là "67.250.AAA.BBB"
Shamoon

7
đó là request.headers ['X-Forwarded-For']
0x6A75616E

4
Lưu ý rằng net.Stream hiện là net.Socket và tài liệu nằm ở đây: nodejs.org/api/net.html#net_group_net_socket
monsur

4
Đối với bất kỳ ai quan tâm, đối với Heroku, đó là: 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);

Lưu ý rằng đôi khi bạn có thể nhận được nhiều hơn một địa chỉ IP req.headers['x-forwarded-for']. Ngoài ra, một x-forwarded-fortiêu đề sẽ không luôn luôn được đặt mà có thể gây ra lỗi.

Định dạng chung của trường là:

x-chuyển tiếp-cho: client, proxy1, proxy2, proxy3

trong đó giá trị là danh sách địa chỉ IP được phân tách bằng dấu phẩy + không gian, phần lớn bên trái là máy khách gốc và mỗi proxy liên tiếp chuyển yêu cầu thêm địa chỉ IP nơi nhận được yêu cầu. Trong ví dụ này, yêu cầu đi qua proxy1, proxy2và sau đó proxy3. proxy3xuất hiện dưới dạng địa chỉ từ xa của yêu cầu.

Đây là giải pháp được đề xuất bởi Arnav Gupta với bản sửa lỗi Martin đã đề xuất bên dưới trong các nhận xét cho các trường hợp khi x-forwarded-forkhông được đặt:

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

9
Làm thế nào để ngăn chặn giả mạo của các tiêu đề mặc dù?
Domi

8
Điều này thường hoạt động tốt nhưng vì một số lý do gần đây tôi đã gặp lỗi "Không thể đọc thuộc tính 'remoteAddress' của không xác định" vì rõ ràng mọi thứ đều không có / không xác định, bao gồm cả req.connection.socket. Tôi không chắc tại sao / điều kiện nào gây ra trường hợp đó nhưng sẽ tốt hơn nếu kiểm tra xem có req.connection.sockettồn tại để tránh máy chủ của bạn gặp sự cố nếu điều này xảy ra.
Matt Browne

9
Dòng cuối req.connection.socket.remoteAddress ném lỗi. Cẩn thận.
yAnTar

11
Địa chỉ IP được trả về là :: 1. Tại sao?
Bagusflyer

3
Nhìn vào cách hoạt động của pop (), có vẻ như bạn sẽ nhận được proxy cuối cùng chứ không phải ứng dụng khách đó là những gì bạn muốn. Tôi có lầm không?
Michel


31

Bạn có thể ở lại DRY và chỉ sử dụng phần mềm nút-ip hỗ trợ cả IPv4IPv6 .

Tải về:

npm install ipware

Trong app.js hoặc phần mềm trung gian của bạn:

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();
});

Nó sẽ cố gắng tốt nhất để lấy địa chỉ IP của người dùng hoặc trả về 127.0.0.1để cho biết rằng họ không thể xác định địa chỉ IP của người dùng. Hãy xem tệp README cho các tùy chọn nâng cao.


40
"hoặc trả về 127.0.0.1 để chỉ ra rằng nó không thể xác định địa chỉ IP của người dùng" Có một sự khác biệt khá lớn giữa 127.0.0.1 và không xác định ...
Nepoxx 13/03/2015

4
Nó trả lại một cái gì đó kỳ lạ cho tôi :ffff:(not my IP address)khi được thử nghiệm từ Heroku. Câu trả lời của @ edmar-miyake đang hoạt động đúng với tôi.
Nilloc

Tôi tự hỏi IP sẽ là gì nếu bạn sử dụng tra cứu right2left trong trường hợp 'x-Forwarded-for'. var ip_info = get_ip (req, right_ ultra_proxy = True), như trong một số thiết lập, IP khách có thể là IP đúng nhất.
un33k

2
Phương pháp đó đang trở lại clientIp: '::1'với tôi. Nó dường như không hoạt động.
JamEngulfer

@JamEngulfer - ipware chỉ hoạt động nếu địa chỉ IP được truyền chính xác đến ứng dụng của bạn thông qua request.headers []. ví dụ: AWS LBS gửi địa chỉ IP trong 'x-Forwarded-for' trong khi NginX tùy chỉnh nhiều người sử dụng các biến khác. ipware thực hiện nỗ lực tốt nhất để tìm ra địa chỉ IP, nhưng chỉ khi IP được truyền lại trong các tiêu đề.
un33k

19

Bạn có thể sử dụng ip yêu cầu , để lấy địa chỉ IP của người dùng. Nó xử lý khá nhiều trường hợp cạnh khác nhau, một số trong đó được đề cập trong các câu trả lời khác.

Tiết lộ: Tôi đã tạo mô-đun này

Tải về:

npm install request-ip

Trong ứng dụng của bạn:

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();
};

Hi vọng điêu nay co ich


2
kiểm tra mã nguồn của gói request-ip tại github.com/pbojinov/request-ip/blob/master/index.js, nó kiểm tra x-Forwarded-for và tất cả các loại tiêu đề khác cho các bộ cân bằng tải phổ biến như AWS ELB, Cloudflare , Akamai, nginx, Rackspace LB và Riverbed's Stingray
Giorgio

1
nó trả lại nullcho tôi
S.M_Emamian

Điều tương tự thay vì sử dụngrequest.headers['x-forwarded-for']
Prathamesh Thêm

19

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

Nếu x-forwarded-fortiêu đề ở đó thì sử dụng nó, nếu không sử dụng thuộc .remoteAddresstính.

Các x-forwarded-fortiêu đề được thêm vào các yêu cầu đi qua cân bằng tải (hoặc các loại proxy) thiết lập cho HTTP hoặc HTTPS (nó cũng có thể thêm tiêu đề này để yêu cầu khi cân bằng tại một TCP mức sử dụng giao thức proxy ). Điều này là do thuộc request.connection.remoteAddresstính sẽ chứa địa chỉ IP riêng của bộ cân bằng tải chứ không phải địa chỉ IP công cộng của máy khách. Bằng cách sử dụng câu lệnh OR , theo thứ tự trên, bạn kiểm tra sự tồn tại của x-forwarded-fortiêu đề và sử dụng nó nếu nó tồn tại nếu không sử dụng request.connection.remoteAddress.


12

Chức năng sau đây có tất cả các trường hợp được bảo hiểm sẽ giúp

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);

Lưu ý các ips có một , giữa cho tôi.
ThomasReggi

8

Có hai cách để lấy địa chỉ IP:

  1. let ip = req.ip

  2. let ip = req.connection.remoteAddress;

Nhưng có một vấn đề với các phương pháp trên.

Nếu bạn đang chạy ứng dụng của mình phía sau Nginx hoặc bất kỳ proxy nào, mọi địa chỉ IP duy nhất sẽ là 127.0.0.1 .

Vì vậy, giải pháp tốt nhất để lấy địa chỉ IP của người dùng là: -

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

6

Nếu bạn đang sử dụng phiên bản express 3.x trở lên, bạn có thể sử dụng cài đặt proxy tin cậy ( http://expressjs.com/api.html#trust.proxy.options.table ) và nó sẽ đi theo chuỗi địa chỉ trong tiêu đề x-Forwarded-for và đặt ip mới nhất vào chuỗi mà bạn chưa cấu hình làm proxy đáng tin cậy vào thuộc tính ip trên đối tượng req.


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
Bạn đã đúng, nếu bạn muốn ip dưới dạng chuỗi, thì bạn có thể thay thế dòng cuối cùng bằng: ip = ip.split (':'). Lát (-1) [0]
Ahmad Agbaryah

Câu trả lời chỉ có mã được khuyến khích. Bạn có thể giải thích như thế nào câu trả lời này là tốt hơn so với tuổi, giải thích tốt hơn, và (nhiều) upvoted nhiều câu trả lời ?
Dan Dascalescu

5

Cảnh báo:

Đừng chỉ mù quáng sử dụng điều này cho giới hạn tỷ lệ quan trọng:

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

Nó rất dễ bị giả mạo:

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

Trong trường hợp đó, địa chỉ IP thực của người dùng sẽ là:

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

Tôi ngạc nhiên rằng không có câu trả lời khác đã đề cập đến điều này.


Các đầu câu trả lời không giải quyết điều này bằng cách pop()ing từ mảng, đó là tổng quát hơn nhận được các phần tử tại chỉ số 1, có thể được lừa bởi curl --header "X-Forwarded-For: 1.2.3.4, 5.6.7.8" "https://example.com".
Dan Dascalescu

3

Nếu bạn nhận được nhiều IP, điều này làm việc cho tôi:

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


3

Đơn giản nhận ip từ xa trong nodejs:

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

3

Trong nút 10.14, đằng sau nginx, bạn có thể truy xuất ip bằng cách yêu cầu nó thông qua tiêu đề nginx như thế này:

proxy_set_header X-Real-IP $remote_addr;

Sau đó, trong app.js của bạn:

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

Sau đó, bất cứ nơi nào bạn muốn nó xuất hiện:

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

2

Tôi nhận ra điều này đã được trả lời cho đến chết, nhưng đây là phiên bản ES6 hiện đại mà tôi đã viết theo tiêu chuẩn eslint cơ sở airbnb.

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;
};

Tiêu đề X-Forwarded-For có thể chứa danh sách IP proxy được phân tách bằng dấu phẩy. Đơn hàng là client, proxy1, proxy2, ..., proxyN. Trong thế giới thực, mọi người thực hiện các proxy có thể cung cấp bất cứ thứ gì họ muốn trong tiêu đề này. Nếu bạn đứng sau một bộ cân bằng tải hoặc một cái gì đó, ít nhất bạn có thể tin tưởng IP đầu tiên trong danh sách ít nhất là bất kỳ proxy nào mà một số yêu cầu đã đưa ra.


1

Nếu bạn đang sử dụng Graphql-Yoga, bạn có thể sử dụng chức năng sau:

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

Có cùng một vấn đề ... tôi cũng mới sử dụng javascript nhưng tôi đã giải quyết vấn đề này với req.connection.remoteAddress; đã cho tôi địa chỉ IP (nhưng ở định dạng ipv6 :: ffff.192.168.0.101) và sau đó .slice để xóa 7 chữ số đầu tiên.

var ip = req.connection.remoteAddress;

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

Đây không phải là một phương pháp tốt, vì ipv6 KHÔNG chỉ là 7 chữ số + IPv4, nhưng có thể hoàn toàn khác nhau.
Radek

@Radek nếu bạn xác thực bắt đầu địa chỉ, nó phù hợp với thông số kỹ thuật (xem en.wikipedia.org/wiki/IPv6_address ctrl-f tìm kiếm "ánh xạ IPv4") ip= (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):undefined))sẽ thay thế nếu ... trong mã trên
không được đồng bộ hóa

Tôi đích thân bọc getClientIp () từ npm request-ip để tạo ra 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)); }chấp nhận một ip đã tìm nạp trước đó hoặc một đối tượng yêu cầu làm đầu vào và đưa ra ip hoặc không xác định do kết quả
không đồng bộ hóa
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.