Skip to content

Commit

Permalink
fix(lib): user ipaddr.js instead of ip
Browse files Browse the repository at this point in the history
- Fix to handle IPv6 address like IPv4-mapped IPv6 addresses
  • Loading branch information
azu committed Sep 5, 2019
1 parent 785c96e commit ef8c769
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 22 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@
"typescript": "^3.5.3"
},
"dependencies": {
"ip": "^1.1.5"
"ipaddr.js": "^1.9.1"
}
}
43 changes: 27 additions & 16 deletions src/request-filtering-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as net from "net";
import { Socket, TcpNetConnectOpts } from "net";
import * as http from "http";
import * as https from "https";
import ip from "ip";
import ipaddr from "ipaddr.js";

// Definition missing interface
declare module "http" {
Expand Down Expand Up @@ -39,23 +39,34 @@ export interface RequestFilteringAgentOptions {
* @param family optional
* @param options
*/
const validateAddress = ({ address, host, family }: { address: string; host?: string; family?: string | number }, options: Required<RequestFilteringAgentOptions>) => {
// prefer allowed list
if (options.allowIPAddressList.length > 0 && options.allowIPAddressList.includes(address)) {
const validateIPAddress = ({ address, host, family }: { address: string; host?: string; family?: string | number }, options: Required<RequestFilteringAgentOptions>) => {
// if it is not IP address, skip it
if (net.isIP(address) === 0) {
return;
}

if (!options.allowMetaIPAddress) {
if (address === "0.0.0.0" || address == "::") {
return new Error(`DNS lookup ${address}(family:${family}, host:${host}) is not allowed. Because, It is meta IP address.`);
try {
const addr = ipaddr.parse(address);
const range = addr.range();
// prefer allowed list
if (options.allowIPAddressList.length > 0 && options.allowIPAddressList.includes(address)) {
return;
}
if (!options.allowMetaIPAddress) {
// address === "0.0.0.0" || address == "::"
if (range === "unspecified") {
return new Error(`DNS lookup ${address}(family:${family}, host:${host}) is not allowed. Because, It is meta IP address.`);
}
}
// TODO: rename option name
if (!options.allowPrivateIPAddress && range !== "unicast") {
return new Error(`DNS lookup ${address}(family:${family}, host:${host}) is not allowed. Because, It is private IP address.`);
}
}
if (!options.allowPrivateIPAddress && ip.isPrivate(address)) {
return new Error(`DNS lookup ${address}(family:${family}, host:${host}) is not allowed. Because, It is private IP address.`);
}

if (options.denyIPAddressList.length > 0 && options.denyIPAddressList.includes(address)) {
return new Error(`DNS lookup ${address}(family:${family}, host:${host}) is not allowed. Because It is defined in denyIPAddressList.`);
if (options.denyIPAddressList.length > 0 && options.denyIPAddressList.includes(address)) {
return new Error(`DNS lookup ${address}(family:${family}, host:${host}) is not allowed. Because It is defined in denyIPAddressList.`);
}
} catch (error) {
return error; // if can not parsed IP address, throw error
}
return;
};
Expand All @@ -66,7 +77,7 @@ const addDropFilterSocket = (options: Required<RequestFilteringAgentOptions>, so
if (err) {
return;
}
const error = validateAddress({ address, family, host }, options);
const error = validateIPAddress({ address, family, host }, options);
if (error) {
socket.destroy(error);
}
Expand Down Expand Up @@ -103,7 +114,7 @@ export function applyRequestFilter<T extends http.Agent | http.Agent>(agent: T,
// Direct ip address request without dns-lookup
// Example: http://127.0.0.1
// https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener
const error = validateAddress({ address: host }, requestFilterOptions);
const error = validateIPAddress({ address: host }, requestFilterOptions);
if (error) {
socket.destroy(error);
}
Expand Down
7 changes: 6 additions & 1 deletion test/request-filtering-agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,12 @@ describe("request-filtering-agent", function() {
const privateIPs = [
`http://0.0.0.0:${TEST_PORT}`, // 0.0.0.0 is special
`http://127.0.0.1:${TEST_PORT}`, //
`http://[email protected]:${TEST_PORT}` //
`http://[email protected]:${TEST_PORT}`, //
`http://[::1]:${TEST_PORT}`, // IPv6
`http://[0:0:0:0:0:0:0:1]:${TEST_PORT}`, // IPv6 explicitly
`http://[0:0:0:0:0:ffff:127.0.0.1]:${TEST_PORT}`, // IPv4-mapped IPv6 addresses
`http://[::ffff:127.0.0.1]:${TEST_PORT}`, // IPv4-mapped IPv6 addresses
`http://[::ffff:7f00:1]:${TEST_PORT}`, // IPv4-mapped IPv6 addresses
];
for (const ipAddress of privateIPs) {
try {
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -729,10 +729,10 @@ invert-kv@^2.0.0:
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==

ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
ipaddr.js@^1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==

is-arrayish@^0.2.1:
version "0.2.1"
Expand Down

0 comments on commit ef8c769

Please sign in to comment.