Pārlūkot izejas kodu

Fixed promox bug

Toby Chui 7 mēneši atpakaļ
vecāks
revīzija
43bea30ce5

+ 21 - 0
mod/dynamicproxy/domainsniff/proxmox.go

@@ -0,0 +1,21 @@
+package domainsniff
+
+import "net/http"
+
+/*
+	Promox API sniffer
+
+	This handler sniff proxmox API endpoint and
+	adjust the request accordingly to fix shits
+	in the proxmox API server
+*/
+
+func IsProxmox(r *http.Request) bool {
+	// Check if any of the cookies is named PVEAuthCookie
+	for _, cookie := range r.Cookies() {
+		if cookie.Name == "PVEAuthCookie" {
+			return true
+		}
+	}
+	return false
+}

+ 6 - 1
mod/dynamicproxy/dpcore/dpcore.go

@@ -11,6 +11,7 @@ import (
 	"strings"
 	"time"
 
+	"imuslab.com/zoraxy/mod/dynamicproxy/domainsniff"
 	"imuslab.com/zoraxy/mod/dynamicproxy/permissionpolicy"
 )
 
@@ -50,7 +51,6 @@ type ReverseProxy struct {
 	ModifyResponse func(*http.Response) error
 
 	//Prepender is an optional prepend text for URL rewrite
-	//
 	Prepender string
 
 	Verbal bool
@@ -313,6 +313,11 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr
 	// Rewrite outbound UA, must be after user headers
 	rewriteUserAgent(outreq.Header, "Zoraxy/"+rrr.Version)
 
+	//Fix proxmox transfer encoding bug if detected Proxmox Cookie with POST request
+	if outreq.Method == http.MethodPost && domainsniff.IsProxmox(req) {
+		outreq.TransferEncoding = []string{"identity"}
+	}
+
 	res, err := transport.RoundTrip(outreq)
 	if err != nil {
 		if p.Verbal {

+ 63 - 0
mod/dynamicproxy/dpcore/utils.go

@@ -1,7 +1,10 @@
 package dpcore
 
 import (
+	"bytes"
+	"io"
 	"net"
+	"net/http"
 	"net/url"
 	"strings"
 )
@@ -92,3 +95,63 @@ func isExternalDomainName(hostname string) bool {
 
 	return true
 }
+
+// DeepCopyRequest returns a deep copy of the given http.Request.
+func DeepCopyRequest(req *http.Request) (*http.Request, error) {
+	// Copy the URL
+	urlCopy := *req.URL
+
+	// Copy the headers
+	headersCopy := make(http.Header, len(req.Header))
+	for k, vv := range req.Header {
+		vvCopy := make([]string, len(vv))
+		copy(vvCopy, vv)
+		headersCopy[k] = vvCopy
+	}
+
+	// Copy the cookies
+	cookiesCopy := make([]*http.Cookie, len(req.Cookies()))
+	for i, cookie := range req.Cookies() {
+		cookieCopy := *cookie
+		cookiesCopy[i] = &cookieCopy
+	}
+
+	// Copy the body, if present
+	var bodyCopy io.ReadCloser
+	if req.Body != nil {
+		var buf bytes.Buffer
+		if _, err := buf.ReadFrom(req.Body); err != nil {
+			return nil, err
+		}
+		// Reset the request body so it can be read again
+		if err := req.Body.Close(); err != nil {
+			return nil, err
+		}
+		req.Body = io.NopCloser(&buf)
+		bodyCopy = io.NopCloser(bytes.NewReader(buf.Bytes()))
+	}
+
+	// Create the new request
+	reqCopy := &http.Request{
+		Method:           req.Method,
+		URL:              &urlCopy,
+		Proto:            req.Proto,
+		ProtoMajor:       req.ProtoMajor,
+		ProtoMinor:       req.ProtoMinor,
+		Header:           headersCopy,
+		Body:             bodyCopy,
+		ContentLength:    req.ContentLength,
+		TransferEncoding: append([]string(nil), req.TransferEncoding...),
+		Close:            req.Close,
+		Host:             req.Host,
+		Form:             req.Form,
+		PostForm:         req.PostForm,
+		MultipartForm:    req.MultipartForm,
+		Trailer:          req.Trailer,
+		RemoteAddr:       req.RemoteAddr,
+		TLS:              req.TLS,
+		// Cancel and Context are not copied as it might cause issues
+	}
+
+	return reqCopy, nil
+}