Skip to content

Commit 0a734e0

Browse files
authored
Merge pull request #275 from tobychui/v3.1.0
v3.1.0 Update
2 parents 02ff288 + f4fa926 commit 0a734e0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+6668
-4215
lines changed

docker/Dockerfile

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ VOLUME [ "/opt/zoraxy/config/" ]
3030
WORKDIR /opt/zoraxy/config/
3131

3232
ENV AUTORENEW="86400"
33+
ENV EARLYRENEW="30"
3334
ENV FASTGEOIP="false"
3435
ENV MDNS="true"
3536
ENV MDNSNAME="''"
@@ -42,6 +43,6 @@ ENV WEBROOT="./www"
4243
ENV ZTAUTH="''"
4344
ENV ZTPORT="9993"
4445

45-
ENTRYPOINT "zoraxy" "-docker=true" "-autorenew=${AUTORENEW}" "-fastgeoip=${FASTGEOIP}" "-mdns=${MDNS}" "-mdnsname=${MDNSNAME}" "-noauth=${NOAUTH}" "-port=:${PORT}" "-sshlb=${SSHLB}" "-version=${VERSION}" "-webfm=${WEBFM}" "-webroot=${WEBROOT}" "-ztauth=${ZTAUTH}" "-ztport=${ZTPORT}"
46+
ENTRYPOINT "zoraxy" "-docker=true" "-autorenew=${AUTORENEW}" "-earlyrenew=${EARLYRENEW}" "-fastgeoip=${FASTGEOIP}" "-mdns=${MDNS}" "-mdnsname=${MDNSNAME}" "-noauth=${NOAUTH}" "-port=:${PORT}" "-sshlb=${SSHLB}" "-version=${VERSION}" "-webfm=${WEBFM}" "-webroot=${WEBROOT}" "-ztauth=${ZTAUTH}" "-ztport=${ZTPORT}"
4647

4748
HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=3 CMD nc -vz 127.0.0.1 $PORT || exit 1

src/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ clean:
1919

2020
$(PLATFORMS):
2121
@echo "Building $(os)/$(arch)"
22-
GOROOT_FINAL=Git/ GOOS=$(os) GOARCH=$(arch) $(if $(filter linux/arm,$(os)/$(arch)),GOARM=6,) go build -o './dist/zoraxy_$(os)_$(arch)' -ldflags "-s -w" -trimpath
22+
GOROOT_FINAL=Git/ GOOS=$(os) GOARCH=$(arch) $(if $(filter linux/arm,$(os)/$(arch)),GOARM=6,) CGO_ENABLED="0" go build -o './dist/zoraxy_$(os)_$(arch)' -ldflags "-s -w" -trimpath
2323
# GOROOT_FINAL=Git/ GOOS=$(os) GOARCH=$(arch) GOARM=6 go build -o './dist/zoraxy_$(os)_$(arch)' -ldflags "-s -w" -trimpath
2424

2525

src/api.go

