merged tui for tcpTunnel (#307)

This commit is contained in:
Michael Quigley 2023-05-01 12:19:06 -04:00
parent 74fd8d9956
commit 28916e8d2a
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
13 changed files with 115 additions and 162 deletions

View File

@ -6,6 +6,7 @@ import (
httptransport "github.com/go-openapi/runtime/client"
"github.com/openziti/zrok/endpoints"
"github.com/openziti/zrok/endpoints/proxy"
"github.com/openziti/zrok/endpoints/tcpTunnel"
"github.com/openziti/zrok/rest_client_zrok"
"github.com/openziti/zrok/rest_client_zrok/share"
"github.com/openziti/zrok/rest_model_zrok"
@ -48,14 +49,6 @@ func newAccessPrivateCommand() *accessPrivateCommand {
func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
shrToken := args[0]
endpointUrl, err := url.Parse("http://" + cmd.bindAddress)
if err != nil {
if !panicInstead {
tui.Error("invalid endpoint address", err)
}
panic(err)
}
zrd, err := zrokdir.Load()
if err != nil {
tui.Error("unable to load zrokdir", err)
@ -88,10 +81,62 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
}
logrus.Infof("allocated frontend '%v'", accessResp.Payload.FrontendToken)
cfg := proxy.DefaultFrontendConfig("backend")
cfg.ShrToken = shrToken
cfg.Address = cmd.bindAddress
cfg.RequestsChan = make(chan *endpoints.Request, 1024)
protocol := "http://"
switch accessResp.Payload.BackendMode {
case "tcpTunnel":
protocol = "tcp://"
}
endpointUrl, err := url.Parse(protocol + cmd.bindAddress)
if err != nil {
if !panicInstead {
tui.Error("invalid endpoint address", err)
}
panic(err)
}
requests := make(chan *endpoints.Request, 1024)
if accessResp.Payload.BackendMode == "tcpTunnel" {
fe, err := tcpTunnel.NewFrontend(&tcpTunnel.FrontendConfig{
BindAddress: cmd.bindAddress,
IdentityName: "backend",
ShrToken: args[0],
RequestsChan: requests,
})
if err != nil {
if !panicInstead {
tui.Error("unable to create private frontend", err)
}
panic(err)
}
go func() {
if err := fe.Run(); err != nil {
if !panicInstead {
tui.Error("error starting frontend", err)
}
panic(err)
}
}()
} else {
cfg := proxy.DefaultFrontendConfig("backend")
cfg.ShrToken = shrToken
cfg.Address = cmd.bindAddress
cfg.RequestsChan = requests
fe, err := proxy.NewFrontend(cfg)
if err != nil {
if !panicInstead {
tui.Error("unable to create private frontend", err)
}
panic(err)
}
go func() {
if err := fe.Run(); err != nil {
if !panicInstead {
tui.Error("unable to run frontend", err)
}
}
}()
}
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
@ -101,27 +146,11 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
os.Exit(0)
}()
frontend, err := proxy.NewFrontend(cfg)
if err != nil {
if !panicInstead {
tui.Error("unable to create private frontend", err)
}
panic(err)
}
go func() {
if err := frontend.Run(); err != nil {
if !panicInstead {
tui.Error("unable to run frontend", err)
}
}
}()
if cmd.headless {
logrus.Infof("access the zrok share at the followind endpoint: %v", endpointUrl.String())
for {
select {
case req := <-cfg.RequestsChan:
case req := <-requests:
logrus.Infof("%v -> %v %v", req.RemoteAddr, req.Method, req.Path)
}
}
@ -135,7 +164,7 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
go func() {
for {
select {
case req := <-cfg.RequestsChan:
case req := <-requests:
if req != nil {
prg.Send(req)
}
@ -147,9 +176,8 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
tui.Error("An error occurred", err)
}
close(cfg.RequestsChan)
close(requests)
cmd.destroy(accessResp.Payload.FrontendToken, zrd.Env.ZId, shrToken, zrok, auth)
}
}

View File

@ -1,107 +0,0 @@
package main
import (
"github.com/go-openapi/runtime"
httptransport "github.com/go-openapi/runtime/client"
"github.com/openziti/zrok/endpoints/tcpTunnel"
"github.com/openziti/zrok/rest_client_zrok"
"github.com/openziti/zrok/rest_client_zrok/share"
"github.com/openziti/zrok/rest_model_zrok"
"github.com/openziti/zrok/tui"
"github.com/openziti/zrok/zrokdir"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"os"
"os/signal"
"syscall"
"time"
)
func init() {
accessPrivateCmd.cmd.AddCommand(newAccessPrivateTunnelCommand().cmd)
}
type accessPrivateTunnelCommand struct {
bindAddress string
cmd *cobra.Command
}
func newAccessPrivateTunnelCommand() *accessPrivateTunnelCommand {
cmd := &cobra.Command{
Use: "tunnel <shareToken>",
Short: "Create a private tunnel frontend to access a share",
Args: cobra.ExactArgs(1),
}
command := &accessPrivateTunnelCommand{cmd: cmd}
cmd.Flags().StringVarP(&command.bindAddress, "bind", "b", "127.0.0.1:9191", "The address to bind the private tunnel")
cmd.Run = command.run
return command
}
func (cmd *accessPrivateTunnelCommand) run(_ *cobra.Command, args []string) {
zrd, err := zrokdir.Load()
if err != nil {
tui.Error("unable to load zrokdir", err)
}
if zrd.Env == nil {
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
}
zrok, err := zrd.Client()
if err != nil {
tui.Error("unable to create zrok client", err)
}
auth := httptransport.APIKeyAuth("X-TOKEN", "header", zrd.Env.Token)
req := share.NewAccessParams()
req.Body = &rest_model_zrok.AccessRequest{
ShrToken: args[0],
EnvZID: zrd.Env.ZId,
}
accessResp, err := zrok.Share.Access(req, auth)
if err != nil {
if !panicInstead {
tui.Error("unable to access", err)
}
panic(err)
}
logrus.Infof("allocated frontend '%v'", accessResp.Payload.FrontendToken)
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
cmd.destroy(accessResp.Payload.FrontendToken, zrd.Env.ZId, args[0], zrok, auth)
os.Exit(0)
}()
fe, err := tcpTunnel.NewFrontend(&tcpTunnel.FrontendConfig{
BindAddress: cmd.bindAddress,
IdentityName: "backend",
ShrToken: args[0],
})
if err != nil {
panic(err)
}
if err := fe.Run(); err != nil {
panic(err)
}
for {
time.Sleep(30 * 24 * time.Hour)
}
}
func (cmd *accessPrivateTunnelCommand) destroy(frontendName, envZId, shrToken string, zrok *rest_client_zrok.Zrok, auth runtime.ClientAuthInfoWriter) {
logrus.Debugf("shutting down '%v'", shrToken)
req := share.NewUnaccessParams()
req.Body = &rest_model_zrok.UnaccessRequest{
FrontendToken: frontendName,
ShrToken: shrToken,
EnvZID: envZId,
}
if _, err := zrok.Share.Unaccess(req, auth); err == nil {
logrus.Debugf("shutdown complete")
} else {
logrus.Errorf("error shutting down: %v", err)
}
}

View File

@ -43,7 +43,7 @@ func newSharePrivateCommand() *sharePrivateCommand {
}
command := &sharePrivateCommand{cmd: cmd}
cmd.Flags().StringArrayVar(&command.basicAuth, "basic-auth", []string{}, "Basic authentication users (<username:password>,...")
cmd.Flags().StringVar(&command.backendMode, "backend-mode", "proxy", "The backend mode {proxy, web, tunnel}")
cmd.Flags().StringVar(&command.backendMode, "backend-mode", "proxy", "The backend mode {proxy, web, tcpTunnel}")
cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless")
cmd.Flags().BoolVar(&command.insecure, "insecure", false, "Enable insecure TLS certificate validation for <target>")
cmd.Run = command.run
@ -67,11 +67,11 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
case "web":
target = args[0]
case "tunnel":
case "tcpTunnel":
target = args[0]
default:
tui.Error(fmt.Sprintf("invalid backend mode '%v'; expected {proxy, web, tunnel}", cmd.backendMode), nil)
tui.Error(fmt.Sprintf("invalid backend mode '%v'; expected {proxy, web, tcpTunnel}", cmd.backendMode), nil)
}
zrd, err := zrokdir.Load()
@ -172,7 +172,7 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
panic(err)
}
case "tunnel":
case "tcpTunnel":
cfg := &tcpTunnel.BackendConfig{
IdentityPath: zif,
EndpointAddress: target,
@ -182,13 +182,13 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
be, err := tcpTunnel.NewBackend(cfg)
if err != nil {
if !panicInstead {
tui.Error("unable to create tunnel backend", err)
tui.Error("unable to create tcpTunnel backend", err)
}
panic(err)
}
go func() {
if err := be.Run(); err != nil {
logrus.Errorf("error running tunnel backend: %v", err)
logrus.Errorf("error running tcpTunnel backend: %v", err)
}
}()

View File

@ -86,5 +86,8 @@ func (h *accessHandler) Handle(params share.AccessParams, principal *rest_model_
return share.NewAccessInternalServerError()
}
return share.NewAccessCreated().WithPayload(&rest_model_zrok.AccessResponse{FrontendToken: feToken})
return share.NewAccessCreated().WithPayload(&rest_model_zrok.AccessResponse{
FrontendToken: feToken,
BackendMode: shr.BackendMode,
})
}

