net: tor support for outgoing conns.
This commit is contained in:
parent
5288e8a619
commit
5073c1508f
@ -162,7 +162,7 @@ WSProxy.prototype._handleConnect = function _handleConnect(ws, port, host, nonce
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IP.isRoutable(raw) || IP.isTor(raw)) {
|
if (!IP.isRoutable(raw) || IP.isOnion(raw)) {
|
||||||
this.log(
|
this.log(
|
||||||
'Client is trying to connect to a bad ip: %s (%s).',
|
'Client is trying to connect to a bad ip: %s (%s).',
|
||||||
host, state.host);
|
host, state.host);
|
||||||
|
|||||||
@ -59,8 +59,9 @@ listen: true
|
|||||||
max-outbound: 8
|
max-outbound: 8
|
||||||
max-inbound: 30
|
max-inbound: 30
|
||||||
|
|
||||||
# Websocket Proxy Server (Browser Only)
|
# Proxy Server (browser=websockets, node=socks)
|
||||||
proxy-server: localhost
|
# proxy: foo:bar@127.0.0.1:9050
|
||||||
|
# onion: true
|
||||||
|
|
||||||
# Custom list of DNS seeds
|
# Custom list of DNS seeds
|
||||||
# seeds: seed.bitcoin.sipa.be
|
# seeds: seed.bitcoin.sipa.be
|
||||||
|
|||||||
@ -468,7 +468,6 @@ function AuthDB(options) {
|
|||||||
|
|
||||||
this.logger = null;
|
this.logger = null;
|
||||||
this.resolve = dns.resolve;
|
this.resolve = dns.resolve;
|
||||||
this.proxyServer = null;
|
|
||||||
this.dnsKnown = [];
|
this.dnsKnown = [];
|
||||||
|
|
||||||
this.known = {};
|
this.known = {};
|
||||||
@ -496,11 +495,6 @@ AuthDB.prototype._init = function _init(options) {
|
|||||||
this.resolve = options.resolve;
|
this.resolve = options.resolve;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.proxyServer != null) {
|
|
||||||
assert(typeof options.proxyServer === 'string');
|
|
||||||
this.proxyServer = options.proxyServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.knownPeers != null) {
|
if (options.knownPeers != null) {
|
||||||
assert(typeof options.knownPeers === 'object');
|
assert(typeof options.knownPeers === 'object');
|
||||||
this.setKnown(options.knownPeers);
|
this.setKnown(options.knownPeers);
|
||||||
@ -638,7 +632,7 @@ AuthDB.prototype.populate = co(function* populate(addr, key) {
|
|||||||
this.logger.info('Resolving authorized hosts from: %s.', addr.host);
|
this.logger.info('Resolving authorized hosts from: %s.', addr.host);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
hosts = yield this.resolve(addr.host, this.proxyServer);
|
hosts = yield this.resolve(addr.host);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (this.logger)
|
if (this.logger)
|
||||||
this.logger.error(e);
|
this.logger.error(e);
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
var ProxySocket = require('./proxysocket');
|
var ProxySocket = require('./proxysocket');
|
||||||
var socket;
|
var socket;
|
||||||
|
|
||||||
exports.resolve = function resolve(host, proxy) {
|
exports.resolve = function resolve(host, proxy, onion) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
if (!socket)
|
if (!socket)
|
||||||
socket = new ProxySocket(proxy);
|
socket = new ProxySocket(proxy);
|
||||||
@ -30,6 +30,6 @@ exports.resolve = function resolve(host, proxy) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.lookup = function lookup(host, proxy) {
|
exports.lookup = function lookup(host, proxy, onion) {
|
||||||
return exports.resolve(host, proxy);
|
return exports.resolve(host, proxy, onion);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var dns = require('dns');
|
var dns = require('dns');
|
||||||
|
var socks = require('./socks');
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
family: 4,
|
family: 4,
|
||||||
@ -14,7 +15,10 @@ var options = {
|
|||||||
all: true
|
all: true
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.resolve = function resolve(host, proxy) {
|
exports.resolve = function resolve(host, proxy, onion) {
|
||||||
|
if (proxy && onion)
|
||||||
|
return socks.resolve(host, proxy);
|
||||||
|
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
dns.resolve(host, 'A', function(err, result) {
|
dns.resolve(host, 'A', function(err, result) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -32,7 +36,10 @@ exports.resolve = function resolve(host, proxy) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.lookup = function lookup(host, proxy) {
|
exports.lookup = function lookup(host, proxy, onion) {
|
||||||
|
if (proxy && onion)
|
||||||
|
return socks.resolve(host, proxy);
|
||||||
|
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
var addrs = [];
|
var addrs = [];
|
||||||
var i, addr;
|
var i, addr;
|
||||||
|
|||||||
@ -32,7 +32,6 @@ function HostList(options) {
|
|||||||
this.network = Network.primary;
|
this.network = Network.primary;
|
||||||
this.logger = null;
|
this.logger = null;
|
||||||
this.address = new NetAddress();
|
this.address = new NetAddress();
|
||||||
this.proxyServer = null;
|
|
||||||
this.resolve = dns.resolve;
|
this.resolve = dns.resolve;
|
||||||
this.banTime = common.BAN_TIME;
|
this.banTime = common.BAN_TIME;
|
||||||
|
|
||||||
@ -89,11 +88,6 @@ HostList.prototype._initOptions = function initOptions(options) {
|
|||||||
this.address = options.address;
|
this.address = options.address;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.proxyServer != null) {
|
|
||||||
assert(typeof options.proxyServer === 'string');
|
|
||||||
this.proxyServer = options.proxyServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.resolve != null) {
|
if (options.resolve != null) {
|
||||||
assert(typeof options.resolve === 'function');
|
assert(typeof options.resolve === 'function');
|
||||||
this.resolve = options.resolve;
|
this.resolve = options.resolve;
|
||||||
@ -804,7 +798,7 @@ HostList.prototype.populate = co(function* populate(target) {
|
|||||||
this.logger.info('Resolving host: %s.', target.host);
|
this.logger.info('Resolving host: %s.', target.host);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
hosts = yield this.resolve(target.host, this.proxyServer);
|
hosts = yield this.resolve(target.host);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (this.logger)
|
if (this.logger)
|
||||||
this.logger.error(e);
|
this.logger.error(e);
|
||||||
|
|||||||
@ -417,12 +417,11 @@ Peer.prototype.accept = function accept(socket) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.connect = function connect(addr) {
|
Peer.prototype.connect = function connect(addr) {
|
||||||
var proxy = this.options.proxyServer;
|
|
||||||
var socket;
|
var socket;
|
||||||
|
|
||||||
assert(!this.socket);
|
assert(!this.socket);
|
||||||
|
|
||||||
socket = this.options.createSocket(addr.port, addr.host, proxy);
|
socket = this.options.createSocket(addr.port, addr.host);
|
||||||
|
|
||||||
this.address = addr;
|
this.address = addr;
|
||||||
this.ts = util.now();
|
this.ts = util.now();
|
||||||
@ -2156,7 +2155,6 @@ function PeerOptions(options) {
|
|||||||
this.network = Network.primary;
|
this.network = Network.primary;
|
||||||
this.logger = Logger.global;
|
this.logger = Logger.global;
|
||||||
|
|
||||||
this.proxyServer = null;
|
|
||||||
this.createSocket = tcp.createSocket;
|
this.createSocket = tcp.createSocket;
|
||||||
this.version = common.PROTOCOL_VERSION;
|
this.version = common.PROTOCOL_VERSION;
|
||||||
this.services = common.LOCAL_SERVICES;
|
this.services = common.LOCAL_SERVICES;
|
||||||
@ -2197,11 +2195,6 @@ PeerOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.logger = options.logger;
|
this.logger = options.logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.proxyServer != null) {
|
|
||||||
assert(typeof options.proxyServer === 'string');
|
|
||||||
this.proxyServer = options.proxyServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.createSocket != null) {
|
if (options.createSocket != null) {
|
||||||
assert(typeof options.createSocket === 'function');
|
assert(typeof options.createSocket === 'function');
|
||||||
this.createSocket = options.createSocket;
|
this.createSocket = options.createSocket;
|
||||||
|
|||||||
@ -291,7 +291,7 @@ Pool.prototype._connect = co(function* connect() {
|
|||||||
|
|
||||||
yield this.listen();
|
yield this.listen();
|
||||||
|
|
||||||
if (this.address.isNull()) {
|
if (this.address.isNull() && !this.options.proxy) {
|
||||||
try {
|
try {
|
||||||
ip = yield this.getIP();
|
ip = yield this.getIP();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -1291,6 +1291,9 @@ Pool.prototype.handleAddr = co(function* handleAddr(peer, packet) {
|
|||||||
if (!addr.hasServices(services))
|
if (!addr.hasServices(services))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!this.options.onion && addr.isOnion())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (addr.ts <= 100000000 || addr.ts > now + 10 * 60)
|
if (addr.ts <= 100000000 || addr.ts > now + 10 * 60)
|
||||||
addr.ts = now - 5 * 24 * 60 * 60;
|
addr.ts = now - 5 * 24 * 60 * 60;
|
||||||
|
|
||||||
@ -2653,6 +2656,9 @@ Pool.prototype.getHost = function getHost() {
|
|||||||
if (!addr.hasServices(services))
|
if (!addr.hasServices(services))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!this.options.onion && addr.isOnion())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (i < 30 && now - entry.lastAttempt < 600)
|
if (i < 30 && now - entry.lastAttempt < 600)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -3222,10 +3228,11 @@ function PoolOptions(options) {
|
|||||||
this.port = this.network.port;
|
this.port = this.network.port;
|
||||||
this.maxOutbound = 8;
|
this.maxOutbound = 8;
|
||||||
this.maxInbound = 8;
|
this.maxInbound = 8;
|
||||||
this.createSocket = tcp.createSocket;
|
this.createSocket = this._createSocket;
|
||||||
this.createServer = tcp.createServer;
|
this.createServer = tcp.createServer;
|
||||||
this.resolve = dns.resolve;
|
this.resolve = this._resolve;
|
||||||
this.proxyServer = null;
|
this.proxy = null;
|
||||||
|
this.onion = false;
|
||||||
this.selfish = false;
|
this.selfish = false;
|
||||||
this.version = common.PROTOCOL_VERSION;
|
this.version = common.PROTOCOL_VERSION;
|
||||||
this.agent = common.USER_AGENT;
|
this.agent = common.USER_AGENT;
|
||||||
@ -3362,9 +3369,14 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.resolve = options.resolve;
|
this.resolve = options.resolve;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.proxyServer) {
|
if (options.proxy) {
|
||||||
assert(typeof options.proxyServer === 'string');
|
assert(typeof options.proxy === 'string');
|
||||||
this.proxyServer = options.proxyServer;
|
this.proxy = options.proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.onion) {
|
||||||
|
assert(typeof options.onion === 'boolean');
|
||||||
|
this.onion = options.onion;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.selfish) {
|
if (options.selfish) {
|
||||||
@ -3454,6 +3466,7 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.checkpoints = true;
|
this.checkpoints = true;
|
||||||
this.compact = false;
|
this.compact = false;
|
||||||
this.bip37 = false;
|
this.bip37 = false;
|
||||||
|
this.listen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.selfish) {
|
if (this.selfish) {
|
||||||
@ -3464,6 +3477,9 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
if (this.bip37)
|
if (this.bip37)
|
||||||
this.services |= common.services.BLOOM;
|
this.services |= common.services.BLOOM;
|
||||||
|
|
||||||
|
if (this.proxy)
|
||||||
|
this.listen = false;
|
||||||
|
|
||||||
if (options.services != null) {
|
if (options.services != null) {
|
||||||
assert(util.isUInt32(options.services));
|
assert(util.isUInt32(options.services));
|
||||||
this.services = options.services;
|
this.services = options.services;
|
||||||
@ -3576,6 +3592,29 @@ PoolOptions.prototype.getRate = function getRate(hash) {
|
|||||||
return entry.getRate();
|
return entry.getRate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default createSocket call.
|
||||||
|
* @private
|
||||||
|
* @param {Number} port
|
||||||
|
* @param {String} host
|
||||||
|
* @returns {net.Socket}
|
||||||
|
*/
|
||||||
|
|
||||||
|
PoolOptions.prototype._createSocket = function createSocket(port, host) {
|
||||||
|
return tcp.createSocket(port, host, this.proxy);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default resolve call.
|
||||||
|
* @private
|
||||||
|
* @param {String} name
|
||||||
|
* @returns {String[]}
|
||||||
|
*/
|
||||||
|
|
||||||
|
PoolOptions.prototype._resolve = function resolve(name) {
|
||||||
|
return dns.resolve(name, this.proxy, this.onion);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Peer List
|
* Peer List
|
||||||
* @constructor
|
* @constructor
|
||||||
|
|||||||
@ -8,9 +8,12 @@
|
|||||||
|
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var net = require('net');
|
var net = require('net');
|
||||||
|
var socks = require('./socks');
|
||||||
var tcp = exports;
|
var tcp = exports;
|
||||||
|
|
||||||
tcp.createSocket = function createSocket(port, host, proxy) {
|
tcp.createSocket = function createSocket(port, host, proxy) {
|
||||||
|
if (proxy)
|
||||||
|
return socks.connect(proxy, port, host);
|
||||||
return net.connect(port, host);
|
return net.connect(port, host);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -192,7 +192,8 @@ config.parseData = function parseData(data, prefix, dirname) {
|
|||||||
options.bip151 = bool(data.bip151);
|
options.bip151 = bool(data.bip151);
|
||||||
options.bip150 = bool(data.bip150);
|
options.bip150 = bool(data.bip150);
|
||||||
options.identityKey = key(data.identitykey);
|
options.identityKey = key(data.identitykey);
|
||||||
options.proxyServer = str(data.proxyserver);
|
options.proxy = str(data.proxy);
|
||||||
|
options.onion = bool(data.onion);
|
||||||
options.seeds = list(data.seeds);
|
options.seeds = list(data.seeds);
|
||||||
options.nodes = list(data.nodes);
|
options.nodes = list(data.nodes);
|
||||||
options.maxOutbound = num(data.maxoutbound);
|
options.maxOutbound = num(data.maxoutbound);
|
||||||
|
|||||||
@ -110,7 +110,8 @@ function FullNode(options) {
|
|||||||
identityKey: this.options.identityKey,
|
identityKey: this.options.identityKey,
|
||||||
maxOutbound: this.options.maxOutbound,
|
maxOutbound: this.options.maxOutbound,
|
||||||
maxInbound: this.options.maxInbound,
|
maxInbound: this.options.maxInbound,
|
||||||
proxyServer: this.options.proxyServer,
|
proxy: this.options.proxy,
|
||||||
|
onion: this.options.onion,
|
||||||
seeds: this.options.seeds,
|
seeds: this.options.seeds,
|
||||||
nodes: this.options.nodes,
|
nodes: this.options.nodes,
|
||||||
publicHost: this.options.publicHost,
|
publicHost: this.options.publicHost,
|
||||||
|
|||||||
@ -60,7 +60,8 @@ function SPVNode(options) {
|
|||||||
network: this.network,
|
network: this.network,
|
||||||
logger: this.logger,
|
logger: this.logger,
|
||||||
chain: this.chain,
|
chain: this.chain,
|
||||||
proxyServer: this.options.proxyServer,
|
proxy: this.options.proxy,
|
||||||
|
onion: this.options.onion,
|
||||||
seeds: this.options.seeds,
|
seeds: this.options.seeds,
|
||||||
nodes: this.options.nodes,
|
nodes: this.options.nodes,
|
||||||
bip151: this.options.bip151,
|
bip151: this.options.bip151,
|
||||||
|
|||||||
@ -164,8 +164,8 @@ NetAddress.prototype.isRoutable = function isRoutable() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.isTor = function isTor() {
|
NetAddress.prototype.isOnion = function isOnion() {
|
||||||
return IP.isTor(this.raw);
|
return IP.isOnion(this.raw);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -47,7 +47,7 @@ IP.types = {
|
|||||||
DNS: -1,
|
DNS: -1,
|
||||||
IPV4: 4,
|
IPV4: 4,
|
||||||
IPV6: 6,
|
IPV6: 6,
|
||||||
TOR: 10
|
ONION: 10
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -178,8 +178,8 @@ IP.getStringType = function getStringType(str) {
|
|||||||
if (IP.isV6String(str))
|
if (IP.isV6String(str))
|
||||||
return IP.types.IPV6;
|
return IP.types.IPV6;
|
||||||
|
|
||||||
if (IP.isTorString(str))
|
if (IP.isOnionString(str))
|
||||||
return IP.types.TOR;
|
return IP.types.ONION;
|
||||||
|
|
||||||
return IP.types.DNS;
|
return IP.types.DNS;
|
||||||
};
|
};
|
||||||
@ -226,7 +226,7 @@ IP.isV6String = function isV6String(str) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
IP.isTorString = function isTorString(str) {
|
IP.isOnionString = function isOnionString(str) {
|
||||||
assert(typeof str === 'string');
|
assert(typeof str === 'string');
|
||||||
|
|
||||||
if (str.length < 7)
|
if (str.length < 7)
|
||||||
@ -278,7 +278,7 @@ IP.toBuffer = function toBuffer(str) {
|
|||||||
return IP.parseV4(str, raw, 12);
|
return IP.parseV4(str, raw, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IP.isTorString(str)) {
|
if (IP.isOnionString(str)) {
|
||||||
data = TOR_ONION;
|
data = TOR_ONION;
|
||||||
data.copy(raw, 0);
|
data.copy(raw, 0);
|
||||||
data = base32.decode(str.slice(0, -6));
|
data = base32.decode(str.slice(0, -6));
|
||||||
@ -420,7 +420,7 @@ IP.toString = function toString(raw) {
|
|||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IP.isTor(raw)) {
|
if (IP.isOnion(raw)) {
|
||||||
host = base32.encode(raw.slice(6));
|
host = base32.encode(raw.slice(6));
|
||||||
return host + '.onion';
|
return host + '.onion';
|
||||||
}
|
}
|
||||||
@ -466,7 +466,7 @@ IP.isIPv4 = function isIPv4(raw) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
IP.isIPv6 = function isIPv6(raw) {
|
IP.isIPv6 = function isIPv6(raw) {
|
||||||
return !IP.isMapped(raw) && !IP.isTor(raw);
|
return !IP.isMapped(raw) && !IP.isOnion(raw);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -482,8 +482,8 @@ IP.getType = function getType(raw) {
|
|||||||
if (IP.isIPv6(raw))
|
if (IP.isIPv6(raw))
|
||||||
return IP.types.IPV6;
|
return IP.types.IPV6;
|
||||||
|
|
||||||
if (IP.isTor(raw))
|
if (IP.isOnion(raw))
|
||||||
return IP.types.TOR;
|
return IP.types.ONION;
|
||||||
|
|
||||||
assert(false, 'Unknown type.');
|
assert(false, 'Unknown type.');
|
||||||
};
|
};
|
||||||
@ -727,7 +727,7 @@ IP.isRFC4843 = function isRFC4843(raw) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
IP.isTor = function isTor(raw) {
|
IP.isOnion = function isOnion(raw) {
|
||||||
return IP.hasPrefix(raw, TOR_ONION);
|
return IP.hasPrefix(raw, TOR_ONION);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -815,7 +815,7 @@ IP.isRoutable = function isRoutable(raw) {
|
|||||||
if (IP.isRFC5737(raw))
|
if (IP.isRFC5737(raw))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (IP.isRFC4193(raw) && !IP.isTor(raw))
|
if (IP.isRFC4193(raw) && !IP.isOnion(raw))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (IP.isRFC4843(raw))
|
if (IP.isRFC4843(raw))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user