Compare commits

...

10 commits
main ... bigip

Author SHA1 Message Date
Bill Church
9537f4da67
fix: read-config-ng references 2024-07-11 11:32:17 +00:00
Bill Church
ea12cc8b7e
fix: version comment in client.html 2024-07-10 12:03:10 -04:00
Bill Church
cfa097bd0e
chore: swap read-config git to read-config-ng 2024-07-10 11:00:53 -04:00
Bill Church
170047517b
chore: build 0.2.12 web assets 2024-07-10 13:50:36 +00:00
Bill Church
cd64cc0637
chore: update webpack 2024-07-10 13:50:18 +00:00
Bill Church
533f719cca
chore: dev build testing 2024-07-10 13:09:24 +00:00
Bill Church
b8782c565a
chore: release 0.2.12 2024-07-10 12:18:21 +00:00
Bill Church
0dda8d56d9
build: release 0.2.12 2024-07-10 12:13:53 +00:00
Bill Church
24c94aed98
chore: update dev environment 2024-07-10 12:12:33 +00:00
Bill Church
7223f2cd8f chore: big-ip specific release v0.2.11 2021-05-12 13:59:43 -04:00
15 changed files with 450 additions and 187 deletions

View file

@ -0,0 +1,42 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node
{
"name": "Node.js & TypeScript",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/base:jammy",
// mount the ssh public identity file for the this project
// I limit to just what I need and not the whole ~/.ssh folder
"mounts": [
"source=${localEnv:HOME}${localEnv:USERPROFILE}/.ssh/personal_id_rsa.pub,target=/home/vscode/.hostssh/id_rsa.pub,readonly,type=bind,consistency=cached"
],
// Features to add to the dev container. More info: https://containers.dev/features.
"features": {
"ghcr.io/devcontainers-contrib/features/node-asdf": {},
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
"customizations": {
"vscode": {
"extensions": [
"mechatroner.rainbow-csv",
"ms-vscode-remote.remote-containers",
"dbaeumer.vscode-eslint",
"GitHub.copilot",
"GitHub.copilot-chat",
"esbenp.prettier-vscode",
"rvest.vs-code-prettier-eslint",
"bierner.markdown-mermaid",
"stylelint.vscode-stylelint"
]
}
},
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "/bin/bash ./.devcontainer/scripts/tools.sh >> ~/post-create-tools.log"
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}

View file

@ -0,0 +1,18 @@
#!/bin/bash
mkdir -p ~/.ssh && \
touch ~/.ssh/known_hosts && \
sudo tee ~/.ssh/config > /dev/null << EOF
Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.hostssh/id_rsa.pub
EOF
sudo chown -R vscode:vscode ~/.ssh
# Install Node.js 6.9.1
asdf install nodejs 6.9.1
asdf local nodejs 6.9.1
git config --global --add safe.directory /workspaces/webssh2

1
.tool-versions Normal file
View file

@ -0,0 +1 @@
nodejs 6.9.1

View file

@ -1,6 +1,47 @@
# Change Log # Change Log
## [0.2.9] 2019-06-13
## [0.2.13] 2024-07-11
BIG-IP Specific version
### Fixes
- fixed missing reference to `read-config-ng` switchover which could prevent `config.json` from being read
## [0.2.12] 2024-07-10
BIG-IP Specific version
### Changes ### Changes
- `[ctrl]+[shift]+[6]` or `[ctrl]+[^]` now sends `RS` or `0x1E`
## [0.2.11] 2020-05-12
BIG-IP Specific version
### BREAKING
- Not compatible with versions of ephemeral_auth before 0.4.8 due to child resources moving under /ssh
### Changes
- in `config.json.sample` - `allowreauth` set to `false` by default
- in `config.json.sample` - potential future proofing for CORS support `http.origins`
- `ssh` module updated to 0.8.9
- Move all child resources to start from under /ssh
- /socket.io -> /ssh/socket.io
- /webssh2.css -> /ssh/webssh2.css
- /webssh2.bundle.js -> /ssh/webssh2.bundle.js
- /reauth -> /ssh/reauth
- perhaps more
## [0.2.10] not actually released
## [0.2.9] 2019-06-13
### Changes
- Missing require('fs') in `server/app.js` See issue [#135](../../issues/135) - Missing require('fs') in `server/app.js` See issue [#135](../../issues/135)
- Patched read-config to mitigate vulnerability in js-yaml - Patched read-config to mitigate vulnerability in js-yaml
- issue not exploitable on webssh2 implementation - issue not exploitable on webssh2 implementation
@ -9,7 +50,9 @@
- See https://github.com/nodeca/js-yaml/issues/475 for more detail - See https://github.com/nodeca/js-yaml/issues/475 for more detail
## [0.2.8] 2019-05-25 ## [0.2.8] 2019-05-25
### Changes ### Changes
- Fixes issue if no password is entered, browser must be closed and restart to attempt to re-auth. See issue [#118](../../issues/118). Thanks @smilesm2 for the idea. - Fixes issue if no password is entered, browser must be closed and restart to attempt to re-auth. See issue [#118](../../issues/118). Thanks @smilesm2 for the idea.
- fixes broken `npm run (build|builddev)` - fixes broken `npm run (build|builddev)`
- update font-awesome fonts to 5.6.3 - update font-awesome fonts to 5.6.3
@ -17,10 +60,13 @@
- update xterm to 3.8.0 - update xterm to 3.8.0
### Fixes ### Fixes
- ILX workspace may not always import properly due to symbolic links (specifically ./node_modules/.bin). This is removed from the ILX package - ILX workspace may not always import properly due to symbolic links (specifically ./node_modules/.bin). This is removed from the ILX package
## [0.2.7] 2018-11-11 ## [0.2.7] 2018-11-11
### Changes ### Changes
- `config.reauth` was not respected if initial auth presented was incorrect, regardless of `reauth` setting in `config.json` reauth would always be attempted. fixes [#117](../../issues/117) - `config.reauth` was not respected if initial auth presented was incorrect, regardless of `reauth` setting in `config.json` reauth would always be attempted. fixes [#117](../../issues/117)
- **BREAKING** moved app files to /app, this may be a breaking change - **BREAKING** moved app files to /app, this may be a breaking change
- Updated dockerfile for new app path - Updated dockerfile for new app path
@ -48,45 +94,59 @@
- webpack-cli v3.1.2 - webpack-cli v3.1.2
## [0.2.6] 2018-11-09 ## [0.2.6] 2018-11-09
### Changes ### Changes
- Reauth didn't work if intial auth presented was incorrect, (see issue #112) fixed thanks @vvalchev - Reauth didn't work if intial auth presented was incorrect, (see issue #112) fixed thanks @vvalchev
- Update node version supported to >=6 (PR #115) thanks @perlun - Update node version supported to >=6 (PR #115) thanks @perlun
- Update packages - Update packages
- developer dependencies - developer dependencies
## [0.2.5] 2018-09-11 ## [0.2.5] 2018-09-11
### Added ### Added
- Reauth function thanks to @vbeskrovny and @vvalchev (9bbc116) - Reauth function thanks to @vbeskrovny and @vvalchev (9bbc116)
- Controlled by `config.json` option `options.allowreauth` true presents reauth dialog and false hides dialog - Controlled by `config.json` option `options.allowreauth` true presents reauth dialog and false hides dialog
### Changed ### Changed
- `options.challengeButton` enabled - `options.challengeButton` enabled
- previously this configuration option did nothing, this now enables the Credentials button site-wide regardless of the `allowreplay` header value - previously this configuration option did nothing, this now enables the Credentials button site-wide regardless of the `allowreplay` header value
- Updated debug module to v4 - Updated debug module to v4
## [0.2.4] 2018-07-18 ## [0.2.4] 2018-07-18
### Added ### Added
- Browser title window now changes with xterm escape sequences (see http://tldp.org/HOWTO/Xterm-Title-3.html) - Browser title window now changes with xterm escape sequences (see http://tldp.org/HOWTO/Xterm-Title-3.html)
- Added bellStyle options - Added bellStyle options
- `GET var`: **bellStyle** - _string_ - Style of terminal bell: ("sound"|"none"). **Default:** "sound". **Enforced Values:** "sound", "none" - `GET var`: **bellStyle** - _string_ - Style of terminal bell: ("sound"|"none"). **Default:** "sound". **Enforced Values:** "sound", "none"
- `config.json`: **terminal.bellStyle** - _string_ - Style of terminal bell: (sound|none). **Default:** "sound". - `config.json`: **terminal.bellStyle** - _string_ - Style of terminal bell: (sound|none). **Default:** "sound".
- `workspace` folder on GITHUB for BIG-IP specific fixes/changes - `workspace` folder on GITHUB for BIG-IP specific fixes/changes
### Changed ### Changed
- Updated xterm.js to 3.1.0 - Updated xterm.js to 3.1.0
- https://github.com/xtermjs/xterm.js/releases/tag/3.1.0 - https://github.com/xtermjs/xterm.js/releases/tag/3.1.0
- Default listen IP in `config.json` changed back to 127.0.0.1 - Default listen IP in `config.json` changed back to 127.0.0.1
### Fixed ### Fixed
- ESC]0; is now removed from log files when using the browser-side logging feature - ESC]0; is now removed from log files when using the browser-side logging feature
## [0.2.3] unreleased ## [0.2.3] unreleased
### Fixed ### Fixed
- ESC]0; is now removed from log files when using the browser-side logging feature - ESC]0; is now removed from log files when using the browser-side logging feature
## [0.2.0] 2018-02-10 ## [0.2.0] 2018-02-10
Mostly client (browser) related changes in this release Mostly client (browser) related changes in this release
### Added ### Added
- Menu system - Menu system
- Fontawesome icons - Fontawesome icons
- Resizing browser window sends resize events to terminal container as well as SSH session (pty) - Resizing browser window sends resize events to terminal container as well as SSH session (pty)
@ -99,6 +159,7 @@ Mostly client (browser) related changes in this release
- Express compression feature - Express compression feature
### Changed ### Changed
- Updated xterm.js to 3.0.2 - Updated xterm.js to 3.0.2
- See https://github.com/xtermjs/xterm.js/releases/tag/3.0.2 - See https://github.com/xtermjs/xterm.js/releases/tag/3.0.2
- See https://github.com/xtermjs/xterm.js/releases/tag/3.0.1 - See https://github.com/xtermjs/xterm.js/releases/tag/3.0.1
@ -109,23 +170,34 @@ Mostly client (browser) related changes in this release
- Removed non-minified options (if you need to disable minification, modify webpack scripts and 'npm run build') - Removed non-minified options (if you need to disable minification, modify webpack scripts and 'npm run build')
### Fixed ### Fixed
- Resolved loss of terminal foucs when interacting with option buttons (Logging, etc...) - Resolved loss of terminal foucs when interacting with option buttons (Logging, etc...)
# Change Log # Change Log
## [0.1.4] 2018-01-30 ## [0.1.4] 2018-01-30
### Changed ### Changed
- Moved socket and util out of folders into .js in root. - Moved socket and util out of folders into .js in root.
- added keepaliveInterval and keepaliveCountMax config options - added keepaliveInterval and keepaliveCountMax config options
## [0.1.3] 2017-09-28 ## [0.1.3] 2017-09-28
### Changed ### Changed
- Upgrade to debug@3.1 to eliminate ReDoS in %o formatter - Upgrade to debug@3.1 to eliminate ReDoS in %o formatter
- Upgrade Express to 4.15.5 for ReDOS - Upgrade Express to 4.15.5 for ReDOS
- Upgrade basic-auth to v2.0 - Upgrade basic-auth to v2.0
## [0.1.2] 2017-07-31 ## [0.1.2] 2017-07-31
### Added ### Added
- ssh.readyTimeout option in config.json (time in ms, default 20000, 20sec) - ssh.readyTimeout option in config.json (time in ms, default 20000, 20sec)
### Changed ### Changed
- Updated xterm.js to 2.9.2 from 2.6.0 - Updated xterm.js to 2.9.2 from 2.6.0
- See https://github.com/sourcelair/xterm.js/releases/tag/2.9.2 - See https://github.com/sourcelair/xterm.js/releases/tag/2.9.2
- See https://github.com/sourcelair/xterm.js/releases/tag/2.9.1 - See https://github.com/sourcelair/xterm.js/releases/tag/2.9.1
@ -145,23 +217,31 @@ Mostly client (browser) related changes in this release
- https://github.com/visionmedia/debug/releases/tag/3.0.0 - https://github.com/visionmedia/debug/releases/tag/3.0.0
- Running in strict mode ('use strict';) - Running in strict mode ('use strict';)
## [0.1.1] 2017-06-03 ## [0.1.1] 2017-06-03
### Added ### Added
- `serverlog.client` and `serverlog.server` options added to `config.json` to enable logging of client commands to server log (only client portion implemented at this time) - `serverlog.client` and `serverlog.server` options added to `config.json` to enable logging of client commands to server log (only client portion implemented at this time)
- morgan express middleware for logging - morgan express middleware for logging
### Changed ### Changed
- Updated socket.io to 1.7.4 - Updated socket.io to 1.7.4
- continued refactoring, breaking up `index.js` - continued refactoring, breaking up `index.js`
- revised error handling methods - revised error handling methods
- revised session termination methods - revised session termination methods
### Fixed ### Fixed
### Removed ### Removed
- color console decorations from `util/index.js` - color console decorations from `util/index.js`
- SanatizeHeaders function from `util/index.js` - SanatizeHeaders function from `util/index.js`
## [0.1.0] 2017-05-27 ## [0.1.0] 2017-05-27
### Added ### Added
- This ChangeLog.md file - This ChangeLog.md file
- Support for UTF-8 characters (thanks @bara666) - Support for UTF-8 characters (thanks @bara666)
- Snyk, Bithound, Travis CI - Snyk, Bithound, Travis CI
@ -177,6 +257,7 @@ and events in the application (not including the ssh2 module debug)
- validation for host (v4,v6,fqdn,hostname), port (integer 2-65535), and header (sanitized) from URL input - validation for host (v4,v6,fqdn,hostname), port (integer 2-65535), and header (sanitized) from URL input
### Changed ### Changed
- error handling in public/client.js - error handling in public/client.js
- moved socket.io operations to their own file /socket/index.js, more changes like this to come (./socket/index.js) - moved socket.io operations to their own file /socket/index.js, more changes like this to come (./socket/index.js)
- all session based variables are now under the req.session.ssh property or socket.request.ssh (./index.js) - all session based variables are now under the req.session.ssh property or socket.request.ssh (./index.js)
@ -192,44 +273,61 @@ and events in the application (not including the ssh2 module debug)
- if header.text is null in `config.json` and header is not defined as a get parameter the Header will not be displayed. Both of these must be null / undefined and not specified as get parameters. - if header.text is null in `config.json` and header is not defined as a get parameter the Header will not be displayed. Both of these must be null / undefined and not specified as get parameters.
### Fixed ### Fixed
- Multiple errors may overwrite status bar which would cause confusion as to what originally caused the error. Example, ssh server disconnects which prompts a cascade of events (conn.on('end'), socket.on('disconnect'), conn.on('close')) and the original reason (conn.on('end')) would be lost and the user would erroneously receive a WEBSOCKET error as the last event to fire would be the websocket connection closing from the app. - Multiple errors may overwrite status bar which would cause confusion as to what originally caused the error. Example, ssh server disconnects which prompts a cascade of events (conn.on('end'), socket.on('disconnect'), conn.on('close')) and the original reason (conn.on('end')) would be lost and the user would erroneously receive a WEBSOCKET error as the last event to fire would be the websocket connection closing from the app.
- ensure ssh session is closed when a browser disconnects from the websocket - ensure ssh session is closed when a browser disconnects from the websocket
- if headerBackground is changed, status background is changed to the same color (typo, fixed) - if headerBackground is changed, status background is changed to the same color (typo, fixed)
### Removed ### Removed
- Express Static References directly to module source directories due to concatenating and minifying js/css - Express Static References directly to module source directories due to concatenating and minifying js/css
## [0.0.5] - 2017-03-23 ## [0.0.5] - 2017-03-23
### Added ### Added
- Added experimental support for logging (see Readme) - Added experimental support for logging (see Readme)
### Fixed ### Fixed
- Terminal geometry now properly fills the browser screen and communicates this to the ssh session. Tested with IE 11 and recent versions of Chrome/Safari/Firefox. - Terminal geometry now properly fills the browser screen and communicates this to the ssh session. Tested with IE 11 and recent versions of Chrome/Safari/Firefox.
## [0.0.4] - 2017-03-23 ## [0.0.4] - 2017-03-23
### Added ### Added
- Set default terminal to xterm-color - Set default terminal to xterm-color
- Mouse event support - Mouse event support
- New config option, config.ssh.term to set terminal - New config option, config.ssh.term to set terminal
### Changed ### Changed
- Update to Xterm.js 2.4.0 - Update to Xterm.js 2.4.0
- Minor code formatting cleanup - Minor code formatting cleanup
## [0.0.3] - 2017-02-16 ## [0.0.3] - 2017-02-16
### Changed ### Changed
- Update xterm to latest (2.3.0) - Update xterm to latest (2.3.0)
### Fixed ### Fixed
- Fixed misspelled config.ssh.port property - Fixed misspelled config.ssh.port property
## [0.0.2] - 2017-02-01 ## [0.0.2] - 2017-02-01
### Changed ### Changed
- Moving terminal emulation to xterm.js - Moving terminal emulation to xterm.js
- updating module version dependencies - updating module version dependencies
### Fixed ### Fixed
- Fixed issue with banners not being displayed properly from UNIX hosts when only lf is used - Fixed issue with banners not being displayed properly from UNIX hosts when only lf is used
## [0.0.1] - 2016-06-28 ## [0.0.1] - 2016-06-28
### Added ### Added
- Initial proof of concept and release. For historical purposes only. - Initial proof of concept and release. For historical purposes only.

View file

@ -86,6 +86,8 @@ docker run --name webssh2 -d -p 2222:2222 webssh2
* **listen.port** - _integer_ - Port node should listen on for client connections, defaults to `2222` * **listen.port** - _integer_ - Port node should listen on for client connections, defaults to `2222`
* **http.origins** - _array_ - COORS origins to allow connections from to socket.io server, defaults to `localhost:2222`. Changed in 0.3.1, to enable previous, less secure, default behavior of everything use `*:*` (not recommended). Check [#240](../../issues/240)
* **user.name** - _string_ - Specify user name to authenticate with. In normal cases this should be left to the default `null` setting. * **user.name** - _string_ - Specify user name to authenticate with. In normal cases this should be left to the default `null` setting.
* **user.password** - _string_ - Specify password to authenticate with. In normal cases this should be left to the default `null` setting. * **user.password** - _string_ - Specify password to authenticate with. In normal cases this should be left to the default `null` setting.

View file

@ -1,12 +1,20 @@
<!-- Version Version 0.2.12 - 2024-07-10T13:49:24.751Z - 533f719 -->
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>WebSSH2</title> <title>WebSSH2</title>
<style> <style>
html, body {background-color: #000;height: 100%;margin: 0;}.dropup-content {display: none;} html,
body {
background-color: #000;
height: 100%;
margin: 0;
}
.dropup-content {
display: none;
}
</style> </style>
<link rel="stylesheet" href="/webssh2.css" /> <link href="/ssh/webssh2.css" rel="stylesheet"></head>
</head>
<body> <body>
<div class="box"> <div class="box">
<div id="header"></div> <div id="header"></div>
@ -20,6 +28,5 @@
<div id="status"></div> <div id="status"></div>
</div> </div>
</div> </div>
<script src="/webssh2.bundle.js" defer></script> <script type="text/javascript" src="/ssh/webssh2.bundle.js"></script></body>
</body>
</html> </html>

File diff suppressed because one or more lines are too long

View file

@ -1,3 +1,4 @@
/*! Version 0.2.12 - 2024-07-10T13:49:24.747Z - 533f719 */
/** /**
* Copyright (c) 2014 The xterm.js authors. All rights reserved. * Copyright (c) 2014 The xterm.js authors. All rights reserved.
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)

View file

@ -1,11 +1,19 @@
<!-- <%= htmlWebpackPlugin.options.version %> -->
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>WebSSH2</title> <title>WebSSH2</title>
<style> <style>
html, body {background-color: #000;height: 100%;margin: 0;}.dropup-content {display: none;} html,
body {
background-color: #000;
height: 100%;
margin: 0;
}
.dropup-content {
display: none;
}
</style> </style>
<link rel="stylesheet" href="/webssh2.css" />
</head> </head>
<body> <body>
<div class="box"> <div class="box">
@ -20,6 +28,5 @@
<div id="status"></div> <div id="status"></div>
</div> </div>
</div> </div>
<script src="/webssh2.bundle.js" defer></script>
</body> </body>
</html> </html>

View file

@ -38,16 +38,9 @@ function resizeScreen () {
socket.emit('resize', { cols: term.cols, rows: term.rows }) socket.emit('resize', { cols: term.cols, rows: term.rows })
} }
if (document.location.pathname) { socket = io.connect({
var parts = document.location.pathname.split('/') path: '/ssh/socket.io'
var base = parts.slice(0, parts.length - 1).join('/') + '/'
var resource = base.substring(1) + 'socket.io'
socket = io.connect(null, {
resource: resource
}) })
} else {
socket = io.connect()
}
term.on('data', function (data) { term.on('data', function (data) {
socket.emit('data', data) socket.emit('data', data)
@ -171,7 +164,7 @@ function drawMenu (data) {
// reauthenticate // reauthenticate
function reauthSession () { // eslint-disable-line function reauthSession () { // eslint-disable-line
console.log('re-authenticating') console.log('re-authenticating')
window.location.href = '/reauth' window.location.href = '/ssh/reauth'
return false return false
} }
@ -241,3 +234,13 @@ function downloadLog () { // eslint-disable-line
} }
term.focus() term.focus()
} }
// Add an event listener for capturing Ctrl + Shift + 6
document.addEventListener('keydown', function(event) {
if (event.ctrlKey && event.shiftKey && event.code === 'Digit6') {
// Prevent the default action
event.preventDefault();
// Emit the desired key sequence to the server
socket.emit('data', '\x1E'); // 0x1E is the RS control character
}
});

View file

@ -3,6 +3,9 @@
"ip": "0.0.0.0", "ip": "0.0.0.0",
"port": 2222 "port": 2222
}, },
"http": {
"origins": ["*:*"]
},
"user": { "user": {
"name": null, "name": null,
"password": null "password": null
@ -31,7 +34,7 @@
}, },
"options": { "options": {
"challengeButton": true, "challengeButton": true,
"allowreauth": true "allowreauth": false
}, },
"algorithms": { "algorithms": {
"kex": [ "kex": [

View file

@ -1,13 +1,18 @@
{ {
"name": "webssh2", "name": "webssh2",
"version": "0.2.9", "version": "0.2.13",
"ignore": [ "ignore": [
".gitignore" ".gitignore"
], ],
"bin": "./index.js", "bin": "./index.js",
"description": "A Websocket to SSH2 gateway using term.js, socket.io, ssh2, and express", "description": "A Websocket to SSH2 gateway using term.js, socket.io, ssh2, and express",
"homepage": "https://github.com/billchurch/WebSSH2", "homepage": "https://github.com/billchurch/WebSSH2",
"keywords": "ssh webssh terminal webterminal", "keywords": [
"ssh",
"webssh",
"terminal",
"webterminal"
],
"license": "SEE LICENSE IN FILE - LICENSE", "license": "SEE LICENSE IN FILE - LICENSE",
"private": false, "private": false,
"repository": { "repository": {
@ -34,9 +39,10 @@
"express": "~4.16.4", "express": "~4.16.4",
"express-session": "~1.15.6", "express-session": "~1.15.6",
"morgan": "~1.9.1", "morgan": "~1.9.1",
"read-config": "git+https://github.com/billchurch/nodejs-read-config.git", "read-config-ng": "~3.0.7",
"serve-favicon": "~2.5.0",
"socket.io": "~2.2.0", "socket.io": "~2.2.0",
"ssh2": "~0.6.1", "ssh2": "~0.8.9",
"validator": "~10.9.0" "validator": "~10.9.0"
}, },
"scripts": { "scripts": {
@ -68,6 +74,7 @@
"css-loader": "^2.1.0", "css-loader": "^2.1.0",
"extract-text-webpack-plugin": "^4.0.0-beta.0", "extract-text-webpack-plugin": "^4.0.0-beta.0",
"file-loader": "^3.0.1", "file-loader": "^3.0.1",
"html-webpack-plugin": "^3.2.0",
"nodaemon": "0.0.5", "nodaemon": "0.0.5",
"postcss-discard-comments": "^4.0.1", "postcss-discard-comments": "^4.0.1",
"snazzy": "^8.0.0", "snazzy": "^8.0.0",
@ -79,6 +86,7 @@
"webpack-cli": "^3.2.1", "webpack-cli": "^3.2.1",
"webpack-merge": "^4.2.1", "webpack-merge": "^4.2.1",
"webpack-stream": "^5.2.1", "webpack-stream": "^5.2.1",
"xterm": "^3.10.1" "xterm": "^3.10.1",
"zip-webpack-plugin": "^4.0.1"
} }
} }

View file

@ -1,41 +1,61 @@
const webpack = require('webpack') const webpack = require("webpack");
const path = require('path') const { BannerPlugin } = require("webpack");
const CleanWebpackPlugin = require('clean-webpack-plugin') const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin') const path = require("path");
const ExtractTextPlugin = require('extract-text-webpack-plugin') const CopyWebpackPlugin = require("copy-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const packageJson = require("../package.json"); // Load package.json
const commitHash = require("child_process")
.execSync("git rev-parse --short HEAD")
.toString()
.trim();
module.exports = { module.exports = {
context: path.resolve('__dirname', '../'), context: path.resolve(__dirname, "../"),
entry: { entry: {
webssh2: './client/src/js/index.js' webssh2: "./client/src/js/index.js",
}, },
plugins: [ plugins: [
new CleanWebpackPlugin(['client/public'], { new BannerPlugin({
root: path.resolve('__dirname', '../'), banner: `Version ${
verbose: true packageJson.version
} - ${new Date().toISOString()} - ${commitHash}`,
include: /\.(js|css|html|htm)$/,
}),
new CleanWebpackPlugin(["client/public"], {
root: path.resolve("__dirname", "../"),
verbose: true,
}),
new HtmlWebpackPlugin({
template: "./client/src/client.htm", // Path to your source template
filename: "client.htm", // Optional: output file name, defaults to index.html
minify: false,
scriptLoading: "defer",
version: `Version ${
packageJson.version
} - ${new Date().toISOString()} - ${commitHash}`,
publicPath: "/ssh/", // Prepend /ssh/ to the script tags
}), }),
new CopyWebpackPlugin([ new CopyWebpackPlugin([
'./client/src/client.htm', { from: "./client/src/favicon.ico", to: "favicon.ico" },
'./client/src/favicon.ico'
]), ]),
new ExtractTextPlugin('[name].css') new ExtractTextPlugin("[name].css"),
], ],
output: { output: {
filename: '[name].bundle.js', filename: "[name].bundle.js",
path: path.resolve(__dirname, '../client/public') path: path.resolve(__dirname, "../client/public"),
publicPath: "/ssh/", // Prepend /ssh/ to the script tags
}, },
module: { module: {
rules: [ rules: [
{ {
test: /\.css$/, test: /\.css$/,
use: ExtractTextPlugin.extract({ use: ExtractTextPlugin.extract({
fallback: 'style-loader', fallback: "style-loader",
use: [ use: [{ loader: "css-loader" }],
{ }),
loader: 'css-loader' },
} ],
] },
}) };
}
]
}
}

View file

@ -1,8 +1,9 @@
const merge = require('webpack-merge') const merge = require("webpack-merge");
const UglifyJSPlugin = require('uglifyjs-webpack-plugin') const UglifyJSPlugin = require("uglifyjs-webpack-plugin");
const common = require('./webpack.common.js') const common = require("./webpack.common.js");
module.exports = merge(common, { module.exports = merge(
{
plugins: [ plugins: [
new UglifyJSPlugin({ new UglifyJSPlugin({
uglifyOptions: { uglifyOptions: {
@ -10,9 +11,11 @@ module.exports = merge(common, {
dead_code: true, dead_code: true,
output: { output: {
comments: false, comments: false,
beautify: false beautify: false,
} },
} },
}) }),
] ],
}) },
common
);

View file

@ -13,49 +13,52 @@ var logger = require('morgan')
// sane defaults if config.json or parts are missing // sane defaults if config.json or parts are missing
let config = { let config = {
'listen': { listen: {
'ip': '0.0.0.0', ip: '0.0.0.0',
'port': 2222 port: 2222
}, },
'user': { http: {
'name': null, origins: ['*:*']
'password': null
}, },
'ssh': { user: {
'host': null, name: null,
'port': 22, password: null
'term': 'xterm-color',
'readyTimeout': 20000,
'keepaliveInterval': 120000,
'keepaliveCountMax': 10
}, },
'terminal': { ssh: {
'cursorBlink': true, host: null,
'scrollback': 10000, port: 22,
'tabStopWidth': 8, term: 'xterm-color',
'bellStyle': 'sound' readyTimeout: 20000,
keepaliveInterval: 120000,
keepaliveCountMax: 10
}, },
'header': { terminal: {
'text': null, cursorBlink: true,
'background': 'green' scrollback: 10000,
tabStopWidth: 8,
bellStyle: 'sound'
}, },
'session': { header: {
'name': 'WebSSH2', text: null,
'secret': 'mysecret' background: 'green'
}, },
'options': { session: {
'challengeButton': true, name: 'WebSSH2',
'allowreauth': true secret: 'mysecret'
}, },
'algorithms': { options: {
'kex': [ challengeButton: true,
allowreauth: true
},
algorithms: {
kex: [
'ecdh-sha2-nistp256', 'ecdh-sha2-nistp256',
'ecdh-sha2-nistp384', 'ecdh-sha2-nistp384',
'ecdh-sha2-nistp521', 'ecdh-sha2-nistp521',
'diffie-hellman-group-exchange-sha256', 'diffie-hellman-group-exchange-sha256',
'diffie-hellman-group14-sha1' 'diffie-hellman-group14-sha1'
], ],
'cipher': [ cipher: [
'aes128-ctr', 'aes128-ctr',
'aes192-ctr', 'aes192-ctr',
'aes256-ctr', 'aes256-ctr',
@ -65,23 +68,15 @@ let config = {
'aes256-gcm@openssh.com', 'aes256-gcm@openssh.com',
'aes256-cbc' 'aes256-cbc'
], ],
'hmac': [ hmac: ['hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1'],
'hmac-sha2-256', compress: ['none', 'zlib@openssh.com', 'zlib']
'hmac-sha2-512',
'hmac-sha1'
],
'compress': [
'none',
'zlib@openssh.com',
'zlib'
]
}, },
'serverlog': { serverlog: {
'client': false, client: false,
'server': false server: false
}, },
'accesslog': false, accesslog: false,
'verify': false verify: false
} }
// test if config.json exists, if not provide error message but try to run // test if config.json exists, if not provide error message but try to run
@ -89,13 +84,19 @@ let config = {
try { try {
if (fs.existsSync(configPath)) { if (fs.existsSync(configPath)) {
console.log('ephemeral_auth service reading config from: ' + configPath) console.log('ephemeral_auth service reading config from: ' + configPath)
config = require('read-config')(configPath) config = require('read-config-ng')(configPath)
} else { } else {
console.error('\n\nERROR: Missing config.json for webssh. Current config: ' + JSON.stringify(config)) console.error(
'\n\nERROR: Missing config.json for webssh. Current config: ' +
JSON.stringify(config)
)
console.error('\n See config.json.sample for details\n\n') console.error('\n See config.json.sample for details\n\n')
} }
} catch (err) { } catch (err) {
console.error('\n\nERROR: Missing config.json for webssh. Current config: ' + JSON.stringify(config)) console.error(
'\n\nERROR: Missing config.json for webssh. Current config: ' +
JSON.stringify(config)
)
console.error('\n See config.json.sample for details\n\n') console.error('\n See config.json.sample for details\n\n')
console.error('ERROR:\n\n ' + err) console.error('ERROR:\n\n ' + err)
} }
@ -112,9 +113,14 @@ var compression = require('compression')
var server = require('http').Server(app) var server = require('http').Server(app)
var myutil = require('./util') var myutil = require('./util')
var validator = require('validator') var validator = require('validator')
var io = require('socket.io')(server, { serveClient: false }) var io = require('socket.io')(server, {
serveClient: false,
path: '/ssh/socket.io',
origins: config.http.origins
})
var socket = require('./socket') var socket = require('./socket')
var expressOptions = require('./expressOptions') var expressOptions = require('./expressOptions')
var favicon = require('serve-favicon')
// express // express
app.use(compression({ level: 9 })) app.use(compression({ level: 9 }))
@ -124,23 +130,38 @@ if (config.accesslog) app.use(logger('common'))
app.disable('x-powered-by') app.disable('x-powered-by')
// static files // static files
app.use(express.static(publicPath, expressOptions)) app.use('/ssh', express.static(publicPath, expressOptions))
// app.use(express.static(publicPath, expressOptions))
app.get('/reauth', function (req, res, next) { // favicon from root if being pre-fetched by browser to prevent a 404
app.use(favicon(path.join(publicPath, 'favicon.ico')))
app.get('/ssh/reauth', function (req, res, next) {
var r = req.headers.referer || '/' var r = req.headers.referer || '/'
res.status(401).send('<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=' + r + '"></head><body bgcolor="#000"></body></html>') res
.status(401)
.send(
'<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=' +
r +
'"></head><body bgcolor="#000"></body></html>'
)
}) })
// eslint-disable-next-line complexity
app.get('/ssh/host/:host?', function (req, res, next) { app.get('/ssh/host/:host?', function (req, res, next) {
res.sendFile(path.join(path.join(publicPath, 'client.htm'))) res.sendFile(path.join(path.join(publicPath, 'client.htm')))
// capture, assign, and validated variables // capture, assign, and validated variables
req.session.ssh = { req.session.ssh = {
host: (validator.isIP(req.params.host + '') && req.params.host) || host:
(validator.isIP(req.params.host + '') && req.params.host) ||
(validator.isFQDN(req.params.host) && req.params.host) || (validator.isFQDN(req.params.host) && req.params.host) ||
(/^(([a-z]|[A-Z]|[0-9]|[!^(){}\-_~])+)?\w$/.test(req.params.host) && (/^(([a-z]|[A-Z]|[0-9]|[!^(){}\-_~])+)?\w$/.test(req.params.host) &&
req.params.host) || config.ssh.host, req.params.host) ||
port: (validator.isInt(req.query.port + '', { min: 1, max: 65535 }) && config.ssh.host,
req.query.port) || config.ssh.port, port:
(validator.isInt(req.query.port + '', { min: 1, max: 65535 }) &&
req.query.port) ||
config.ssh.port,
header: { header: {
name: req.query.header || config.header.text, name: req.query.header || config.header.text,
background: req.query.headerBackground || config.header.background background: req.query.headerBackground || config.header.background
@ -148,26 +169,53 @@ app.get('/ssh/host/:host?', function (req, res, next) {
algorithms: config.algorithms, algorithms: config.algorithms,
keepaliveInterval: config.ssh.keepaliveInterval, keepaliveInterval: config.ssh.keepaliveInterval,
keepaliveCountMax: config.ssh.keepaliveCountMax, keepaliveCountMax: config.ssh.keepaliveCountMax,
term: (/^(([a-z]|[A-Z]|[0-9]|[!^(){}\-_~])+)?\w$/.test(req.query.sshterm) && term:
req.query.sshterm) || config.ssh.term, (/^(([a-z]|[A-Z]|[0-9]|[!^(){}\-_~])+)?\w$/.test(req.query.sshterm) &&
req.query.sshterm) ||
config.ssh.term,
terminal: { terminal: {
cursorBlink: (validator.isBoolean(req.query.cursorBlink + '') ? myutil.parseBool(req.query.cursorBlink) : config.terminal.cursorBlink), cursorBlink: validator.isBoolean(req.query.cursorBlink + '')
scrollback: (validator.isInt(req.query.scrollback + '', { min: 1, max: 200000 }) && req.query.scrollback) ? req.query.scrollback : config.terminal.scrollback, ? myutil.parseBool(req.query.cursorBlink)
tabStopWidth: (validator.isInt(req.query.tabStopWidth + '', { min: 1, max: 100 }) && req.query.tabStopWidth) ? req.query.tabStopWidth : config.terminal.tabStopWidth, : config.terminal.cursorBlink,
bellStyle: ((req.query.bellStyle) && (['sound', 'none'].indexOf(req.query.bellStyle) > -1)) ? req.query.bellStyle : config.terminal.bellStyle scrollback:
validator.isInt(req.query.scrollback + '', { min: 1, max: 200000 }) &&
req.query.scrollback
? req.query.scrollback
: config.terminal.scrollback,
tabStopWidth:
validator.isInt(req.query.tabStopWidth + '', { min: 1, max: 100 }) &&
req.query.tabStopWidth
? req.query.tabStopWidth
: config.terminal.tabStopWidth,
bellStyle:
req.query.bellStyle &&
['sound', 'none'].indexOf(req.query.bellStyle) > -1
? req.query.bellStyle
: config.terminal.bellStyle
}, },
allowreplay: config.options.challengeButton || (validator.isBoolean(req.headers.allowreplay + '') ? myutil.parseBool(req.headers.allowreplay) : false), allowreplay:
config.options.challengeButton ||
(validator.isBoolean(req.headers.allowreplay + '')
? myutil.parseBool(req.headers.allowreplay)
: false),
allowreauth: config.options.allowreauth || false, allowreauth: config.options.allowreauth || false,
mrhsession: ((validator.isAlphanumeric(req.headers.mrhsession + '') && req.headers.mrhsession) ? req.headers.mrhsession : 'none'), mrhsession:
validator.isAlphanumeric(req.headers.mrhsession + '') &&
req.headers.mrhsession
? req.headers.mrhsession
: 'none',
serverlog: { serverlog: {
client: config.serverlog.client || false, client: config.serverlog.client || false,
server: config.serverlog.server || false server: config.serverlog.server || false
}, },
readyTimeout: (validator.isInt(req.query.readyTimeout + '', { min: 1, max: 300000 }) && readyTimeout:
req.query.readyTimeout) || config.ssh.readyTimeout (validator.isInt(req.query.readyTimeout + '', { min: 1, max: 300000 }) &&
req.query.readyTimeout) ||
config.ssh.readyTimeout
} }
if (req.session.ssh.header.name) validator.escape(req.session.ssh.header.name) if (req.session.ssh.header.name) validator.escape(req.session.ssh.header.name)
if (req.session.ssh.header.background) validator.escape(req.session.ssh.header.background) if (req.session.ssh.header.background)
validator.escape(req.session.ssh.header.background)
}) })
// express error handling // express error handling
@ -183,7 +231,8 @@ app.use(function (err, req, res, next) {
// socket.io // socket.io
// expose express session with socket.request.session // expose express session with socket.request.session
io.use(function (socket, next) { io.use(function (socket, next) {
(socket.request.res) ? session(socket.request, socket.request.res, next) socket.request.res
? session(socket.request, socket.request.res, next)
: next(next) : next(next)
}) })