Comparing version 2.5.1 to 2.6.0-beta.1
@@ -48,3 +48,3 @@ "use strict"; | ||
callback(err); | ||
return resolve(); // Resolves pending promise (prevents memory leaks). | ||
return resolve(err); // Resolves pending promise (prevents memory leaks). | ||
} | ||
@@ -61,3 +61,3 @@ else { | ||
callback(null, info); | ||
resolve(); // Resolves pending promise (prevents memory leaks). | ||
resolve(info); // Resolves pending promise (prevents memory leaks). | ||
} | ||
@@ -73,3 +73,3 @@ else { | ||
callback(err); | ||
resolve(); // Resolves pending promise (prevents memory leaks). | ||
resolve(err); // Resolves pending promise (prevents memory leaks). | ||
} | ||
@@ -100,3 +100,3 @@ else { | ||
callback(err); | ||
return resolve(); // Resolves pending promise (prevents memory leaks). | ||
return resolve(err); // Resolves pending promise (prevents memory leaks). | ||
} | ||
@@ -128,2 +128,3 @@ else { | ||
destination: nextDestination, | ||
// Initial connection ignores this as sock is undefined. Subsequent connections re-use the first proxy socket to form a chain. | ||
}); | ||
@@ -137,3 +138,3 @@ // If sock is undefined, assign it here. | ||
callback(null, { socket: sock }); | ||
resolve(); // Resolves pending promise (prevents memory leaks). | ||
resolve({ socket: sock }); // Resolves pending promise (prevents memory leaks). | ||
} | ||
@@ -147,3 +148,3 @@ else { | ||
callback(err); | ||
resolve(); // Resolves pending promise (prevents memory leaks). | ||
resolve(err); // Resolves pending promise (prevents memory leaks). | ||
} | ||
@@ -482,14 +483,19 @@ else { | ||
const buff = new smart_buffer_1.SmartBuffer(); | ||
buff.writeUInt8(0x05); | ||
// By default we always support no auth. | ||
const supportedAuthMethods = [constants_1.Socks5Auth.NoAuth]; | ||
// We should only tell the proxy we support user/pass auth if auth info is actually provided. | ||
// Note: As of Tor v0.3.5.7+, if user/pass auth is an option from the client, by default it will always take priority. | ||
if (this.options.proxy.userId || this.options.proxy.password) { | ||
buff.writeUInt8(2); | ||
buff.writeUInt8(constants_1.Socks5Auth.NoAuth); | ||
buff.writeUInt8(constants_1.Socks5Auth.UserPass); | ||
supportedAuthMethods.push(constants_1.Socks5Auth.UserPass); | ||
} | ||
else { | ||
buff.writeUInt8(1); | ||
buff.writeUInt8(constants_1.Socks5Auth.NoAuth); | ||
// Custom auth method? | ||
if (this.options.proxy.custom_auth_method !== undefined) { | ||
supportedAuthMethods.push(this.options.proxy.custom_auth_method); | ||
} | ||
// Build handshake packet | ||
buff.writeUInt8(0x05); | ||
buff.writeUInt8(supportedAuthMethods.length); | ||
for (const authMethod of supportedAuthMethods) { | ||
buff.writeUInt8(authMethod); | ||
} | ||
this.nextRequiredPacketBufferSize = | ||
@@ -509,3 +515,3 @@ constants_1.SOCKS_INCOMING_PACKET_SIZES.Socks5InitialHandshakeResponse; | ||
} | ||
else if (data[1] === 0xff) { | ||
else if (data[1] === constants_1.SOCKS5_NO_ACCEPTABLE_AUTH) { | ||
this.closeSocket(constants_1.ERRORS.InvalidSocks5InitialHandshakeNoAcceptedAuthType); | ||
@@ -516,2 +522,3 @@ } | ||
if (data[1] === constants_1.Socks5Auth.NoAuth) { | ||
this.socks5ChosenAuthType = constants_1.Socks5Auth.NoAuth; | ||
this.sendSocks5CommandRequest(); | ||
@@ -521,4 +528,10 @@ // If selected Socks v5 auth method is user/password, send auth handshake. | ||
else if (data[1] === constants_1.Socks5Auth.UserPass) { | ||
this.socks5ChosenAuthType = constants_1.Socks5Auth.UserPass; | ||
this.sendSocks5UserPassAuthentication(); | ||
// If selected Socks v5 auth method is the custom_auth_method, send custom handshake. | ||
} | ||
else if (data[1] === this.options.proxy.custom_auth_method) { | ||
this.socks5ChosenAuthType = this.options.proxy.custom_auth_method; | ||
this.sendSocks5CustomAuthentication(); | ||
} | ||
else { | ||
@@ -548,2 +561,24 @@ this.closeSocket(constants_1.ERRORS.InvalidSocks5InitialHandshakeUnknownAuthType); | ||
} | ||
sendSocks5CustomAuthentication() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.nextRequiredPacketBufferSize = this.options.proxy.custom_auth_response_size; | ||
this.socket.write(yield this.options.proxy.custom_auth_request_handler()); | ||
this.setState(constants_1.SocksClientState.SentAuthentication); | ||
}); | ||
} | ||
handleSocks5CustomAuthHandshakeResponse(data) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return yield this.options.proxy.custom_auth_response_handler(data); | ||
}); | ||
} | ||
handleSocks5AuthenticationNoAuthHandshakeResponse(data) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return data[1] === 0x00; | ||
}); | ||
} | ||
handleSocks5AuthenticationUserPassHandshakeResponse(data) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return data[1] === 0x00; | ||
}); | ||
} | ||
/** | ||
@@ -554,10 +589,21 @@ * Handles Socks v5 auth handshake response. | ||
handleInitialSocks5AuthenticationHandshakeResponse() { | ||
this.setState(constants_1.SocksClientState.ReceivedAuthenticationResponse); | ||
const data = this.receiveBuffer.get(2); | ||
if (data[1] !== 0x00) { | ||
this.closeSocket(constants_1.ERRORS.Socks5AuthenticationFailed); | ||
} | ||
else { | ||
this.sendSocks5CommandRequest(); | ||
} | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.setState(constants_1.SocksClientState.ReceivedAuthenticationResponse); | ||
let authResult = false; | ||
if (this.socks5ChosenAuthType === constants_1.Socks5Auth.NoAuth) { | ||
authResult = yield this.handleSocks5AuthenticationNoAuthHandshakeResponse(this.receiveBuffer.get(2)); | ||
} | ||
else if (this.socks5ChosenAuthType === constants_1.Socks5Auth.UserPass) { | ||
authResult = yield this.handleSocks5AuthenticationUserPassHandshakeResponse(this.receiveBuffer.get(2)); | ||
} | ||
else if (this.socks5ChosenAuthType === this.options.proxy.custom_auth_method) { | ||
authResult = yield this.handleSocks5CustomAuthHandshakeResponse(this.receiveBuffer.get(this.options.proxy.custom_auth_response_size)); | ||
} | ||
if (!authResult) { | ||
this.closeSocket(constants_1.ERRORS.Socks5AuthenticationFailed); | ||
} | ||
else { | ||
this.sendSocks5CommandRequest(); | ||
} | ||
}); | ||
} | ||
@@ -564,0 +610,0 @@ /** |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SOCKS_INCOMING_PACKET_SIZES = exports.SocksClientState = exports.Socks5Response = exports.Socks5HostType = exports.Socks5Auth = exports.Socks4Response = exports.SocksCommand = exports.ERRORS = exports.DEFAULT_TIMEOUT = void 0; | ||
exports.SOCKS5_NO_ACCEPTABLE_AUTH = exports.SOCKS5_CUSTOM_AUTH_END = exports.SOCKS5_CUSTOM_AUTH_START = exports.SOCKS_INCOMING_PACKET_SIZES = exports.SocksClientState = exports.Socks5Response = exports.Socks5HostType = exports.Socks5Auth = exports.Socks4Response = exports.SocksCommand = exports.ERRORS = exports.DEFAULT_TIMEOUT = void 0; | ||
const DEFAULT_TIMEOUT = 30000; | ||
@@ -16,2 +16,4 @@ exports.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT; | ||
InvalidSocksClientOptionsProxiesLength: 'At least two socks proxies must be provided for chaining.', | ||
InvalidSocksClientOptionsCustomAuthRange: 'Custom auth must be a value between 0x80 and 0xFE.', | ||
InvalidSocksClientOptionsCustomAuthOptions: 'When a custom_auth_method is provided, custom_auth_request_handler, custom_auth_response_size, and custom_auth_response_handler must also be provided and valid.', | ||
NegotiationError: 'Negotiation error', | ||
@@ -45,3 +47,3 @@ SocketClosed: 'Socket closed', | ||
// Command response + incoming connection (bind) | ||
Socks4Response: 8, | ||
Socks4Response: 8, // 2 header + 2 port + 4 ip | ||
}; | ||
@@ -71,2 +73,8 @@ exports.SOCKS_INCOMING_PACKET_SIZES = SOCKS_INCOMING_PACKET_SIZES; | ||
exports.Socks5Auth = Socks5Auth; | ||
const SOCKS5_CUSTOM_AUTH_START = 0x80; | ||
exports.SOCKS5_CUSTOM_AUTH_START = SOCKS5_CUSTOM_AUTH_START; | ||
const SOCKS5_CUSTOM_AUTH_END = 0xfe; | ||
exports.SOCKS5_CUSTOM_AUTH_END = SOCKS5_CUSTOM_AUTH_END; | ||
const SOCKS5_NO_ACCEPTABLE_AUTH = 0xff; | ||
exports.SOCKS5_NO_ACCEPTABLE_AUTH = SOCKS5_NO_ACCEPTABLE_AUTH; | ||
var Socks5Response; | ||
@@ -73,0 +81,0 @@ (function (Socks5Response) { |
@@ -29,2 +29,4 @@ "use strict"; | ||
} | ||
// Validate custom auth (if set) | ||
validateCustomProxyAuth(options.proxy, options); | ||
// Check timeout | ||
@@ -65,2 +67,4 @@ if (options.timeout && !isValidTimeoutValue(options.timeout)) { | ||
} | ||
// Validate custom auth (if set) | ||
validateCustomProxyAuth(proxy, options); | ||
}); | ||
@@ -73,2 +77,25 @@ // Check timeout | ||
exports.validateSocksClientChainOptions = validateSocksClientChainOptions; | ||
function validateCustomProxyAuth(proxy, options) { | ||
if (proxy.custom_auth_method !== undefined) { | ||
// Invalid auth method range | ||
if (proxy.custom_auth_method < constants_1.SOCKS5_CUSTOM_AUTH_START || | ||
proxy.custom_auth_method > constants_1.SOCKS5_CUSTOM_AUTH_END) { | ||
throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsCustomAuthRange, options); | ||
} | ||
// Missing custom_auth_request_handler | ||
if (proxy.custom_auth_request_handler === undefined || | ||
typeof proxy.custom_auth_request_handler !== 'function') { | ||
throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsCustomAuthOptions, options); | ||
} | ||
// Missing custom_auth_response_size | ||
if (proxy.custom_auth_response_size === undefined) { | ||
throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsCustomAuthOptions, options); | ||
} | ||
// Missing/invalid custom_auth_response_handler | ||
if (proxy.custom_auth_response_handler === undefined || | ||
typeof proxy.custom_auth_response_handler !== 'function') { | ||
throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsCustomAuthOptions, options); | ||
} | ||
} | ||
} | ||
/** | ||
@@ -75,0 +102,0 @@ * Validates a SocksRemoteHost |
{ | ||
"name": "socks", | ||
"private": false, | ||
"version": "2.5.1", | ||
"version": "2.6.0-beta.1", | ||
"description": "Fully featured SOCKS proxy client supporting SOCKSv4, SOCKSv4a, and SOCKSv5. Includes Bind and Associate functionality.", | ||
@@ -37,13 +37,13 @@ "main": "build/index.js", | ||
"@types/ip": "1.1.0", | ||
"@types/mocha": "^8.0.3", | ||
"@types/node": "^14.14.3", | ||
"@types/mocha": "^8.2.1", | ||
"@types/node": "^14.14.35", | ||
"coveralls": "3.1.0", | ||
"mocha": "^8.2.0", | ||
"mocha": "^8.3.2", | ||
"nyc": "15.1.0", | ||
"prettier": "^2.1.2", | ||
"prettier": "^2.2.1", | ||
"socks5-server": "^0.1.1", | ||
"ts-node": "^9.0.0", | ||
"ts-node": "^9.1.1", | ||
"tslint": "^6.1.3", | ||
"tslint-config-airbnb": "^5.11.2", | ||
"typescript": "^4.0.3" | ||
"typescript": "^4.2.3" | ||
}, | ||
@@ -61,3 +61,3 @@ "dependencies": { | ||
"lint": "tslint --project tsconfig.json 'src/**/*.ts'", | ||
"build": "rm -rf build typings && tslint --project tsconfig.json && prettier --write ./src/**/*.ts --config .prettierrc.yaml && tsc -p ." | ||
"build": "rm -rf build typings && prettier --write ./src/**/*.ts --config .prettierrc.yaml && tsc -p ." | ||
}, | ||
@@ -64,0 +64,0 @@ "nyc": { |
@@ -25,2 +25,3 @@ /// <reference types="node" /> | ||
private nextRequiredPacketBufferSize; | ||
private socks5ChosenAuthType; | ||
private onDataReceived; | ||
@@ -136,2 +137,6 @@ private onClose; | ||
private sendSocks5UserPassAuthentication; | ||
private sendSocks5CustomAuthentication; | ||
private handleSocks5CustomAuthHandshakeResponse; | ||
private handleSocks5AuthenticationNoAuthHandshakeResponse; | ||
private handleSocks5AuthenticationUserPassHandshakeResponse; | ||
/** | ||
@@ -138,0 +143,0 @@ * Handles Socks v5 auth handshake response. |
@@ -16,2 +16,4 @@ /// <reference types="node" /> | ||
InvalidSocksClientOptionsProxiesLength: string; | ||
InvalidSocksClientOptionsCustomAuthRange: string; | ||
InvalidSocksClientOptionsCustomAuthOptions: string; | ||
NegotiationError: string; | ||
@@ -61,2 +63,5 @@ SocketClosed: string; | ||
} | ||
declare const SOCKS5_CUSTOM_AUTH_START = 128; | ||
declare const SOCKS5_CUSTOM_AUTH_END = 254; | ||
declare const SOCKS5_NO_ACCEPTABLE_AUTH = 255; | ||
declare enum Socks5Response { | ||
@@ -103,2 +108,6 @@ Granted = 0, | ||
password?: string; | ||
custom_auth_method?: number; | ||
custom_auth_request_handler?: () => Promise<Buffer>; | ||
custom_auth_response_size?: number; | ||
custom_auth_response_handler?: (data: Buffer) => Promise<boolean>; | ||
}, 'host' | 'ipaddress'>; | ||
@@ -144,2 +153,2 @@ /** | ||
} | ||
export { DEFAULT_TIMEOUT, ERRORS, SocksProxyType, SocksCommand, Socks4Response, Socks5Auth, Socks5HostType, Socks5Response, SocksClientState, SocksProxy, SocksRemoteHost, SocksCommandOption, SocksClientOptions, SocksClientChainOptions, SocksClientEstablishedEvent, SocksClientBoundEvent, SocksUDPFrameDetails, SOCKS_INCOMING_PACKET_SIZES, }; | ||
export { DEFAULT_TIMEOUT, ERRORS, SocksProxyType, SocksCommand, Socks4Response, Socks5Auth, Socks5HostType, Socks5Response, SocksClientState, SocksProxy, SocksRemoteHost, SocksCommandOption, SocksClientOptions, SocksClientChainOptions, SocksClientEstablishedEvent, SocksClientBoundEvent, SocksUDPFrameDetails, SOCKS_INCOMING_PACKET_SIZES, SOCKS5_CUSTOM_AUTH_START, SOCKS5_CUSTOM_AUTH_END, SOCKS5_NO_ACCEPTABLE_AUTH, }; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
150623
1462
1