1 | var socks = require('socks').SocksClient;
|
2 | var toPull = require('stream-to-pull-stream')
|
3 | var debug = require('debug')('multiserver:onion')
|
4 |
|
5 | module.exports = function (opts) {
|
6 | if(!socks) {
|
7 | debug('onion dialing through socks proxy not supported in browser setting')
|
8 | return {
|
9 | name: 'onion',
|
10 | scope: function() { return 'public' },
|
11 | parse: function (s) { return null }
|
12 | }
|
13 | }
|
14 |
|
15 | opts = opts || {}
|
16 | var daemonProxyOpts = {
|
17 | ipaddress: "127.0.0.1",
|
18 | port: 9050,
|
19 | type: 5
|
20 | }
|
21 | var browserProxyOpts = {
|
22 | ipaddress: "127.0.0.1",
|
23 | port: 9150,
|
24 | type: 5
|
25 | }
|
26 |
|
27 | return {
|
28 | name: 'onion',
|
29 | scope: function() { return opts.scope || 'public' },
|
30 | server: function (onConnection, cb) {
|
31 | cb(new Error("Use net plugin for onion server instead"))
|
32 | },
|
33 | client: function (opts, cb) {
|
34 | var started = false, _socket, destroy
|
35 |
|
36 | function tryConnect(connectOpts, onFail) {
|
37 | socks.createConnection(connectOpts, function(err, result) {
|
38 | if (err) return onFail(err)
|
39 |
|
40 | var socket = result.socket
|
41 |
|
42 | if(destroy) return socket.destroy()
|
43 | _socket = socket
|
44 |
|
45 | var duplexStream = toPull.duplex(socket)
|
46 | duplexStream.address = 'onion:'+connectOpts.destination.host+':'+connectOpts.destination.port
|
47 |
|
48 | cb(null, duplexStream)
|
49 |
|
50 |
|
51 | socket.resume()
|
52 | })
|
53 | }
|
54 |
|
55 | function connectOpts(proxyOpts) {
|
56 | return {
|
57 | proxy: proxyOpts,
|
58 | command: "connect",
|
59 | destination: {
|
60 | host: opts.host,
|
61 | port: opts.port
|
62 | }
|
63 | }
|
64 | }
|
65 |
|
66 | tryConnect(connectOpts(daemonProxyOpts), function(err) {
|
67 | tryConnect(connectOpts(browserProxyOpts), function(err) {
|
68 | cb(err)
|
69 | })
|
70 | })
|
71 |
|
72 | return function () {
|
73 | if(_socket) _socket.destroy()
|
74 | else destroy = true
|
75 | }
|
76 | },
|
77 |
|
78 | parse: function (s) {
|
79 | var ary = s.split(':')
|
80 | if(ary.length < 3) return null
|
81 | if('onion' !== ary.shift()) return null
|
82 | var port = +ary.pop()
|
83 | if(isNaN(port)) return null
|
84 | return {
|
85 | name: 'onion',
|
86 | host: ary.join(':') || 'localhost',
|
87 | port: port
|
88 | }
|
89 | },
|
90 | stringify: function (scope) {
|
91 | return null
|
92 | }
|
93 | }
|
94 | }
|