merge in mainline commercial (use our lib/server.js)

This commit is contained in:
AJ ONeal 2018-10-07 20:54:26 -06:00
commit 156c07a099
21 changed files with 845 additions and 123 deletions

4
.gitignore vendored
View File

@ -1,4 +1,8 @@
emails
lib/extensions/permissions.json
lib/extensions/permissions.json.bak
lib/extensions/admin/sclient/dist/
lib/extensions/admin/optify/dist/
node_modules.*
include
bin/node

View File

@ -2,6 +2,10 @@
(function () {
'use strict';
var fs = require('fs');
var path = require('path');
var os = require('os');
var pkg = require('../package.json');
var argv = process.argv.slice(2);
@ -67,54 +71,59 @@ function applyConfig(config) {
state.config.greenlock.configDir = require('os').homedir() + require('path').sep + 'acme';
}
// The domains being approved for the first time are listed in opts.domains
// Certs being renewed are listed in certs.altnames
function approveDomains(opts, certs, cb) {
if (state.debug) { console.log('[debug] approveDomains', opts.domains); }
// This is where you check your database and associated
// email addresses with domains and agreements and such
// The domains being approved for the first time are listed in opts.domains
// Certs being renewed are listed in certs.altnames
if (certs) {
opts.domains = certs.altnames;
cb(null, { options: opts, certs: certs });
return;
}
if (!state.validHosts) { state.validHosts = {}; }
if (!state.validHosts[opts.domains[0]] && state.config.vhost) {
if (state.debug) { console.log('[sni] vhost checking is turned on'); }
var vhost = state.config.vhost.replace(/:hostname/, opts.domains[0]);
require('fs').readdir(vhost, function (err, nodes) {
if (state.debug) { console.log('[sni] checking fs vhost', opts.domains[0], !err); }
if (err) { check(); return; }
if (nodes) { approve(); }
});
return;
}
function approve() {
function allow() {
state.validHosts[opts.domains[0]] = true;
opts.email = state.config.email;
opts.agreeTos = state.config.agreeTos;
opts.communityMember = state.config.communityMember || state.config.greenlock.communityMember;
opts.challenges = {
// TODO dns-01
'http-01': require('le-challenge-fs').create({ webrootPath: '/tmp/acme-challenges' })
'http-01': require('le-challenge-fs').create({ webrootPath: path.join(os.tmpdir(), 'acme-challenges') })
};
opts.communityMember = state.config.communityMember;
cb(null, { options: opts, certs: certs });
}
function check() {
if (state.debug) { console.log('[sni] checking servername'); }
if (-1 !== state.servernames.indexOf(opts.domain) || -1 !== (state._servernames||[]).indexOf(opts.domain)) {
approve();
} else {
cb(new Error("failed the approval chain '" + opts.domains[0] + "'"));
}
function deny() {
cb(new Error("[bin/telebit-relay.js] failed the approval chain '" + opts.domains[0] + "'"));
return;
}
check();
// 1) If the host was already allowed => allow
if (!state.validHosts) { state.validHosts = {}; }
if (state.validHosts[opts.domains[0]]) {
allow();
return;
}
// 2) If the host is in the config => allow
if (state.debug) { console.log('[sni] checking servername'); }
if (-1 !== state.servernames.indexOf(opts.domain)
|| -1 !== (state._servernames||[]).indexOf(opts.domain)) {
allow();
return;
}
// 3) If dynamic vhosting is allowed
// & a vhost folder exist for this domain => allow
if (state.config.vhost) {
if (state.debug) { console.log('[sni] vhost checking is turned on'); }
var vhost = state.config.vhost.replace(/:hostname/, opts.domains[0]);
require('fs').readdir(vhost, function (err, nodes) {
if (state.debug) { console.log('[sni] checking fs vhost', opts.domains[0], !err); }
if (err) { deny(); return; }
if (nodes) { allow(); }
});
return;
}
// 4) fallback => fail
deny();
}
state.greenlock = Greenlock.create({
@ -196,7 +205,7 @@ function applyConfig(config) {
//});
}
require('fs').readFile(confpath, 'utf8', function (err, text) {
fs.readFile(confpath, 'utf8', function (err, text) {
var config;
var recase = require('recase').create({});

86
lib/extensions/admin/dist/notes.txt vendored Normal file
View File

@ -0,0 +1,86 @@
Release Notes
=============
Table of Contents
* v0.20.6 - protocol upgrade
Re: v0.20.6
===========
Saturday, Sept 29, 2018
This version is a required update. I had to make some changes to the network
protocol that were easy enough to make backwards-compatible in the client, but
not worth the effort to do so on the server.
Mac, Linux, Raspberry Pi Users:
-------------------------------
curl -fsSL https://get.telebit.io | bash
That should be quick and easy, but you may need to reboot your computer.
Windows & npm users
-------------------
npm install -g npm
Note that on Windows the upgrade will **NOT** work while Telebit is
running. `telebit restart` should kill it but, on Windows, won't actually
restart it.
This is not well tested, so please contact me (aj@ppl.family) if you have any
trouble.
Upgrading *really* old versions
---------------------
If you have a version of telebit prior to v0.18.1 (which may not even list its
version in `telebit help` yet), it'll probably be easiest to manually remove
the old telebit files first:
sudo rm -rf ~/Applications/telebit* ~/.config/telebit*
sudo rm -rf /opt/telebit* /etc/telebit* /etc/systemd/system/telebit*
You'll lose your current domain. If that's an issue, contact me and we can work
it out.
Rationale
---------
> "If it ain't broke, don't fix it" - Ancient Redneck Proverb
> "When is broke, is most right time to fix" - Ageless Chinese Adage
There's a delicate balance between the two and in my infinite wisdom I've
decided that now is the right time to fix.
There are some rather disruptive bugs in the network protocol and fixing them
means breaking most existing clients.
If you've been using telebit on a daily basis, especially with ssh, I believe
that'll you see benefit immediately and even moreso once the server is updated.
It's worth it.
Additional Notes
----------------
A number of good fixes are in here:
### `telebit help`
The in-app cli help is now correctly documented. Not everything _works_ as
documented, however. Feel free to poke around and give me feedback.
### `telebit ssh none`
Previously `telebit ssh none` behaved identically to `telebit ssh auto`.
The output correctly showed the actual behavior, but it didn't make sense.
Bascially this was happening: `telebit.ssh = telebit.ssh || 22`. So when it
it was `false` it became `true`
It was changed to this `if (!('ssh' in telebit)) { telebit.ssh = 22; }`.

View File

@ -2,13 +2,36 @@
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=900">
<title>Telebit&trade; Cloud</title>
<link href="static-site-assets/styles/main.css" rel="stylesheet">
<link href="static-site-assets/styles/vertical-slide.css" rel="stylesheet">
<link
href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,900"
rel="stylesheet"
>
<link href="static-site-assets/styles/1200.css" rel="stylesheet" media="(max-width:1075px)">
<style>
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-display: block;
font-weight: 400;
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(/static-site-assets/fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 700;
font-display: block;
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url(/static-site-assets/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
font-family: 'Source Code Pro';
font-style: normal;
font-weight: 400;
src: local('Source Code Pro'), local('SourceCodePro-Regular'), url(/static-site-assets/fonts/HI_SiYsKILxRpg3hIP6sJ7fM7PqlPevW.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
</style>
</head>
<body>
<header>
@ -29,10 +52,9 @@
</header><div class="hero">
<div class="container">
<div class="spiel">
<h1>Work from 127.0.0.1</h1>
</div>
<div class="hero-download">
<a class="link-button wide" href="#download-section">Download</a>
<h1>Access your devices
<br>Share your stuff
</h1>
</div>
<div aria-hidden="true" class="demo-row">
<div class="demo-container">
@ -44,7 +66,7 @@
<div class="demo-browser-address-bar">
<img src="static-site-assets/images/green-secure.png">
<div class="demo-browser-url">
https://test-app.telebit.cloud
https://jondoe.telebit.io
</div>
</div>
</div>
@ -55,12 +77,12 @@
<div class="demo-terminal">
<div class="demo-terminal-input">
~/telebit http 3000
telebit http 3000
</div>
<div class="demo-terminal-line">&nbsp;
</div>
<div class="demo-terminal-output">
Forwarding https://jondoe.telebit.io => localhost:3000
Forwarding https://jondoe.telebit.io =&gt; localhost:3000
</div>
</div>
</div>
@ -68,7 +90,7 @@
</div>
</div>
<div class="content">
<div class="container">
<div class="container quickstart-container">
<h2 class="use-it">Use it <div class="sliding-vertical">
<!-- to add more of or remove some of these, you will also need to update
./static-site-assets/styles/vertical-slide.css
@ -84,13 +106,17 @@
</div></h2>
<h2 id="download-section">Quickstart with bash</h2>
<div class="quickstart-step">
<div class="quickstart-step-number">1</div>
<div class="quickstart-step-text">Install Telebit</div>
<pre class="quickstart-terminal qickstart-terminal-prompt">curl https://get.telebit.io | bash</pre>
<div class="quickstart-step-text">
<div class="quickstart-step-number">1</div>
<div class="quickstart-step-name">Install Telebit</div>
</div>
<pre class="quickstart-terminal qickstart-terminal-prompt">curl https://get.telebit.io/ | bash</pre>
</div>
<div class="quickstart-step">
<div class="quickstart-step-number">2</div>
<div class="quickstart-step-text">Claim your device via Email</div>
<div class="quickstart-step-text">
<div class="quickstart-step-number">2</div>
<div class="quickstart-step-name">Claim your device via Email</div>
</div>
<pre class="quickstart-terminal">Hello!
Want to use 'Jon's Macbook Pro' with Telebit?
@ -99,8 +125,10 @@ Just confirm your email address:
<u>Confirm Email Address</u></pre>
</div>
<div class="quickstart-step">
<div class="quickstart-step-number">3</div>
<div class="quickstart-step-text">Enjoy Anytime, Anywhere Access</div>
<div class="quickstart-step-text">
<div class="quickstart-step-number">3</div>
<div class="quickstart-step-name">Enjoy Anytime, Anywhere Access</div>
</div>
<pre class="quickstart-terminal"><strong>For Local Development</strong>
<code class="quickstart-input">~/telebit http 3000</code>
@ -122,7 +150,7 @@ Just confirm your email address:
<code class="quickstart-output">Forwarding ssh+https (openssl proxy) =&gt; localhost:22</code>
<code class="quickstart-input">ssh -p 5050 jondoe.telebit.io</code>
<code class="quickstart-input">ssh -o ProxyCommand="sclient %h:443" jondoe.telebit.io</code>
<code class="quickstart-input">ssh -o ProxyCommand="<a href="sclient/">sclient</a> %h" jondoe.telebit.io</code>
<strong>For Debugging with TCP</strong>
@ -304,7 +332,7 @@ Just confirm your email address:
<div class="input-error email js-inactive"></div>
<input type="email" name="email" id="email" placeholder="Email">
</span>
<input class="link-button" type="submit">
<input class="link-button" type="submit" value="Join">
</form>
<ul>
<li><img src="static-site-assets/images/done.svg" />Get exclusive invites to try new features</li>

View File

@ -4,9 +4,11 @@
document.body.hidden = false;
function formSubmit() {
// to be used for good, not evil
var msg = {
address: document.querySelector('.js-list-address').value
, comment: 'telebit.cloud: ' + (document.querySelector('.js-list-comment').value || '')
name: document.querySelector('.js-list-comment').value
, address: document.querySelector('.js-list-address').value
, list: 'telebit@ppl.family'
};
window.fetch('https://api.ppl.family/api/ppl.family/public/list', {

View File

@ -0,0 +1,228 @@
body {
font-family: Source Sans Pro, sans-serif;
font-size: 18px;
color: #1a1a1a;
letter-spacing: -0.022222222em;
line-height: 1.33;
margin: 0;
padding-bottom: 4em;
box-sizing: border-box;
}
p {
margin: 0;
}
h2 {
font-size: 1.777777778em;
margin: 0 0 1em 0;
}
svg {
width: 1.333333333em;
height: 1.333333333em;
fill: #1a1a1a;
}
svg.icon-computer {width: 4em;height: 4em;}
button {
width: 100%;
background-color: #1a1a1a;
border: none;
font-size: 1em;
color: white;
padding: 0.44444em;
margin: 1em 0;
}
button:disabled {
background-color: #d9d9d9;
}
input[type=text] {
font-size: 1em;
padding: 0.444444444em 0.888889em;
width: 100%;
border: solid 1px #d9d9d9;
border-radius: 2px;
box-sizing: border-box;
margin: 0.888888889em 0;
}
.container {
text-align: center;
width: 17.777777778em;
margin: auto;
}
.checkbox-array {
display: flex;
flex-direction: column;
padding: 1em 0;
}
.checkbox-array input[type=checkbox] {
opacity: 0;
position: absolute;
}
.checkbox-array input[type=checkbox] ~ .icon-checked-box {
display: none;
}
.checkbox-array input[type=checkbox] ~ .icon-unchecked-box {
display: initial;
}
.checkbox-array input[type=checkbox]:checked ~ .icon-checked-box {
display: initial;
}
.checkbox-array input[type=checkbox]:checked ~ .icon-unchecked-box {
display: none;
}
.checkbox-array input[type=checkbox]:focus ~ .icon-checked-box, .checkbox-array input[type=checkbox]:focus ~ .icon-unchecked-box {
background: #DDDDDD;
}
.checkbox-array .icon-checked-box, .checkbox-array .icon-unchecked-box {
margin-right: 0.666666667em;
}
.checkbox-array label {
display: flex;
height: 1.333333333em;
font-size: 0.833333333em;
margin: 0.4em 0;
}
h1.logo {
font-size: 1.555555556em;
margin-bottom: 1.777777778em;
}
svg.authorized-check {
fill: #63f794;
margin-right: 0.666666667em;
}
.progress .row {
display: flex;
justify-content: left;
margin: 0 0 0.6666em 0;
}
.spinner-ball {
width: 4px;
height: 4px;
border-radius: 5px;
background: #1a1a1a;
margin: 2px;
}
span.spinner {
display: flex;
align-items: center;
margin-right: 0.666666667em;
}
.important-text {
font-weight: bold;
}
.progress {
display: inline-block;
margin-bottom: 1.111177778em;
}
.debugging-info-container {
text-align: center;
position: fixed;
bottom: 0;
width: 100%;
/* overflow: hidden; */
}
.debugging-info-container pre {
word-break: break-all;
white-space: pre-wrap;
}
.debugging-info {
max-width: 65em;
margin: 0 auto;
}
span.debugging.button {
display: inline-flex;
}
span.js-debugging-button.debugging-button {
display: inline-flex;
}
.debugging-button {
display: inline-flex;
padding: 0.3em;
position: absolute;
bottom: 100%;
transform: translateX(-50%);
background: white;
border: solid #eee 1px;
border-radius: 5px 5px 0 0;
border-bottom: none;
}
.debugging-info-container.visible .debugging-button svg {
transform: rotate(180deg);
}
.debugging-button svg {transition: transform 0.3s;}
.debug-drawer {
/* position: relative; */
transform: translateY(100%);
transition: transform 0.3s;
padding: 0.1em 0;
background: white;
pointer-events: initial;
border-top: solid #eee 1px;
padding-top: 1em;
}
.debugging-info-container.visible .debug-drawer {
transform: translateY(0);
}
.debugging-info-container {
padding-top: 3em;
overflow: hidden;
pointer-events: none;
}
.spinner .spinner-ball {
animation: pulsing 2s ease infinite;
}
.spinner .spinner-ball:nth-child(2) {
animation-delay: 0.2s;
}
.spinner .spinner-ball:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes pulsing {
0% {transform: scale(1);}
35% {transform: scale(1);}
60% {transform: scale(1.3);}
75% {transform: scale(1.3);}
100% {transform: scale(1);}
}
.finish-button {
margin-top: 2.222222222em;
}

View File

@ -1,63 +1,161 @@
<!DOCTYPE html>
<html>
<head>
<!--meta http-equiv="refresh" content="5;url=https://' + tokenData.domains.join(',') + '/?serviceport=' + tokenData.ports.join(',')" /-->
<title>Telebit - Pair Device</title>
<link href="./css/main.css" rel="stylesheet">
<style>
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-display: block;
font-weight: 400;
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(/static-site-assets/fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 700;
font-display: block;
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url(/static-site-assets/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
</style>
<link rel="preload" href="/static-site-assets/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2" as="font" crossorigin="anonymous">
<link rel="preload" href="/static-site-assets/fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2" as="font" crossorigin="anonymous">
</head>
<body>
<script>document.body.hidden = true;</script>
<!-- let's define our SVG that we will use later -->
<svg width="0" height="0" viewBox="0 0 24 24">
<defs>
<g id="svg-check">
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/>
</g>
<g id="svg-checked">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
</g>
<g id="svg-unchecked">
<path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</g>
<g id="svg-download">
<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</g>
<g id="svg-computer">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z"/>
</g>
<g id="svg-circle-check">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
</g>
<g id="svg-arrow-down">
<path d="M7.41,8.59L12,13.17l4.59-4.58L18,10l-6,6l-6-6L7.41,8.59z"/>
<path fill="none" d="M0,0h24v24H0V0z"/>
</g>
</defs>
</svg>
<div class="js-error" hidden>
<h1>Invalid Magic Link</h1>
<div class="js-magic-link">'{{magic_link}}' isn't a valid magic link code.
<h1>Invalid Pairing Link</h1>
<div class="js-magic-link">'{{magic_link}}' isn't a valid pairing link code.
<br>Links are only valid for a limited time, so you gotta act fast.
</div>
</div>
<div class="js-magic" hidden><form class="js-submit">
<h1>Telebit</h1>
<div class="container js-magic" hidden><form class="js-submit">
<h1 class="logo">Telebit</h1>
<svg class="icon-computer" viewBox="0 0 24 24">
<use xlink:href="#svg-computer"></use>
</svg>
<h2>Pair <span class="js-hostname">Device</span></h1>
<p>Enter your device pairing code:
<input type="text" name="pair-code" placeholder="ex: 000 000">
</p>
<ul>
<li><label><input name="telebit-agree" type="checkbox" required> Agree to Telebit Terms of Service</label>
</li>
<li><label><input name="letsencrypt-agree" type="checkbox" required> Agree to Let's Encrypt Terms of Service</label>
</li>
</ul>
<p>
<button type="submit">Claim Device</button>
</p>
<label><span class="important-text">Enter your device pairing code</span>
<input type="text" name="pair-code" placeholder="ex: 0000" autofocus>
</label>
<div class="checkbox-array">
<label>
<input name="telebit-agree" type="checkbox" required>
<svg class="icon-checked-box" viewBox="0 0 24 24">
<use xlink:href="#svg-checked"></use>
</svg>
<svg class="icon-unchecked-box" viewBox="0 0 24 24">
<use xlink:href="#svg-unchecked"></use>
</svg>
<div>Agree to <a target="_blank" href="/legal/">Telebit&trade; Terms of Service</a></div>
</label>
<label>
<input name="letsencrypt-agree" type="checkbox" required>
<svg class="icon-checked-box" viewBox="0 0 24 24">
<use xlink:href="#svg-checked"></use>
</svg>
<svg class="icon-unchecked-box" viewBox="0 0 24 24">
<use xlink:href="#svg-unchecked"></use>
</svg>
<div>Agree to <a target="_blank" href="https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"> Let's Encrypt&trade; Terms of Service</a></div>
</label>
</div>
<div>
<button type="submit" disabled>Claim Device</button>
</div>
</form></div>
<div class="js-authz" hidden>
<h1>Telebit Authorized</h1>
<h2>Waiting for your device to connect...</h2>
<p>Check your device to complete the pairing.</p>
<h2>🔒 <span class="js-domainname">xxx-xxx-xxx.example.com</span></h2>
<p>When your device is paired you will be redirected to
<a class="js-new-href">{{js-new-href}}</a>.
</p>
<h2 class="js-serviceport">xxxxx</h2>
<p>When your device is paired you will be able to use <span class="js-serviceport">xxxxx</span>
for SSH, and other TCP protocols.</p>
<pre><code>telebit ssh auto
ssh <span class="js-domainname">{{servername}}</span> -p <span class="js-serviceport">{{serviceport}}</span></code></pre>
</code></pre>
<h2>Authorization Token</h2>
<small><pre><code class="js-token">{{js-token}}</code></pre></small>
<div class="container js-authz" hidden>
<h1 class="logo">Telebit</h1>
<svg class="icon-computer" viewBox="0 0 24 24">
<use xlink:href="#svg-computer"></use>
</svg>
<h2>Pair <span class="js-hostname">Device</span></h1>
<div>
<div class="progress">
<div class="row">
<svg class="authorized-check" viewBox="0 0 24 24">
<use xlink:href="#svg-circle-check"></use>
</svg>
Authorized
</div>
<div class="row">
<span class="spinner">
<div class="spinner-ball ball-1"></div>
<div class="spinner-ball ball-1"></div>
<div class="spinner-ball ball-1"></div>
</span>
Waiting for device to pair
</div>
</div>
</div>
<div class="important-text">
Check the command line on your device to finish pairing.
</div>
</div>
<div class="js-debug-container debugging-info-container" hidden>
<div class="debug-drawer">
<span class="js-debug-button debugging-button">
Debugging info <svg class="debugging-arrow" viewBox="0 0 24 24">
<use xlink:href="#svg-arrow-down"></use>
</svg>
</span>
<div class="js-debug-info debugging-info">
<p><a class="js-new-href">{{js-new-href}}</a></p>
<p class="js-serviceport">xxxxx</p>
<p><small>Authorization Token:
<pre><code class="js-token">{{js-token}}</code></pre></small></p>
</div>
</div>
</div>
<div class="container js-finish" hidden>
<h1 class="logo">Telebit</h1>
<svg class="icon-computer" viewBox="0 0 24 24">
<use xlink:href="#svg-computer"></use>
</svg>
<h2>Success!</h1>
<div>
<span class="important-text js-new-domain">______</span> is paired and ready to use for accessing your device and sharing your stuff.
</div>
<button class="js-finish-button finish-button">Take Me There</button>
<script src="js/app.js"></script>
</div>
<script src="js/app.js"></script>
</body>
</html>

View File

@ -4,6 +4,7 @@
var meta = {};
var magic;
var domainname;
var port;
function checkStatus() {
// TODO use Location or Link
@ -18,6 +19,7 @@ function checkStatus() {
return;
}
if ('complete' === data.status) {
successScreen();
setTimeout(function () {
//window.document.body.innerHTML += ('<img src="https://' + domainname + '/_apis/telebit.cloud/clear.gif">');
// TODO once this is loaded (even error) Let's Encrypt is done,
@ -33,6 +35,18 @@ function checkStatus() {
});
}
function successScreen() {
document.querySelector('.js-authz').hidden = true;
document.querySelector('.js-finish-button').addEventListener('click', function(e) {
window.location.href='https://' + domainname + "/#/serviceport=" + port;
});
document.querySelectorAll('.js-new-domain').forEach(function(ele) {
ele.innerHTML = domainname;
});
document.querySelector('.js-finish').hidden = false;
}
function submitCode(pair) {
// TODO use Location or Link
document.querySelector('.js-magic').hidden = true;
@ -63,6 +77,7 @@ function submitCode(pair) {
setTimeout(checkStatus, 0);
document.querySelector('.js-authz').hidden = false;
document.querySelector('.js-debug-container').hidden = false;
/*
document.querySelectorAll('.js-token-data').forEach(function ($el) {
@ -71,6 +86,7 @@ function submitCode(pair) {
*/
document.querySelectorAll('.js-new-href').forEach(function ($el) {
domainname = data.domains[0];
port = data.port;
$el.href = 'https://' + data.domains[0] + '/';
$el.innerText = '🔐 https://' + data.domains[0];
});
@ -113,7 +129,9 @@ function init() {
return;
}
document.querySelector('.js-magic').hidden = false;
document.querySelector('.js-hostname').innerText = data.hostname || 'Device';
document.querySelectorAll('.js-hostname').forEach(function(ele) {
ele.innerText = data.hostname || 'Device';
});
//document.querySelector('.js-token-data').innerText = JSON.stringify(data, null, 2);
});
});
@ -129,6 +147,23 @@ function init() {
console.log(pair);
submitCode(pair);
});
var formElements = document.querySelector('.js-submit').elements;
for(var i = 0; i < formElements.length; ++i) {
var tosCheck = document.querySelector('[name=telebit-agree]');
var leCheck = document.querySelector('[name=letsencrypt-agree]');
var pairCodeInput = document.querySelector('[name=pair-code]');
formElements[i].addEventListener('input', function(ev) {
if(tosCheck.checked && leCheck.checked && pairCodeInput.value.length) {
document.querySelector('.js-submit button').disabled = false;
} else {
document.querySelector('.js-submit button').disabled = true;
}
});
};
document.querySelector('.js-debug-button').addEventListener("click", function(e) {
document.querySelector('.js-debug-container').classList.toggle("visible");
})
}
window.fetch('https://' + location.hostname + '/_apis/telebit.cloud/index.json', {

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<title>Optify - Containerize without the container</title>
</head>
<body>
<h1>Optify</h1>
<p>containerize without the container</p>
<p>Holds your hand without being so hands on.
Like brew and Docker had a baby that <em>did</em> care about versions and <em>didn't</em> care about port numbers.
Only for the masters of their domain.
Be wise and be bold.</p>
</body>
</html>

View File

@ -0,0 +1,58 @@
#!/bin/bash
#<pre><code>
set -e
set -u
# minimal os detection
my_os="$(uname -s | tr '[:upper:]' '[:lower:]')"
# https://github.com/golang/go/wiki/GoArm#supported-architectures
# minimal cpu arch detection
my_arch="$(uname -m)"
if [ "x86_64" == "$my_arch" ]; then
my_arch="amd64"
elif [ "i386" == "$my_arch" ]; then
my_arch="386"
elif [ -n "$($my_arch | grep arm)" ]; then
if [ -n "$(uname -a | grep aarch64)" ]; then
my_arch="arm64"
elif [ -n "$(uname -a | grep armv8l)" ]; then
my_arch="arm64"
elif [ -n "$(uname -a | grep armv7l)" ]; then
my_arch="armv7l"
elif [ -n "$(uname -a | grep armv6l)" ]; then
my_arch="armv6l"
else
echo "could not determine arm cpu architecture" >&2
exit 1
fi
else
echo "could not determine cpu architecture" >&2
exit 1
fi
# get optify for this cpu and arch
if [ -z "${OPTIFY_VERSION:-}" ]; then
latest_version="$(curl -fsSL https://telebit.cloud/optify/latest)"
OPTIFY_VERSION=$latest_version
echo "Installing optify-$OPTIFY_VERSION (latest)"
else
echo "Installing optify OPTIFY_VERSION=$OPTIFY_VERSION"
fi
# download to a tmp folder
#my_tmpdir="$(mktemp -d /tmp/optify.XXXXXXXX)"
my_tmpdir="$(mktemp -d -t optify.XXXXXXXX)"
my_url="https://telebit.cloud/optify/dist/${my_os}/${my_arch}/optify-${OPTIFY_VERSION}"
if [ -n "$(type -p curl || true)" ]; then
my_out="$(curl -fsSL -o "$my_tmpdir/optify-${OPTIFY_VERSION}" "$my_url" || true)"
elif [ -n "$(type -p wget || true)" ]; then
my_out="$(wget -q -c "$my_url" -O "$my_tmpdir/optify-${OPTIFY_VERSION}" || true)"
else
echo "found neither wget nor curl" >&2
exit 1
fi
# check for downloader success
chmod a+x "$my_tmpdir/optify-${OPTIFY_VERSION}"
"$my_tmpdir/optify-${OPTIFY_VERSION}" --install

View File

@ -0,0 +1 @@
v0.0.5

View File

@ -14,10 +14,13 @@
(think <code>telnet</code>, <code>netcat</code>, <code>ssh</code>, <code>openvpn</code>, etc).</p>
<h2>Usage</h2>
<pre><code>$ sclient [-k] &lt;remote> &lt;local></code></pre>
<pre><code>$ sclient [flags] &lt;remote&gt; &lt;local&gt;</code></pre>
<pre><code>$ sclient example.com:443 localhost:3000</code></pre>
<h3>Flags</h3>
<ul>
<li><kbd>-k, --insecure</kbd> ignore invalid tls certificates</li>
<li><kbd>--servername &lt;string&gt;</kbd> spoof SNI
(to disable use IP as &lt;remote&gt; and do not use this option)</li>
</ul>
<h3>Arguments</h3>
<ul>
@ -25,17 +28,37 @@
<li><kbd>&lt;local&gt;</kbd> the local address and port to bind to (default bind address is 127.0.0.1 or ::1)
<ul>
<li><code>-</code> may be used to read from stdin (like netcat)</li>
<li>may be omitted when piping <code>printf "GET / HTTP/1.1\r\n\r\n" | sclient telebit.cloud</code></li>
<li>may be omitted when piping (see pipe example below)</li>
</ul>
</li>
</ul>
<h2>Example</h2>
<h2>Examples</h2>
<h3>SSH</h3>
<pre><code>$ ssh -o ProxyCommand="sclient %h" jon.telebit.io</code></pre>
<p>This is useful to be able to connect to SSH even from behind a corporate packet-inspection firewall.
It can also be used to multiplex and relay multiple ssh connections through a single host.
</p>
<h3>Telnet </h3>
<pre><code>$ sclient example.com:443 localhost:3000
&gt; [listening] example.com:443 &lt;= localhost:3000</code></pre>
<pre><code>$ telnet localhost 3000</code></pre>
<h3>stdin/stdout</h3>
<pre><code>$ sclient whatever.com -
&gt; (connected to whatever.com:443 and reading from stdin)</code></pre>
Use just like netcat or telnet. A manual HTTP request, for example:
<pre><code>&gt; GET / HTTP/1.1
&gt; Host: whatever.com
&gt; Connection: close
&gt;
</code></pre>
<h2>Downloads (standalone) <small>v1.1</small></h2>
<h3>pipe</h3>
<pre><code>$ printf "GET / HTTP/1.1\r\nHost: telebit.cloud\r\n\r\n" | sclient telebit.cloud</code></pre>
<h2>Downloads (standalone) <small>v1.2</small></h2>
<ul>
<li>Windows 7/8/10
<a href="dist/windows/amd64/sclient.exe">Download</a>

View File

@ -0,0 +1,47 @@
.quickstart-step-text {
align-items: center;
justify-content: center;
margin: 0 0 1.5em;
}
.quickstart-step {
flex-direction: column;
justify-content: center;
align-items: center;
}
.quickstart-terminal {
flex: 0 0;
}
.container.quickstart-container {
padding: 0;
}
@media (max-width: 900px) {
.donate-section p {
margin: 1.77777778em 10%;
font-size: 1.6em;
}
.quickstart-terminal {
width: 100%;
box-sizing: border-box;
font-size: .95em;
}
h2 {
font-size: 1.9em;
}
.quickstart-step-name {
font-size: 1.2em;
}
h3 {
font-size: 1.5em;
}
}

View File

@ -1,8 +1,10 @@
body{
font-family: Source Sans Pro, sans-serrif;
font-size: 18px;
font-size: 17px;
line-height: 1.3333;
margin: 0;
-webkit-text-size-adjust: none;
text-size-adjust: none;
}
a {
@ -30,7 +32,7 @@ a:hover, u:hover {
}
.container {
width: 840px;
width: 788px;
margin: auto;
}
@ -93,7 +95,7 @@ a.link-button.wide {
}
.demo-container {
margin: 1em 9.4444em 0;
margin-top: 1em;
position: relative;
height: 236px;
width: 644px;
@ -191,13 +193,13 @@ a.link-button.wide {
content: ">";
}
h2 {text-align: center;font-size: 1.777778em;margin: 0 0 1.25em 0;}
h2 {text-align: center;font-size: 1.77778em;margin: 0 0 1.25em 0;}
body {}
.donate-section {
background-color: #f7f7f7;
padding: 1.777778em;
padding: 1.777778em 0;
}
.use-it {
@ -215,7 +217,7 @@ body {}
height: 1.583333333em;
width: 1.5833333333em;
font-weight: bold;
display: flex;
display: inline-flex;
align-items: center;
justify-content: space-around;
background-color: #f8f8f8;
@ -226,24 +228,27 @@ body {}
.quickstart-step {
font-size: 1.33333em;
display: flex;
flex-wrap: wrap;
margin-bottom: 2em;
overflow: hidden;
justify-content: center;
}
.quickstart-step-text {
width: 7.833333333em;
min-width: 9.583336em;
margin-right: 1.3333333em;
flex-shrink: 0;
flex: 1 1;
display: flex;
}
.quickstart-terminal {
flex: 1;
flex: 0 0 36.7em;
background-color: #f7f7f7;
font-family: monospace;
font-size: 0.625em;
font-size: 0.8em;
width: 36.7em;
line-height: 1.33;
margin: 0;
padding: 0.8em 0 0.8em 2em;
padding: 0.8em 1em 0.8em 2em;
}
.quickstart-line:before {
content: " ";
@ -263,6 +268,7 @@ h3 {
.install-badges {
display: flex;
justify-content: space-between;
margin: auto;
}
.install-badge {
@ -307,7 +313,7 @@ h3 {
}
.feature-list {
margin: 4em;
margin: 4em 0;
}
.donate-section h2 {
@ -347,7 +353,7 @@ input {
.mailing-list-form {
background-color: #d9d9d9;
padding: 1.77777778em;
padding: 1.77777778em 0;
}
.mailing-list-form li img {
@ -365,7 +371,7 @@ footer .container {
footer {
background-color: #b3b3b3;
color: white;
padding: 1.444444444em;
padding: 1.444444444em 0;
}
footer li {
@ -410,3 +416,18 @@ a {}
.install-badge:hover path {
fill: #ababab;
}
input[type="submit"] {
appearance: none;
-webkit-appearance: none;
}
.quickstart-container {
max-width: 1025px;
width: auto;
padding: 0px 3.111111111em;
}
.quickstart-step-name {
display: inline-block;
}

View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0;url=https://docs.google.com/presentation/d/e/2PACX-1vRQ1YyZcTDKYINLvUe8OdaDn_mIoCc0v8XSK-rgI3-b8EldgqpwbZEGmPn7J9pN1vnEJ1-pOcl_T-QP/pub">
<style>
body, html {
height: 100%;
margin: 0%;
padding: 0%;
background-color: black;
}
.bg {
background-image: url("http://www.tshirtvortex.net/wp-content/uploads/thenamesrex.jpg");
height: 100%;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
a {
color: white;
}
</style>
</head>
<body>
<div class="bg">
<center>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<h1><a href="https://docs.google.com/presentation/d/e/2PACX-1vRQ1YyZcTDKYINLvUe8OdaDn_mIoCc0v8XSK-rgI3-b8EldgqpwbZEGmPn7J9pN1vnEJ1-pOcl_T-QP/pub?start=false&loop=false&delayms=3000">Access Ability (look ma, no cloud) [slides]</a></h1>
</center>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -39,4 +39,9 @@ files.forEach(function (fname) {
, os: mdata.os_type, arch: mdata.os_arch });
});
});
console.log('');
console.log('[\n' + Object.keys(emails).map(function (k) { return JSON.stringify(emails[k]); }).join(',\n') + '\n]');
console.log('');
console.log('');
console.log(Object.keys(emails).join(', '));
console.log('');

View File

@ -0,0 +1,12 @@
'use strict';
var perms = require('./permissions.json');
var emails = {};
perms.forEach(function (p) {
p.nodes.forEach(function (n) {
if ('email' === n.type) {
emails[n.name] = true;
}
});
});
console.log(Object.keys(emails).join(', '));