dh_ackergaul
vor 4 Tagen bb80cdf5a6157ca1f3a276e12e9faae9a4739cb7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
 * Author: petar bojinov - @pbojinov
 * Date: 01/27/16
 */
 
'use strict';
 
/**
 * Get client IP address
 *
 * Will return 127.0.0.1 when testing locally
 * Useful when you need the user ip for geolocation or serving localized content
 *
 * @method getClientIp
 * @param req
 * @returns {string} ip
 */
function getClientIp(req) {
 
    // TESTING FLAG
    // custom header passed to app to delete all request attributes we look for
    // we do this so we can test the scenario where nothing exists and we return null
    if (req && req.headers && req.headers['x-testing-null-condition-so-delete-everything']) {
        delete req.headers;
        delete req.connection;
        delete req.socket;
        delete req.info;
    }
 
    // the ipAddress we return
    var ipAddress;
 
    // workaround to get real client IP
    // most likely because our app will be behind a [reverse] proxy or load balancer
    if (req.headers) {
 
        // Amazon EC2 / Heroku workaround to get real client IP
        if ((ipAddress = req.headers['x-client-ip'])) {
            return ipAddress;
        }
 
        // (typically when your node app is behind a load-balancer (eg. AWS ELB) or proxy)
        if ((ipAddress = parseForwardedForAlt(req.headers['x-forwarded-for']))) {
            return ipAddress;
        }
 
        // Cloudflare.
        // @see https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-
        // CF-Connecting-IP - applied to every request to the origin.
        if ((ipAddress = req.headers['cf-connecting-ip'])) {
            return ipAddress
        }
 
        // Akamai and Cloudflare: True-Client-IP.
        if ((ipAddress = req.headers['true-client-ip'])) {
            return ipAddress
        }
 
        // (default nginx proxy/fcgi)
        // alternative to x-forwarded-for, used by some proxies
        if ((ipAddress = req.headers['x-real-ip'])) {
            return ipAddress;
        }
 
        // (Rackspace LB and Riverbed's Stingray)
        // http://www.rackspace.com/knowledge_center/article/controlling-access-to-linux-cloud-sites-based-on-the-client-ip-address
        // https://splash.riverbed.com/docs/DOC-1926
        if ((ipAddress = req.headers['x-cluster-client-ip'])) {
            return ipAddress;
        }
 
        if ((ipAddress = req.headers['x-forwarded'])) {
            return ipAddress;
        }
 
        if ((ipAddress = req.headers['forwarded-for'])) {
            return ipAddress;
        }
 
        if ((ipAddress = req.headers['forwarded'])) {
            return ipAddress;
        }
    }
 
    // remote address check
    var reqConnectionRemoteAddress = req.connection ? req.connection.remoteAddress : null;
    var reqSocketRemoteAddress = req.socket ? req.socket.remoteAddress : null;
    var reqConnectionSocketRemoteAddress = (req.connection && req.connection.socket) ? req.connection.socket.remoteAddress : null;
    var reqInfoRemoteAddress = req.info ? req.info.remoteAddress : null;
 
    // remote address checks
    if ((ipAddress = req.connection && req.connection.remoteAddress)) {
        return ipAddress;
    }
    if ((ipAddress = req.socket && req.socket.remoteAddress)) {
        return ipAddress;
    }
    if ((ipAddress = req.connection && req.connection.socket && req.connection.socket.remoteAddress)) {
        return ipAddress;
    }
    if ((ipAddress = req.info && req.info.remoteAddress)) {
        return ipAddress;
    } 
 
    // return null if we cannot find an address
    return null;
}
 
function parseForwardedForAlt(forwardedForAlt) {
    if (!forwardedForAlt) {
        return;
    }
    // x-forwarded-for may return multiple IP addresses in the format:
    // "client IP, proxy 1 IP, proxy 2 IP"
    // Therefore, the right-most IP address is the IP address of the most recent proxy
    // and the left-most IP address is the IP address of the originating client.
    // source: http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html
    var forwardedIps = forwardedForAlt.split(',');
    // Sometimes IP addresses in this header can be 'unknown' (http://stackoverflow.com/a/11285650).
    // Therefore taking the left-most IP address that is not unknown
    // A Squid configuration directive can also set the value to "unknown" (http://www.squid-cache.org/Doc/config/forwarded_for/)
    for (var i = 0; i < forwardedIps.length; ++i) {
        var ipAddress = forwardedIps[i].trim();
        if (ipAddress && ipAddress !== 'unknown') {
            return ipAddress;
        }
    }
}
 
 
/**
 * Expose mode public functions
 */
exports.getClientIp = getClientIp;
 
 
/**
 * Expose a default implemtation for a connect middleware
 * 
 * @options.attributeName - name of attribute to augment request object with
 */
exports.mw = function(options) {
    if (!options) options = {};
    var attr = options.attributeName || "clientIp";
    return function(req, res, next) {
        req[attr] = getClientIp(req);
        next();
    }
};