mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-08-12 08:05:19 +02:00
Updates 2.6.4
+ Added force TLS v1.2 above toggle + Added trace route + Added ICMP ping + Added special routing rules module for up-coming acme integration + Fixed IPv6 check bug in black/whitelist + Optimized UI for TCP Proxy +
This commit is contained in:
100
src/mod/pathrule/handler.go
Normal file
100
src/mod/pathrule/handler.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package pathrule
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"imuslab.com/zoraxy/mod/utils"
|
||||
)
|
||||
|
||||
/*
|
||||
handler.go
|
||||
|
||||
This script handles pathblock api
|
||||
*/
|
||||
|
||||
func (h *Handler) HandleListBlockingPath(w http.ResponseWriter, r *http.Request) {
|
||||
js, _ := json.Marshal(h.BlockingPaths)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
}
|
||||
|
||||
func (h *Handler) HandleAddBlockingPath(w http.ResponseWriter, r *http.Request) {
|
||||
matchingPath, err := utils.PostPara(r, "matchingPath")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid matching path given")
|
||||
return
|
||||
}
|
||||
|
||||
exactMatch, err := utils.PostPara(r, "exactMatch")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid exact match value given")
|
||||
return
|
||||
}
|
||||
|
||||
statusCodeString, err := utils.PostPara(r, "statusCode")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid status code given")
|
||||
return
|
||||
}
|
||||
|
||||
statusCode, err := strconv.Atoi(statusCodeString)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid status code given")
|
||||
return
|
||||
}
|
||||
|
||||
enabled, err := utils.PostPara(r, "enabled")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid enabled value given")
|
||||
return
|
||||
}
|
||||
|
||||
caseSensitive, err := utils.PostPara(r, "caseSensitive")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid case sensitive value given")
|
||||
return
|
||||
}
|
||||
|
||||
targetBlockingPath := BlockingPath{
|
||||
UUID: uuid.NewV4().String(),
|
||||
MatchingPath: matchingPath,
|
||||
ExactMatch: exactMatch == "true",
|
||||
StatusCode: statusCode,
|
||||
CustomHeaders: http.Header{},
|
||||
CustomHTML: []byte(""),
|
||||
Enabled: enabled == "true",
|
||||
CaseSenitive: caseSensitive == "true",
|
||||
}
|
||||
|
||||
err = h.AddBlockingPath(&targetBlockingPath)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
utils.SendOK(w)
|
||||
}
|
||||
|
||||
func (h *Handler) HandleRemoveBlockingPath(w http.ResponseWriter, r *http.Request) {
|
||||
blockerUUID, err := utils.PostPara(r, "uuid")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid uuid given")
|
||||
return
|
||||
}
|
||||
|
||||
targetRule := h.GetPathBlockerFromUUID(blockerUUID)
|
||||
if targetRule == nil {
|
||||
//Not found
|
||||
utils.SendErrorResponse(w, "target path blocker not found")
|
||||
return
|
||||
}
|
||||
|
||||
err = h.RemoveBlockingPathByUUID(blockerUUID)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
utils.SendOK(w)
|
||||
}
|
175
src/mod/pathrule/pathrule.go
Normal file
175
src/mod/pathrule/pathrule.go
Normal file
@@ -0,0 +1,175 @@
|
||||
package pathrule
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"imuslab.com/zoraxy/mod/utils"
|
||||
)
|
||||
|
||||
/*
|
||||
Pathblock.go
|
||||
|
||||
This script block off some of the specific pathname in access
|
||||
For example, this module can help you block request for a particular
|
||||
apache directory or functional endpoints like /.well-known/ when you
|
||||
are not using it
|
||||
*/
|
||||
|
||||
type Options struct {
|
||||
ConfigFolder string //The folder to store the path blocking config files
|
||||
}
|
||||
|
||||
type BlockingPath struct {
|
||||
UUID string
|
||||
MatchingPath string
|
||||
ExactMatch bool
|
||||
StatusCode int
|
||||
CustomHeaders http.Header
|
||||
CustomHTML []byte
|
||||
Enabled bool
|
||||
CaseSenitive bool
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
Options *Options
|
||||
BlockingPaths []*BlockingPath
|
||||
}
|
||||
|
||||
// Create a new path blocker handler
|
||||
func NewPathBlocker(options *Options) *Handler {
|
||||
//Create folder if not exists
|
||||
if !utils.FileExists(options.ConfigFolder) {
|
||||
os.Mkdir(options.ConfigFolder, 0775)
|
||||
}
|
||||
|
||||
//Load the configs from file
|
||||
//TODO
|
||||
|
||||
return &Handler{
|
||||
Options: options,
|
||||
BlockingPaths: []*BlockingPath{},
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) ListBlockingPath() []*BlockingPath {
|
||||
return h.BlockingPaths
|
||||
}
|
||||
|
||||
// Get the blocker from matching path (path match, ignore tailing slash)
|
||||
func (h *Handler) GetPathBlockerFromMatchingPath(matchingPath string) *BlockingPath {
|
||||
for _, blocker := range h.BlockingPaths {
|
||||
if blocker.MatchingPath == matchingPath {
|
||||
return blocker
|
||||
} else if strings.TrimSuffix(blocker.MatchingPath, "/") == strings.TrimSuffix(matchingPath, "/") {
|
||||
return blocker
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) GetPathBlockerFromUUID(UUID string) *BlockingPath {
|
||||
for _, blocker := range h.BlockingPaths {
|
||||
if blocker.UUID == UUID {
|
||||
return blocker
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) AddBlockingPath(pathBlocker *BlockingPath) error {
|
||||
//Check if the blocker exists
|
||||
blockerPath := pathBlocker.MatchingPath
|
||||
targetBlocker := h.GetPathBlockerFromMatchingPath(blockerPath)
|
||||
if targetBlocker != nil {
|
||||
//Blocker with the same matching path already exists
|
||||
return errors.New("path blocker with the same path already exists")
|
||||
}
|
||||
|
||||
h.BlockingPaths = append(h.BlockingPaths, pathBlocker)
|
||||
|
||||
//Write the new config to file
|
||||
return h.SaveBlockerToFile(pathBlocker)
|
||||
}
|
||||
|
||||
func (h *Handler) RemoveBlockingPathByUUID(uuid string) error {
|
||||
newBlockingList := []*BlockingPath{}
|
||||
for _, thisBlocker := range h.BlockingPaths {
|
||||
if thisBlocker.UUID != uuid {
|
||||
newBlockingList = append(newBlockingList, thisBlocker)
|
||||
}
|
||||
}
|
||||
|
||||
if len(h.BlockingPaths) == len(newBlockingList) {
|
||||
//Nothing is removed
|
||||
return errors.New("given matching path blocker not exists")
|
||||
}
|
||||
|
||||
h.BlockingPaths = newBlockingList
|
||||
|
||||
return h.RemoveBlockerFromFile(uuid)
|
||||
}
|
||||
|
||||
func (h *Handler) SaveBlockerToFile(pathBlocker *BlockingPath) error {
|
||||
saveFilename := filepath.Join(h.Options.ConfigFolder, pathBlocker.UUID)
|
||||
js, _ := json.MarshalIndent(pathBlocker, "", " ")
|
||||
return os.WriteFile(saveFilename, js, 0775)
|
||||
}
|
||||
|
||||
func (h *Handler) RemoveBlockerFromFile(uuid string) error {
|
||||
expectedConfigFile := filepath.Join(h.Options.ConfigFolder, uuid)
|
||||
if !utils.FileExists(expectedConfigFile) {
|
||||
return errors.New("config file not found on disk")
|
||||
}
|
||||
|
||||
return os.Remove(expectedConfigFile)
|
||||
}
|
||||
|
||||
// Get all the matching blockers for the given URL path
|
||||
// return all the path blockers and the max length matching rule
|
||||
func (h *Handler) GetMatchingBlockers(urlPath string) ([]*BlockingPath, *BlockingPath) {
|
||||
urlPath = strings.TrimSuffix(urlPath, "/")
|
||||
matchingBlockers := []*BlockingPath{}
|
||||
var longestMatchingPrefix *BlockingPath = nil
|
||||
for _, thisBlocker := range h.BlockingPaths {
|
||||
if thisBlocker.Enabled == false {
|
||||
//This blocker is not enabled. Ignore this
|
||||
continue
|
||||
}
|
||||
|
||||
incomingURLPath := urlPath
|
||||
matchingPath := strings.TrimSuffix(thisBlocker.MatchingPath, "/")
|
||||
|
||||
if !thisBlocker.CaseSenitive {
|
||||
//This is not case sensitive
|
||||
incomingURLPath = strings.ToLower(incomingURLPath)
|
||||
matchingPath = strings.ToLower(matchingPath)
|
||||
}
|
||||
|
||||
if matchingPath == incomingURLPath {
|
||||
//This blocker have exact url path match
|
||||
matchingBlockers = append(matchingBlockers, thisBlocker)
|
||||
if longestMatchingPrefix == nil || len(thisBlocker.MatchingPath) > len(longestMatchingPrefix.MatchingPath) {
|
||||
longestMatchingPrefix = thisBlocker
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if !thisBlocker.ExactMatch && strings.HasPrefix(incomingURLPath, matchingPath) {
|
||||
//This blocker have prefix url match
|
||||
matchingBlockers = append(matchingBlockers, thisBlocker)
|
||||
if longestMatchingPrefix == nil || len(thisBlocker.MatchingPath) > len(longestMatchingPrefix.MatchingPath) {
|
||||
longestMatchingPrefix = thisBlocker
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return matchingBlockers, longestMatchingPrefix
|
||||
}
|
Reference in New Issue
Block a user