Initial Commit

Initial Commit
This commit is contained in:
billchurch 2016-05-18 11:34:49 -04:00
commit 638fafb95d
6 changed files with 281 additions and 0 deletions

37
.gitignore vendored Normal file
View file

@ -0,0 +1,37 @@
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history

104
index.js Normal file
View file

@ -0,0 +1,104 @@
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var path = require('path');
var basicAuth = require('basic-auth');
var term = require('term.js');
var ssh = require('ssh2');
var username = null;
var password = null;
var host = null;
var port = 22;
var header = 'Default Header';
var headerBackground = 'rgb (0,90,0)';
function checkParams(arr) {
return function(req, res, next) {
// Make sure each param listed in arr is present in req.query
var missing_params = [];
for (var i = 0; i < arr.length; i++) {
if (!eval("req.query." + arr[i])) {
missing_params.push(arr[i]);
}
}
if (missing_params.length == 0) {
next();
} else {
next(JSON.stringify({
"error": "query error",
"message": "Parameter(s) missing: " + missing_params.join(",")
}));
}
}
}
server.listen({
host: '127.0.0.1',
port: 2222
});
app.use(express.static(__dirname + '/public')).use(term.middleware()).use(function(req, res, next) {
var myAuth = basicAuth(req);
if (myAuth === undefined) {
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="WebSSH"');
res.end('Username and password required for web SSH service.');
} else {
username = myAuth['name'];
password = myAuth['pass'];
next();
}
}).get('/', checkParams(["host"]), function(req, res) {
res.sendFile(path.join(__dirname + '/public/client.htm'))
host = req.query.host
if (typeof req.query.port !== 'undefined' && req.query.port !== null){ port = req.query.port;}
if (typeof req.query.header !== 'undefined' && req.query.header !== null){ header = req.query.header;}
if (typeof req.query.headerBackground !== 'undefined' && req.query.headerBackground !== null){ headerBackground = req.query.headerBackground;}
// debug // console.log('varibles passwd: ' + username + '/' + host + '/' + port);
});
io.on('connection', function(socket) {
var conn = new ssh();
conn.on('banner', function(msg, lng) {
socket.emit('data', msg);
}).on('ready', function() {
socket.emit('title', 'ssh://' + host);
socket.emit('headerBackground', headerBackground);
socket.emit('header', header);
socket.emit('footer', 'ssh://' + username + '@' + host + ':' + port);
socket.emit('status', 'SSH CONNECTION ESTABLISHED');
socket.emit('statusBackground', 'green');
conn.shell(function(err, stream) {
if (err) return socket.emit('status', 'SSH EXEC ERROR: ' + err.message).emit('statusBackground', 'red');
socket.on('data', function(data) {
stream.write(data);
});
stream.on('data', function(d) {
socket.emit('data', d.toString('binary'));
}).on('close', function() {
conn.end();
});
});
}).on('end', function() {
socket.emit('status', 'SSH CONNECTION CLOSED BY HOST');
socket.emit('statusBackground', 'red');
}).on('close', function() {
socket.emit('status', 'SSH CONNECTION CLOSED');
socket.emit('statusBackground', 'red');
}).on('error', function(error) {
socket.emit('status', 'SSH CONNECTION ERROR - ' + error)
socket.emit('statusBackground', 'red');
}).connect({
host: host,
port: port,
username: username,
password: password,
// some cisco routers need the these cipher strings
algorithms: {
'cipher': ['aes128-cbc', '3des-cbc', 'aes256-cbc'],
'hmac': ['hmac-sha1', 'hmac-sha1-96', 'hmac-md5-96']
}
});
});

19
package.json Normal file
View file

@ -0,0 +1,19 @@
{
"BIG-IP-comments": [
"package.json is the standard npm (www.npmjs.org) package definition file.",
"For more information please see www.npmjs.org/doc/package.json.html. "
],
"description": "A custom iRulesLX extension for BIG-IP",
"private": true,
"repository": {},
"engines": {
"node": "0.11.12"
},
"dependencies": {
"basic-auth": "^1.0.3",
"express": "^4.13.4",
"socket.io": "^1.4.5",
"ssh2": "^0.5.0",
"term.js": "0.0.7"
}
}

22
public/client.htm Normal file
View file

@ -0,0 +1,22 @@
<html>
<head>
<title>Web SSH</title>
<link rel="stylesheet" href="/xterm.css" />
<link rel="stylesheet" href="/style.css" />
<script src="/term.js"></script>
<script src="/client.js"></script>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
<div id="header"></div>
<div id="terminal" class="terminal">
<script>
client.run();
</script>
</div>
<div id="bottomdiv">
<div id="footer"></div>
<div id="status"></div>
</div>
</body>
</html>

33
public/client.js Normal file
View file

@ -0,0 +1,33 @@
var client = {};
client.run = function(options) {
options = options || {};
window.addEventListener('load', function() {
var socket = io.connect();
socket.on('connect', function() {
var term = new Terminal();
term.on('data', function(data) {
socket.emit('data', data);
});
socket.on('title', function(data) {
document.title = data;
}).on('status', function(data) {
document.getElementById('status').innerHTML = data;
}).on('headerBackground', function(data) {
document.getElementById('header').style.backgroundColor = data;
}).on('header', function(data) {
document.getElementById('header').innerHTML = data;
}).on('footer', function(data) {
document.getElementById('footer').innerHTML = data;
}).on('statusBackground', function(data) {
document.getElementById('status').style.backgroundColor = data;
});
term.open(document.getElementById("terminal"));
socket.on('data', function(data) {
term.write(data);
}).on('disconnect', function() {
document.getElementById('status').innerHTML = 'WEBSOCKET SERVER DISCONNECTED';
socket.io.reconnection(false);
});
});
}, false);
}

66
public/style.css Normal file
View file

@ -0,0 +1,66 @@
body {
font-family: helvetica, sans-serif, arial;
font-size: 1em;
color: #111;
background-color: rgb(0, 0, 0);
color: rgb(240, 240, 240);
}
#header {
color: rgb(240, 240, 240);
background-color: rgb(0, 128, 0);
width: 100%;
border-color: white;
border-style: none none solid none;
border-width: 1px;
text-align: center;
z-index: 99;
}
#terminal {
width: 960px;
height: 600px;
margin: 0 auto;
padding: 2px;
}
#terminal .terminal {
background-color: #111;
color: #fafafa;
padding: 2px;
}
#terminal .terminal .terminal-cursor {
background-color: #fafafa;
}
#bottomdiv {
width: 100%;
background-color: rgb(50, 50, 50);
border-color: white;
border-style: solid none none none;
border-width: 1px;
z-index: 99;
}
#footer {
display: inline-block;
color: rgb(240, 240, 240);
background-color: rgb(50, 50, 50);
padding-left: 10px;
padding-right: 10px;
text-align: left;
}
#status {
display: inline-block;
color: rgb(240, 240, 240);
background-color: rgb(50, 50, 50);
padding-left: 10px;
padding-right: 10px;
border-color: white;
border-style: none solid none solid;
border-width: 1px;
text-align: left;
z-index: 100;
}