Skip to content
This repository was archived by the owner on Nov 21, 2019. It is now read-only.

Commit ba5605f

Browse files
author
icymind
committed
replace scp2 with ssh2
1 parent 94c9eb6 commit ba5605f

File tree

7 files changed

+208
-417
lines changed

7 files changed

+208
-417
lines changed

js/manage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ const myApp = new Vue({
276276
switch (currentProxies) {
277277
case 'ss':
278278
vrouter.generateConfig('shadowsocks')
279-
vrouter.scpConfig('shadowsocks')
279+
this.remote.scpConfig('shadowsocks')
280280
this.remote.service('shadowsocks', 'restart')
281281
break
282282
case 'ssr':

js/vrouter-local.js

Lines changed: 41 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
const { exec } = require('child_process')
22
const Client = require('ssh2').Client
3-
const scpClient = require('scp2')
43
const { URL } = require('url')
54
const http = require('http')
65
const https = require('https')
@@ -274,26 +273,49 @@ class VRouter {
274273
await this.wait(10000)
275274

276275
await this.installPackage()
277-
this.process.emit('build', '更新软件源并安装必要软件包, 请稍候60秒')
278-
await this.wait(60000)
276+
this.process.emit('build', '更新软件源并安装必要软件包, 请稍候20-60秒')
277+
await this.wait(20000)
278+
// return this.serialLog('done: install package && restart dropbear')
279+
280+
let remote
281+
let retry = -1
282+
while (true) {
283+
try {
284+
retry += 1
285+
remote = await this.connect()
286+
const output = await remote.remoteExec('tail -n 1 /vrouter.log')
287+
if (output === 'done: install package && restart dropbear') {
288+
winston.debug('安装软件包完成')
289+
this.process.emit('build', '安装软件包完成')
290+
break
291+
} else {
292+
throw Error('未完成')
293+
}
294+
} catch (err) {
295+
if (retry >= 4) {
296+
throw Error('未能安装软件包, 请确保网络通畅后重试')
297+
}
298+
winston.debug('安装软件包未完成, 10秒后重试')
299+
// this.process.emit('buid', '无法登录到虚拟机, 10秒后重试')
300+
await this.wait(10000)
301+
}
302+
}
303+
this.process.emit('build', '成功登录虚拟机')
304+
await this.serialLog('done: connect to vm')
279305

280306
const src = path.join(__dirname, '..', 'third_party')
281307
const dst = this.config.vrouter.configDir + '/third_party/'
282-
await this.scp(src, dst)
308+
await remote.scp(src, dst)
283309
.catch((error) => {
284310
throw error
285311
})
286312
this.process.emit('build', '拷贝 shadowsocks[r] 以及 kcptun 到虚拟机')
287313
await this.serialLog('done: scp third_party')
288314

289-
await this.scpConfigAll()
315+
await remote.scpConfigAll()
290316
this.process.emit('build', '拷贝配置文件到虚拟机')
291317
await this.serialLog('done: scpConfigAll')
292318

293-
const remote = await this.connect()
294-
this.process.emit('build', '登录虚拟机')
295-
await this.serialLog('done: connect to vm')
296-
297319
await remote.installKt()
298320
await this.serialLog('done: installKt')
299321
this.process.emit('build', '安装 kcptun')
@@ -1495,10 +1517,10 @@ class VRouter {
14951517
this.config = newCfg
14961518

14971519
const thirdParty = path.join(__dirname, '..', 'third_party')
1498-
await this.scp(`${thirdParty}/ssr-tunnel`, '/usr/bin/')
1499-
await this.scp(`${thirdParty}/ssr-redir`, '/usr/bin/')
15001520
const remote = await this.connect()
1501-
await this.remoteExec('chmod +x /usr/bin/ssr-*')
1521+
await remote.scp(`${thirdParty}/ssr-tunnel`, '/usr/bin/')
1522+
await remote.scp(`${thirdParty}/ssr-redir`, '/usr/bin/')
1523+
await remote.remoteExec('chmod +x /usr/bin/ssr-*')
15021524
await remote.remoteExec('opkg update && opkg install libopenssl')
15031525
await remote.service('shadowsocks', 'stop').catch(() => {})
15041526
await remote.service('kcptun', 'stop').catch(() => {})
@@ -1508,27 +1530,6 @@ class VRouter {
15081530
}
15091531
return this.saveCfg2File()
15101532
}
1511-
async scp (src, dst) {
1512-
if (!src) {
1513-
throw Error('must specify src for scp')
1514-
}
1515-
let dest = dst || this.config.vrouter.configDir
1516-
const opt = {
1517-
host: this.config.vrouter.ip,
1518-
username: this.config.vrouter.username,
1519-
password: this.config.vrouter.password,
1520-
path: dest
1521-
}
1522-
return new Promise((resolve, reject) => {
1523-
scpClient.scp(src, opt, (err) => {
1524-
if (err) {
1525-
reject(err)
1526-
} else {
1527-
resolve(dest)
1528-
}
1529-
})
1530-
})
1531-
}
15321533
async copyTemplate (fileName) {
15331534
const template = path.join(__dirname, '..', 'config', fileName)
15341535
const dest = path.join(this.config.host.configDir, fileName)
@@ -1541,91 +1542,6 @@ class VRouter {
15411542
return dest
15421543
}
15431544
}
1544-
async scpConfig (type = 'shadowsocks', overwrite = false) {
1545-
let p
1546-
switch (type) {
1547-
case 'tunnelDnsService':
1548-
p = await this.generateService('tunnelDns')
1549-
await this.scp(p, '/etc/init.d/')
1550-
await this.serialExec(`chmod +x /etc/init.d/${this.config.tunnelDns.service}`)
1551-
break
1552-
case 'ssService':
1553-
p = await this.generateService('shadowsocks')
1554-
await this.scp(p, '/etc/init.d/')
1555-
await this.serialExec(`chmod +x /etc/init.d/${this.config.shadowsocks.service}`)
1556-
break
1557-
case 'ssrService':
1558-
p = await this.generateService('shadowsocksr')
1559-
await this.scp(p, '/etc/init.d/')
1560-
await this.serialExec(`chmod +x /etc/init.d/${this.config.shadowsocksr.service}`)
1561-
break
1562-
case 'ktService':
1563-
p = await this.generateService('kcptun')
1564-
winston.debug(`generateService-kcptun for proxies: ${this.config.firewall.currentProxies}`)
1565-
await this.scp(p, '/etc/init.d/')
1566-
await this.serialExec(`chmod +x /etc/init.d/${this.config.kcptun.service}`)
1567-
break
1568-
case 'tunnelDns':
1569-
case 'shadowsocks':
1570-
case 'shadowsocksr':
1571-
case 'kcptun':
1572-
p = await this.generateConfig(type)
1573-
for (let i = 0; i < p.length; i++) {
1574-
await this.scp(p[i], this.config.vrouter.configDir)
1575-
}
1576-
break
1577-
case 'dnsmasq':
1578-
p = await this.generateDnsmasqCf(overwrite)
1579-
await this.scp(p, '/etc/dnsmasq.d/')
1580-
break
1581-
case 'ipset':
1582-
p = await this.generateIPsets(overwrite)
1583-
winston.debug('generated ipset')
1584-
await this.scp(p, this.config.vrouter.configDir)
1585-
break
1586-
case 'firewall':
1587-
p = await this.generateFWRules(null, null, overwrite)
1588-
await this.scp(p, '/etc/')
1589-
break
1590-
case 'watchdog':
1591-
p = await this.generateWatchdog()
1592-
await this.scp(p, this.config.vrouter.configDir)
1593-
await this.serialExec(`chmod +x ${this.config.vrouter.configDir}/${this.config.firewall.watchdogFile}`)
1594-
break
1595-
case 'cron':
1596-
p = await this.generateCronJob()
1597-
await this.scp(p, this.config.vrouter.configDir)
1598-
break
1599-
}
1600-
}
1601-
async scpConfigAll (overwrite) {
1602-
const types = [
1603-
'dnsmasq',
1604-
'ipset',
1605-
'firewall',
1606-
'watchdog',
1607-
'cron'
1608-
]
1609-
if (this.config.firewall.enableTunnelDns) {
1610-
types.push('tunnelDnsService')
1611-
types.push('tunnelDns')
1612-
}
1613-
const proxies = this.config.firewall.currentProxies
1614-
if (proxies.includes('Kt')) {
1615-
types.push('kcptun')
1616-
types.push('ktService')
1617-
}
1618-
if (proxies.substr(0, 3) === 'ssr') {
1619-
types.push('shadowsocksr')
1620-
types.push('ssrService')
1621-
} else if (proxies.substr(0, 2) === 'ss') {
1622-
types.push('shadowsocks')
1623-
types.push('ssService')
1624-
}
1625-
for (let i = 0; i < types.length; i += 1) {
1626-
await this.scpConfig(types[i], overwrite)
1627-
}
1628-
}
16291545
async connect (startFirst) {
16301546
const state = await this.getvmState()
16311547
if (state !== 'running') {
@@ -1634,7 +1550,13 @@ class VRouter {
16341550
return new Promise((resolve, reject) => {
16351551
const conn = new Client()
16361552
conn.on('ready', () => {
1637-
resolve(new VRouterRemote(conn, this.config, this))
1553+
conn.sftp((err, sftp) => {
1554+
if (err) {
1555+
reject(err)
1556+
} else {
1557+
resolve(new VRouterRemote(conn, sftp, this.config, this))
1558+
}
1559+
})
16381560
}).connect({
16391561
host: this.config.vrouter.ip,
16401562
port: this.config.vrouter.port,

js/vrouter-remote.js

Lines changed: 127 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
const path = require('path')
12
class VRouterRemote {
23
// todo: reconnect
34

4-
constructor (connect, config, local) {
5+
constructor (connect, sftp, config, local) {
56
this.connect = connect
67
this.config = config
78
this.local = local
9+
this.sftp = sftp
810
}
911

1012
// vm
@@ -37,6 +39,126 @@ class VRouterRemote {
3739
})
3840
})
3941
}
42+
async scp (src, dest) {
43+
let isDestDir = false
44+
if (dest.endsWith('/')) {
45+
isDestDir = true
46+
await this.remoteExec(`mkdir -p ${dest}`)
47+
} else {
48+
await this.remoteExec(`mkdir -p ${path.dirname(dest)}`)
49+
}
50+
51+
let files
52+
try {
53+
const names = require('fs').readdirSync(src)
54+
files = names.map(name => `${src}/${name}`)
55+
} catch (error) {
56+
if (error.code === 'ENOTDIR') {
57+
files = [src]
58+
} else {
59+
throw error
60+
}
61+
}
62+
const promises = []
63+
for (let i = 0; i < files.length; i++) {
64+
const p = new Promise((resolve, reject) => {
65+
let s = files[i]
66+
let d = isDestDir ? `${dest}${path.basename(files[i])}` : dest
67+
this.sftp.fastPut(s, d, (err) => {
68+
if (err) {
69+
reject(err)
70+
} else {
71+
resolve()
72+
}
73+
})
74+
})
75+
promises.push(p)
76+
}
77+
return Promise.all(promises)
78+
}
79+
async scpConfig (type = 'shadowsocks', overwrite = false) {
80+
let p
81+
switch (type) {
82+
case 'tunnelDnsService':
83+
p = await this.local.generateService('tunnelDns')
84+
await this.scp(p, '/etc/init.d/')
85+
await this.remoteExec(`chmod +x /etc/init.d/${this.config.tunnelDns.service}`)
86+
break
87+
case 'ssService':
88+
p = await this.local.generateService('shadowsocks')
89+
await this.scp(p, '/etc/init.d/')
90+
await this.remoteExec(`chmod +x /etc/init.d/${this.config.shadowsocks.service}`)
91+
break
92+
case 'ssrService':
93+
p = await this.local.generateService('shadowsocksr')
94+
await this.scp(p, '/etc/init.d/')
95+
await this.remoteExec(`chmod +x /etc/init.d/${this.config.shadowsocksr.service}`)
96+
break
97+
case 'ktService':
98+
p = await this.local.generateService('kcptun')
99+
await this.scp(p, '/etc/init.d/')
100+
await this.remoteExec(`chmod +x /etc/init.d/${this.config.kcptun.service}`)
101+
break
102+
case 'tunnelDns':
103+
case 'shadowsocks':
104+
case 'shadowsocksr':
105+
case 'kcptun':
106+
p = await this.local.generateConfig(type)
107+
for (let i = 0; i < p.length; i++) {
108+
await this.scp(p[i], `${this.config.vrouter.configDir}/`)
109+
}
110+
break
111+
case 'dnsmasq':
112+
p = await this.local.generateDnsmasqCf(overwrite)
113+
await this.scp(p, '/etc/dnsmasq.d/')
114+
break
115+
case 'ipset':
116+
p = await this.local.generateIPsets(overwrite)
117+
await this.scp(p, `${this.config.vrouter.configDir}/`)
118+
break
119+
case 'firewall':
120+
p = await this.local.generateFWRules(null, null, overwrite)
121+
await this.scp(p, '/etc/')
122+
break
123+
case 'watchdog':
124+
p = await this.local.generateWatchdog()
125+
await this.scp(p, `${this.config.vrouter.configDir}/`)
126+
await this.remoteExec(`chmod +x ${this.config.vrouter.configDir}/${this.config.firewall.watchdogFile}`)
127+
break
128+
case 'cron':
129+
p = await this.local.generateCronJob()
130+
await this.scp(p, `${this.config.vrouter.configDir}/`)
131+
break
132+
}
133+
}
134+
async scpConfigAll (overwrite) {
135+
const types = [
136+
'dnsmasq',
137+
'ipset',
138+
'firewall',
139+
'watchdog',
140+
'cron'
141+
]
142+
if (this.config.firewall.enableTunnelDns) {
143+
types.push('tunnelDnsService')
144+
types.push('tunnelDns')
145+
}
146+
const proxies = this.config.firewall.currentProxies
147+
if (proxies.includes('Kt')) {
148+
types.push('kcptun')
149+
types.push('ktService')
150+
}
151+
if (proxies.substr(0, 3) === 'ssr') {
152+
types.push('shadowsocksr')
153+
types.push('ssrService')
154+
} else if (proxies.substr(0, 2) === 'ss') {
155+
types.push('shadowsocks')
156+
types.push('ssService')
157+
}
158+
for (let i = 0; i < types.length; i += 1) {
159+
await this.scpConfig(types[i], overwrite)
160+
}
161+
}
40162
makeExecutable (file) {
41163
const cmd = `chmod +x ${file}`
42164
return this.remoteExec(cmd)
@@ -176,7 +298,7 @@ class VRouterRemote {
176298
await this.service(this.config.tunnelDns.service, 'stop').catch(() => {})
177299

178300
// let s = Date.now()
179-
await this.local.scpConfigAll(true)
301+
await this.scpConfigAll(true)
180302
// console.log(`scpConfigAll time: ${(Date.now() - s) / 1000}`)
181303
const promises = []
182304
switch (proxies) {
@@ -230,9 +352,9 @@ class VRouterRemote {
230352
this.local.generateFWRules(mode, proxies, true)
231353
])
232354
await Promise.all([
233-
this.local.scpConfig('ipset'),
234-
this.local.scpConfig('dnsmasq'),
235-
this.local.scpConfig('firewall')
355+
this.scpConfig('ipset'),
356+
this.scpConfig('dnsmasq'),
357+
this.scpConfig('firewall')
236358
])
237359
await Promise.all([
238360
this.service('firewall', 'restart'),

0 commit comments

Comments
 (0)