This commit is contained in:
AJ ONeal 2020-11-13 05:19:12 -07:00
parent eef6ca679f
commit c234077fdc
71 changed files with 68 additions and 1548 deletions

View File

@ -1,2 +0,0 @@
vendor
go.sum

View File

@ -1,18 +0,0 @@
{ "node": true
, "browser": true
, "jquery": true
, "globals": { "angular": true, "Promise": true }
, "indent": 2
, "onevar": true
, "laxcomma": true
, "laxbreak": true
, "curly": true
, "nonbsp": true
, "eqeqeq": true
, "immed": true
, "undef": true
, "unused": true
, "latedef": true
}

View File

@ -1,4 +1,4 @@
// +build !dev // +build !dev
//go:generate go run -mod vendor github.com/shurcooL/vfsgen/cmd/vfsgendev -source="git.rootprojects.org/root/telebit/admin".AdminFS //go:generate go run -mod vendor github.com/shurcooL/vfsgen/cmd/vfsgendev -source="git.rootprojects.org/root/telebit/assets/admin".AdminFS
package admin package admin

View File

@ -1,4 +1,4 @@
// +build !dev // +build !dev
//go:generate go run -mod vendor github.com/shurcooL/vfsgen/cmd/vfsgendev -source="git.rootprojects.org/root/telebit/files".Assets //go:generate go run -mod vendor github.com/shurcooL/vfsgen/cmd/vfsgendev -source="git.rootprojects.org/root/telebit/assets/files".Assets
package files package files

View File

