Browse Source

Autologin Feature Added (#122)

Login by passing username and password in url as query parameters. 
Migrated to node-pty which is currently maintained and updated. 
added feature to put in global username and password
Added server keep alive in ssh options to keep the session alive.
pull/143/head
Koushik M.L.N 6 years ago
committed by Cian Butler
parent
commit
c14ee99081
  1. 1
      .gitignore
  2. 8
      Dockerfile
  3. 3
      Dockerfile-ssh
  4. 26
      README.md
  5. 7
      cli.mjs
  6. 15
      docker-compose.yml
  7. 1
      public/wetty/index.html
  8. 2
      src/hterm_all.js
  9. 22
      wetty.mjs

1
.gitignore

@ -13,5 +13,6 @@ logs
results results
npm-debug.log npm-debug.log
.idea
node_modules/* node_modules/*
.esm-cache .esm-cache

8
Dockerfile

@ -3,13 +3,15 @@ WORKDIR /usr/src/app
RUN apk add --update build-base python RUN apk add --update build-base python
COPY . /usr/src/app COPY . /usr/src/app
RUN yarn RUN yarn
FROM node:8-alpine 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 openssh-client apk add openssh-client && \
apk add sshpass
USER term
EXPOSE 3000 EXPOSE 3000
COPY --from=builder /usr/src/app /app COPY --from=builder /usr/src/app /app
CMD node bin RUN mkdir ~/.ssh
CMD ssh-keyscan -H wetty-ssh >> ~/.ssh/known_hosts && node bin

3
Dockerfile-ssh

@ -0,0 +1,3 @@
FROM sickp/alpine-sshd:latest
RUN adduser -D -h /home/term -s /bin/sh term && \
( echo "term:term" | chpasswd )

26
README.md

@ -22,6 +22,12 @@ wetty -p 3000
If you run it as root it will launch `/bin/login` (where you can specify the If you run it as root it will launch `/bin/login` (where you can specify the
user name), else it will launch `ssh` and connect by default to `localhost`. user name), else it will launch `ssh` and connect by default to `localhost`.
* `apt-get install sshpass` (debian eg. Ubuntu) for auto-login feature
* `yum install sshpass` (red hat flavours eg. CentOs) for auto-login feature
Run on HTTP:
-----------
If instead you wish to connect to a remote host you can specify the `--sshhost` If instead you wish to connect to a remote host you can specify the `--sshhost`
option, the SSH port using the `--sshport` option and the SSH user using the option, the SSH port using the `--sshport` option and the SSH user using the
@ -35,8 +41,26 @@ or
`http://yourserver:3000/ssh/<username>` `http://yourserver:3000/ssh/<username>`
You can pass an optional password as query parameter to use auto-login feature.
`http://yourserver:3000/wetty/ssh/<username>?sshpass=<password>`
or
`http://yourserver:3000/ssh/<username>?sshpass=<password>`
## Run on HTTPS ## Run on HTTPS
You can also pass the SSH user name and password as query parameters and auto-login the user like this (Only while running as a non root account):
`http://yourserver:3000/wetty/autologin?sshuser=<username>&sshpass=<password>`
This is just an additional feature and the security implications for passing the password in the url will have to be taken care separately.
Run on HTTPS:
------------
Always use HTTPS. If you don't have SSL certificates from a CA you can create a Always use HTTPS. If you don't have SSL certificates from a CA you can create a
self signed certificate using this command: self signed certificate using this command:
@ -88,6 +112,8 @@ use:
http://yourserver.com/wetty http://yourserver.com/wetty
``` ```
**Note that if your Nginx is configured for HTTPS you should run wetty without SSL.**
Else if you are running `bin/index.js` as a regular user you can use: Else if you are running `bin/index.js` as a regular user you can use:
``` ```

7
cli.mjs

@ -25,6 +25,10 @@ const opts = optimist
demand : false, demand : false,
description: 'ssh user', description: 'ssh user',
}, },
sshpass: {
demand : false,
description: 'ssh password',
},
sshauth: { sshauth: {
demand : false, demand : false,
description: 'defaults to "password", you can use "publickey,password" instead', description: 'defaults to "password", you can use "publickey,password" instead',
@ -52,6 +56,7 @@ if (opts.help) {
} }
const sshuser = opts.sshuser || process.env.SSHUSER || ''; const sshuser = opts.sshuser || process.env.SSHUSER || '';
const sshpass = opts.sshpass || process.env.SSHPASS || '';
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;
@ -81,7 +86,7 @@ process.on('uncaughtException', err => {
console.error(`Error: ${err}`); console.error(`Error: ${err}`);
}); });
const tty = wetty(port, sshuser, sshhost, sshport, sshauth, sshkey, opts.ssl); const tty = wetty(port, sshuser, sshpass, 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}`);
}); });

15
docker-compose.yml

@ -1,4 +1,4 @@
version: "3" version: "3.5"
services: services:
wetty: wetty:
@ -11,5 +11,16 @@ services:
- "3000:3000" - "3000:3000"
environment: environment:
PORT: 3000 PORT: 3000
SSHHOST: 'localhost' SSHHOST: 'wetty-ssh'
SSHPORT: 22 SSHPORT: 22
wetty-ssh:
build:
context: .
dockerfile: Dockerfile-ssh
container_name: 'wetty-ssh'
networks:
default:
name: wetty

1
public/wetty/index.html

@ -3,7 +3,6 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Wetty - The WebTTY Terminal Emulator</title> <title>Wetty - The WebTTY Terminal Emulator</title>
<script src="/wetty/socket.io/socket.io.js"></script>
<style> <style>
html, body { html, body {
height: 100%; height: 100%;

2
src/hterm_all.js

@ -18388,5 +18388,3 @@ lib.resource.add('hterm/git/HEAD', 'text/plain',
'git rev-parse HEAD' + 'git rev-parse HEAD' +
'' ''
); );

22
wetty.mjs

@ -6,6 +6,7 @@ import server from 'socket.io';
import { spawn } from 'node-pty'; import { spawn } from 'node-pty';
import EventEmitter from 'events'; import EventEmitter from 'events';
import favicon from 'serve-favicon'; import favicon from 'serve-favicon';
import url from 'url';
const app = express(); const app = express();
app.use(favicon(`${__dirname}/public/favicon.ico`)); app.use(favicon(`${__dirname}/public/favicon.ico`));
@ -36,12 +37,14 @@ function createServer(port, sslopts) {
}); });
} }
function getCommand(socket, sshuser, sshhost, sshport, sshauth, sshkey) { function getCommand(socket, sshuser, sshpass, 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 referer = url.parse(request.headers.referer, true);
const ssh = match ? `${match[0].split('/ssh/').pop()}@${sshhost}` : sshAddress; sshpass = referer.query.sshpass ? referer.query.sshpass : sshpass;
let sshPath = sshuser || match ? 'ssh' : path.join(__dirname, 'bin/ssh');
const ssh = match ? `${match[0].split('/ssh/').pop().split('?')[0]}@${sshhost}` : sshAddress;
const sshRemoteOptsBase = [ const sshRemoteOptsBase = [
sshPath, sshPath,
ssh, ssh,
@ -50,9 +53,14 @@ function getCommand(socket, sshuser, sshhost, sshport, sshauth, sshkey) {
'-o', '-o',
`PreferredAuthentications=${sshauth}`, `PreferredAuthentications=${sshauth}`,
] ]
const sshRemoteOpts = sshkey ? sshRemoteOptsBase.concat(['-i', sshkey]) let sshRemoteOpts;
: sshRemoteOptsBase
if (sshkey)
sshRemoteOpts = sshRemoteOptsBase.concat(['-i', sshkey]);
else if (sshpass)
sshRemoteOpts = ['sshpass', '-p', sshpass].concat(sshRemoteOptsBase);
else
sshRemoteOpts = sshRemoteOptsBase;
return [ return [
process.getuid() === 0 && sshhost === 'localhost' process.getuid() === 0 && sshhost === 'localhost'
? ['login', '-h', socket.client.conn.remoteAddress.split(':')[3]] ? ['login', '-h', socket.client.conn.remoteAddress.split(':')[3]]
@ -62,12 +70,12 @@ function getCommand(socket, sshuser, sshhost, sshport, sshauth, sshkey) {
]; ];
} }
export default function start(port, sshuser, sshhost, sshport, sshauth, sshkey, sslopts) { export default function start(port, sshuser, sshpass, 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, sshkey); const [args, ssh] = getCommand(socket, sshuser, sshpass, 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