+18-16
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ import (
2222

2323
var requireAuth = true
2424

25-
func initAPIs() {
26-
25+
func initAPIs(targetMux *http.ServeMux) {
2726
authRouter := auth.NewManagedHTTPRouter(auth.RouterOption{
2827
AuthAgent: authAgent,
2928
RequireAuth: requireAuth,
29+
TargetMux: targetMux,
3030
DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
3131
http.Error(w, "401 - Unauthorized", http.StatusUnauthorized)
3232
},
@@ -37,12 +37,12 @@ func initAPIs() {
3737
if development {
3838
fs = http.FileServer(http.Dir("web/"))
3939
}
40-
//Add a layer of middleware for advance control
40+
//Add a layer of middleware for advance control
4141
advHandler := FSHandler(fs)
42-
http.Handle("/", advHandler)
42+
targetMux.Handle("/", advHandler)
4343

4444
//Authentication APIs
45-
registerAuthAPIs(requireAuth)
45+
registerAuthAPIs(requireAuth, targetMux)
4646

4747
//Reverse proxy
4848
authRouter.HandleFunc("/api/proxy/enable", ReverseProxyHandleOnOff)
@@ -77,6 +77,8 @@ func initAPIs() {
7777
authRouter.HandleFunc("/api/proxy/header/add", HandleCustomHeaderAdd)
7878
authRouter.HandleFunc("/api/proxy/header/remove", HandleCustomHeaderRemove)
7979
authRouter.HandleFunc("/api/proxy/header/handleHSTS", HandleHSTSState)
80+
authRouter.HandleFunc("/api/proxy/header/handleHopByHop", HandleHopByHop)
81+
authRouter.HandleFunc("/api/proxy/header/handleHostOverwrite", HandleHostOverwrite)
8082
authRouter.HandleFunc("/api/proxy/header/handlePermissionPolicy", HandlePermissionPolicy)
8183
//Reverse proxy auth related APIs
8284
authRouter.HandleFunc("/api/proxy/auth/exceptions/list", ListProxyBasicAuthExceptionPaths)
@@ -185,8 +187,8 @@ func initAPIs() {
185187
authRouter.HandleFunc("/api/tools/fwdproxy/port", forwardProxy.HandlePort)
186188

187189
//Account Reset
188-
http.HandleFunc("/api/account/reset", HandleAdminAccountResetEmail)
189-
http.HandleFunc("/api/account/new", HandleNewPasswordSetup)
190+
targetMux.HandleFunc("/api/account/reset", HandleAdminAccountResetEmail)
191+
targetMux.HandleFunc("/api/account/new", HandleNewPasswordSetup)
190192

191193
//ACME & Auto Renewer
192194
authRouter.HandleFunc("/api/acme/listExpiredDomains", acmeHandler.HandleGetExpiredDomains)
@@ -226,7 +228,7 @@ func initAPIs() {
226228
authRouter.HandleFunc("/api/docker/containers", DockerUXOptimizer.HandleDockerContainersList)
227229

228230
//Others
229-
http.HandleFunc("/api/info/x", HandleZoraxyInfo)
231+
targetMux.HandleFunc("/api/info/x", HandleZoraxyInfo)
230232
authRouter.HandleFunc("/api/info/geoip", HandleGeoIpLookup)
231233
authRouter.HandleFunc("/api/conf/export", ExportConfigAsZip)
232234
authRouter.HandleFunc("/api/conf/import", ImportConfigFromZip)
@@ -241,18 +243,18 @@ func initAPIs() {
241243
}
242244

243245
// Function to renders Auth related APIs
244-
func registerAuthAPIs(requireAuth bool) {
246+
func registerAuthAPIs(requireAuth bool, targetMux *http.ServeMux) {
245247
//Auth APIs
246-
http.HandleFunc("/api/auth/login", authAgent.HandleLogin)
247-
http.HandleFunc("/api/auth/logout", authAgent.HandleLogout)
248-
http.HandleFunc("/api/auth/checkLogin", func(w http.ResponseWriter, r *http.Request) {
248+
targetMux.HandleFunc("/api/auth/login", authAgent.HandleLogin)
249+
targetMux.HandleFunc("/api/auth/logout", authAgent.HandleLogout)
250+
targetMux.HandleFunc("/api/auth/checkLogin", func(w http.ResponseWriter, r *http.Request) {
249251
if requireAuth {
250252
authAgent.CheckLogin(w, r)
251253
} else {
252254
utils.SendJSONResponse(w, "true")
253255
}
254256
})
255-
http.HandleFunc("/api/auth/username", func(w http.ResponseWriter, r *http.Request) {
257+
targetMux.HandleFunc("/api/auth/username", func(w http.ResponseWriter, r *http.Request) {
256258
username, err := authAgent.GetUserName(w, r)
257259
if err != nil {
258260
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
@@ -262,12 +264,12 @@ func registerAuthAPIs(requireAuth bool) {
262264
js, _ := json.Marshal(username)
263265
utils.SendJSONResponse(w, string(js))
264266
})
265-
http.HandleFunc("/api/auth/userCount", func(w http.ResponseWriter, r *http.Request) {
267+
targetMux.HandleFunc("/api/auth/userCount", func(w http.ResponseWriter, r *http.Request) {
266268
uc := authAgent.GetUserCounts()
267269
js, _ := json.Marshal(uc)
268270
utils.SendJSONResponse(w, string(js))
269271
})
270-
http.HandleFunc("/api/auth/register", func(w http.ResponseWriter, r *http.Request) {
272+
targetMux.HandleFunc("/api/auth/register", func(w http.ResponseWriter, r *http.Request) {
271273
if authAgent.GetUserCounts() == 0 {
272274
//Allow register root admin
273275
authAgent.HandleRegisterWithoutEmail(w, r, func(username, reserved string) {
@@ -278,7 +280,7 @@ func registerAuthAPIs(requireAuth bool) {
278280
utils.SendErrorResponse(w, "Root management account already exists")
279281
}
280282
})
281-
http.HandleFunc("/api/auth/changePassword", func(w http.ResponseWriter, r *http.Request) {
283+
targetMux.HandleFunc("/api/auth/changePassword", func(w http.ResponseWriter, r *http.Request) {
282284
username, err := authAgent.GetUserName(w, r)
283285
if err != nil {
284286
http.Error(w, "401 - Unauthorized", http.StatusUnauthorized)

src/cert.go

+12-11
Original file line numberDiff line numberDiff line change
@@ -182,27 +182,28 @@ func handleToggleTLSProxy(w http.ResponseWriter, r *http.Request) {
182182
sysdb.Read("settings", "usetls", &currentTlsSetting)
183183
}
184184

185-
newState, err := utils.PostPara(r, "set")
186-
if err != nil {
187-
//No setting. Get the current status
185+
if r.Method == http.MethodGet {
186+
//Get the current status
188187
js, _ := json.Marshal(currentTlsSetting)
189188
utils.SendJSONResponse(w, string(js))
190-
} else {
191-
if newState == "true" {
189+
} else if r.Method == http.MethodPost {
190+
newState, err := utils.PostBool(r, "set")
191+
if err != nil {
192+
utils.SendErrorResponse(w, "new state not set or invalid")
193+
return
194+
}
195+
if newState {
192196
sysdb.Write("settings", "usetls", true)
193197
SystemWideLogger.Println("Enabling TLS mode on reverse proxy")
194198
dynamicProxyRouter.UpdateTLSSetting(true)
195-
} else if newState == "false" {
199+
} else {
196200
sysdb.Write("settings", "usetls", false)
197201
SystemWideLogger.Println("Disabling TLS mode on reverse proxy")
198202
dynamicProxyRouter.UpdateTLSSetting(false)
199-
} else {
200-
utils.SendErrorResponse(w, "invalid state given. Only support true or false")
201-
return
202203
}
203-
204204
utils.SendOK(w)
205-
205+
} else {
206+
http.Error(w, "405 - Method not allowed", http.StatusMethodNotAllowed)
206207
}
207208
}
208209

src/go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ require (
9595
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
9696
github.com/googleapis/gax-go/v2 v2.12.2 // indirect
9797
github.com/gophercloud/gophercloud v1.0.0 // indirect
98+
github.com/gorilla/csrf v1.7.2 // indirect
9899
github.com/gorilla/css v1.0.1 // indirect
99100
github.com/gorilla/securecookie v1.1.2 // indirect
100101
github.com/hashicorp/errwrap v1.0.0 // indirect

src/go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7
317317
github.com/gophercloud/gophercloud v1.0.0 h1:9nTGx0jizmHxDobe4mck89FyQHVyA3CaXLIUSGJjP9k=
318318
github.com/gophercloud/gophercloud v1.0.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c=
319319
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
320+
github.com/gorilla/csrf v1.7.2 h1:oTUjx0vyf2T+wkrx09Trsev1TE+/EbDAeHtSTbtC2eI=
321+
github.com/gorilla/csrf v1.7.2/go.mod h1:F1Fj3KG23WYHE6gozCmBAezKookxbIvUJT+121wTuLk=
320322
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
321323
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
322324
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=

src/main.go

+21-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"time"
1313

1414
"github.com/google/uuid"
15+
"github.com/gorilla/csrf"
1516
"imuslab.com/zoraxy/mod/access"
1617
"imuslab.com/zoraxy/mod/acme"
1718
"imuslab.com/zoraxy/mod/auth"
@@ -50,14 +51,15 @@ var ztAuthToken = flag.String("ztauth", "", "ZeroTier authtoken for the local no
5051
var ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port")
5152
var runningInDocker = flag.Bool("docker", false, "Run Zoraxy in docker compatibility mode")
5253
var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)")
54+
var acmeCertAutoRenewDays = flag.Int("earlyrenew", 30, "Number of days to early renew a soon expiring certificate (days)")
5355
var enableHighSpeedGeoIPLookup = flag.Bool("fastgeoip", false, "Enable high speed geoip lookup, require 1GB extra memory (Not recommend for low end devices)")
5456
var staticWebServerRoot = flag.String("webroot", "./www", "Static web server root folder. Only allow chnage in start paramters")
5557
var allowWebFileManager = flag.Bool("webfm", true, "Enable web file manager for static web server root folder")
5658
var enableAutoUpdate = flag.Bool("cfgupgrade", true, "Enable auto config upgrade if breaking change is detected")
5759

5860
var (
5961
name = "Zoraxy"
60-
version = "3.0.9"
62+
version = "3.1.0"
6163
nodeUUID = "generic" //System uuid, in uuidv4 format
6264
development = false //Set this to false to use embedded web fs
6365
bootTime = time.Now().Unix()
@@ -71,10 +73,12 @@ var (
7173
/*
7274
Handler Modules
7375
*/
74-
sysdb *database.Database //System database
75-
authAgent *auth.AuthAgent //Authentication agent
76-
tlsCertManager *tlscert.Manager //TLS / SSL management
77-
redirectTable *redirection.RuleTable //Handle special redirection rule sets
76+
sysdb *database.Database //System database
77+
authAgent *auth.AuthAgent //Authentication agent
78+
tlsCertManager *tlscert.Manager //TLS / SSL management
79+
redirectTable *redirection.RuleTable //Handle special redirection rule sets
80+
webminPanelMux *http.ServeMux //Server mux for handling webmin panel APIs
81+
csrfMiddleware func(http.Handler) http.Handler //CSRF protection middleware
7882

7983
pathRuleHandler *pathrule.Handler //Handle specific path blocking or custom headers
8084
geodbStore *geodb.Store //GeoIP database, for resolving IP into country code
@@ -175,12 +179,22 @@ func main() {
175179
}
176180
nodeUUID = string(uuidBytes)
177181

182+
//Create a new webmin mux and csrf middleware layer
183+
webminPanelMux = http.NewServeMux()
184+
csrfMiddleware = csrf.Protect(
185+
[]byte(nodeUUID),
186+
csrf.CookieName("zoraxy-csrf"),
187+
csrf.Secure(false),
188+
csrf.Path("/"),
189+
csrf.SameSite(csrf.SameSiteLaxMode),
190+
)
191+
178192
//Startup all modules
179193
startupSequence()
180194

181195
//Initiate management interface APIs
182196
requireAuth = !(*noauth)
183-
initAPIs()
197+
initAPIs(webminPanelMux)
184198

185199
//Start the reverse proxy server in go routine
186200
go func() {
@@ -193,7 +207,7 @@ func main() {
193207
finalSequence()
194208

195209
SystemWideLogger.Println("Zoraxy started. Visit control panel at http://localhost" + *webUIPort)
196-
err = http.ListenAndServe(*webUIPort, nil)
210+
err = http.ListenAndServe(*webUIPort, csrfMiddleware(webminPanelMux))
197211

198212
if err != nil {
199213
log.Fatal(err)

0 commit comments

Comments
 (0)