@ -1,6 +0,0 @@
go generate ./...
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod vendor -o mgmt-server-linux ./cmd/mgmt/*.go
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -mod vendor -o mgmt-server-macos ./cmd/mgmt/*.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -o mgmt-server-windows-debug.exe ./cmd/mgmt/*.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -ldflags "-H windowsgui" -o mgmt-server-windows.exe ./cmd/mgmt/*.go

View File

@ -1,11 +0,0 @@
#!/bin/bash
set -e
set -u
go generate ./...
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod vendor -o telebit-relay-linux ./cmd/telebit/*.go
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -mod vendor -o telebit-relay-macos ./cmd/telebit/*.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -o telebit-relay-windows-debug.exe ./cmd/telebit/*.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -ldflags "-H windowsgui" -o telebit-relay-windows.exe ./cmd/telebit/*.go

View File

@ -5,7 +5,7 @@ import (
"net" "net"
"os" "os"
"git.rootprojects.org/root/telebit/iplist" "git.rootprojects.org/root/telebit/internal/iplist"
) )
func help() { func help() {

View File

@ -11,9 +11,9 @@ import (
"strconv" "strconv"
"time" "time"
"git.rootprojects.org/root/telebit" "git.rootprojects.org/root/telebit/internal/dbg"
"git.rootprojects.org/root/telebit/dbg"
"git.rootprojects.org/root/telebit/internal/mgmt/authstore" "git.rootprojects.org/root/telebit/internal/mgmt/authstore"
"git.rootprojects.org/root/telebit/internal/telebit"
"github.com/denisbrodbeck/machineid" "github.com/denisbrodbeck/machineid"
_ "github.com/joho/godotenv/autoload" _ "github.com/joho/godotenv/autoload"

View File

@ -19,17 +19,15 @@ import (
"strings" "strings"
"time" "time"
"git.rootprojects.org/root/telebit" "git.rootprojects.org/root/telebit/internal/dbg"
"git.rootprojects.org/root/telebit/dbg"
"git.rootprojects.org/root/telebit/internal/dns01" "git.rootprojects.org/root/telebit/internal/dns01"
"git.rootprojects.org/root/telebit/internal/http01" "git.rootprojects.org/root/telebit/internal/http01"
"git.rootprojects.org/root/telebit/internal/iplist"
"git.rootprojects.org/root/telebit/internal/mgmt" "git.rootprojects.org/root/telebit/internal/mgmt"
"git.rootprojects.org/root/telebit/internal/mgmt/authstore" "git.rootprojects.org/root/telebit/internal/mgmt/authstore"
"git.rootprojects.org/root/telebit/internal/service" "git.rootprojects.org/root/telebit/internal/service"
telebitX "git.rootprojects.org/root/telebit/internal/telebit" "git.rootprojects.org/root/telebit/internal/telebit"
"git.rootprojects.org/root/telebit/iplist" "git.rootprojects.org/root/telebit/internal/tunnel"
"git.rootprojects.org/root/telebit/table"
"git.rootprojects.org/root/telebit/tunnel"
"github.com/coolaj86/certmagic" "github.com/coolaj86/certmagic"
"github.com/denisbrodbeck/machineid" "github.com/denisbrodbeck/machineid"
@ -590,7 +588,7 @@ func muxAll(
if "" != *apiHostname { if "" != *apiHostname {
// this is a generic net listener // this is a generic net listener
r := chi.NewRouter() r := chi.NewRouter()
telebitX.RouteAdmin(*authURL, r) telebit.RouteAdmin(*authURL, r)
apiListener := tunnel.NewListener() apiListener := tunnel.NewListener()
go func() { go func() {
httpsrv := &http.Server{Handler: r} httpsrv := &http.Server{Handler: r}
@ -716,7 +714,7 @@ func routeSubscribersAndClients(client net.Conn) error {
// tryToServeName picks the server tunnel with the least connections, if any // tryToServeName picks the server tunnel with the least connections, if any
func tryToServeName(servername string, wconn *telebit.ConnWrap) bool { func tryToServeName(servername string, wconn *telebit.ConnWrap) bool {
srv, ok := table.GetServer(servername) srv, ok := telebit.GetServer(servername)
if !ok || nil == srv { if !ok || nil == srv {
if ok { if ok {
// TODO BUG: Sometimes srv=nil & ok=true, which should not be possible // TODO BUG: Sometimes srv=nil & ok=true, which should not be possible

View File

@ -11,9 +11,9 @@ import (
"strings" "strings"
"time" "time"
"git.rootprojects.org/root/telebit"
"git.rootprojects.org/root/telebit/internal/mgmt" "git.rootprojects.org/root/telebit/internal/mgmt"
"git.rootprojects.org/root/telebit/internal/mgmt/authstore" "git.rootprojects.org/root/telebit/internal/mgmt/authstore"
"git.rootprojects.org/root/telebit/internal/telebit"
"github.com/denisbrodbeck/machineid" "github.com/denisbrodbeck/machineid"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"

View File

@ -13,9 +13,8 @@ import (
"strings" "strings"
"sync" "sync"
telebit "git.rootprojects.org/root/telebit"
tbDns01 "git.rootprojects.org/root/telebit/internal/dns01" tbDns01 "git.rootprojects.org/root/telebit/internal/dns01"
"git.rootprojects.org/root/telebit/table" "git.rootprojects.org/root/telebit/internal/telebit"
"github.com/coolaj86/certmagic" "github.com/coolaj86/certmagic"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
@ -219,7 +218,7 @@ func upgradeWebsocket(w http.ResponseWriter, r *http.Request) {
} }
wsTun := telebit.NewWebsocketTunnel(conn) wsTun := telebit.NewWebsocketTunnel(conn)
server := &table.SubscriberConn{ server := &telebit.SubscriberConn{
RemoteAddr: r.RemoteAddr, RemoteAddr: r.RemoteAddr,
WSConn: conn, WSConn: conn,
WSTun: wsTun, WSTun: wsTun,
@ -243,7 +242,7 @@ func upgradeWebsocket(w http.ResponseWriter, r *http.Request) {
fmt.Printf("a subscriber stream is done: %q\n", err) fmt.Printf("a subscriber stream is done: %q\n", err)
}() }()
table.Add(server) telebit.Add(server)
} }
func getACMEProvider(acmeRelay, token *string) (challenge.Provider, error) { func getACMEProvider(acmeRelay, token *string) (challenge.Provider, error) {

View File

@ -1,57 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Page Not Found</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
* {
line-height: 1.2;
margin: 0;
}
html {
color: #888;
display: table;
font-family: sans-serif;
height: 100%;
text-align: center;
width: 100%;
}
body {
display: table-cell;
vertical-align: middle;
margin: 2em auto;
}
h1 {
color: #555;
font-size: 2em;
font-weight: 400;
}
p {
margin: 0 auto;
width: 280px;
}
@media only screen and (max-width: 280px) {
body,
p {
width: 95%;
}
h1 {
font-size: 1.5em;
margin: 0 0 0.3em;
}
}
</style>
</head>
<body>
<h1>Page Not Found</h1>
<p>Sorry, but the page you were trying to view does not exist.</p>
</body>
</html>
<!-- IE needs 512+ bytes: http://blogs.msdn.com/b/ieinternals/archive/2010/08/19/http-error-pages-in-internet-explorer.aspx -->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Please read: https://msdn.microsoft.com/en-us/library/ie/dn455106.aspx -->
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="tile.png"/>
<square150x150logo src="tile.png"/>
<wide310x150logo src="tile-wide.png"/>
<square310x310logo src="tile.png"/>
</tile>
</msapplication>
</browserconfig>

View File

@ -1,15 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<!-- Read this: https://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html -->
<!-- Most restrictive policy: -->
<site-control permitted-cross-domain-policies="none"/>
<!-- Least restrictive policy: -->
<!--
<site-control permitted-cross-domain-policies="all"/>
<allow-access-from domain="*" to-ports="*" secure="false"/>
<allow-http-request-headers-from domain="*" headers="*" secure="false"/>
-->
</cross-domain-policy>

View File

@ -1,263 +0,0 @@
/*! HTML5 Boilerplate v5.3.0 | MIT License | https://html5boilerplate.com/ */
/*
* What follows is the result of much research on cross-browser styling.
* Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal,
* Kroc Camen, and the H5BP dev community and team.
*/
/* ==========================================================================
Base styles: opinionated defaults
========================================================================== */
html {
color: #222;
font-size: 1em;
line-height: 1.4;
}
/*
* Remove text-shadow in selection highlight:
* https://twitter.com/miketaylr/status/12228805301
*
* These selection rule sets have to be separate.
* Customize the background color to match your design.
*/
::-moz-selection {
background: #b3d4fc;
text-shadow: none;
}
::selection {
background: #b3d4fc;
text-shadow: none;
}
/*
* A better looking default horizontal rule
*/
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #ccc;
margin: 1em 0;
padding: 0;
}
/*
* Remove the gap between audio, canvas, iframes,
* images, videos and the bottom of their containers:
* https://github.com/h5bp/html5-boilerplate/issues/440
*/
audio,
canvas,
iframe,
img,
svg,
video {
vertical-align: middle;
}
/*
* Remove default fieldset styles.
*/
fieldset {
border: 0;
margin: 0;
padding: 0;
}
/*
* Allow only vertical resizing of textareas.
*/
textarea {
resize: vertical;
}
/* ==========================================================================
Browser Upgrade Prompt
========================================================================== */
.browserupgrade {
margin: 0.2em 0;
background: #ccc;
color: #000;
padding: 0.2em 0;
}
/* ==========================================================================
Author's custom styles
========================================================================== */
/* ==========================================================================
Helper classes
========================================================================== */
/*
* Hide visually and from screen readers
*/
.hidden {
display: none !important;
}
/*
* Hide only visually, but have it available for screen readers:
* http://snook.ca/archives/html_and_css/hiding-content-for-accessibility
*/
.visuallyhidden {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
/*
* Extends the .visuallyhidden class to allow the element
* to be focusable when navigated to via the keyboard:
* https://www.drupal.org/node/897638
*/
.visuallyhidden.focusable:active,
.visuallyhidden.focusable:focus {
clip: auto;
height: auto;
margin: 0;
overflow: visible;
position: static;
width: auto;
}
/*
* Hide visually and from screen readers, but maintain layout
*/
.invisible {
visibility: hidden;
}
/*
* Clearfix: contain floats
*
* For modern browsers
* 1. The space content is one way to avoid an Opera bug when the
* `contenteditable` attribute is included anywhere else in the document.
* Otherwise it causes space to appear at the top and bottom of elements
* that receive the `clearfix` class.
* 2. The use of `table` rather than `block` is only necessary if using
* `:before` to contain the top-margins of child elements.
*/
.clearfix:before,
.clearfix:after {
content: " "; /* 1 */
display: table; /* 2 */
}
.clearfix:after {
clear: both;
}
/* ==========================================================================
EXAMPLE Media Queries for Responsive Design.
These examples override the primary ('mobile first') styles.
Modify as content requires.
========================================================================== */
@media only screen and (min-width: 35em) {
/* Style adjustments for viewports that meet the condition */
}
@media print, (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 1.25dppx), (min-resolution: 120dpi) {
/* Style adjustments for high resolution devices */
}
/* ==========================================================================
Print styles.
Inlined to avoid the additional HTTP request:
http://www.phpied.com/delay-loading-your-print-css/
========================================================================== */
@media print {
*,
*:before,
*:after,
*:first-letter,
*:first-line {
background: transparent !important;
color: #000 !important; /* Black prints faster:
http://www.sanbeiji.com/archives/953 */
box-shadow: none !important;
text-shadow: none !important;
}
a,
a:visited {
text-decoration: underline;
}
a[href]:after {
content: " (" attr(href) ")";
}
abbr[title]:after {
content: " (" attr(title) ")";
}
/*
* Don't show links that are fragment identifiers,
* or use the `javascript:` pseudo protocol
*/
a[href^="#"]:after,
a[href^="javascript:"]:after {
content: "";
}
pre,
blockquote {
border: 1px solid #999;
page-break-inside: avoid;
}
/*
* Printing Tables:
* http://css-discuss.incutio.com/wiki/Printing_Tables
*/
thead {
display: table-header-group;
}
tr,
img {
page-break-inside: avoid;
}
img {
max-width: 100% !important;
}
p,
h2,
h3 {
orphans: 3;
widows: 3;
}
h2,
h3 {
page-break-after: avoid;
}
}

View File

@ -1,424 +0,0 @@
/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
/**
* 1. Set default font family to sans-serif.
* 2. Prevent iOS and IE text size adjust after device orientation change,
* without disabling user zoom.
*/
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/**
* Remove default margin.
*/
body {
margin: 0;
}
/* HTML5 display definitions
========================================================================== */
/**
* Correct `block` display not defined for any HTML5 element in IE 8/9.
* Correct `block` display not defined for `details` or `summary` in IE 10/11
* and Firefox.
* Correct `block` display not defined for `main` in IE 11.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
display: block;
}
/**
* 1. Correct `inline-block` display not defined in IE 8/9.
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
*/
audio,
canvas,
progress,
video {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address `[hidden]` styling not present in IE 8/9/10.
* Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
*/
[hidden],
template {
display: none;
}
/* Links
========================================================================== */
/**
* Remove the gray background color from active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* Improve readability of focused elements when they are also in an
* active/hover state.
*/
a:active,
a:hover {
outline: 0;
}
/* Text-level semantics
========================================================================== */
/**
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/**
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
*/
b,
strong {
font-weight: bold;
}
/**
* Address styling not present in Safari and Chrome.
*/
dfn {
font-style: italic;
}
/**
* Address variable `h1` font-size and margin within `section` and `article`
* contexts in Firefox 4+, Safari, and Chrome.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/**
* Address styling not present in IE 8/9.
*/
mark {
background: #ff0;
color: #000;
}
/**
* Address inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* Embedded content
========================================================================== */
/**
* Remove border when inside `a` element in IE 8/9/10.
*/
img {
border: 0;
}
/**
* Correct overflow not hidden in IE 9/10/11.
*/
svg:not(:root) {
overflow: hidden;
}
/* Grouping content
========================================================================== */
/**
* Address margin not present in IE 8/9 and Safari.
*/
figure {
margin: 1em 40px;
}
/**
* Address differences between Firefox and other browsers.
*/
hr {
box-sizing: content-box;
height: 0;
}
/**
* Contain overflow in all browsers.
*/
pre {
overflow: auto;
}
/**
* Address odd `em`-unit font size rendering in all browsers.
*/
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
/* Forms
========================================================================== */
/**
* Known limitation: by default, Chrome and Safari on OS X allow very limited
* styling of `select`, unless a `border` property is set.
*/
/**
* 1. Correct color not being inherited.
* Known issue: affects color of disabled elements.
* 2. Correct font properties not being inherited.
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
*/
button,
input,
optgroup,
select,
textarea {
color: inherit; /* 1 */
font: inherit; /* 2 */
margin: 0; /* 3 */
}
/**
* Address `overflow` set to `hidden` in IE 8/9/10/11.
*/
button {
overflow: visible;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
* Correct `select` style inheritance in Firefox.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* Remove inner padding and border in Firefox 4+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
input {
line-height: normal;
}
/**
* It's recommended that you don't attempt to style these elements.
* Firefox's implementation doesn't respect box-sizing, padding, or width.
*
* 1. Address box sizing set to `content-box` in IE 8/9/10.
* 2. Remove excess padding in IE 8/9/10.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
* `font-size` values of the `input`, it causes the cursor style of the
* decrement button to change from `default` to `text`.
*/
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
box-sizing: content-box; /* 2 */
}
/**
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
* Safari (but not Chrome) clips the cancel button when the search input has
* padding (and `textfield` appearance).
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct `color` not being inherited in IE 8/9/10/11.
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
*/
legend {
border: 0; /* 1 */
padding: 0; /* 2 */
}
/**
* Remove default vertical scrollbar in IE 8/9/10/11.
*/
textarea {
overflow: auto;
}
/**
* Don't inherit the `font-weight` (applied by a rule above).
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
*/
optgroup {
font-weight: bold;
}
/* Tables
========================================================================== */
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 766 B

View File

@ -1,15 +0,0 @@
# humanstxt.org/
# The humans responsible & technology colophon
# TEAM
<name> -- <role> -- <twitter>
# THANKS
<name>
# TECHNOLOGY COLOPHON
CSS3, HTML5
Apache Server Configs, jQuery, Modernizr, Normalize.css

View File

View File

@ -1,97 +0,0 @@
<!DOCTYPE html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title></title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
<!-- Place favicon.ico in the root directory -->
<link rel="stylesheet" href="css/normalize.css" />
<link rel="stylesheet" href="css/main.css" />
<script src="js/vendor/modernizr-2.8.3.min.js"></script>
<base href="/" />
</head>
<body ng-app="rvpnApp">
<!--[if lt IE 8]>
<p class="browserupgrade">
You are using an <strong>outdated</strong> browser. Please
<a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.
</p>
<![endif]-->
<!-- Admin GUI Begins Here -->
<header class="bs-docs-nav navbar navbar-static-top" id="top">
<div class="container">
<div class="navbar-header">
<a href="/admin/index.html" target="_parent" class="navbar-brand">RVPN Admin</a>
</div>
<nav class="collapse navbar-collapse" id="bs-navbar">
<ul class="nav navbar-nav">
<li><a href="/admin/status">Status</a></li>
<li><a href="/admin/servers">Servers</a></li>
<li><a href="/admin/#domains">Domains</a></li>
<li><a href="/admin/#connections">Connections</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Help</a></li>
<li><a href="#">Login</a></li>
</ul>
</nav>
</div>
</header>
<div ng-view></div>
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<script>
window.jQuery || document.write('<script src="admin/js/vendor/jquery-1.12.0.min.js"><\/script>');
</script>
<script src="admin/js/plugins.js"></script>
<script src="admin/js/main.js"></script>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<script>
(function (b, o, i, l, e, r) {
b.GoogleAnalyticsObject = l;
b[l] ||
(b[l] = function () {
(b[l].q = b[l].q || []).push(arguments);
});
b[l].l = +new Date();
e = o.createElement(i);
r = o.getElementsByTagName(i)[0];
e.src = "https://www.google-analytics.com/analytics.js";
r.parentNode.insertBefore(e, r);
})(window, document, "script", "ga");
ga("create", "UA-XXXXX-X", "auto");
ga("send", "pageview");
</script>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-route.js"></script>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp"
crossorigin="anonymous"
/>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"
></script>
<script src="/admin/js/vendor/filter.js"></script>
<script src="/admin/js/app.js"></script>
</html>

View File

@ -1,129 +0,0 @@
console.log("app.sh startup");
var app = angular.module("rvpnApp", ["ngRoute", "angular-duration-format"]);
app.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when("/admin/status/", {
templateUrl: "admin/partials/status.html"
})
.when("/admin/index.html", {
templateUrl: "admin/partials/servers.html"
})
.when("/admin/servers/", {
templateUrl: "admin/partials/servers.html"
})
.when("/admin/#domains", {
templateUrl: "green.htm"
})
.when("/blue", {
templateUrl: "blue.htm"
});
$locationProvider.html5Mode(true);
});
app.filter("bytes", function () {
return function (bytes, precision) {
if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) return "-";
if (typeof precision === "undefined") precision = 1;
var units = ["bytes", "kB", "MB", "GB", "TB", "PB"],
number = Math.floor(Math.log(bytes) / Math.log(1024));
return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + " " + units[number];
};
});
app.filter("hfcduration", function () {
return function (duration, precision) {
remain = duration;
duration_day = 24 * 60 * 60;
duration_hour = 60 * 60;
duration_minute = 60;
duration_str = "";
days = Math.floor(remain / duration_day);
if (days > 0) {
remain = remain - days * duration_day;
duration_str = duration_str + days + "d";
}
hours = Math.floor(remain / duration_hour);
if (hours > 0) {
remain = remain - hours * duration_hour;
duration_str = duration_str + hours + "h";
}
mins = Math.floor(remain / duration_minute);
if (mins > 0) {
remain = remain - mins * duration_minute;
duration_str = duration_str + mins + "m";
}
secs = Math.floor(remain);
duration_str = duration_str + secs + "s";
return duration_str;
};
});
app.controller("statusController", function ($scope, $http) {
console.log("statusController");
$scope.status_search = "";
var api = "/api/org.rootprojects.tunnel/status";
$scope.updateView = function () {
$http.get(api).then(function (response) {
console.log(response);
data = response.data;
if (data.error == "ok") {
$scope.status = data.result;
}
});
};
$scope.updateView();
});
app.controller("serverController", function ($scope, $http) {
$scope.servers = [];
$scope.servers_search = "";
$scope.servers_trigger_details = [];
$scope.filtered;
var api = "/api/org.rootprojects.tunnel/servers";
$scope.updateView = function () {
$http.get(api).then(function (response) {
//console.log(response);
data = response.data;
if (data.error == "ok") {
$scope.servers = data.result.servers;
}
});
};
$scope.triggerDetail = function (id) {
//console.log("triggerDetail ", id, $scope.servers_trigger_details[id])
if ($scope.servers_trigger_details[id] == true) {
$scope.servers_trigger_details[id] = false;
} else {
$scope.servers_trigger_details[id] = true;
}
};
$scope.checkDetail = function (id) {
//console.log("checkDetail ", id, $scope.servers_trigger_details[id])
if ($scope.servers_trigger_details[id] == true) {
return false;
} else {
return true;
}
};
$scope.updateView();
});

