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