Initial Commit
Initial Commit
This commit is contained in:
commit
638fafb95d
6 changed files with 281 additions and 0 deletions
37
.gitignore
vendored
Normal file
37
.gitignore
vendored
Normal 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
104
index.js
Normal 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
19
package.json
Normal 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
22
public/client.htm
Normal 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
33
public/client.js
Normal 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
66
public/style.css
Normal 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;
|
||||||
|
}
|
Loading…
Reference in a new issue