mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-07-04 13:21:44 +02:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
75d773887c | |||
a944c3ff36 | |||
465f332dfc | |||
dfda3fe94b | |||
8b4c601d50 | |||
3a2eaf8766 | |||
a45092a449 |
16
CHANGELOG.md
16
CHANGELOG.md
@ -1,3 +1,19 @@
|
|||||||
|
# v3.1.1. 09 Sep 2024
|
||||||
|
|
||||||
|
+ Updated country name in access list [#287](https://github.com/tobychui/zoraxy/issues/287)
|
||||||
|
+ Added tour for basic operations
|
||||||
|
+ Updated acme log to system wide logger implementation
|
||||||
|
+ Fixed path traversal in file manager [#274](https://github.com/tobychui/zoraxy/issues/274)
|
||||||
|
+ Removed Proxmox debug code
|
||||||
|
+ Fixed trie tree implementations
|
||||||
|
|
||||||
|
**Thanks to all contributors**
|
||||||
|
|
||||||
|
+ Fix existing containers list in docker popup [7brend7](https://github.com/tobychui/zoraxy/issues?q=is%3Apr+author%3A7brend7)
|
||||||
|
+ Fix network I/O chart not rendering [JokerQyou](https://github.com/tobychui/zoraxy/issues?q=is%3Apr+author%3AJokerQyou)
|
||||||
|
+ Fix typo remvoeClass to removeClass [Aahmadsyamim](https://github.com/tobychui/zoraxy/issues?q=is%3Apr+author%3Aahmadsyamim)
|
||||||
|
+ Updated weighted random upstream implementation [bouroo](https://github.com/tobychui/zoraxy/issues?q=is%3Apr+author%3Abouroo)
|
||||||
|
|
||||||
# v3.1.0 31 Jul 2024
|
# v3.1.0 31 Jul 2024
|
||||||
|
|
||||||
+ Updated log viewer with filter and auto refresh [#243](https://github.com/tobychui/zoraxy/issues/243)
|
+ Updated log viewer with filter and auto refresh [#243](https://github.com/tobychui/zoraxy/issues/243)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM docker.io/golang:alpine AS build
|
FROM docker.io/golang:alpine AS build-zoraxy
|
||||||
|
|
||||||
RUN mkdir -p /opt/zoraxy/source/ &&\
|
RUN mkdir -p /opt/zoraxy/source/ &&\
|
||||||
mkdir -p /usr/local/bin/
|
mkdir -p /usr/local/bin/
|
||||||
@ -12,17 +12,31 @@ RUN go mod tidy &&\
|
|||||||
go build -o /usr/local/bin/zoraxy &&\
|
go build -o /usr/local/bin/zoraxy &&\
|
||||||
chmod 755 /usr/local/bin/zoraxy
|
chmod 755 /usr/local/bin/zoraxy
|
||||||
|
|
||||||
FROM docker.io/alpine:latest
|
FROM docker.io/ubuntu:latest AS build-zerotier
|
||||||
|
|
||||||
WORKDIR /opt/zoraxy/source/
|
RUN mkdir -p /opt/zerotier/source/ &&\
|
||||||
|
mkdir -p /usr/local/bin/
|
||||||
|
|
||||||
RUN apk add --no-cache bash netcat-openbsd sudo &&\
|
WORKDIR /opt/zerotier/source/
|
||||||
wget https://dl-cdn.alpinelinux.org/alpine/v3.17/community/x86_64/zerotier-one-1.10.2-r0.apk &&\
|
|
||||||
apk add --no-cache zerotier-one-1.10.2-r0.apk &&\
|
RUN apt-get update -y &&\
|
||||||
rm -r /opt/zoraxy/source/
|
apt-get install -y curl jq build-essential pkg-config clang cargo libssl-dev
|
||||||
|
|
||||||
|
RUN curl -Lo ZeroTierOne.tar.gz https://codeload.github.com/zerotier/ZeroTierOne/tar.gz/refs/tags/1.10.6 &&\
|
||||||
|
tar -xzvf ZeroTierOne.tar.gz &&\
|
||||||
|
cd ZeroTierOne-* &&\
|
||||||
|
make &&\
|
||||||
|
mv ./zerotier-one /usr/local/bin/zerotier-one &&\
|
||||||
|
chmod 755 /usr/local/bin/zerotier-one
|
||||||
|
|
||||||
|
FROM docker.io/ubuntu:latest
|
||||||
|
|
||||||
|
RUN apt-get update -y &&\
|
||||||
|
apt-get install -y bash sudo netcat-openbsd libssl-dev ca-certificates
|
||||||
|
|
||||||
COPY --from=build /usr/local/bin/zoraxy /usr/local/bin/zoraxy
|
|
||||||
COPY --chmod=700 ./entrypoint.sh /opt/zoraxy/
|
COPY --chmod=700 ./entrypoint.sh /opt/zoraxy/
|
||||||
|
COPY --from=build-zoraxy /usr/local/bin/zoraxy /usr/local/bin/zoraxy
|
||||||
|
COPY --from=build-zerotier /usr/local/bin/zerotier-one /usr/local/bin/zerotier-one
|
||||||
|
|
||||||
WORKDIR /opt/zoraxy/config/
|
WORKDIR /opt/zoraxy/config/
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
update-ca-certificates
|
||||||
|
echo "CA certificates updated"
|
||||||
|
|
||||||
if [ "$ZEROTIER" = "true" ]; then
|
if [ "$ZEROTIER" = "true" ]; then
|
||||||
echo "Starting ZeroTier daemon..."
|
|
||||||
zerotier-one -d
|
zerotier-one -d
|
||||||
|
echo "ZeroTier daemon started"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Starting Zoraxy..."
|
echo "Starting Zoraxy..."
|
||||||
|
@ -43,9 +43,10 @@ func (fm *FileManager) HandleList(w http.ResponseWriter, r *http.Request) {
|
|||||||
targetDir := filepath.Join(fm.Directory, directory)
|
targetDir := filepath.Join(fm.Directory, directory)
|
||||||
|
|
||||||
// Clean path to prevent path escape #274
|
// Clean path to prevent path escape #274
|
||||||
targetDir = filepath.ToSlash(filepath.Clean(targetDir))
|
isValidRequest := validatePathEscape(targetDir, fm.Directory)
|
||||||
for strings.Contains(targetDir, "../") {
|
if !isValidRequest {
|
||||||
targetDir = strings.ReplaceAll(targetDir, "../", "")
|
http.Error(w, "403 - Forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the target directory
|
// Open the target directory
|
||||||
@ -124,6 +125,14 @@ func (fm *FileManager) HandleUpload(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Specify the directory where you want to save the uploaded file
|
// Specify the directory where you want to save the uploaded file
|
||||||
uploadDir := filepath.Join(fm.Directory, dir)
|
uploadDir := filepath.Join(fm.Directory, dir)
|
||||||
|
|
||||||
|
// Clean path to prevent path escape #274
|
||||||
|
isValidRequest := validatePathEscape(uploadDir, fm.Directory)
|
||||||
|
if !isValidRequest {
|
||||||
|
http.Error(w, "403 - Forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if !utils.FileExists(uploadDir) {
|
if !utils.FileExists(uploadDir) {
|
||||||
utils.SendErrorResponse(w, "upload target directory not exists")
|
utils.SendErrorResponse(w, "upload target directory not exists")
|
||||||
return
|
return
|
||||||
@ -163,14 +172,20 @@ func (fm *FileManager) HandleDownload(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filePath := filepath.Join(fm.Directory, filename)
|
||||||
|
// Clean path to prevent path escape #274
|
||||||
|
isValidRequest := validatePathEscape(filePath, fm.Directory)
|
||||||
|
if !isValidRequest {
|
||||||
|
http.Error(w, "403 - Forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
previewMode, _ := utils.GetPara(r, "preview")
|
previewMode, _ := utils.GetPara(r, "preview")
|
||||||
if previewMode == "true" {
|
if previewMode == "true" {
|
||||||
// Serve the file using http.ServeFile
|
// Serve the file using http.ServeFile
|
||||||
filePath := filepath.Join(fm.Directory, filename)
|
|
||||||
http.ServeFile(w, r, filePath)
|
http.ServeFile(w, r, filePath)
|
||||||
} else {
|
} else {
|
||||||
// Trigger a download with content disposition headers
|
// Trigger a download with content disposition headers
|
||||||
filePath := filepath.Join(fm.Directory, filename)
|
|
||||||
w.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(filename))
|
w.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(filename))
|
||||||
http.ServeFile(w, r, filePath)
|
http.ServeFile(w, r, filePath)
|
||||||
}
|
}
|
||||||
@ -191,6 +206,11 @@ func (fm *FileManager) HandleNewFolder(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Specify the directory where you want to create the new folder
|
// Specify the directory where you want to create the new folder
|
||||||
newFolderPath := filepath.Join(fm.Directory, dirName)
|
newFolderPath := filepath.Join(fm.Directory, dirName)
|
||||||
|
isValidRequest := validatePathEscape(newFolderPath, fm.Directory)
|
||||||
|
if !isValidRequest {
|
||||||
|
http.Error(w, "403 - Forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the folder already exists
|
// Check if the folder already exists
|
||||||
if _, err := os.Stat(newFolderPath); os.IsNotExist(err) {
|
if _, err := os.Stat(newFolderPath); os.IsNotExist(err) {
|
||||||
@ -232,6 +252,18 @@ func (fm *FileManager) HandleFileCopy(w http.ResponseWriter, r *http.Request) {
|
|||||||
absSrcPath := filepath.Join(fm.Directory, srcPath)
|
absSrcPath := filepath.Join(fm.Directory, srcPath)
|
||||||
absDestPath := filepath.Join(fm.Directory, destPath)
|
absDestPath := filepath.Join(fm.Directory, destPath)
|
||||||
|
|
||||||
|
//Make sure the copy source and dest are within web directory folder
|
||||||
|
isValidRequest := validatePathEscape(absSrcPath, fm.Directory)
|
||||||
|
if !isValidRequest {
|
||||||
|
http.Error(w, "403 - Forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isValidRequest = validatePathEscape(absDestPath, fm.Directory)
|
||||||
|
if !isValidRequest {
|
||||||
|
http.Error(w, "403 - Forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the source path exists
|
// Check if the source path exists
|
||||||
if _, err := os.Stat(absSrcPath); os.IsNotExist(err) {
|
if _, err := os.Stat(absSrcPath); os.IsNotExist(err) {
|
||||||
utils.SendErrorResponse(w, "source path does not exist")
|
utils.SendErrorResponse(w, "source path does not exist")
|
||||||
@ -294,6 +326,18 @@ func (fm *FileManager) HandleFileMove(w http.ResponseWriter, r *http.Request) {
|
|||||||
absSrcPath := filepath.Join(fm.Directory, srcPath)
|
absSrcPath := filepath.Join(fm.Directory, srcPath)
|
||||||
absDestPath := filepath.Join(fm.Directory, destPath)
|
absDestPath := filepath.Join(fm.Directory, destPath)
|
||||||
|
|
||||||
|
//Make sure move source and target are within web server directory
|
||||||
|
isValidRequest := validatePathEscape(absSrcPath, fm.Directory)
|
||||||
|
if !isValidRequest {
|
||||||
|
http.Error(w, "403 - Forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isValidRequest = validatePathEscape(absDestPath, fm.Directory)
|
||||||
|
if !isValidRequest {
|
||||||
|
http.Error(w, "403 - Forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the source path exists
|
// Check if the source path exists
|
||||||
if _, err := os.Stat(absSrcPath); os.IsNotExist(err) {
|
if _, err := os.Stat(absSrcPath); os.IsNotExist(err) {
|
||||||
utils.SendErrorResponse(w, "source path does not exist")
|
utils.SendErrorResponse(w, "source path does not exist")
|
||||||
@ -325,6 +369,11 @@ func (fm *FileManager) HandleFileProperties(w http.ResponseWriter, r *http.Reque
|
|||||||
|
|
||||||
// Construct the absolute path to the target file or directory
|
// Construct the absolute path to the target file or directory
|
||||||
absPath := filepath.Join(fm.Directory, filePath)
|
absPath := filepath.Join(fm.Directory, filePath)
|
||||||
|
isValidRequest := validatePathEscape(absPath, fm.Directory)
|
||||||
|
if !isValidRequest {
|
||||||
|
http.Error(w, "403 - Forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the target path exists
|
// Check if the target path exists
|
||||||
_, err = os.Stat(absPath)
|
_, err = os.Stat(absPath)
|
||||||
@ -392,6 +441,11 @@ func (fm *FileManager) HandleFileDelete(w http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
// Construct the absolute path to the target file or directory
|
// Construct the absolute path to the target file or directory
|
||||||
absPath := filepath.Join(fm.Directory, filePath)
|
absPath := filepath.Join(fm.Directory, filePath)
|
||||||
|
isValidRequest := validatePathEscape(absPath, fm.Directory)
|
||||||
|
if !isValidRequest {
|
||||||
|
http.Error(w, "403 - Forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the target path exists
|
// Check if the target path exists
|
||||||
_, err = os.Stat(absPath)
|
_, err = os.Stat(absPath)
|
||||||
@ -410,3 +464,25 @@ func (fm *FileManager) HandleFileDelete(w http.ResponseWriter, r *http.Request)
|
|||||||
// Respond with a success message or appropriate response
|
// Respond with a success message or appropriate response
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return true if the path is within the root path
|
||||||
|
func validatePathEscape(reqestPath string, rootPath string) bool {
|
||||||
|
reqestPath = filepath.ToSlash(filepath.Clean(reqestPath))
|
||||||
|
rootPath = filepath.ToSlash(filepath.Clean(rootPath))
|
||||||
|
|
||||||
|
requestPathAbs, err := filepath.Abs(reqestPath)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
rootPathAbs, err := filepath.Abs(rootPath)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(requestPathAbs, rootPathAbs) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user