Skip to content

Commit

Permalink
Added docker conditional compilation
Browse files Browse the repository at this point in the history
- Moved docker UX optimization into module
- Added conditional compilation for Windows build
- Added Permission Policy header editor
- Fixed docker container list ui error message bug
  • Loading branch information
tobychui committed Jun 16, 2024
1 parent dfb8151 commit 0397416
Show file tree
Hide file tree
Showing 13 changed files with 334 additions and 120 deletions.
4 changes: 2 additions & 2 deletions src/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,8 @@ func initAPIs() {
}

//Docker UX Optimizations
authRouter.HandleFunc("/api/docker/available", HandleDockerAvailable)
authRouter.HandleFunc("/api/docker/containers", HandleDockerContainersList)
authRouter.HandleFunc("/api/docker/available", DockerUXOptimizer.HandleDockerAvailable)
authRouter.HandleFunc("/api/docker/containers", DockerUXOptimizer.HandleDockerContainersList)

//Others
http.HandleFunc("/api/info/x", HandleZoraxyInfo)
Expand Down
84 changes: 0 additions & 84 deletions src/docker.go

This file was deleted.

9 changes: 6 additions & 3 deletions src/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"imuslab.com/zoraxy/mod/acme"
"imuslab.com/zoraxy/mod/auth"
"imuslab.com/zoraxy/mod/database"
"imuslab.com/zoraxy/mod/dockerux"
"imuslab.com/zoraxy/mod/dynamicproxy/redirection"
"imuslab.com/zoraxy/mod/email"
"imuslab.com/zoraxy/mod/forwardproxy"
Expand Down Expand Up @@ -44,6 +45,7 @@ var allowMdnsScanning = flag.Bool("mdns", true, "Enable mDNS scanner and transpo
var mdnsName = flag.String("mdnsname", "", "mDNS name, leave empty to use default (zoraxy_{node-uuid}.local)")
var ztAuthToken = flag.String("ztauth", "", "ZeroTier authtoken for the local node")
var ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port")
var runningInDocker = flag.Bool("docker", false, "Run Zoraxy in docker compatibility mode")
var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)")
var enableHighSpeedGeoIPLookup = flag.Bool("fastgeoip", false, "Enable high speed geoip lookup, require 1GB extra memory (Not recommend for low end devices)")
var staticWebServerRoot = flag.String("webroot", "./www", "Static web server root folder. Only allow chnage in start paramters")
Expand Down Expand Up @@ -86,9 +88,10 @@ var (
forwardProxy *forwardproxy.Handler //HTTP Forward proxy, basically VPN for web browser

//Helper modules
EmailSender *email.Sender //Email sender that handle email sending
AnalyticLoader *analytic.DataLoader //Data loader for Zoraxy Analytic
SystemWideLogger *logger.Logger //Logger for Zoraxy
EmailSender *email.Sender //Email sender that handle email sending
AnalyticLoader *analytic.DataLoader //Data loader for Zoraxy Analytic
DockerUXOptimizer *dockerux.UXOptimizer //Docker user experience optimizer, community contribution only
SystemWideLogger *logger.Logger //Logger for Zoraxy
)

// Kill signal handler. Do something before the system the core terminate.
Expand Down
60 changes: 60 additions & 0 deletions src/mod/dockerux/docker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//go:build !windows
// +build !windows

package dockerux

/* Windows docker optimizer*/

import (
"context"
"encoding/json"
"net/http"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"imuslab.com/zoraxy/mod/utils"
)

// Windows build not support docker
func (d *UXOptimizer) HandleDockerAvailable(w http.ResponseWriter, r *http.Request) {
js, _ := json.Marshal(d.RunninInDocker)
utils.SendJSONResponse(w, string(js))
}

