Browse Source

Merge branch 'master' into prompt-if-no-user-given

pull/137/head
Oleg Kurapov 7 years ago
committed by GitHub
parent
commit
570ce1edec
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      Dockerfile
  2. 17
      cli.mjs
  3. 22
      wetty.mjs

7
Dockerfile

@ -2,8 +2,9 @@ FROM node:8-alpine
MAINTAINER butlerx@notthe.cloud MAINTAINER butlerx@notthe.cloud
WORKDIR /app WORKDIR /app
RUN adduser -D -h /home/term -s /bin/sh term && \ RUN adduser -D -h /home/term -s /bin/sh term && \
echo "term:term" | chpasswd ( echo "term:term" | chpasswd ) && \
apk add --update build-base python openssh-client
EXPOSE 3000 EXPOSE 3000
COPY . /app COPY . /app
RUN apk add --update build-base python openssh && yarn RUN yarn
CMD yarn start CMD node bin

17
cli.mjs

@ -29,6 +29,10 @@ const opts = optimist
demand : false, demand : false,
description: 'defaults to "password", you can use "publickey,password" instead', description: 'defaults to "password", you can use "publickey,password" instead',
}, },
sshkey: {
demand : false,
description: 'path to an optional client private key (connection will be password-less and insecure!)',
},
port: { port: {
demand : false, demand : false,
alias : 'p', alias : 'p',
@ -51,6 +55,7 @@ const sshuser = opts.sshuser || process.env.SSHUSER || '';
const sshhost = opts.sshhost || process.env.SSHHOST || 'localhost'; const sshhost = opts.sshhost || process.env.SSHHOST || 'localhost';
const sshauth = opts.sshauth || process.env.SSHAUTH || 'password,keyboard-interactive'; const sshauth = opts.sshauth || process.env.SSHAUTH || 'password,keyboard-interactive';
const sshport = opts.sshport || process.env.SSHPORT || 22; const sshport = opts.sshport || process.env.SSHPORT || 22;
const sshkey = opts.sshkey || process.env.SSHKEY || '';
const port = opts.port || process.env.PORT || 3000; const port = opts.port || process.env.PORT || 3000;
loadSSL(opts) loadSSL(opts)
@ -62,11 +67,21 @@ loadSSL(opts)
process.exit(1); process.exit(1);
}); });
const sshkeyWarning =
`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Password-less auth enabled using private key from \'%s\'.
! This is dangerous, anything that reaches the wetty server
! will be able to run remote operations without authentication.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`;
if(sshkey) {
console.warn(sshkeyWarning);
}
process.on('uncaughtException', err => { process.on('uncaughtException', err => {
console.error(`Error: ${err}`); console.error(`Error: ${err}`);
}); });
const tty = wetty(port, sshuser, sshhost, sshport, sshauth, opts.ssl); const tty = wetty(port, sshuser, sshhost, sshport, sshauth, sshkey, opts.ssl);
tty.on('exit', code => { tty.on('exit', code => {
console.log(`exit with code: ${code}`); console.log(`exit with code: ${code}`);
}); });

22
wetty.mjs

@ -36,34 +36,38 @@ function createServer(port, sslopts) {
}); });
} }
function getCommand(socket, sshuser, sshhost, sshport, sshauth) { function getCommand(socket, sshuser, sshhost, sshport, sshauth, sshkey) {
const { request } = socket; const { request } = socket;
const match = request.headers.referer.match('.+/ssh/.+$'); const match = request.headers.referer.match('.+/ssh/.+$');
const sshAddress = sshuser ? `${sshuser}@${sshhost}` : sshhost; const sshAddress = sshuser ? `${sshuser}@${sshhost}` : sshhost;
const sshPath = sshuser || match ? 'ssh' : path.join(__dirname, 'bin/ssh'); const sshPath = sshuser || match ? 'ssh' : path.join(__dirname, 'bin/ssh');
const ssh = match ? `${match[0].split('/ssh/').pop()}@${sshhost}` : sshAddress; const ssh = match ? `${match[0].split('/ssh/').pop()}@${sshhost}` : sshAddress;
const sshRemoteOptsBase = [
return [
process.getuid() === 0 && sshhost === 'localhost'
? ['login', '-h', socket.client.conn.remoteAddress.split(':')[3]]
: [
sshPath, sshPath,
ssh, ssh,
'-p', '-p',
sshport, sshport,
'-o', '-o',
`PreferredAuthentications=${sshauth}`, `PreferredAuthentications=${sshauth}`,
], ]
const sshRemoteOpts = sshkey ? sshRemoteOptsBase.concat(['-i', sshkey])
: sshRemoteOptsBase
return [
process.getuid() === 0 && sshhost === 'localhost'
? ['login', '-h', socket.client.conn.remoteAddress.split(':')[3]]
: sshRemoteOpts
,
ssh, ssh,
]; ];
} }
export default function start(port, sshuser, sshhost, sshport, sshauth, sslopts) { export default function start(port, sshuser, sshhost, sshport, sshauth, sshkey, sslopts) {
const events = new EventEmitter(); const events = new EventEmitter();
const io = server(createServer(port, sslopts), { path: '/wetty/socket.io' }); const io = server(createServer(port, sslopts), { path: '/wetty/socket.io' });
io.on('connection', socket => { io.on('connection', socket => {
console.log(`${new Date()} Connection accepted.`); console.log(`${new Date()} Connection accepted.`);
const [args, ssh] = getCommand(socket, sshuser, sshhost, sshport, sshauth); const [args, ssh] = getCommand(socket, sshuser, sshhost, sshport, sshauth, sshkey);
const term = spawn('/usr/bin/env', args, { const term = spawn('/usr/bin/env', args, {
name: 'xterm-256color', name: 'xterm-256color',
cols: 80, cols: 80,

Loading…
Cancel
Save