UNPKG

ssh-tunneling

Version:
269 lines (219 loc) 7.98 kB
# Ssh tunneling for nodejs A ssh tunneling client based on ssh2, which can do command executing and port forwarding. ## Installation ```sh npm i ssh-tunneling ``` ## Features - ✨ ***connection keep-alive***: Keeping the ssh connection alive whenever you use it. - ✨ ***port forwarding***: Ssh tunneling port forward even behind a hopping server,such as a socks server. - ✨ ***port checking and finding***: The client will automatically find a available local port to forward when the port is using. - ✨ ***command executing***: Execute linux commands. ## API ### `new SshTunnel(config)` options - host: <**required**> ssh ip - port: <**required**> ssh port - username: <**required**> ssh user name - privateKey: [**optional**] ssh private key - password: [**optional**] ssh password - hoppingServer: [**optional**] Currently it just supports the socks4 or socks5 server,such as 'socks5://180.80.80.80:1080' or 'socks4://180.80.80.80:1080' ```typescript import { SshTunnel } from 'ssh-tunneling'; import type { SshConfig } from 'ssh-tunneling'; const sshConfig: SshConfig = { host: '192.168.1.1', port: 22, username: 'myUsername', privateKey: fs.readFileSync('~/.ssh/myPrivateKey'), }; const client = new SshTunnel(sshConfig); ``` or establish a connection behind a socks5 server ```typescript import { SshTunnel } from 'ssh-tunneling'; import type { SshConfig } from 'ssh-tunneling'; const sshConfig: SshConfig = { host: '192.168.1.1', port: 22, username: 'myUsername', privateKey: fs.readFileSync('~/.ssh/myPrivateKey'), // or password // password: 'myPassword', hoppingServer: 'socks://180.80.80.80:1080' }; const client = new SshTunnel(sshConfig); ``` ### `forwardOut` Forward local port to remote port. ```typescript import { SshTunnel } from 'ssh-tunneling'; import type { SshConfig } from 'ssh-tunneling'; const sshConfig: SshConfig = { host: '192.168.1.1', port: 22, username: 'myUsername', privateKey: fs.readFileSync('~/.ssh/myPrivateKey'), }; const client = new SshTunnel(sshConfig); const forwardInfo1 = client.forwardOut('3000:192.168.1.1:3000'); console.log(forwardInfo1); // { localPort: 3000, destPort: 3000, destHost: '192.168.1.1', id: '3000:192.168.1.1:3000', type: 'out' } // or passing an id, it'll use that id. const forwardInfo2 = await client.forwardOut({ id: 'my-id', proxy: '3001:192.168.1.1:3000' }); console.log(forwardInfo2); // { localPort: 3000, destPort: 3000, destHost: '192.168.1.1', id: 'my-id', type: 'out' } ``` If the local port is occupied, it will choose a idle local port to listen and return the info in result. ```typescript import { SshTunnel } from 'ssh-tunneling'; import type { SshConfig } from 'ssh-tunneling'; const sshConfig: SshConfig = { host: '192.168.1.1', port: 22, username: 'myUsername', privateKey: fs.readFileSync('~/.ssh/myPrivateKey'), }; const client = new SshTunnel(sshConfig); const forwardInfo1 = client.forwardOut('3000:192.168.1.1:3000'); const forwardInfo2 = client.forwardOut('3000:192.168.1.1:3000'); console.log(forwardInfo1); // port 3000 is idle // { localPort: 3000, destPort: 3000, destHost: '192.168.1.1', id: '3000:192.168.1.1:3000', type: 'out' } console.log(forwardInfo2); // port 3000 is using, so it use another idle port 3001 // { localPort: 3001, destPort: 3000, destHost: '192.168.1.1', id: '3000:192.168.1.1:3000', type: 'out' } ``` Also, you can pass an array to forward multiple ports and it will return the result array too. ```typescript import { SshTunnel } from 'ssh-tunneling'; import type { SshConfig } from 'ssh-tunneling'; const sshConfig: SshConfig = { host: '192.168.1.1', port: 22, username: 'myUsername', privateKey: fs.readFileSync('~/.ssh/myPrivateKey'), }; const client = new SshTunnel(sshConfig); const forwardInfo1 = client.forwardOut(['3000:192.168.1.1:3000', '3001:192.168.1.1:3001']); console.log(forwardInfo1); // [ // { localPort: 3000, destPort: 3000, destHost: '192.168.1.1', id: '3000:192.168.1.1:3000', type: 'out' }, // { localPort: 3001, destPort: 3001, destHost: '192.168.1.1', id: '3001:192.168.1.1:3001', type: 'out' }, // ] // or passing an id and it'll use that id const forwardInfo2 = client.forwardOut([ { id: 'my-id-1', proxy: '3000:192.168.1.1:3000' }, { id: 'my-id-2', proxy: '3001:192.168.1.1:3000' } ]); console.log(forwardInfo2); // [ // { localPort: 3000, destPort: 3000, destHost: '192.168.1.1', id: 'my-id-1', type: 'out' }, // { localPort: 3001, destPort: 3001, destHost: '192.168.1.1', id: 'my-id-2', type: 'out' }, // ] ``` ### `exec` ```typescript import { SshTunnel } from 'ssh-tunneling'; import type { SshConfig } from 'ssh-tunneling'; const sshConfig: SshConfig = { host: '192.168.1.1', port: 22, username: 'myUsername', privateKey: fs.readFileSync('~/.ssh/myPrivateKey'), }; const client = new SshTunnel(sshConfig); // execute echo command const echo = await client.exec('echo 1'); console.log(echo); // 1 // Also, if passing a command array, it will execute every commands one time and return by order const batchEcho = await sshTunnel.exec([ 'echo 1', 'echo 2', 'echo 3' ]); // batchEcho: [{ command: 'echo 1', result: '1' }, { command: 'echo 2', result: '2' }, { command: 'echo 3', result: '3' }] ``` ### `close` Since the ssh connection is established, it can be closed manualy. - close one server `close(serverKey)` - close all server `close()` ```typescript import { SshTunnel } from 'ssh-tunneling'; import type { SshConfig } from 'ssh-tunneling'; const sshConfig: SshConfig = { host: '192.168.1.1', port: 22, username: 'myUsername', privateKey: fs.readFileSync('~/.ssh/myPrivateKey'), }; const client = new SshTunnel(sshConfig); // execute echo command const echo = await client.exec('echo 1'); const forwardInfo = client.forwardOut(['3000:192.168.1.1:3000', '3001:192.168.1.1:3001']); // close one proxy server client.close(forwardInfo[0].id); // close all proxy server client.close(); ``` ## Examples ### Simple ssh port forwarding out An example that fowarding port 3000 to 192.168.1.1:3000 through a ssh tunnel. The original ssh command is `ssh -L 3000:192.168.1.1:3000 -i ~/.ssh/myPrivateKey myUsername@192.168.1.1` ```typescript import { SshTunnel } from 'ssh-tunneling'; import type { SshConfig } from 'ssh-tunneling'; const sshConfig: SshConfig = { host: '192.168.1.1', port: 22, username: 'myUsername', privateKey: fs.readFileSync('~/.ssh/myPrivateKey'), }; const client = new SshTunnel(sshConfig); const forwardInfo = await client.forwardOut('3000:192.168.1.1:3000'); // { localPort: 3000, destHost: '192.168.1.1', destPort: 3000, id: '3000:192.168.1.1:3000', type: 'out' } ``` ### Ssh port forwarding through a socks5 server An example that fowarding port 3000 to 192.168.1.1:3000 through a ssh tunnel which only can be connect through a sock5 server. The original ssh command is `ssh -o ProxyCommand="nc -X 5 -x 180.80.80.80:1080 %h %p" -L 3000:192.168.1.1:3000 -i ~/.ssh/myPrivateKey myUsername@192.168.1.1` ```typescript import { SshTunnel } from 'ssh-tunneling'; import type { SshConfig } from 'ssh-tunneling'; const sshConfig: SshConfig = { host: '192.168.1.1', port: 22, username: 'myUsername', privateKey: fs.readFileSync('~/.ssh/myPrivateKey'), hoppingServer: 'socks5://180.80.80.80:1080', }; const client = new SshTunnel(sshConfig); const forwardInfo = await client.forwardOut('3000:192.168.1.1:3000'); // { localPort: 3000, destHost: '192.168.1.1', destPort: 3000, id: '3000:192.168.1.1:3000', type: 'out' } ``` ### Commands executing ```typescript import { SshTunnel } from 'ssh-tunneling'; import type { SshConfig } from 'ssh-tunneling'; const sshConfig: SshConfig = { host: '192.168.1.1', port: 22, username: 'myUsername', privateKey: fs.readFileSync('~/.ssh/myPrivateKey'), }; const client = new SshTunnel(sshConfig); const result = await client.exec('echo 1'); // 1 ``` ## coming soon - forward in - ssh server hopping