func (d *UXOptimizer) HandleDockerContainersList(w http.ResponseWriter, r *http.Request) {
apiClient, err := client.NewClientWithOpts(client.WithVersion("1.43"))
if err != nil {
d.SystemWideLogger.PrintAndLog("Docker", "Unable to create new docker client", err)
utils.SendErrorResponse(w, "Docker client initiation failed")
return
}
defer apiClient.Close()

containers, err := apiClient.ContainerList(context.Background(), container.ListOptions{All: true})
if err != nil {
d.SystemWideLogger.PrintAndLog("Docker", "List docker container failed", err)
utils.SendErrorResponse(w, "List docker container failed")
return
}

networks, err := apiClient.NetworkList(context.Background(), types.NetworkListOptions{})
if err != nil {
d.SystemWideLogger.PrintAndLog("Docker", "List docker network failed", err)
utils.SendErrorResponse(w, "List docker network failed")
return
}

result := map[string]interface{}{
"network": networks,
"containers": containers,
}

js, err := json.Marshal(result)
if err != nil {
utils.SendErrorResponse(w, err.Error())
return
}

utils.SendJSONResponse(w, string(js))
}
32 changes: 32 additions & 0 deletions src/mod/dockerux/docker_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//go:build windows
// +build windows

package dockerux

/*
Windows docker UX optimizer dummy
This is a dummy module for Windows as docker features
is useless on Windows and create a larger binary size
docker on Windows build are trimmed to reduce binary size
and make it compatibile with Windows 7
*/

import (
"encoding/json"
"net/http"

"imuslab.com/zoraxy/mod/utils"
)

// Windows build not support docker
func (d *UXOptimizer) HandleDockerAvailable(w http.ResponseWriter, r *http.Request) {
js, _ := json.Marshal(d.RunninInDocker)
utils.SendJSONResponse(w, string(js))
}

func (d *UXOptimizer) HandleDockerContainersList(w http.ResponseWriter, r *http.Request) {
utils.SendErrorResponse(w, "Platform not supported")
}
24 changes: 24 additions & 0 deletions src/mod/dockerux/dockerux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dockerux

import "imuslab.com/zoraxy/mod/info/logger"

/*
Docker Optimizer
This script add support for optimizing docker user experience
Note that this module are community contribute only. For bug
report, please directly tag the Pull Request author.
*/

type UXOptimizer struct {
RunninInDocker bool
SystemWideLogger *logger.Logger
}

//Create a new docker optimizer
func NewDockerOptimizer(IsRunningInDocker bool, logger *logger.Logger) *UXOptimizer {
return &UXOptimizer{
RunninInDocker: IsRunningInDocker,
SystemWideLogger: logger,
}
}
25 changes: 19 additions & 6 deletions src/mod/dynamicproxy/customHeader.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package dynamicproxy

import "strconv"
import (
"strconv"

"imuslab.com/zoraxy/mod/dynamicproxy/permissionpolicy"
)

/*
CustomHeader.go
Expand All @@ -9,9 +13,9 @@ import "strconv"
into the dpcore routing logic
*/

