The LM Control website. Simple yet efficient.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

index.js 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /*!
  2. * proxy-addr
  3. * Copyright(c) 2014-2016 Douglas Christopher Wilson
  4. * MIT Licensed
  5. */
  6. 'use strict'
  7. /**
  8. * Module exports.
  9. * @public
  10. */
  11. module.exports = proxyaddr
  12. module.exports.all = alladdrs
  13. module.exports.compile = compile
  14. /**
  15. * Module dependencies.
  16. * @private
  17. */
  18. var forwarded = require('forwarded')
  19. var ipaddr = require('ipaddr.js')
  20. /**
  21. * Variables.
  22. * @private
  23. */
  24. var DIGIT_REGEXP = /^[0-9]+$/
  25. var isip = ipaddr.isValid
  26. var parseip = ipaddr.parse
  27. /**
  28. * Pre-defined IP ranges.
  29. * @private
  30. */
  31. var IP_RANGES = {
  32. linklocal: ['169.254.0.0/16', 'fe80::/10'],
  33. loopback: ['127.0.0.1/8', '::1/128'],
  34. uniquelocal: ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', 'fc00::/7']
  35. }
  36. /**
  37. * Get all addresses in the request, optionally stopping
  38. * at the first untrusted.
  39. *
  40. * @param {Object} request
  41. * @param {Function|Array|String} [trust]
  42. * @public
  43. */
  44. function alladdrs (req, trust) {
  45. // get addresses
  46. var addrs = forwarded(req)
  47. if (!trust) {
  48. // Return all addresses
  49. return addrs
  50. }
  51. if (typeof trust !== 'function') {
  52. trust = compile(trust)
  53. }
  54. for (var i = 0; i < addrs.length - 1; i++) {
  55. if (trust(addrs[i], i)) continue
  56. addrs.length = i + 1
  57. }
  58. return addrs
  59. }
  60. /**
  61. * Compile argument into trust function.
  62. *
  63. * @param {Array|String} val
  64. * @private
  65. */
  66. function compile (val) {
  67. if (!val) {
  68. throw new TypeError('argument is required')
  69. }
  70. var trust
  71. if (typeof val === 'string') {
  72. trust = [val]
  73. } else if (Array.isArray(val)) {
  74. trust = val.slice()
  75. } else {
  76. throw new TypeError('unsupported trust argument')
  77. }
  78. for (var i = 0; i < trust.length; i++) {
  79. val = trust[i]
  80. if (!Object.prototype.hasOwnProperty.call(IP_RANGES, val)) {
  81. continue
  82. }
  83. // Splice in pre-defined range
  84. val = IP_RANGES[val]
  85. trust.splice.apply(trust, [i, 1].concat(val))
  86. i += val.length - 1
  87. }
  88. return compileTrust(compileRangeSubnets(trust))
  89. }
  90. /**
  91. * Compile `arr` elements into range subnets.
  92. *
  93. * @param {Array} arr
  94. * @private
  95. */
  96. function compileRangeSubnets (arr) {
  97. var rangeSubnets = new Array(arr.length)
  98. for (var i = 0; i < arr.length; i++) {
  99. rangeSubnets[i] = parseipNotation(arr[i])
  100. }
  101. return rangeSubnets
  102. }
  103. /**
  104. * Compile range subnet array into trust function.
  105. *
  106. * @param {Array} rangeSubnets
  107. * @private
  108. */
  109. function compileTrust (rangeSubnets) {
  110. // Return optimized function based on length
  111. var len = rangeSubnets.length
  112. return len === 0
  113. ? trustNone
  114. : len === 1
  115. ? trustSingle(rangeSubnets[0])
  116. : trustMulti(rangeSubnets)
  117. }
  118. /**
  119. * Parse IP notation string into range subnet.
  120. *
  121. * @param {String} note
  122. * @private
  123. */
  124. function parseipNotation (note) {
  125. var pos = note.lastIndexOf('/')
  126. var str = pos !== -1
  127. ? note.substring(0, pos)
  128. : note
  129. if (!isip(str)) {
  130. throw new TypeError('invalid IP address: ' + str)
  131. }
  132. var ip = parseip(str)
  133. if (pos === -1 && ip.kind() === 'ipv6' && ip.isIPv4MappedAddress()) {
  134. // Store as IPv4
  135. ip = ip.toIPv4Address()
  136. }
  137. var max = ip.kind() === 'ipv6'
  138. ? 128
  139. : 32
  140. var range = pos !== -1
  141. ? note.substring(pos + 1, note.length)
  142. : null
  143. if (range === null) {
  144. range = max
  145. } else if (DIGIT_REGEXP.test(range)) {
  146. range = parseInt(range, 10)
  147. } else if (ip.kind() === 'ipv4' && isip(range)) {
  148. range = parseNetmask(range)
  149. } else {
  150. range = null
  151. }
  152. if (range <= 0 || range > max) {
  153. throw new TypeError('invalid range on address: ' + note)
  154. }
  155. return [ip, range]
  156. }
  157. /**
  158. * Parse netmask string into CIDR range.
  159. *
  160. * @param {String} netmask
  161. * @private
  162. */
  163. function parseNetmask (netmask) {
  164. var ip = parseip(netmask)
  165. var kind = ip.kind()
  166. return kind === 'ipv4'
  167. ? ip.prefixLengthFromSubnetMask()
  168. : null
  169. }
  170. /**
  171. * Determine address of proxied request.
  172. *
  173. * @param {Object} request
  174. * @param {Function|Array|String} trust
  175. * @public
  176. */
  177. function proxyaddr (req, trust) {
  178. if (!req) {
  179. throw new TypeError('req argument is required')
  180. }
  181. if (!trust) {
  182. throw new TypeError('trust argument is required')
  183. }
  184. var addrs = alladdrs(req, trust)
  185. var addr = addrs[addrs.length - 1]
  186. return addr
  187. }
  188. /**
  189. * Static trust function to trust nothing.
  190. *
  191. * @private
  192. */
  193. function trustNone () {
  194. return false
  195. }
  196. /**
  197. * Compile trust function for multiple subnets.
  198. *
  199. * @param {Array} subnets
  200. * @private
  201. */
  202. function trustMulti (subnets) {
  203. return function trust (addr) {
  204. if (!isip(addr)) return false
  205. var ip = parseip(addr)
  206. var ipconv
  207. var kind = ip.kind()
  208. for (var i = 0; i < subnets.length; i++) {
  209. var subnet = subnets[i]
  210. var subnetip = subnet[0]
  211. var subnetkind = subnetip.kind()
  212. var subnetrange = subnet[1]
  213. var trusted = ip
  214. if (kind !== subnetkind) {
  215. if (subnetkind === 'ipv4' && !ip.isIPv4MappedAddress()) {
  216. // Incompatible IP addresses
  217. continue
  218. }
  219. if (!ipconv) {
  220. // Convert IP to match subnet IP kind
  221. ipconv = subnetkind === 'ipv4'
  222. ? ip.toIPv4Address()
  223. : ip.toIPv4MappedAddress()
  224. }
  225. trusted = ipconv
  226. }
  227. if (trusted.match(subnetip, subnetrange)) {
  228. return true
  229. }
  230. }
  231. return false
  232. }
  233. }
  234. /**
  235. * Compile trust function for single subnet.
  236. *
  237. * @param {Object} subnet
  238. * @private
  239. */
  240. function trustSingle (subnet) {
  241. var subnetip = subnet[0]
  242. var subnetkind = subnetip.kind()
  243. var subnetisipv4 = subnetkind === 'ipv4'
  244. var subnetrange = subnet[1]
  245. return function trust (addr) {
  246. if (!isip(addr)) return false
  247. var ip = parseip(addr)
  248. var kind = ip.kind()
  249. if (kind !== subnetkind) {
  250. if (subnetisipv4 && !ip.isIPv4MappedAddress()) {
  251. // Incompatible IP addresses
  252. return false
  253. }
  254. // Convert IP to match subnet IP kind
  255. ip = subnetisipv4
  256. ? ip.toIPv4Address()
  257. : ip.toIPv4MappedAddress()
  258. }
  259. return ip.match(subnetip, subnetrange)
  260. }
  261. }