View File

View File

@ -1,44 +0,0 @@
// Avoid `console` errors in browsers that lack a console.
(function () {
var method;
var noop = function () {};
var methods = [
"assert",
"clear",
"count",
"debug",
"dir",
"dirxml",
"error",
"exception",
"group",
"groupCollapsed",
"groupEnd",
"info",
"log",
"markTimeline",
"profile",
"profileEnd",
"table",
"time",
"timeEnd",
"timeline",
"timelineEnd",
"timeStamp",
"trace",
"warn"
];
var length = methods.length;
var console = (window.console = window.console || {});
while (length--) {
method = methods[length];
// Only stub undefined methods.
if (!console[method]) {
console[method] = noop;
}
}
})();
// Place any jQuery/helper plugins in here.

View File

@ -1,165 +0,0 @@
// ### filter.js >>
angular.module("angular-duration-format.filter", []).filter("duration", function () {
var DURATION_FORMATS_SPLIT = /((?:[^ydhms']+)|(?:'(?:[^']|'')*')|(?:y+|d+|h+|m+|s+))(.*)/;
var DURATION_FORMATS = {
y: {
// years
// "longer" years are not supported
value: 365 * 24 * 60 * 60 * 1000
},
yy: {
value: "y",
pad: 2
},
d: {
// days
value: 24 * 60 * 60 * 1000
},
dd: {
value: "d",
pad: 2
},
h: {
// hours
value: 60 * 60 * 1000
},
hh: {
// padded hours
value: "h",
pad: 2
},
m: {
// minutes
value: 60 * 1000
},
mm: {
// padded minutes
value: "m",
pad: 2
},
s: {
// seconds
value: 1000
},
ss: {
// padded seconds
value: "s",
pad: 2
},
sss: {
// milliseconds
value: 1
},
ssss: {
// padded milliseconds
value: "sss",
pad: 4
}
};
function _parseFormat(string) {
// @inspiration AngularJS date filter
var parts = [];
var format = string ? string.toString() : "";
while (format) {
var match = DURATION_FORMATS_SPLIT.exec(format);
if (match) {
parts = parts.concat(match.slice(1));
format = parts.pop();
} else {
parts.push(format);
format = null;
}
}
return parts;
}
function _formatDuration(timestamp, format) {
var text = "";
var values = {};
format
.filter(function (format) {
// filter only value parts of format
return DURATION_FORMATS.hasOwnProperty(format);
})
.map(function (format) {
// get formats with values only
var config = DURATION_FORMATS[format];
if (config.hasOwnProperty("pad")) {
return config.value;
} else {
return format;
}
})
.filter(function (format, index, arr) {
// remove duplicates
return arr.indexOf(format) === index;
})
.map(function (format) {
// get format configurations with values
return angular.extend(
{
name: format
},
DURATION_FORMATS[format]
);
})
.sort(function (a, b) {
// sort formats descending by value
return b.value - a.value;
})
.forEach(function (format) {
// create values for format parts
var value = (values[format.name] = Math.floor(timestamp / format.value));
timestamp = timestamp - value * format.value;
});
format.forEach(function (part) {
var format = DURATION_FORMATS[part];
if (format) {
var value = values[format.value];
text += format.hasOwnProperty("pad")
? _padNumber(value, Math.max(format.pad, value.toString().length))
: values[part];
} else {
text += part.replace(/(^'|'$)/g, "").replace(/''/g, "'");
}
});
return text;
}
function _padNumber(number, len) {
return (new Array(len + 1).join("0") + number).slice(-len);
}
return function (value, format) {
var parsedValue = parseFloat(value, 10);
var parsedFormat = _parseFormat(format);
if (isNaN(parsedValue) || parsedFormat.length === 0) {
return value;
} else {
return _formatDuration(parsedValue, parsedFormat);
}
};
});
// ### << filter.js
// ### main.js >>
angular.module("angular-duration-format", ["angular-duration-format.filter"]);
// ### << main.js

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,98 +0,0 @@
<div class="panel panel-default" data-ng-controller="serverController">
<div class="panel-heading">
<div class="panel-title">
<div class="row">
<div class="col-md-6">
Servers
</div>
<div class="col-md-6">
<form class="form-inline pull-right">
<div class="form-group">
<label for="search">Search:</label>
<input type="text" class="form-control" id="search" data-ng-model="servers_search" />
</div>
<button type="button" title="Refresh" class="btn btn-default" aria-label="Refresh">
<span
class="glyphicon glyphicon-refresh"
title="Refresh"
aria-hidden="false"
ng-click="updateView()"
></span>
</button>
</form>
</div>
</div>
</div>
</div>
<div class="panel-body">
<table class="table table-striped table-bordered">
<th width="3%">ID</th>
<th width="10%">Name</th>
<th width="10%">Address</th>
<th width="10%">Xfer (in/out)</th>
<th width="10%">Req/Resp</th>
<th width="5%">Duration</th>
<th width="5%">State</th>
<th width="5%">Idle</th>
<th width="1%">
<center><span class="glyphicon glyphicon-option-vertical" aria-hidden="true"></span></center>
</th>
<tr ng-repeat="s in servers | filter:servers_search | orderBy:'server_id'">
<td>{{ s.server_id }}</td>
<td>{{ s.server_name }}</td>
<td>
{{ s.source_address }}
<div ng-hide="checkDetail(s.server_id)">
domains({{ s.domains.length}})
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
&nbsp&nbsp&nbsp{{ d.domain_name }}
</div>
</div>
</td>
<td>
{{ s.bytes_in | bytes }}/{{ s.bytes_out | bytes }}
<div ng-hide="checkDetail(s.server_id)">
&nbsp
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
&nbsp&nbsp&nbsp{{ d.bytes_in | bytes }}/{{ d.bytes_out | bytes }}
</div>
</div>
</td>
<td>
{{ s.requests }}/{{ s.responses }}
<div ng-hide="checkDetail(s.server_id)">
&nbsp
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
&nbsp&nbsp&nbsp{{ d.requests }}/{{ d.responses }}
</div>
</div>
</td>
<td>{{ s.duration | hfcduration }}</td>
<td>{{ s.server_state }}</td>
<td>{{ s.idle | hfcduration }}</td>
<td>
<span
class="glyphicon glyphicon-zoom-in"
title="Detail"
aria-hidden="false"
ng-click="triggerDetail(s.server_id)"
></span>
<div ng-hide="checkDetail(s.server_id)">
&nbsp
<div ng-repeat="d in s.domains | orderBy:'domain_name'">
<span
class="glyphicon glyphicon-zoom-in"
title="Detail"
aria-hidden="false"
ng-click="triggerDetail(s.server_id+d.domain_name)"
></span>
</div>
</div>
</td>
</tr>
</table>
</div>
</div>

View File

@ -1,52 +0,0 @@
<div class="panel panel-default" data-ng-controller="statusController">
<div class="panel-heading">
<div class="panel-title">
<div class="row">
<div class="col-md-6">
Status
</div>
<div class="col-md-6">
<form class="form-inline pull-right">
<div class="form-group">
<label for="search">Search:</label>
<input type="text" class="form-control" id="search" data-ng-model="servers_search" />
</div>
<button type="button" title="Refresh" class="btn btn-default" aria-label="Refresh">
<span
class="glyphicon glyphicon-refresh"
title="Refresh"
aria-hidden="false"
ng-click="updateView()"
></span>
</button>
</form>
</div>
</div>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-8">Server Name: {{ status.name }} (Uptime: {{ status.uptime | hfcduration }}</div>
</div>
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-8">Administrative Domain: {{ status.admin_domain }}</div>
</div>
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-8">Server Domain: {{ status.wss_domain }}</div>
</div>
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-8">Default LB Method: {{ status.loadbalance_default_method }}</div>
</div>
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-8">
Deadtime: dwell:{{ status.dead_time.dwell}} idle:{{ status.dead_time.idle}} cancel:{{
status.dead_time.cancel_check}}
</div>
</div>
</div>
</div>

View File

@ -1,5 +0,0 @@
# www.robotstxt.org/
# Allow crawling of all content
User-agent: *
Disallow:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -7,9 +7,9 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
telebit "git.rootprojects.org/root/telebit" "git.rootprojects.org/root/telebit/internal/dbg"
"git.rootprojects.org/root/telebit/dbg"
"git.rootprojects.org/root/telebit/internal/mgmt/authstore" "git.rootprojects.org/root/telebit/internal/mgmt/authstore"
"git.rootprojects.org/root/telebit/internal/telebit"
) )
type SuccessResponse struct { type SuccessResponse struct {

View File

@ -9,7 +9,8 @@ import (
"os" "os"
"time" "time"
"git.rootprojects.org/root/telebit/dbg" "git.rootprojects.org/root/telebit/internal/dbg"
jwt "github.com/dgrijalva/jwt-go" jwt "github.com/dgrijalva/jwt-go"
) )

View File

@ -7,7 +7,7 @@ import (
"io/ioutil" "io/ioutil"
"time" "time"
"git.rootprojects.org/root/telebit/files" "git.rootprojects.org/root/telebit/assets/files"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
// pq injects itself into sql as 'postgres' // pq injects itself into sql as 'postgres'

View File

@ -11,7 +11,7 @@ import (
"strings" "strings"
"time" "time"
"git.rootprojects.org/root/telebit/dbg" "git.rootprojects.org/root/telebit/internal/dbg"
"git.rootprojects.org/root/telebit/internal/mgmt/authstore" "git.rootprojects.org/root/telebit/internal/mgmt/authstore"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"

View File

@ -13,17 +13,15 @@ import (
"sync" "sync"
"time" "time"
"git.rootprojects.org/root/telebit" "git.rootprojects.org/root/telebit/assets/admin"
"git.rootprojects.org/root/telebit/admin" "git.rootprojects.org/root/telebit/internal/dbg"
"git.rootprojects.org/root/telebit/dbg"
"git.rootprojects.org/root/telebit/table"
"github.com/go-chi/chi" "github.com/go-chi/chi"
"github.com/go-chi/chi/middleware" "github.com/go-chi/chi/middleware"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
var authorizer telebit.Authorizer var authorizer Authorizer
// RouteAdmin sets up the API, including the Mgmt proxy and ACME relay // RouteAdmin sets up the API, including the Mgmt proxy and ACME relay
func RouteAdmin(authURL string, r chi.Router) { func RouteAdmin(authURL string, r chi.Router) {
@ -134,7 +132,7 @@ type SubscriberStatus struct {
func getAllSubscribers(w http.ResponseWriter, r *http.Request) { func getAllSubscribers(w http.ResponseWriter, r *http.Request) {
statuses := []*SubscriberStatus{} statuses := []*SubscriberStatus{}
table.Servers.Range(func(key, value interface{}) bool { Servers.Range(func(key, value interface{}) bool {
srvMap := value.(*sync.Map) srvMap := value.(*sync.Map)
status := getSubscribersHelper(srvMap) status := getSubscribersHelper(srvMap)
statuses = append(statuses, status) statuses = append(statuses, status)
@ -160,7 +158,7 @@ func getSubscribers(w http.ResponseWriter, r *http.Request) {
} }
var srvMap *sync.Map var srvMap *sync.Map
srvMapX, ok := table.Servers.Load(subject) srvMapX, ok := Servers.Load(subject)
if ok { if ok {
srvMap = srvMapX.(*sync.Map) srvMap = srvMapX.(*sync.Map)
statuses.Subscribers = append(statuses.Subscribers, getSubscribersHelper(srvMap)) statuses.Subscribers = append(statuses.Subscribers, getSubscribersHelper(srvMap))
@ -179,7 +177,7 @@ func getSubscribersHelper(srvMap *sync.Map) *SubscriberStatus {
srvMap.Range(func(k, v interface{}) bool { srvMap.Range(func(k, v interface{}) bool {
status.Sockets = append(status.Sockets, k.(string)) status.Sockets = append(status.Sockets, k.(string))
srv := v.(*table.SubscriberConn) srv := v.(*SubscriberConn)
if nil == status.Since || srv.Since.Sub(*status.Since) < 0 { if nil == status.Since || srv.Since.Sub(*status.Since) < 0 {
copied := srv.Since.Truncate(time.Second) copied := srv.Since.Truncate(time.Second)
status.Since = &copied status.Since = &copied
@ -199,7 +197,7 @@ func getSubscribersHelper(srvMap *sync.Map) *SubscriberStatus {
func delSubscribers(w http.ResponseWriter, r *http.Request) { func delSubscribers(w http.ResponseWriter, r *http.Request) {
subject := chi.URLParam(r, "subject") subject := chi.URLParam(r, "subject")
ok := table.Remove(subject) ok := Remove(subject)
if !ok { if !ok {
// TODO should this be an error? // TODO should this be an error?
_ = json.NewEncoder(w).Encode(&struct { _ = json.NewEncoder(w).Encode(&struct {
@ -243,7 +241,7 @@ func upgradeWebsocket(w http.ResponseWriter, r *http.Request) {
return return
} }
wsTun := telebit.NewWebsocketTunnel(conn) wsTun := NewWebsocketTunnel(conn)
fmt.Printf("New Authenticated WebSocket Remote Server\n") fmt.Printf("New Authenticated WebSocket Remote Server\n")
fmt.Printf("\thttp.req.RemoteAddr: %+v\n", r.RemoteAddr) fmt.Printf("\thttp.req.RemoteAddr: %+v\n", r.RemoteAddr)
fmt.Printf("\tconn.RemoteAddr(): %+v\n", conn.RemoteAddr()) fmt.Printf("\tconn.RemoteAddr(): %+v\n", conn.RemoteAddr())
@ -255,15 +253,15 @@ func upgradeWebsocket(w http.ResponseWriter, r *http.Request) {
// Rather the client's local address (the specific relay server) would be more useful. // Rather the client's local address (the specific relay server) would be more useful.
ctxEncoder, cancelEncoder := context.WithCancel(context.Background()) ctxEncoder, cancelEncoder := context.WithCancel(context.Background())
now := time.Now() now := time.Now()
server := &table.SubscriberConn{ server := &SubscriberConn{
Since: &now, Since: &now,
RemoteAddr: r.RemoteAddr, RemoteAddr: r.RemoteAddr,
WSConn: conn, WSConn: conn,
WSTun: wsTun, WSTun: wsTun,
Grants: grants, Grants: grants,
Clients: &sync.Map{}, Clients: &sync.Map{},
MultiEncoder: telebit.NewEncoder(ctxEncoder, wsTun), MultiEncoder: NewEncoder(ctxEncoder, wsTun),
MultiDecoder: telebit.NewDecoder(wsTun), MultiDecoder: NewDecoder(wsTun),
} }
// TODO should this happen at NewEncoder()? // TODO should this happen at NewEncoder()?
// (or is it even necessary anymore?) // (or is it even necessary anymore?)
@ -283,8 +281,8 @@ func upgradeWebsocket(w http.ResponseWriter, r *http.Request) {
fmt.Printf("a subscriber stream is done: %q\n", err) fmt.Printf("a subscriber stream is done: %q\n", err)
// TODO check what happens when we leave a junk connection // TODO check what happens when we leave a junk connection
//fmt.Println("[debug] [warn] removing server turned off") //fmt.Println("[debug] [warn] removing server turned off")
table.RemoveServer(server) RemoveServer(server)
}() }()
table.Add(server) Add(server)
} }

View File

@ -4,12 +4,10 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"strings" "strings"
"git.rootprojects.org/root/telebit"
) )
func NewAuthorizer(authURL string) telebit.Authorizer { func NewAuthorizer(authURL string) Authorizer {
return func(r *http.Request) (*telebit.Grants, error) { return func(r *http.Request) (*Grants, error) {
// do we have a valid wss_client? // do we have a valid wss_client?
fmt.Printf("[authz] Authorization = %s\n", r.Header.Get("Authorization")) fmt.Printf("[authz] Authorization = %s\n", r.Header.Get("Authorization"))
@ -28,7 +26,7 @@ func NewAuthorizer(authURL string) telebit.Authorizer {
fmt.Printf("[authz] authURL = %s\n", authURL) fmt.Printf("[authz] authURL = %s\n", authURL)
fmt.Printf("[authz] token = %s\n", tokenString) fmt.Printf("[authz] token = %s\n", tokenString)
grants, err := telebit.Inspect(authURL, tokenString) grants, err := Inspect(authURL, tokenString)
if nil != err { if nil != err {
fmt.Printf("[authorizer] error inspecting %q: %s\ntoken: %s\n", authURL, err, tokenString) fmt.Printf("[authorizer] error inspecting %q: %s\ntoken: %s\n", authURL, err, tokenString)

View File

@ -7,8 +7,8 @@ import (
"os" "os"
"time" "time"
"git.rootprojects.org/root/telebit/dbg" "git.rootprojects.org/root/telebit/internal/dbg"
"git.rootprojects.org/root/telebit/sni" "git.rootprojects.org/root/telebit/internal/sni"
) )
// ConnWrap is just a cheap way to DRY up some switch conn.(type) statements to handle special features of Conn // ConnWrap is just a cheap way to DRY up some switch conn.(type) statements to handle special features of Conn

View File

@ -5,7 +5,7 @@ import (
"io" "io"
"os" "os"
"git.rootprojects.org/root/telebit/dbg" "git.rootprojects.org/root/telebit/internal/dbg"
) )
// Decoder handles a Reader stream containing mplexy-encoded clients // Decoder handles a Reader stream containing mplexy-encoded clients

View File

@ -9,7 +9,7 @@ import (
"strings" "strings"
"sync" "sync"
"git.rootprojects.org/root/telebit/dbg" "git.rootprojects.org/root/telebit/internal/dbg"
) )
// TODO: try to be more like encoding/csv, or more like encoding/pem and encoding/json? // TODO: try to be more like encoding/csv, or more like encoding/pem and encoding/json?

View File

@ -9,7 +9,7 @@ import (
"os" "os"
"strings" "strings"
"git.rootprojects.org/root/telebit/dbg" "git.rootprojects.org/root/telebit/internal/dbg"
) )
// A Listener transforms a multiplexed websocket connection into individual net.Conn-like connections. // A Listener transforms a multiplexed websocket connection into individual net.Conn-like connections.

View File

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"os" "os"
"git.rootprojects.org/root/telebit/dbg" "git.rootprojects.org/root/telebit/internal/dbg"
) )
type Parser struct { type Parser struct {

View File

@ -9,7 +9,7 @@ import (
"strings" "strings"
"time" "time"
"git.rootprojects.org/root/telebit/dbg" "git.rootprojects.org/root/telebit/internal/dbg"
) )
// A RouteMux is a net.Conn multiplexer. // A RouteMux is a net.Conn multiplexer.

View File

@ -1,18 +1,17 @@
package table package telebit
import ( import (
"fmt" "fmt"
"io"
"net" "net"
"os" "os"
"strconv"
"strings"
"sync" "sync"
"time" "time"
"io" "git.rootprojects.org/root/telebit/internal/dbg"
"strconv"
"strings"
telebit "git.rootprojects.org/root/telebit"
"git.rootprojects.org/root/telebit/dbg"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
@ -108,18 +107,18 @@ type SubscriberConn struct {
Since *time.Time Since *time.Time
RemoteAddr string RemoteAddr string
WSConn *websocket.Conn WSConn *websocket.Conn
WSTun net.Conn // *telebit.WebsocketTunnel WSTun net.Conn // *WebsocketTunnel
Grants *telebit.Grants Grants *Grants
Clients *sync.Map Clients *sync.Map
// TODO is this the right codec type? // TODO is this the right codec type?
MultiEncoder *telebit.Encoder MultiEncoder *Encoder
MultiDecoder *telebit.Decoder MultiDecoder *Decoder
// to fulfill Router interface // to fulfill Router interface
} }
func (s *SubscriberConn) RouteBytes(src, dst telebit.Addr, payload []byte) { func (s *SubscriberConn) RouteBytes(src, dst Addr, payload []byte) {
id := fmt.Sprintf("%s:%d", src.Hostname(), src.Port()) id := fmt.Sprintf("%s:%d", src.Hostname(), src.Port())
if dbg.Debug { if dbg.Debug {
fmt.Fprintf( fmt.Fprintf(
@ -163,9 +162,9 @@ func (s *SubscriberConn) RouteBytes(src, dst telebit.Addr, payload []byte) {
} }
func (s *SubscriberConn) Serve(client net.Conn) error { func (s *SubscriberConn) Serve(client net.Conn) error {
var wconn *telebit.ConnWrap var wconn *ConnWrap
switch conn := client.(type) { switch conn := client.(type) {
case *telebit.ConnWrap: case *ConnWrap:
wconn = conn wconn = conn
default: default:
// this probably isn't strictly necessary // this probably isn't strictly necessary
@ -201,27 +200,27 @@ func (s *SubscriberConn) Serve(client net.Conn) error {
servername := wconn.Servername() servername := wconn.Servername()
termination := telebit.Unknown termination := Unknown
scheme := telebit.None scheme := None
if "" != servername { if "" != servername {
dstAddr = servername dstAddr = servername
//scheme = telebit.TLS //scheme = TLS
scheme = telebit.HTTPS scheme = HTTPS
} }
if 80 == dstPort { if 80 == dstPort {
scheme = telebit.HTTPS scheme = HTTPS
} else if 443 == dstPort { } else if 443 == dstPort {
// TODO dstAddr = wconn.Servername() // TODO dstAddr = wconn.Servername()
scheme = telebit.HTTP scheme = HTTP
} }
src := telebit.NewAddr( src := NewAddr(
scheme, scheme,
termination, termination,
srcAddr, srcAddr,
srcPort, srcPort,
) )
dst := telebit.NewAddr( dst := NewAddr(
scheme, scheme,
termination, termination,
dstAddr, dstAddr,

View File

@ -16,8 +16,8 @@ import (
"strings" "strings"
"time" "time"
"git.rootprojects.org/root/telebit/dbg" "git.rootprojects.org/root/telebit/internal/dbg"
httpshim "git.rootprojects.org/root/telebit/tunnel" httpshim "git.rootprojects.org/root/telebit/internal/tunnel"
"github.com/coolaj86/certmagic" "github.com/coolaj86/certmagic"
"github.com/mholt/acmez" "github.com/mholt/acmez"

View File

@ -7,7 +7,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"git.rootprojects.org/root/telebit/dbg" "git.rootprojects.org/root/telebit/internal/dbg"
) )
const ( const (

View File

@ -10,7 +10,7 @@ import (
"strings" "strings"
"time" "time"
"git.rootprojects.org/root/telebit/dbg" "git.rootprojects.org/root/telebit/internal/dbg"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )

View File

@ -1,8 +0,0 @@
TOKEN=$(go run cmd/signjwt/*.go)
echo "TOKEN: $TOKEN"
echo "Active:"
curl -L http://localhost:3000/api/devices -H "Authorization: Bearer ${TOKEN}"
echo "Inactive:"
curl -L http://localhost:3000/api/devices?inactive=true -H "Authorization: Bearer ${TOKEN}"

43
mgmt.sh
View File

@ -1,43 +0,0 @@
#!/bin/bash
set -e
set -u
# 1. (srv) create a new shared key for a given slug
# 2. (dev) try to update via ping
# 3. (dev) use key to exchange machine id
# 4. (dev) use key to connect to remote
# 5. (dev) ping occasionally
TOKEN=$(go run cmd/signjwt/*.go)
echo "TOKEN: $TOKEN"
my_shared="ZR2rxYmcKJcmtKgmH9D5Qw"
my_domain="example.com"
my_client="1-client-slug"
TOK=$(curl -X POST http://localhost:3000/api/devices -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" -d '{ "slug": "'$my_client'", "shared_key": "'$my_shared'" }')
echo Response: $TOK
SHARED=$(echo "$TOK" | sed 's/.*shared_key":"//g' | sed 's/".*//')
echo Shared Key: $SHARED
my_parts=$(go run cmd/signjwt/*.go $SHARED machineid)
my_ppid=$(echo $my_parts | cut -d' ' -f1)
my_keyid=$(echo $my_parts | cut -d' ' -f2)
echo "PPID: $my_ppid KeyID: $my_keyid"
TOKEN=$(go run cmd/signjwt/*.go $my_ppid)
echo "PING 1 (should fail)"
curl -X POST http://localhost:3000/api/ping -H "Authorization: Bearer ${TOKEN}"
echo ""
curl -X POST http://localhost:3000/api/register-device/$SHARED -H "Content-Type: application/json" -d '{ "machine_ppid": "'$my_ppid'", "public_key": "'$my_keyid'" }'
echo ''
echo "PING 2 (should work)"
curl -X POST http://localhost:3000/api/ping -H "Authorization: Bearer ${TOKEN}"
echo ""
curl -X POST http://localhost:3000/api/dns/"${my_client}.${my_domain}" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{ "token": "xxxx", "key_authorization": "yyyy" }'