//SplitInboundOutboundHeaders split user defined headers into upstream and downstream headers
//return upstream header and downstream header key-value pairs
//if the header is expected to be deleted, the value will be set to empty string
// SplitInboundOutboundHeaders split user defined headers into upstream and downstream headers
// return upstream header and downstream header key-value pairs
// if the header is expected to be deleted, the value will be set to empty string
func (ept *ProxyEndpoint) SplitInboundOutboundHeaders() ([][]string, [][]string) {
if len(ept.UserDefinedHeaders) == 0 {
//Early return if there are no defined headers
Expand Down Expand Up @@ -52,8 +56,17 @@ func (ept *ProxyEndpoint) SplitInboundOutboundHeaders() ([][]string, [][]string)
}

//Check if the endpoint require Permission Policy
if ept.EnablePermissionPolicyHeader && ept.PermissionPolicy != nil {
downstreamHeaders[downstreamHeaderCounter] = ept.PermissionPolicy.ToKeyValueHeader()
if ept.EnablePermissionPolicyHeader {
var usingPermissionPolicy *permissionpolicy.PermissionsPolicy
if ept.PermissionPolicy != nil {
//Custom permission policy
usingPermissionPolicy = ept.PermissionPolicy
} else {
//Permission policy is enabled but not customized. Use default
usingPermissionPolicy = permissionpolicy.GetDefaultPermissionPolicy()
}

downstreamHeaders[downstreamHeaderCounter] = usingPermissionPolicy.ToKeyValueHeader()
downstreamHeaderCounter++
}

Expand Down
33 changes: 33 additions & 0 deletions src/reverseproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -1314,7 +1314,40 @@ func HandlePermissionPolicy(w http.ResponseWriter, r *http.Request) {
utils.SendJSONResponse(w, string(js))
return
} else if r.Method == http.MethodPost {
//Update the enable state of permission policy
enableState, err := utils.PostBool(r, "enable")
if err != nil {
utils.SendErrorResponse(w, "invalid enable state given")
return
}

targetProxyEndpoint.EnablePermissionPolicyHeader = enableState
SaveReverseProxyConfig(targetProxyEndpoint)
targetProxyEndpoint.UpdateToRuntime()
utils.SendOK(w)
return
} else if r.Method == http.MethodPut {
//Store the new permission policy
newPermissionPolicyJSONString, err := utils.PostPara(r, "pp")
if err != nil {
utils.SendErrorResponse(w, "missing pp (permission policy) paramter")
return
}

//Parse the permission policy from JSON string
newPermissionPolicy := permissionpolicy.GetDefaultPermissionPolicy()
err = json.Unmarshal([]byte(newPermissionPolicyJSONString), &newPermissionPolicy)
if err != nil {
utils.SendErrorResponse(w, "permission policy parse error: "+err.Error())
return
}

//Save it to file
targetProxyEndpoint.PermissionPolicy = newPermissionPolicy
SaveReverseProxyConfig(targetProxyEndpoint)
targetProxyEndpoint.UpdateToRuntime()
utils.SendOK(w)
return
}

http.Error(w, "405 - Method not allowed", http.StatusMethodNotAllowed)
Expand Down
8 changes: 8 additions & 0 deletions src/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"log"
"net/http"
"os"
"runtime"
"strconv"
"strings"
"time"
Expand All @@ -12,6 +13,7 @@ import (
"imuslab.com/zoraxy/mod/acme"
"imuslab.com/zoraxy/mod/auth"
"imuslab.com/zoraxy/mod/database"
"imuslab.com/zoraxy/mod/dockerux"
"imuslab.com/zoraxy/mod/dynamicproxy/redirection"
"imuslab.com/zoraxy/mod/forwardproxy"
"imuslab.com/zoraxy/mod/ganserv"
Expand Down Expand Up @@ -269,6 +271,12 @@ func startupSequence() {
log.Fatal(err)
}

/* Docker UX Optimizer */
if runtime.GOOS == "windows" && *runningInDocker {
SystemWideLogger.PrintAndLog("WARNING", "Invalid start flag combination: docker=true && runtime.GOOS == windows. Running in docker UX development mode.", nil)
}
DockerUXOptimizer = dockerux.NewDockerOptimizer(*runningInDocker, SystemWideLogger)

}

// This sequence start after everything is initialized
Expand Down
23 changes: 12 additions & 11 deletions src/web/components/rules.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,11 @@ <h2>New Proxy Rule</h2>
</div>
<div class="field">
<label>Target IP Address or Domain Name with port</label>

<input type="text" id="proxyDomain" onchange="autoCheckTls(this.value);">

<small>E.g. 192.168.0.101:8000 or example.com</small>
</div>
<div class="field" class="dockerOptimizations" style="display:none;">
<button class="ui basic button" onclick="openDockerContainersList();"><i class="blue docker icon"></i> Pick from Docker Containers</button>
<div class="field dockerOptimizations" style="display:none;">
<button style="margin-top: -2em;" class="ui basic small button" onclick="openDockerContainersList();"><i class="blue docker icon"></i> Pick from Docker Containers</button>
</div>
<div class="field">
<div class="ui checkbox">
Expand Down Expand Up @@ -433,13 +431,16 @@ <h2>New Proxy Rule</h2>
}

/* Docker Optimizations */
$("/api/docker/available", function(dockerAvailable){
if (dockerAvailable){
$(".dockerOptimizations").show();
}else{
$(".dockerOptimizations").hide();
}
})
function initDockerUXOptimizations(){
$.get("/api/docker/available", function(dockerAvailable){
if (dockerAvailable){
$(".dockerOptimizations").show();
}else{
$(".dockerOptimizations").hide();
}
});
}
initDockerUXOptimizations();

function openDockerContainersList(){
showSideWrapper('snippet/dockerContainersList.html');
Expand Down
Loading

0 comments on commit 0397416

Please sign in to comment.