squash refactor
This commit is contained in:
parent
e57917a252
commit
7d6437f4c5
|
@ -12,7 +12,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
telebit "git.coolaj86.com/coolaj86/go-telebitd"
|
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/log"
|
"git.coolaj86.com/coolaj86/go-telebitd/log"
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/relay"
|
"git.coolaj86.com/coolaj86/go-telebitd/relay"
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/relay/api"
|
"git.coolaj86.com/coolaj86/go-telebitd/relay/api"
|
||||||
|
@ -46,7 +45,7 @@ var (
|
||||||
connectionTable *api.Table
|
connectionTable *api.Table
|
||||||
secretKey string
|
secretKey string
|
||||||
wssHostName = "localhost.rootprojects.org"
|
wssHostName = "localhost.rootprojects.org"
|
||||||
adminHostName = telebit.InvalidAdminDomain
|
adminHostName string
|
||||||
idle int
|
idle int
|
||||||
dwell int
|
dwell int
|
||||||
cancelcheck int
|
cancelcheck int
|
||||||
|
|
124
dump/admin.html
124
dump/admin.html
|
@ -1,124 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Websock VPN Instrumentation</title>
|
|
||||||
</head>
|
|
||||||
<body ng-app="vpnAdmin" ng-controller="vpnInstrumentationController">
|
|
||||||
<div class="panel panel-default panel-primary">
|
|
||||||
<div class="panel-heading">VPN Instrumentation</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="panel panel-default panel-info">
|
|
||||||
<div class="panel-heading">Control Plane</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="row">
|
|
||||||
<!-- Auth -->
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button class="btn btn-default" type="button" ng-click="startWebSocket()">
|
|
||||||
Start WebSocket
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
class="btn btn-default"
|
|
||||||
type="button"
|
|
||||||
ng-class="conn == false && 'btn-danger' || 'btn-success'"
|
|
||||||
>
|
|
||||||
{[{ conn == false && 'False' || 'True' }]}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button class="btn btn-default" type="button">Auth</button>
|
|
||||||
</span>
|
|
||||||
<input type="text" class="form-control" placeholder="Enter auth data here" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="panel panel-default panel-info">
|
|
||||||
<div class="panel-heading">Data</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<p ng-repeat="text in log_elements">{[{text}]}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</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.min.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 type="text/javascript">
|
|
||||||
console.log("startup");
|
|
||||||
|
|
||||||
var vpnAdmin = angular.module("vpnAdmin", []);
|
|
||||||
vpnAdmin.config(function ($interpolateProvider) {
|
|
||||||
console.log("vpnTest Config");
|
|
||||||
$interpolateProvider.startSymbol("{[{");
|
|
||||||
$interpolateProvider.endSymbol("}]}");
|
|
||||||
});
|
|
||||||
vpnAdmin.controller("vpnInstrumentationController", function ($scope) {
|
|
||||||
console.log("vpnInstrumentationController startup");
|
|
||||||
|
|
||||||
$scope.log_elements = [];
|
|
||||||
$scope.auth_key = "";
|
|
||||||
$scope.conn = false;
|
|
||||||
|
|
||||||
$scope.webSocketStatus = function () {
|
|
||||||
if ($scope.conn == false) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.startWebSocket = function () {
|
|
||||||
console.log("Start webSocket {{$}}");
|
|
||||||
if (window["WebSocket"]) {
|
|
||||||
$scope.conn = new WebSocket("wss://{{$}}/ws/admin");
|
|
||||||
$scope.append_log("Websocket opened");
|
|
||||||
$scope.conn.onclose = function (evt) {
|
|
||||||
$scope.append_log("Connection closed.");
|
|
||||||
};
|
|
||||||
$scope.conn.onmessage = function (evt) {
|
|
||||||
$scope.append_log(evt.data);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
appendLog($("<div><b>Your browser does not support WebSockets.</b></div>"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.auth_click = function () {
|
|
||||||
$scope.append_log($scope.auth_key);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.append_log = function (txt) {
|
|
||||||
$scope.log_elements.push(txt);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</html>
|
|
151
dump/client.html
151
dump/client.html
|
@ -1,151 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Websock VPN Test Client</title>
|
|
||||||
</head>
|
|
||||||
<body ng-app="vpnTest" ng-controller="vpnTestController">
|
|
||||||
<div class="panel panel-default panel-primary">
|
|
||||||
<div class="panel-heading">WebSocket Client Test</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="panel panel-default panel-info">
|
|
||||||
<div class="panel-heading">Control Plane</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="row">
|
|
||||||
<!-- Auth -->
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button class="btn btn-default" type="button" ng-click="startWebSocket()">
|
|
||||||
Start WebSocket
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
class="btn btn-default"
|
|
||||||
type="button"
|
|
||||||
ng-class="conn == false && 'btn-danger' || 'btn-success'"
|
|
||||||
>
|
|
||||||
{[{ conn == false && 'False' || 'True' }]}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button class="btn btn-default" type="button">Auth</button>
|
|
||||||
</span>
|
|
||||||
<input type="text" class="form-control" placeholder="Enter auth data here" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button class="btn btn-default" ng-click="send_click()" type="button">
|
|
||||||
Send
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
<input
|
|
||||||
ng-model="send_data"
|
|
||||||
type="text"
|
|
||||||
class="form-control"
|
|
||||||
placeholder="Enter send data here"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="panel panel-default panel-danger">
|
|
||||||
<div class="panel-heading">Messages</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<p ng-repeat="text in log_elements">{[{text}]}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</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.min.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 type="text/javascript">
|
|
||||||
console.log("startup");
|
|
||||||
|
|
||||||
var vpnTest = angular.module("vpnTest", []);
|
|
||||||
vpnTest.config(function ($interpolateProvider) {
|
|
||||||
console.log("vpnTest Config");
|
|
||||||
$interpolateProvider.startSymbol("{[{");
|
|
||||||
$interpolateProvider.endSymbol("}]}");
|
|
||||||
});
|
|
||||||
vpnTest.controller("vpnTestController", function ($scope) {
|
|
||||||
console.log("vpnTestController startup");
|
|
||||||
|
|
||||||
$scope.log_elements = [];
|
|
||||||
$scope.auth_key = "";
|
|
||||||
$scope.conn = false;
|
|
||||||
$scope.send_data = "";
|
|
||||||
|
|
||||||
$scope.webSocketStatus = function () {
|
|
||||||
if ($scope.conn == false) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.startWebSocket = function () {
|
|
||||||
console.log("Start webSocket {{$}}");
|
|
||||||
if (window["WebSocket"]) {
|
|
||||||
$scope.conn = new WebSocket("wss://{{$}}/ws/client");
|
|
||||||
$scope.append_log("Websocket opened");
|
|
||||||
$scope.conn.onclose = function (evt) {
|
|
||||||
$scope.append_log("Connection closed.");
|
|
||||||
};
|
|
||||||
$scope.conn.onmessage = function (evt) {
|
|
||||||
console.log(evt.data);
|
|
||||||
$scope.append_log(evt.data);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
appendLog($("<div><b>Your browser does not support WebSockets.</b></div>"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.auth_click = function () {
|
|
||||||
$scope.append_log($scope.auth_key);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.send_click = function () {
|
|
||||||
console.log("send_click");
|
|
||||||
$scope.conn.send($scope.send_data);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.append_log = function (txt) {
|
|
||||||
$scope.log_elements.push(txt);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</html>
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
telebit "git.coolaj86.com/coolaj86/go-telebitd"
|
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/relay/api"
|
"git.coolaj86.com/coolaj86/go-telebitd/relay/api"
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/relay/mplexy"
|
"git.coolaj86.com/coolaj86/go-telebitd/relay/mplexy"
|
||||||
|
|
||||||
|
@ -48,13 +47,23 @@ func ListenAndServe(mx *mplexy.MPlexy, adminListener net.Listener) error {
|
||||||
|
|
||||||
switch url := r.URL.Path; url {
|
switch url := r.URL.Path; url {
|
||||||
case "/":
|
case "/":
|
||||||
// check to see if we are using the administrative Host
|
var hostname string
|
||||||
if strings.Contains(r.Host, telebit.InvalidAdminDomain) {
|
host := strings.Split(r.Host, ":")
|
||||||
http.Redirect(w, r, "/admin", 301)
|
if len(host) > 0 {
|
||||||
serverStatus.AdminStats.IncResponses()
|
hostname = host[0]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check to see if we are using the administrative Host
|
||||||
|
if hostname == mplexy.InvalidAdminDomain {
|
||||||
|
http.Redirect(w, r, "/admin", 301)
|
||||||
|
serverStatus.AdminStats.IncResponses()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if hostname == mx.AdminDomain() {
|
||||||
|
http.Redirect(w, r, "/admin", 301)
|
||||||
|
serverStatus.AdminStats.IncResponses()
|
||||||
|
return
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
http.Error(w, "Not Found", 404)
|
http.Error(w, "Not Found", 404)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/tunnel"
|
"git.coolaj86.com/coolaj86/go-telebitd/relay/tunnel"
|
||||||
)
|
)
|
||||||
|
|
||||||
//Status --
|
//Status --
|
||||||
|
|
|
@ -13,11 +13,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
telebit "git.coolaj86.com/coolaj86/go-telebitd"
|
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/packer"
|
"git.coolaj86.com/coolaj86/go-telebitd/packer"
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/relay/api"
|
"git.coolaj86.com/coolaj86/go-telebitd/relay/api"
|
||||||
|
"git.coolaj86.com/coolaj86/go-telebitd/relay/tunnel"
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/sni"
|
"git.coolaj86.com/coolaj86/go-telebitd/sni"
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/tunnel"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type contextKey string
|
type contextKey string
|
||||||
|
@ -29,7 +28,6 @@ const (
|
||||||
ctxListenerRegistration contextKey = "listenerRegistration"
|
ctxListenerRegistration contextKey = "listenerRegistration"
|
||||||
ctxConnectionTrack contextKey = "connectionTrack"
|
ctxConnectionTrack contextKey = "connectionTrack"
|
||||||
ctxWssHostName contextKey = "wsshostname"
|
ctxWssHostName contextKey = "wsshostname"
|
||||||
ctxAdminHostName contextKey = "adminHostName"
|
|
||||||
ctxCancelCheck contextKey = "cancelcheck"
|
ctxCancelCheck contextKey = "cancelcheck"
|
||||||
ctxLoadbalanceDefaultMethod contextKey = "lbdefaultmethod"
|
ctxLoadbalanceDefaultMethod contextKey = "lbdefaultmethod"
|
||||||
//ctxConnectionTable contextKey = "connectionTable"
|
//ctxConnectionTable contextKey = "connectionTable"
|
||||||
|
@ -55,19 +53,19 @@ const (
|
||||||
// - if TLS, consume connection with TLS certbundle, pass to request identifier
|
// - if TLS, consume connection with TLS certbundle, pass to request identifier
|
||||||
// - else, just pass to the request identififer
|
// - else, just pass to the request identififer
|
||||||
func (mx *MPlexy) multiListenAndServe(ctx context.Context, listenerRegistration *ListenerRegistration) {
|
func (mx *MPlexy) multiListenAndServe(ctx context.Context, listenerRegistration *ListenerRegistration) {
|
||||||
Loginfo.Println(":" + string(listenerRegistration.port))
|
loginfo.Println(":" + string(listenerRegistration.port))
|
||||||
cancelCheck := ctx.Value(ctxCancelCheck).(int)
|
cancelCheck := ctx.Value(ctxCancelCheck).(int)
|
||||||
|
|
||||||
listenAddr, err := net.ResolveTCPAddr("tcp", ":"+strconv.Itoa(listenerRegistration.port))
|
listenAddr, err := net.ResolveTCPAddr("tcp", ":"+strconv.Itoa(listenerRegistration.port))
|
||||||
|
|
||||||
if nil != err {
|
if nil != err {
|
||||||
Loginfo.Println(err)
|
loginfo.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ln, err := net.ListenTCP("tcp", listenAddr)
|
ln, err := net.ListenTCP("tcp", listenAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Loginfo.Println("unable to bind", err)
|
loginfo.Println("unable to bind", err)
|
||||||
listenerRegistration.status = listenerFault
|
listenerRegistration.status = listenerFault
|
||||||
listenerRegistration.err = err
|
listenerRegistration.err = err
|
||||||
listenerRegistration.commCh <- listenerRegistration
|
listenerRegistration.commCh <- listenerRegistration
|
||||||
|
@ -80,7 +78,7 @@ func (mx *MPlexy) multiListenAndServe(ctx context.Context, listenerRegistration
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
Loginfo.Println("Cancel signal hit")
|
loginfo.Println("Cancel signal hit")
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
ln.SetDeadline(time.Now().Add(time.Duration(cancelCheck) * time.Second))
|
ln.SetDeadline(time.Now().Add(time.Duration(cancelCheck) * time.Second))
|
||||||
|
@ -91,7 +89,7 @@ func (mx *MPlexy) multiListenAndServe(ctx context.Context, listenerRegistration
|
||||||
if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
|
if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
Loginfo.Println(err)
|
loginfo.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,10 +112,10 @@ func (mx *MPlexy) accept(ctx context.Context, wConn *tunnel.WedgeConn) {
|
||||||
|
|
||||||
encryptMode := encryptNone
|
encryptMode := encryptNone
|
||||||
|
|
||||||
Loginfo.Println("new conn", wConn, wConn.LocalAddr().String(), wConn.RemoteAddr().String())
|
loginfo.Println("new conn", wConn, wConn.LocalAddr().String(), wConn.RemoteAddr().String())
|
||||||
peek, err := wConn.Peek(peekCnt)
|
peek, err := wConn.Peek(peekCnt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Loginfo.Println("error while peeking")
|
loginfo.Println("error while peeking")
|
||||||
wConn.Close()
|
wConn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -131,7 +129,7 @@ func (mx *MPlexy) accept(ctx context.Context, wConn *tunnel.WedgeConn) {
|
||||||
|
|
||||||
} else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x01}) {
|
} else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x01}) {
|
||||||
encryptMode = encryptTLS10
|
encryptMode = encryptTLS10
|
||||||
Loginfo.Println("TLS10")
|
loginfo.Println("TLS10")
|
||||||
|
|
||||||
} else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x02}) {
|
} else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x02}) {
|
||||||
encryptMode = encryptTLS11
|
encryptMode = encryptTLS11
|
||||||
|
@ -145,19 +143,19 @@ func (mx *MPlexy) accept(ctx context.Context, wConn *tunnel.WedgeConn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if encryptMode == encryptSSLV2 {
|
if encryptMode == encryptSSLV2 {
|
||||||
Loginfo.Println("<= SSLv2 is not accepted")
|
loginfo.Println("<= SSLv2 is not accepted")
|
||||||
wConn.Close()
|
wConn.Close()
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if encryptMode == encryptNone {
|
if encryptMode == encryptNone {
|
||||||
Loginfo.Println("Handle Unencrypted")
|
loginfo.Println("Handle Unencrypted")
|
||||||
mx.acceptPlainStream(ctx, wConn, false)
|
mx.acceptPlainStream(ctx, wConn, false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Loginfo.Println("Handle Encryption")
|
loginfo.Println("Handle Encryption")
|
||||||
mx.acceptEncryptedStream(ctx, wConn)
|
mx.acceptEncryptedStream(ctx, wConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,21 +164,21 @@ func (mx *MPlexy) acceptEncryptedStream(ctx context.Context, wConn *tunnel.Wedge
|
||||||
|
|
||||||
peek, err := wConn.PeekAll()
|
peek, err := wConn.PeekAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Loginfo.Println("Bad socket: read error from", wConn.RemoteAddr(), err)
|
loginfo.Println("Bad socket: read error from", wConn.RemoteAddr(), err)
|
||||||
Loginfo.Println(hex.Dump(peek[0:]))
|
loginfo.Println(hex.Dump(peek[0:]))
|
||||||
wConn.Close()
|
wConn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sniHostName, err := sni.GetHostname(peek)
|
sniHostName, err := sni.GetHostname(peek)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Loginfo.Println("Bad socket: no SNI from", wConn.RemoteAddr(), err)
|
loginfo.Println("Bad socket: no SNI from", wConn.RemoteAddr(), err)
|
||||||
Loginfo.Println(err)
|
loginfo.Println(err)
|
||||||
wConn.Close()
|
wConn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Loginfo.Println("SNI:", sniHostName)
|
loginfo.Println("SNI:", sniHostName)
|
||||||
|
|
||||||
if sniHostName == mx.wssHostName || sniHostName == mx.adminHostName {
|
if sniHostName == mx.wssHostName || sniHostName == mx.adminHostName {
|
||||||
// The TLS should be terminated and handled internally
|
// The TLS should be terminated and handled internally
|
||||||
|
@ -194,7 +192,7 @@ func (mx *MPlexy) acceptEncryptedStream(ctx context.Context, wConn *tunnel.Wedge
|
||||||
//oneConn := &oneConnListener{wConn}
|
//oneConn := &oneConnListener{wConn}
|
||||||
|
|
||||||
// TLS remains intact and shall be routed downstream, wholesale
|
// TLS remains intact and shall be routed downstream, wholesale
|
||||||
Loginfo.Println("processing non terminating traffic", mx.wssHostName, sniHostName)
|
loginfo.Println("processing non terminating traffic", mx.wssHostName, sniHostName)
|
||||||
go mx.routeToTarget(ctx, wConn, sniHostName, "https")
|
go mx.routeToTarget(ctx, wConn, sniHostName, "https")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,13 +205,13 @@ func (mx *MPlexy) acceptEncryptedStream(ctx context.Context, wConn *tunnel.Wedge
|
||||||
// - else handle as raw http
|
// - else handle as raw http
|
||||||
// - handle other?
|
// - handle other?
|
||||||
func (mx *MPlexy) acceptPlainStream(ctx context.Context, wConn *tunnel.WedgeConn, encrypted bool) {
|
func (mx *MPlexy) acceptPlainStream(ctx context.Context, wConn *tunnel.WedgeConn, encrypted bool) {
|
||||||
Loginfo.Println("Plain Conn", wConn.LocalAddr().String(), wConn.RemoteAddr().String())
|
loginfo.Println("Plain Conn", wConn.LocalAddr().String(), wConn.RemoteAddr().String())
|
||||||
|
|
||||||
// TODO couldn't reading everything be dangerous? Or is it limited to a single packet?
|
// TODO couldn't reading everything be dangerous? Or is it limited to a single packet?
|
||||||
peek, err := wConn.PeekAll()
|
peek, err := wConn.PeekAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Loginfo.Println("error while peeking", err)
|
loginfo.Println("error while peeking", err)
|
||||||
Loginfo.Println(hex.Dump(peek[0:]))
|
loginfo.Println(hex.Dump(peek[0:]))
|
||||||
wConn.Close()
|
wConn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -233,17 +231,23 @@ func (mx *MPlexy) acceptPlainStream(ctx context.Context, wConn *tunnel.WedgeConn
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Loginfo.Println("identified HTTP")
|
loginfo.Println("identified HTTP")
|
||||||
|
|
||||||
r, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(peek)))
|
r, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(peek)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Loginfo.Println("identified as HTTP, failed request parsing", err)
|
loginfo.Println("identified as HTTP, failed request parsing", err)
|
||||||
wConn.Close()
|
wConn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(r.Host, telebit.InvalidAdminDomain) {
|
var hostname string
|
||||||
Loginfo.Println("admin")
|
host := strings.Split(r.Host, ":")
|
||||||
|
if len(host) > 0 {
|
||||||
|
hostname = host[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if hostname == InvalidAdminDomain {
|
||||||
|
loginfo.Println("admin.invalid")
|
||||||
// TODO mx.Admin.CheckRemoteIP(conn) here
|
// TODO mx.Admin.CheckRemoteIP(conn) here
|
||||||
// handle admin path
|
// handle admin path
|
||||||
mx.AcceptAdminClient(wConn)
|
mx.AcceptAdminClient(wConn)
|
||||||
|
@ -251,19 +255,24 @@ func (mx *MPlexy) acceptPlainStream(ctx context.Context, wConn *tunnel.WedgeConn
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO add newtypes
|
if hostname == mx.adminHostName {
|
||||||
// TODO check if this is a websocket
|
loginfo.Println("admin")
|
||||||
_, err = mx.AuthorizeTarget(r)
|
// TODO mx.Admin.CheckRemoteIP(conn) here
|
||||||
if err == nil {
|
// handle admin path
|
||||||
Loginfo.Println("Valid WSS dected...sending to handler")
|
mx.AcceptAdminClient(wConn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if "Upgrade" == r.Header.Get("Connection") || "WebSocket" == r.Header.Get("Upgrade") {
|
||||||
|
loginfo.Println("WebSocket Upgrade is in order...")
|
||||||
mx.AcceptTargetServer(wConn)
|
mx.AcceptTargetServer(wConn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO sniHostName is the key to the route, which could also be a port or hostname
|
// TODO sniHostName is the key to the route, which could also be a port or hostname
|
||||||
//traffic not terminating on the rvpn do not decrypt
|
//traffic not terminating on the rvpn do not decrypt
|
||||||
Loginfo.Println("processing non terminating traffic", mx.wssHostName, r.Host)
|
loginfo.Println("processing non terminating traffic", mx.wssHostName, r.Host)
|
||||||
Loginfo.Println(hex.Dump(peek))
|
loginfo.Println(hex.Dump(peek))
|
||||||
if !encrypted {
|
if !encrypted {
|
||||||
// TODO request and cache http resources as a feature??
|
// TODO request and cache http resources as a feature??
|
||||||
go mx.routeToTarget(ctx, wConn, r.Host, "http")
|
go mx.routeToTarget(ctx, wConn, r.Host, "http")
|
||||||
|
@ -271,7 +280,7 @@ func (mx *MPlexy) acceptPlainStream(ctx context.Context, wConn *tunnel.WedgeConn
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is not presently possible
|
// This is not presently possible
|
||||||
Loginfo.Println("impossible condition: local decryption of routable client", mx.wssHostName, r.Host)
|
loginfo.Println("impossible condition: local decryption of routable client", mx.wssHostName, r.Host)
|
||||||
go mx.routeToTarget(ctx, wConn, r.Host, "https")
|
go mx.routeToTarget(ctx, wConn, r.Host, "https")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +302,7 @@ func (mx *MPlexy) routeToTarget(ctx context.Context, extConn *tunnel.WedgeConn,
|
||||||
conn, ok := serverStatus.ConnectionTable.ConnByDomain(hostname)
|
conn, ok := serverStatus.ConnectionTable.ConnByDomain(hostname)
|
||||||
if !ok {
|
if !ok {
|
||||||
//matching connection can not be found based on ConnByDomain
|
//matching connection can not be found based on ConnByDomain
|
||||||
Loginfo.Println("unable to match ", hostname, " to an existing connection")
|
loginfo.Println("unable to match ", hostname, " to an existing connection")
|
||||||
//http.Error(, "Domain not supported", http.StatusBadRequest)
|
//http.Error(, "Domain not supported", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -302,15 +311,15 @@ func (mx *MPlexy) routeToTarget(ctx context.Context, extConn *tunnel.WedgeConn,
|
||||||
serverStatus.ExtConnectionRegister(track)
|
serverStatus.ExtConnectionRegister(track)
|
||||||
|
|
||||||
remoteStr := extConn.RemoteAddr().String()
|
remoteStr := extConn.RemoteAddr().String()
|
||||||
Loginfo.Println("Domain Accepted", hostname, remoteStr)
|
loginfo.Println("Domain Accepted", hostname, remoteStr)
|
||||||
|
|
||||||
var header *packer.Header
|
var header *packer.Header
|
||||||
if rAddr, rPort, err := net.SplitHostPort(remoteStr); err != nil {
|
if rAddr, rPort, err := net.SplitHostPort(remoteStr); err != nil {
|
||||||
Loginfo.Println("unable to decode hostport", remoteStr, err)
|
loginfo.Println("unable to decode hostport", remoteStr, err)
|
||||||
} else if port, err := strconv.Atoi(rPort); err != nil {
|
} else if port, err := strconv.Atoi(rPort); err != nil {
|
||||||
Loginfo.Printf("unable to parse port string %q: %v\n", rPort, err)
|
loginfo.Printf("unable to parse port string %q: %v\n", rPort, err)
|
||||||
} else if header, err = packer.NewHeader(rAddr, port, service); err != nil {
|
} else if header, err = packer.NewHeader(rAddr, port, service); err != nil {
|
||||||
Loginfo.Println("unable to create packer header", err)
|
loginfo.Println("unable to create packer header", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if header == nil {
|
if header == nil {
|
||||||
|
@ -320,17 +329,17 @@ func (mx *MPlexy) routeToTarget(ctx context.Context, extConn *tunnel.WedgeConn,
|
||||||
for {
|
for {
|
||||||
buffer, err := extConn.PeekAll()
|
buffer, err := extConn.PeekAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Loginfo.Println("unable to peekAll", err)
|
loginfo.Println("unable to peekAll", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Loginfo.Println("Before Packer", hex.Dump(buffer))
|
loginfo.Println("Before Packer", hex.Dump(buffer))
|
||||||
|
|
||||||
p := packer.NewPacker(header)
|
p := packer.NewPacker(header)
|
||||||
p.Data.AppendBytes(buffer)
|
p.Data.AppendBytes(buffer)
|
||||||
buf := p.PackV1()
|
buf := p.PackV1()
|
||||||
|
|
||||||
//Loginfo.Println(hex.Dump(buf.Bytes()))
|
//loginfo.Println(hex.Dump(buf.Bytes()))
|
||||||
|
|
||||||
//Bundle up the send request and dispatch
|
//Bundle up the send request and dispatch
|
||||||
sendTrack := api.NewSendTrack(buf.Bytes(), hostname)
|
sendTrack := api.NewSendTrack(buf.Bytes(), hostname)
|
||||||
|
@ -338,7 +347,7 @@ func (mx *MPlexy) routeToTarget(ctx context.Context, extConn *tunnel.WedgeConn,
|
||||||
|
|
||||||
cnt := len(buffer)
|
cnt := len(buffer)
|
||||||
if _, err = extConn.Discard(cnt); err != nil {
|
if _, err = extConn.Discard(cnt); err != nil {
|
||||||
Loginfo.Println("unable to discard", cnt, err)
|
loginfo.Println("unable to discard", cnt, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,10 @@ import (
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/relay/api"
|
"git.coolaj86.com/coolaj86/go-telebitd/relay/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Loginfo = log.Loginfo
|
// InvalidAdminDomain is for bootstrapping the setup of a relay device
|
||||||
|
var InvalidAdminDomain = "admin.telebit.invalid"
|
||||||
|
|
||||||
|
var loginfo = log.Loginfo
|
||||||
var connectionID int64 = 0
|
var connectionID int64 = 0
|
||||||
|
|
||||||
//ListenerRegistrationStatus - post registration status
|
//ListenerRegistrationStatus - post registration status
|
||||||
|
@ -112,13 +115,18 @@ func New(
|
||||||
return mx
|
return mx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AdminDomain returns the Admin Domain as set on startup
|
||||||
|
func (mx *MPlexy) AdminDomain() string {
|
||||||
|
return mx.adminHostName
|
||||||
|
}
|
||||||
|
|
||||||
//Run -- Execute
|
//Run -- Execute
|
||||||
// - execute the GenericLister
|
// - execute the GenericLister
|
||||||
// - pass initial port, we'll announce that
|
// - pass initial port, we'll announce that
|
||||||
func (mx *MPlexy) Run() error {
|
func (mx *MPlexy) Run() error {
|
||||||
Loginfo.Println("ConnectionTable starting")
|
loginfo.Println("ConnectionTable starting")
|
||||||
|
|
||||||
Loginfo.Println(mx.connectionTracking)
|
loginfo.Println(mx.connectionTracking)
|
||||||
|
|
||||||
ctx := mx.ctx
|
ctx := mx.ctx
|
||||||
|
|
||||||
|
@ -129,7 +137,6 @@ func (mx *MPlexy) Run() error {
|
||||||
ctx = context.WithValue(ctx, ctxConfig, mx.tlsConfig)
|
ctx = context.WithValue(ctx, ctxConfig, mx.tlsConfig)
|
||||||
ctx = context.WithValue(ctx, ctxListenerRegistration, mx.register)
|
ctx = context.WithValue(ctx, ctxListenerRegistration, mx.register)
|
||||||
ctx = context.WithValue(ctx, ctxWssHostName, mx.wssHostName)
|
ctx = context.WithValue(ctx, ctxWssHostName, mx.wssHostName)
|
||||||
ctx = context.WithValue(ctx, ctxAdminHostName, mx.adminHostName)
|
|
||||||
ctx = context.WithValue(ctx, ctxCancelCheck, mx.cancelCheck)
|
ctx = context.WithValue(ctx, ctxCancelCheck, mx.cancelCheck)
|
||||||
ctx = context.WithValue(ctx, ctxLoadbalanceDefaultMethod, mx.lbDefaultMethod)
|
ctx = context.WithValue(ctx, ctxLoadbalanceDefaultMethod, mx.lbDefaultMethod)
|
||||||
ctx = context.WithValue(ctx, ctxServerStatus, mx.Status)
|
ctx = context.WithValue(ctx, ctxServerStatus, mx.Status)
|
||||||
|
@ -138,29 +145,30 @@ func (mx *MPlexy) Run() error {
|
||||||
select {
|
select {
|
||||||
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
Loginfo.Println("Cancel signal hit")
|
loginfo.Println("Cancel signal hit")
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case registration := <-mx.register:
|
case registration := <-mx.register:
|
||||||
Loginfo.Println("register fired", registration.port)
|
loginfo.Println("register fired", registration.port)
|
||||||
|
|
||||||
// check to see if port is already running
|
// check to see if port is already running
|
||||||
for listener := range mx.listeners {
|
for listener := range mx.listeners {
|
||||||
if mx.listeners[listener] == registration.port {
|
if mx.listeners[listener] == registration.port {
|
||||||
Loginfo.Println("listener already running", registration.port)
|
loginfo.Println("listener already running", registration.port)
|
||||||
registration.status = listenerExists
|
registration.status = listenerExists
|
||||||
registration.commCh <- registration
|
registration.commCh <- registration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loginfo.Println("listener starting up ", registration.port)
|
|
||||||
Loginfo.Println(ctx.Value(ctxConnectionTrack).(*api.Tracking))
|
loginfo.Println("listener starting up ", registration.port)
|
||||||
|
loginfo.Println("[track]", ctx.Value(ctxConnectionTrack).(*api.Tracking))
|
||||||
go mx.multiListenAndServe(ctx, registration)
|
go mx.multiListenAndServe(ctx, registration)
|
||||||
|
|
||||||
status := <-registration.commCh
|
status := <-registration.commCh
|
||||||
if status.status == listenerAdded {
|
if status.status == listenerAdded {
|
||||||
mx.listeners[status.listener] = status.port
|
mx.listeners[status.listener] = status.port
|
||||||
} else if status.status == listenerFault {
|
} else if status.status == listenerFault {
|
||||||
Loginfo.Println("Unable to create a new listerer", registration.port)
|
loginfo.Println("Unable to create a new listerer", registration.port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,6 +176,7 @@ func (mx *MPlexy) Run() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start calls go Run()
|
||||||
func (mx *MPlexy) Start() {
|
func (mx *MPlexy) Start() {
|
||||||
go mx.Run()
|
go mx.Run()
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/relay/admin"
|
"git.coolaj86.com/coolaj86/go-telebitd/relay/admin"
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/relay/api"
|
"git.coolaj86.com/coolaj86/go-telebitd/relay/api"
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/relay/mplexy"
|
"git.coolaj86.com/coolaj86/go-telebitd/relay/mplexy"
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/tunnel"
|
"git.coolaj86.com/coolaj86/go-telebitd/relay/tunnel"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
@ -78,7 +78,7 @@ func (r *Relay) ListenAndServe(port int) error {
|
||||||
return r.mx.Run()
|
return r.mx.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func listenAndServeTargets(mx *mplexy.MPlexy, handler net.Listener) error {
|
func listenAndServeTargets(mx *mplexy.MPlexy, listener net.Listener) error {
|
||||||
serverStatus := mx.Status
|
serverStatus := mx.Status
|
||||||
|
|
||||||
router := mux.NewRouter().StrictSlash(true)
|
router := mux.NewRouter().StrictSlash(true)
|
||||||
|
@ -121,5 +121,5 @@ func listenAndServeTargets(mx *mplexy.MPlexy, handler net.Listener) error {
|
||||||
Addr: ":80",
|
Addr: ":80",
|
||||||
Handler: router,
|
Handler: router,
|
||||||
}
|
}
|
||||||
return s.Serve(handler)
|
return s.Serve(listener)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package sni
|
package sni
|
||||||
|
|
||||||
|
// TODO this was probably copied from somewhere that deserves attribution
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
|
@ -1,8 +0,0 @@
|
||||||
package telebit
|
|
||||||
|
|
||||||
// InvalidAdminDomain is a domain that can only be accessed by Domain Fronting
|
|
||||||
// (i.e. trixy clients sending fake headers), not browsers
|
|
||||||
var InvalidAdminDomain = "chilly-bobcat-15.telebit.io"
|
|
||||||
|
|
||||||
//var InvalidAdminDomain = "invalid.rootprojects.org"
|
|
||||||
//var InvalidAdminDomain = "rvpn.rootprojects.invalid"
|
|
Loading…
Reference in New Issue