You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
8.5 KiB

6 months ago
  1. # ipaddr.js — an IPv6 and IPv4 address manipulation library
  2. [![Build Status](https://github.com/whitequark/ipaddr.js/workflows/CI%20Tests/badge.svg)](https://github.com/whitequark/ipaddr.js/actions?query=workflow%3A%22CI+Tests%22)
  3. ipaddr.js is a small (1.9K minified and gzipped) library for manipulating
  4. IP addresses in JavaScript environments. It runs on both CommonJS runtimes
  5. (e.g. [nodejs]) and in a web browser.
  6. ipaddr.js allows you to verify and parse string representation of an IP
  7. address, match it against a CIDR range or range list, determine if it falls
  8. into some reserved ranges (examples include loopback and private ranges),
  9. and convert between IPv4 and IPv4-mapped IPv6 addresses.
  10. [nodejs]: http://nodejs.org
  11. ## Installation
  12. `npm install ipaddr.js`
  13. or
  14. `bower install ipaddr.js`
  15. ## Older Node support
  16. Use 2.x release for nodejs versions 10+.
  17. Use the 1.x release for versions of nodejs older than 10.
  18. ## API
  19. ipaddr.js defines one object in the global scope: `ipaddr`. In CommonJS,
  20. it is exported from the module:
  21. ```js
  22. const ipaddr = require('ipaddr.js');
  23. ```
  24. The API consists of several global methods and two classes: ipaddr.IPv6 and ipaddr.IPv4.
  25. ### Global methods
  26. There are four global methods defined: `ipaddr.isValid`, `ipaddr.isValidCIDR`,
  27. `ipaddr.parse`, and `ipaddr.process`. All of them receive a string as a single
  28. parameter.
  29. The `ipaddr.isValid` method returns `true` if the address is a valid IPv4 or
  30. IPv6 address, and `false` otherwise. It does not throw any exceptions.
  31. The `ipaddr.isValidCIDR` method returns `true` if the address is a valid IPv4 or
  32. IPv6 address in CIDR notation, and `false` otherwise. It does not throw any exceptions.
  33. The `ipaddr.parse` method returns an object representing the IP address,
  34. or throws an `Error` if the passed string is not a valid representation of an
  35. IP address.
  36. The `ipaddr.process` method works just like the `ipaddr.parse` one, but it
  37. automatically converts IPv4-mapped IPv6 addresses to their IPv4 counterparts
  38. before returning. It is useful when you have a Node.js instance listening
  39. on an IPv6 socket, and the `net.ivp6.bindv6only` sysctl parameter (or its
  40. equivalent on non-Linux OS) is set to 0. In this case, you can accept IPv4
  41. connections on your IPv6-only socket, but the remote address will be mangled.
  42. Use `ipaddr.process` method to automatically demangle it.
  43. ### Object representation
  44. Parsing methods return an object which descends from `ipaddr.IPv6` or
  45. `ipaddr.IPv4`. These objects share some properties, but most of them differ.
  46. #### Shared properties
  47. One can determine the type of address by calling `addr.kind()`. It will return
  48. either `"ipv6"` or `"ipv4"`.
  49. An address can be converted back to its string representation with `addr.toString()`.
  50. Note that this method:
  51. * does not return the original string used to create the object (in fact, there is
  52. no way of getting that string)
  53. * returns a compact representation (when it is applicable)
  54. A `match(range, bits)` method can be used to check if the address falls into a
  55. certain CIDR range. Note that an address can be (obviously) matched only against an address of the same type.
  56. For example:
  57. ```js
  58. const addr = ipaddr.parse('2001:db8:1234::1');
  59. const range = ipaddr.parse('2001:db8::');
  60. addr.match(range, 32); // => true
  61. ```
  62. Alternatively, `match` can also be called as `match([range, bits])`. In this way, it can be used together with the `parseCIDR(string)` method, which parses an IP address together with a CIDR range.
  63. For example:
  64. ```js
  65. const addr = ipaddr.parse('2001:db8:1234::1');
  66. addr.match(ipaddr.parseCIDR('2001:db8::/32')); // => true
  67. ```
  68. A `range()` method returns one of predefined names for several special ranges defined by IP protocols. The exact names (and their respective CIDR ranges) can be looked up in the source: [IPv6 ranges] and [IPv4 ranges]. Some common ones include `"unicast"` (the default one) and `"reserved"`.
  69. You can match against your own range list by using
  70. `ipaddr.subnetMatch(address, rangeList, defaultName)` method. It can work with a mix of IPv6 or IPv4 addresses, and accepts a name-to-subnet map as the range list. For example:
  71. ```js
  72. const rangeList = {
  73. documentationOnly: [ ipaddr.parse('2001:db8::'), 32 ],
  74. tunnelProviders: [
  75. [ ipaddr.parse('2001:470::'), 32 ], // he.net
  76. [ ipaddr.parse('2001:5c0::'), 32 ] // freenet6
  77. ]
  78. };
  79. ipaddr.subnetMatch(ipaddr.parse('2001:470:8:66::1'), rangeList, 'unknown'); // => "tunnelProviders"
  80. ```
  81. The addresses can be converted to their byte representation with `toByteArray()`. (Actually, JavaScript mostly does not know about byte buffers. They are emulated with arrays of numbers, each in range of 0..255.)
  82. ```js
  83. const bytes = ipaddr.parse('2a00:1450:8007::68').toByteArray(); // ipv6.google.com
  84. bytes // => [42, 0x00, 0x14, 0x50, 0x80, 0x07, 0x00, <zeroes...>, 0x00, 0x68 ]
  85. ```
  86. The `ipaddr.IPv4` and `ipaddr.IPv6` objects have some methods defined, too. All of them have the same interface for both protocols, and are similar to global methods.
  87. `ipaddr.IPvX.isValid(string)` can be used to check if the string is a valid address for particular protocol, and `ipaddr.IPvX.parse(string)` is the error-throwing parser.
  88. `ipaddr.IPvX.isValid(string)` uses the same format for parsing as the POSIX `inet_ntoa` function, which accepts unusual formats like `0xc0.168.1.1` or `0x10000000`. The function `ipaddr.IPv4.isValidFourPartDecimal(string)` validates the IPv4 address and also ensures that it is written in four-part decimal format.
  89. [IPv6 ranges]: https://github.com/whitequark/ipaddr.js/blob/master/lib/ipaddr.js#L530
  90. [IPv4 ranges]: https://github.com/whitequark/ipaddr.js/blob/master/lib/ipaddr.js#L182
  91. #### IPv6 properties
  92. Sometimes you will want to convert IPv6 not to a compact string representation (with the `::` substitution); the `toNormalizedString()` method will return an address where all zeroes are explicit.
  93. For example:
  94. ```js
  95. const addr = ipaddr.parse('2001:0db8::0001');
  96. addr.toString(); // => '2001:db8::1'
  97. addr.toNormalizedString(); // => '2001:db8:0:0:0:0:0:1'
  98. ```
  99. The `isIPv4MappedAddress()` method will return `true` if this address is an IPv4-mapped
  100. one, and `toIPv4Address()` will return an IPv4 object address.
  101. To access the underlying binary representation of the address, use `addr.parts`.
  102. ```js
  103. const addr = ipaddr.parse('2001:db8:10::1234:DEAD');
  104. addr.parts // => [0x2001, 0xdb8, 0x10, 0, 0, 0, 0x1234, 0xdead]
  105. ```
  106. A IPv6 zone index can be accessed via `addr.zoneId`:
  107. ```js
  108. const addr = ipaddr.parse('2001:db8::%eth0');
  109. addr.zoneId // => 'eth0'
  110. ```
  111. #### IPv4 properties
  112. `toIPv4MappedAddress()` will return a corresponding IPv4-mapped IPv6 address.
  113. To access the underlying representation of the address, use `addr.octets`.
  114. ```js
  115. const addr = ipaddr.parse('192.168.1.1');
  116. addr.octets // => [192, 168, 1, 1]
  117. ```
  118. `prefixLengthFromSubnetMask()` will return a CIDR prefix length for a valid IPv4 netmask or
  119. null if the netmask is not valid.
  120. ```js
  121. ipaddr.IPv4.parse('255.255.255.240').prefixLengthFromSubnetMask() == 28
  122. ipaddr.IPv4.parse('255.192.164.0').prefixLengthFromSubnetMask() == null
  123. ```
  124. `subnetMaskFromPrefixLength()` will return an IPv4 netmask for a valid CIDR prefix length.
  125. ```js
  126. ipaddr.IPv4.subnetMaskFromPrefixLength(24) == '255.255.255.0'
  127. ipaddr.IPv4.subnetMaskFromPrefixLength(29) == '255.255.255.248'
  128. ```
  129. `broadcastAddressFromCIDR()` will return the broadcast address for a given IPv4 interface and netmask in CIDR notation.
  130. ```js
  131. ipaddr.IPv4.broadcastAddressFromCIDR('172.0.0.1/24') == '172.0.0.255'
  132. ```
  133. `networkAddressFromCIDR()` will return the network address for a given IPv4 interface and netmask in CIDR notation.
  134. ```js
  135. ipaddr.IPv4.networkAddressFromCIDR('172.0.0.1/24') == '172.0.0.0'
  136. ```
  137. #### Conversion
  138. IPv4 and IPv6 can be converted bidirectionally to and from network byte order (MSB) byte arrays.
  139. The `fromByteArray()` method will take an array and create an appropriate IPv4 or IPv6 object
  140. if the input satisfies the requirements. For IPv4 it has to be an array of four 8-bit values,
  141. while for IPv6 it has to be an array of sixteen 8-bit values.
  142. For example:
  143. ```js
  144. const addr = ipaddr.fromByteArray([0x7f, 0, 0, 1]);
  145. addr.toString(); // => '127.0.0.1'
  146. ```
  147. or
  148. ```js
  149. const addr = ipaddr.fromByteArray([0x20, 1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
  150. addr.toString(); // => '2001:db8::1'
  151. ```
  152. Both objects also offer a `toByteArray()` method, which returns an array in network byte order (MSB).
  153. For example:
  154. ```js
  155. const addr = ipaddr.parse('127.0.0.1');
  156. addr.toByteArray(); // => [0x7f, 0, 0, 1]
  157. ```
  158. or
  159. ```js
  160. const addr = ipaddr.parse('2001:db8::1');
  161. addr.toByteArray(); // => [0x20, 1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
  162. ```