View File

@ -1,3 +1,4 @@
-- +migrate Up
alter type backend_mode rename value 'dav' to 'tunnel';
alter type backend_mode rename value 'dav' to 'tcpTunnel';
alter type backend_mode add value 'udpTunnel';

View File

@ -18,7 +18,7 @@ create table shares (
constraint chk_z_id check (z_id <> ''),
constraint chk_token check (token <> ''),
constraint chk_share_mode check (share_mode == 'public' or share_mode == 'private'),
constraint chk_backend_mode check (backend_mode == 'proxy' or backend_mode == 'web' or backend_mode == 'tunnel')
constraint chk_backend_mode check (backend_mode == 'proxy' or backend_mode == 'web' or backend_mode == 'tcpTunnel' or backend_mode == 'udpTunnel')
);
insert into shares select * from shares_old;
drop table shares_old;

View File

@ -62,11 +62,13 @@ func (b *Backend) handle(conn net.Conn) {
if rConn, err := net.DialTCP("tcp", nil, rAddr); err == nil {
go endpoints.TXer(conn, rConn)
go endpoints.TXer(rConn, conn)
b.cfg.RequestsChan <- &endpoints.Request{
Stamp: time.Now(),
RemoteAddr: conn.RemoteAddr().String(),
Method: "OPEN",
Path: rAddr.String(),
if b.cfg.RequestsChan != nil {
b.cfg.RequestsChan <- &endpoints.Request{
Stamp: time.Now(),
RemoteAddr: conn.RemoteAddr().String(),
Method: "ACCEPT",
Path: rAddr.String(),
}
}
} else {
logrus.Errorf("error dialing '%v': %v", b.cfg.EndpointAddress, err)

View File

@ -9,12 +9,14 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"net"
"time"
)
type FrontendConfig struct {
BindAddress string
IdentityName string
ShrToken string
RequestsChan chan *endpoints.Request
}
type Frontend struct {
@ -53,7 +55,7 @@ func (f *Frontend) Run() error {
for {
if conn, err := l.Accept(); err == nil {
go f.accept(conn)
logrus.Infof("accepted tcp connection from '%v'", conn.RemoteAddr())
logrus.Debugf("accepted tcp connection from '%v'", conn.RemoteAddr())
} else {
return err
}
@ -64,7 +66,14 @@ func (f *Frontend) accept(conn net.Conn) {
if zConn, err := f.zCtx.Dial(f.cfg.ShrToken); err == nil {
go endpoints.TXer(conn, zConn)
go endpoints.TXer(zConn, conn)
logrus.Infof("accepted '%v' <=> '%v'", conn.RemoteAddr(), zConn.RemoteAddr())
if f.cfg.RequestsChan != nil {
f.cfg.RequestsChan <- &endpoints.Request{
Stamp: time.Now(),
RemoteAddr: conn.RemoteAddr().String(),
Method: "ACCEPT",
Path: f.cfg.ShrToken,
}
}
} else {
logrus.Errorf("error dialing '%v': %v", f.cfg.ShrToken, err)
_ = conn.Close()

View File

@ -17,6 +17,9 @@ import (
// swagger:model accessResponse
type AccessResponse struct {
// backend mode
BackendMode string `json:"backendMode,omitempty"`
// frontend token
FrontendToken string `json:"frontendToken,omitempty"`
}

View File

@ -28,7 +28,7 @@ type ShareRequest struct {
AuthUsers []*AuthUser `json:"authUsers"`
// backend mode
// Enum: [proxy web tunnel]
// Enum: [proxy web tcpTunnel udpTunnel]
BackendMode string `json:"backendMode,omitempty"`
// backend proxy endpoint
@ -100,7 +100,7 @@ var shareRequestTypeBackendModePropEnum []interface{}
func init() {
var res []string
if err := json.Unmarshal([]byte(`["proxy","web","tunnel"]`), &res); err != nil {
if err := json.Unmarshal([]byte(`["proxy","web","tcpTunnel","udpTunnel"]`), &res); err != nil {
panic(err)
}
for _, v := range res {
@ -116,8 +116,11 @@ const (
// ShareRequestBackendModeWeb captures enum value "web"
ShareRequestBackendModeWeb string = "web"
// ShareRequestBackendModeTunnel captures enum value "tunnel"
ShareRequestBackendModeTunnel string = "tunnel"
// ShareRequestBackendModeTCPTunnel captures enum value "tcpTunnel"
ShareRequestBackendModeTCPTunnel string = "tcpTunnel"
// ShareRequestBackendModeUDPTunnel captures enum value "udpTunnel"
ShareRequestBackendModeUDPTunnel string = "udpTunnel"
)
// prop value enum

View File

@ -852,6 +852,9 @@ func init() {
"accessResponse": {
"type": "object",
"properties": {
"backendMode": {
"type": "string"
},
"frontendToken": {
"type": "string"
}
@ -1167,7 +1170,8 @@ func init() {
"enum": [
"proxy",
"web",
"tunnel"
"tcpTunnel",
"udpTunnel"
]
},
"backendProxyEndpoint": {
@ -2130,6 +2134,9 @@ func init() {
"accessResponse": {
"type": "object",
"properties": {
"backendMode": {
"type": "string"
},
"frontendToken": {
"type": "string"
}
@ -2445,7 +2452,8 @@ func init() {
"enum": [
"proxy",
"web",
"tunnel"
"tcpTunnel",
"udpTunnel"
]
},
"backendProxyEndpoint": {

View File

@ -537,6 +537,8 @@ definitions:
properties:
frontendToken:
type: string
backendMode:
type: string
authUser:
type: object
@ -771,7 +773,7 @@ definitions:
type: string
backendMode:
type: string
enum: ["proxy", "web", "tunnel"]
enum: ["proxy", "web", "tcpTunnel", "udpTunnel"]
backendProxyEndpoint:
type: string
authScheme:

View File

@ -14,6 +14,7 @@
* @memberof module:types
*
* @property {string} frontendToken
* @property {string} backendMode
*/
/**