@@ -6,6 +6,7 @@ var express = require('express');
66var defaultRequest = require ( 'request' ) ;
77var url = require ( 'url' ) ;
88var bodyParser = require ( 'body-parser' ) ;
9+ var rangeCheck = require ( 'range_check' ) ;
910
1011var DO_NOT_PROXY_REGEX = / ^ (?: H o s t | X - F o r w a r d e d - H o s t | P r o x y - C o n n e c t i o n | C o n n e c t i o n | K e e p - A l i v e | T r a n s f e r - E n c o d i n g | T E | T r a i l e r | P r o x y - A u t h o r i z a t i o n | P r o x y - A u t h e n t i c a t e | U p g r a d e | E x p i r e s | p r a g m a | S t r i c t - T r a n s p o r t - S e c u r i t y ) $ / i;
1112var PROTOCOL_REGEX = / ^ \w + : \/ / ;
@@ -46,12 +47,49 @@ module.exports = function(options) {
4647 var proxyDomains = options . proxyableDomains || [ ] ;
4748 var proxyAuth = options . proxyAuth || { } ;
4849 var proxyPostSizeLimit = options . proxyPostSizeLimit || '102400' ;
50+
51+ // If you change this, also change the same list in serverconfig.json.example.
52+ // This page is helpful: https://en.wikipedia.org/wiki/Reserved_IP_addresses
53+ var blacklistedAddresses = options . blacklistedAddresses || [
54+ // loopback addresses
55+ '127.0.0.0/8' ,
56+ '::1/128' ,
57+ // link local addresses
58+ '169.254.0.0/16' ,
59+ 'fe80::/10' ,
60+ // private network addresses
61+ '10.0.0.0/8' ,
62+ '172.16.0.0/12' ,
63+ '192.168.0.0/16' ,
64+ 'fc00::/7' ,
65+ // other
66+ '0.0.0.0/8' ,
67+ '100.64.0.0/10' ,
68+ '192.0.0.0/24' ,
69+ '192.0.2.0/24' ,
70+ '198.18.0.0/15' ,
71+ '192.88.99.0/24' ,
72+ '198.51.100.0/24' ,
73+ '203.0.113.0/24' ,
74+ '224.0.0.0/4' ,
75+ '240.0.0.0/4' ,
76+ '255.255.255.255/32' ,
77+ '::/128' ,
78+ '2001:db8::/32' ,
79+ 'ff00::/8'
80+ ] ;
4981
5082 //Non CORS hosts and domains we proxy to
5183 function proxyAllowedHost ( host ) {
84+ // Exclude hosts that are really IP addresses and are in our blacklist.
85+ if ( rangeCheck . inRange ( host , blacklistedAddresses ) ) {
86+ return false ;
87+ }
88+
5289 if ( proxyAllDomains ) {
5390 return true ;
5491 }
92+
5593 host = host . toLowerCase ( ) ;
5694 //check that host is from one of these domains
5795 for ( var i = 0 ; i < proxyDomains . length ; i ++ ) {
@@ -190,7 +228,27 @@ module.exports = function(options) {
190228 headers : filteredRequestHeaders ,
191229 encoding : null ,
192230 proxy : proxy ,
193- body : req . body
231+ body : req . body ,
232+ followRedirect : function ( response ) {
233+ var location = response . headers . location ;
234+ if ( location && location . length > 0 ) {
235+ var parsed = url . parse ( location ) ;
236+ if ( proxyAllowedHost ( parsed . host ) ) {
237+ // redirect is ok
238+ return true ;
239+ }
240+ }
241+ // redirect is forbidden
242+ return false ;
243+ }
244+ } ) . on ( 'socket' , function ( socket ) {
245+ socket . once ( 'lookup' , function ( err , address , family , host ) {
246+ if ( rangeCheck . inRange ( address , blacklistedAddresses ) ) {
247+ res . status ( 403 ) . send ( 'IP address is not allowed: ' + address ) ;
248+ res . end ( ) ;
249+ proxiedRequest . abort ( ) ;
250+ }
251+ } ) ;
194252 } ) . on ( 'error' , function ( err ) {
195253 console . error ( err ) ;
196254
0 commit comments