Compare commits
5 Commits
Original
...
vala-sshwi
| Author | SHA1 | Date | |
|---|---|---|---|
| 6840a25901 | |||
| af24e54ce1 | |||
| 0cd699b2d3 | |||
| a2a0d85e5d | |||
| 8f39f4e907 |
@@ -68,6 +68,7 @@ ENV SSHWIFTY_HOSTNAME= \
|
|||||||
SSHWIFTY_ONLYALLOWPRESETREMOTES=
|
SSHWIFTY_ONLYALLOWPRESETREMOTES=
|
||||||
COPY --from=builder /sshwifty /
|
COPY --from=builder /sshwifty /
|
||||||
COPY . /sshwifty-src
|
COPY . /sshwifty-src
|
||||||
|
RUN apk add --no-cache tzdata
|
||||||
RUN set -ex && \
|
RUN set -ex && \
|
||||||
adduser -D sshwifty && \
|
adduser -D sshwifty && \
|
||||||
chmod +x /sshwifty && \
|
chmod +x /sshwifty && \
|
||||||
|
|||||||
@@ -254,45 +254,45 @@ func (s socket) Get(
|
|||||||
// DO NOT rely on this if you want to secured communitcation, in
|
// DO NOT rely on this if you want to secured communitcation, in
|
||||||
// that case, you need to use HTTPS.
|
// that case, you need to use HTTPS.
|
||||||
//
|
//
|
||||||
readNonce := [socketGCMStandardNonceSize]byte{}
|
// readNonce := [socketGCMStandardNonceSize]byte{}
|
||||||
_, nonceReadErr := io.ReadFull(&wsReader, readNonce[:])
|
// _, nonceReadErr := io.ReadFull(&wsReader, readNonce[:])
|
||||||
|
|
||||||
if nonceReadErr != nil {
|
// if nonceReadErr != nil {
|
||||||
return NewError(http.StatusBadRequest, fmt.Sprintf(
|
// return NewError(http.StatusBadRequest, fmt.Sprintf(
|
||||||
"Unable to read initial client nonce: %s", nonceReadErr.Error()))
|
// "Unable to read initial client nonce: %s", nonceReadErr.Error()))
|
||||||
}
|
// }
|
||||||
|
|
||||||
writeNonce := [socketGCMStandardNonceSize]byte{}
|
// writeNonce := [socketGCMStandardNonceSize]byte{}
|
||||||
nonceReadErr = s.generateNonce(writeNonce[:])
|
// nonceReadErr = s.generateNonce(writeNonce[:])
|
||||||
|
|
||||||
if nonceReadErr != nil {
|
// if nonceReadErr != nil {
|
||||||
return NewError(http.StatusBadRequest, fmt.Sprintf(
|
// return NewError(http.StatusBadRequest, fmt.Sprintf(
|
||||||
"Unable to generate initial server nonce: %s",
|
// "Unable to generate initial server nonce: %s",
|
||||||
nonceReadErr.Error()))
|
// nonceReadErr.Error()))
|
||||||
}
|
// }
|
||||||
|
|
||||||
_, nonceSendErr := wsWriter.Write(writeNonce[:])
|
// _, nonceSendErr := wsWriter.Write(writeNonce[:])
|
||||||
|
|
||||||
if nonceSendErr != nil {
|
// if nonceSendErr != nil {
|
||||||
return NewError(http.StatusBadRequest, fmt.Sprintf(
|
// return NewError(http.StatusBadRequest, fmt.Sprintf(
|
||||||
"Unable to send server nonce to client: %s", nonceSendErr.Error()))
|
// "Unable to send server nonce to client: %s", nonceSendErr.Error()))
|
||||||
}
|
// }
|
||||||
|
|
||||||
cipherKey := s.buildCipherKey(r)
|
// cipherKey := s.buildCipherKey(r)
|
||||||
|
|
||||||
readCipher, writeCipher, cipherCreationErr := s.createCipher(cipherKey[:])
|
// readCipher, writeCipher, cipherCreationErr := s.createCipher(cipherKey[:])
|
||||||
|
|
||||||
if cipherCreationErr != nil {
|
// if cipherCreationErr != nil {
|
||||||
return NewError(http.StatusInternalServerError, fmt.Sprintf(
|
// return NewError(http.StatusInternalServerError, fmt.Sprintf(
|
||||||
"Unable to create cipher: %s", cipherCreationErr.Error()))
|
// "Unable to create cipher: %s", cipherCreationErr.Error()))
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Start service
|
// Start service
|
||||||
const cipherReadBufSize = 4096
|
const cipherReadBufSize = 4096
|
||||||
|
|
||||||
cipherReadBuf := [cipherReadBufSize]byte{}
|
cipherReadBuf := [cipherReadBufSize]byte{}
|
||||||
cipherWriteBuf := [cipherReadBufSize]byte{}
|
cipherWriteBuf := [cipherReadBufSize]byte{}
|
||||||
maxWriteLen := int(cipherReadBufSize) - (writeCipher.Overhead() + 2)
|
maxWriteLen := int(cipherReadBufSize) // - (writeCipher.Overhead() + 2)
|
||||||
|
|
||||||
senderLock := sync.Mutex{}
|
senderLock := sync.Mutex{}
|
||||||
cmdExec, cmdExecErr := s.commander.New(
|
cmdExec, cmdExecErr := s.commander.New(
|
||||||
@@ -301,7 +301,7 @@ func (s socket) Get(
|
|||||||
DialTimeout: s.commonCfg.DecideDialTimeout(s.serverCfg.ReadTimeout),
|
DialTimeout: s.commonCfg.DecideDialTimeout(s.serverCfg.ReadTimeout),
|
||||||
},
|
},
|
||||||
rw.NewFetchReader(func() ([]byte, error) {
|
rw.NewFetchReader(func() ([]byte, error) {
|
||||||
defer s.increaseNonce(readNonce[:])
|
// defer s.increaseNonce(readNonce[:])
|
||||||
|
|
||||||
// Size is unencrypted
|
// Size is unencrypted
|
||||||
_, rErr := io.ReadFull(&wsReader, cipherReadBuf[:2])
|
_, rErr := io.ReadFull(&wsReader, cipherReadBuf[:2])
|
||||||
@@ -326,8 +326,10 @@ func (s socket) Get(
|
|||||||
return nil, rErr
|
return nil, rErr
|
||||||
}
|
}
|
||||||
|
|
||||||
return readCipher.Open(
|
copy(cipherReadBuf[2:], rData)
|
||||||
cipherReadBuf[:0], readNonce[:], rData, nil)
|
return cipherReadBuf[2 : 2+packageSize], nil
|
||||||
|
// return readCipher.Open(
|
||||||
|
// cipherReadBuf[:0], readNonce[:], rData, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, rErr = io.ReadFull(&wsReader, cipherReadBuf[:packageSize])
|
_, rErr = io.ReadFull(&wsReader, cipherReadBuf[:packageSize])
|
||||||
@@ -336,11 +338,12 @@ func (s socket) Get(
|
|||||||
return nil, rErr
|
return nil, rErr
|
||||||
}
|
}
|
||||||
|
|
||||||
return readCipher.Open(
|
return cipherReadBuf[:packageSize], nil
|
||||||
cipherReadBuf[:0],
|
// return readCipher.Open(
|
||||||
readNonce[:],
|
// cipherReadBuf[:0],
|
||||||
cipherReadBuf[:packageSize],
|
// readNonce[:],
|
||||||
nil)
|
// cipherReadBuf[:packageSize],
|
||||||
|
// nil)
|
||||||
}),
|
}),
|
||||||
socketPackageWriter{
|
socketPackageWriter{
|
||||||
w: wsWriter,
|
w: wsWriter,
|
||||||
@@ -354,15 +357,18 @@ func (s socket) Get(
|
|||||||
readLen = maxWriteLen
|
readLen = maxWriteLen
|
||||||
}
|
}
|
||||||
|
|
||||||
encrypted := writeCipher.Seal(
|
// encrypted := writeCipher.Seal(
|
||||||
cipherWriteBuf[2:2],
|
// cipherWriteBuf[2:2],
|
||||||
writeNonce[:],
|
// writeNonce[:],
|
||||||
b[start:start+readLen],
|
// b[start:start+readLen],
|
||||||
nil)
|
// nil)
|
||||||
|
|
||||||
s.increaseNonce(writeNonce[:])
|
// s.increaseNonce(writeNonce[:])
|
||||||
|
|
||||||
encryptedSize := uint16(len(encrypted))
|
copy(cipherWriteBuf[2+start:2+start+readLen], b[start:start+readLen])
|
||||||
|
|
||||||
|
// encryptedSize := uint16(len(cipherWriteBuf[2:]))
|
||||||
|
encryptedSize := readLen
|
||||||
|
|
||||||
if encryptedSize <= 0 {
|
if encryptedSize <= 0 {
|
||||||
return ErrSocketInvalidDataPackage
|
return ErrSocketInvalidDataPackage
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"HostName": "",
|
"HostName": "",
|
||||||
"SharedKey": "WEB_ACCESS_PASSWORD",
|
"SharedKey": "",
|
||||||
"DialTimeout": 5,
|
"DialTimeout": 5,
|
||||||
"Socks5": "",
|
"Socks5": "",
|
||||||
"Socks5User": "",
|
"Socks5User": "",
|
||||||
|
|||||||
18
ui/app.js
18
ui/app.js
@@ -286,16 +286,16 @@ function startApp(rootEl) {
|
|||||||
clientTime = new Date().getTime(),
|
clientTime = new Date().getTime(),
|
||||||
timeDiff = Math.abs(serverTime - clientTime);
|
timeDiff = Math.abs(serverTime - clientTime);
|
||||||
|
|
||||||
if (timeDiff > maxTimeDiff) {
|
// if (timeDiff > maxTimeDiff) {
|
||||||
this.loadErr =
|
// this.loadErr =
|
||||||
"The time difference between this client " +
|
// "The time difference between this client " +
|
||||||
"and the backend server is beyond operational limit.\r\n\r\n" +
|
// "and the backend server is beyond operational limit.\r\n\r\n" +
|
||||||
"Please try reload the page, and if the problem persisted, " +
|
// "Please try reload the page, and if the problem persisted, " +
|
||||||
"consider to adjust your local time so both the client and " +
|
// "consider to adjust your local time so both the client and " +
|
||||||
"the server are running at same date time";
|
// "the server are running at same date time";
|
||||||
|
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="home">
|
<div id="home">
|
||||||
<header id="home-header">
|
<header id="home-header">
|
||||||
<h1 id="home-hd-title">Sshwifty</h1>
|
<h1 id="home-hd-title">Vala Terminal</h1>
|
||||||
|
|
||||||
<a id="home-hd-delay" href="javascript:;" @click="showDelayWindow">
|
<a id="home-hd-delay" href="javascript:;" @click="showDelayWindow">
|
||||||
<span
|
<span
|
||||||
@@ -32,7 +32,6 @@
|
|||||||
socket.message
|
socket.message
|
||||||
}}</span>
|
}}</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
id="home-hd-plus"
|
id="home-hd-plus"
|
||||||
class="icon icon-plus1"
|
class="icon icon-plus1"
|
||||||
@@ -75,6 +74,8 @@
|
|||||||
servers without downloading any additional software.
|
servers without downloading any additional software.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h1>Eli Cohen</h1>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
To get started, click the
|
To get started, click the
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ import * as history from "./history.js";
|
|||||||
import { ECHO_FAILED } from "./socket.js";
|
import { ECHO_FAILED } from "./socket.js";
|
||||||
|
|
||||||
export function build(ctx) {
|
export function build(ctx) {
|
||||||
const connectionStatusNotConnected = "Sshwifty is ready to connect";
|
const connectionStatusNotConnected = "Vala Terminal is ready to connect";
|
||||||
const connectionStatusConnecting =
|
const connectionStatusConnecting =
|
||||||
"Connecting to Sshwifty backend server. It should only take " +
|
"Connecting to Vala Terminal backend server. It should only take " +
|
||||||
"less than a second, or two";
|
"less than a second, or two";
|
||||||
const connectionStatusDisconnected =
|
const connectionStatusDisconnected =
|
||||||
"Sshwifty is disconnected from it's backend server";
|
"Vala Terminal is disconnected from it's backend server";
|
||||||
const connectionStatusConnected =
|
const connectionStatusConnected =
|
||||||
"Sshwifty is connected to it's backend server, user interface operational";
|
"Vala Terminal is connected to it's backend server, user interface operational";
|
||||||
const connectionStatusUnmeasurable =
|
const connectionStatusUnmeasurable =
|
||||||
"Unable to measure connection delay. The connection maybe very " +
|
"Unable to measure connection delay. The connection maybe very " +
|
||||||
"busy or already lost";
|
"busy or already lost";
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>Sshwifty Web SSH Client</title>
|
<title>Vala Terminal</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
<div id="landing-message">
|
<div id="landing-message">
|
||||||
<div id="landing-message-logo"></div>
|
<div id="landing-message-logo"></div>
|
||||||
|
|
||||||
<h1 id="landing-message-title">Loading Sshwifty</h1>
|
<h1 id="landing-message-title">Loading Vala Terminal</h1>
|
||||||
|
|
||||||
<div id="landing-message-info">
|
<div id="landing-message-info">
|
||||||
<p>
|
<p>
|
||||||
@@ -45,9 +45,6 @@
|
|||||||
Copyright © 2019-2022 Ni Rui <ranqus@gmail.com>
|
Copyright © 2019-2022 Ni Rui <ranqus@gmail.com>
|
||||||
</p>
|
</p>
|
||||||
<p class="copy">
|
<p class="copy">
|
||||||
<a href="https://github.com/nirui/sshwifty" target="blank">
|
|
||||||
Source code
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="/sshwifty/assets/DEPENDENCIES.md" target="blank">
|
<a href="/sshwifty/assets/DEPENDENCIES.md" target="blank">
|
||||||
Third-party
|
Third-party
|
||||||
|
|||||||
30
ui/socket.js
30
ui/socket.js
@@ -36,10 +36,10 @@ class Dial {
|
|||||||
* decrypt socket traffic
|
* decrypt socket traffic
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
constructor(address, timeout, privateKey) {
|
constructor(address, timeout) {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
this.privateKey = privateKey;
|
// this.privateKey = privateKey;
|
||||||
this.keepAliveTicker = null;
|
this.keepAliveTicker = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,17 +205,17 @@ class Dial {
|
|||||||
10 // max 10 buffered requests
|
10 // max 10 buffered requests
|
||||||
);
|
);
|
||||||
|
|
||||||
let senderNonce = crypt.generateNonce();
|
// let senderNonce = crypt.generateNonce();
|
||||||
sd.send(senderNonce);
|
// sd.send(senderNonce);
|
||||||
|
|
||||||
let receiverNonce = await reader.readN(rd, crypt.GCMNonceSize);
|
// let receiverNonce = await reader.readN(rd, crypt.GCMNonceSize);
|
||||||
|
|
||||||
let key = await this.buildKey();
|
// let key = await this.buildKey();
|
||||||
|
|
||||||
sdDataConvert = async (rawData) => {
|
sdDataConvert = async (rawData) => {
|
||||||
let encoded = await crypt.encryptGCM(key, senderNonce, rawData);
|
let encoded = rawData; // await crypt.encryptGCM(key, senderNonce, rawData);
|
||||||
|
|
||||||
crypt.increaseNonce(senderNonce);
|
// crypt.increaseNonce(senderNonce);
|
||||||
|
|
||||||
let dataToSend = new Uint8Array(encoded.byteLength + 2);
|
let dataToSend = new Uint8Array(encoded.byteLength + 2);
|
||||||
|
|
||||||
@@ -236,13 +236,13 @@ class Dial {
|
|||||||
dSize <<= 8;
|
dSize <<= 8;
|
||||||
dSize |= dSizeBytes[1];
|
dSize |= dSizeBytes[1];
|
||||||
|
|
||||||
let decoded = await crypt.decryptGCM(
|
// let decoded = await crypt.decryptGCM(
|
||||||
key,
|
// key,
|
||||||
receiverNonce,
|
// receiverNonce,
|
||||||
await reader.readN(rd, dSize)
|
let decoded = await reader.readN(rd, dSize);
|
||||||
);
|
// );
|
||||||
|
|
||||||
crypt.increaseNonce(receiverNonce);
|
// crypt.increaseNonce(receiverNonce);
|
||||||
|
|
||||||
r.feed(
|
r.feed(
|
||||||
new reader.Buffer(new Uint8Array(decoded), () => {}),
|
new reader.Buffer(new Uint8Array(decoded), () => {}),
|
||||||
@@ -276,7 +276,7 @@ export class Socket {
|
|||||||
* @param {number} echoInterval Echo interval
|
* @param {number} echoInterval Echo interval
|
||||||
*/
|
*/
|
||||||
constructor(address, privateKey, timeout, echoInterval) {
|
constructor(address, privateKey, timeout, echoInterval) {
|
||||||
this.dial = new Dial(address, timeout, privateKey);
|
this.dial = new Dial(address, timeout);
|
||||||
this.echoInterval = echoInterval;
|
this.echoInterval = echoInterval;
|
||||||
this.streamHandler = null;
|
this.streamHandler = null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user