mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-03 06:07:20 +02:00
init commit
+ Added fastly_client_ip to X-Real-IP auto rewrite + Updated header rewrite data structure (wip) + Added atomic accumulator to TCP proxy + Added wip UDP proxy + Added white logo for future dark theme
This commit is contained in:
parent
7193defad7
commit
136d1ecafb
@ -52,7 +52,7 @@ var logOutputToFile = flag.Bool("log", true, "Log terminal output to file")
|
||||
|
||||
var (
|
||||
name = "Zoraxy"
|
||||
version = "3.0.5"
|
||||
version = "3.0.6"
|
||||
nodeUUID = "generic"
|
||||
development = false //Set this to false to use embedded web fs
|
||||
bootTime = time.Now().Unix()
|
||||
|
@ -14,11 +14,16 @@ import (
|
||||
Main server for dynamic proxy core
|
||||
|
||||
Routing Handler Priority (High to Low)
|
||||
- Blacklist
|
||||
- Whitelist
|
||||
- Special Routing Rule (e.g. acme)
|
||||
- Redirectable
|
||||
- Subdomain Routing
|
||||
- Vitrual Directory Routing
|
||||
- Access Router
|
||||
- Blacklist
|
||||
- Whitelist
|
||||
- Basic Auth
|
||||
- Vitrual Directory Proxy
|
||||
- Subdomain Proxy
|
||||
- Root router (default site router)
|
||||
*/
|
||||
|
||||
func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -304,9 +304,13 @@ func addXForwardedForHeader(req *http.Request) {
|
||||
if req.Header.Get("X-Real-Ip") == "" {
|
||||
//Check if CF-Connecting-IP header exists
|
||||
CF_Connecting_IP := req.Header.Get("CF-Connecting-IP")
|
||||
Fastly_Client_IP := req.Header.Get("Fastly-Client-IP")
|
||||
if CF_Connecting_IP != "" {
|
||||
//Use CF Connecting IP
|
||||
req.Header.Set("X-Real-Ip", CF_Connecting_IP)
|
||||
} else if Fastly_Client_IP != "" {
|
||||
//Use Fastly Client IP
|
||||
req.Header.Set("X-Real-Ip", Fastly_Client_IP)
|
||||
} else {
|
||||
// Not exists. Fill it in with first entry in X-Forwarded-For
|
||||
ips := strings.Split(clientIP, ",")
|
||||
|
@ -72,10 +72,21 @@ type BasicAuthExceptionRule struct {
|
||||
PathPrefix string
|
||||
}
|
||||
|
||||
// Header injection direction type
|
||||
type HeaderDirection int
|
||||
|
||||
const (
|
||||
HeaderDirection_ZoraxyToUpstream HeaderDirection = 0 //Inject (or remove) header to request out-going from Zoraxy to backend server
|
||||
HeaderDirection_ZoraxyToDownstream HeaderDirection = 1 //Inject (or remove) header to request out-going from Zoraxy to client (e.g. browser)
|
||||
)
|
||||
|
||||
// User defined headers to add into a proxy endpoint
|
||||
type UserDefinedHeader struct {
|
||||
Key string
|
||||
Value string
|
||||
Direction HeaderDirection
|
||||
Key string
|
||||
Value string
|
||||
IsRemove bool //Instead of set, remove this key instead
|
||||
IsAppend bool //Instead of set, append to the current one with "," as seperator
|
||||
}
|
||||
|
||||
// A Virtual Directory endpoint, provide a subset of ProxyEndpoint for better
|
||||
|
@ -9,13 +9,13 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
//Rewrite url based on proxy root
|
||||
// Rewrite url based on proxy root (default site)
|
||||
func RewriteURL(rooturl string, requestURL string) (*url.URL, error) {
|
||||
rewrittenURL := strings.TrimPrefix(requestURL, rooturl)
|
||||
return url.Parse(rewrittenURL)
|
||||
}
|
||||
|
||||
//Check if the current platform support web.ssh function
|
||||
// Check if the current platform support web.ssh function
|
||||
func IsWebSSHSupported() bool {
|
||||
//Check if the binary exists in system/gotty/
|
||||
binary := "gotty_" + runtime.GOOS + "_" + runtime.GOARCH
|
||||
@ -34,7 +34,7 @@ func IsWebSSHSupported() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
//Check if a given domain and port is a valid ssh server
|
||||
// Check if a given domain and port is a valid ssh server
|
||||
func IsSSHConnectable(ipOrDomain string, port int) bool {
|
||||
timeout := time.Second * 3
|
||||
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ipOrDomain, port), timeout)
|
||||
@ -60,7 +60,7 @@ func IsSSHConnectable(ipOrDomain string, port int) bool {
|
||||
return string(buf[:7]) == "SSH-2.0"
|
||||
}
|
||||
|
||||
//Check if the port is used by other process or application
|
||||
// Check if the port is used by other process or application
|
||||
func isPortInUse(port int) bool {
|
||||
address := fmt.Sprintf(":%d", port)
|
||||
listener, err := net.Listen("tcp", address)
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"net"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -38,8 +39,12 @@ func isReachable(target string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup, accumulator *int64) {
|
||||
io.Copy(conn1, conn2)
|
||||
func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup, accumulator *atomic.Int64) {
|
||||
n, err := io.Copy(conn1, conn2)
|
||||
if err != nil {
|
||||
//Add to accumulator
|
||||
accumulator.Add(n)
|
||||
}
|
||||
conn1.Close()
|
||||
log.Println("[←]", "close the connect at local:["+conn1.LocalAddr().String()+"] and remote:["+conn1.RemoteAddr().String()+"]")
|
||||
//conn2.Close()
|
||||
@ -47,7 +52,7 @@ func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup, accumulator *i
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func forward(conn1 net.Conn, conn2 net.Conn, aTob *int64, bToa *int64) {
|
||||
func forward(conn1 net.Conn, conn2 net.Conn, aTob *atomic.Int64, bToa *atomic.Int64) {
|
||||
log.Printf("[+] start transmit. [%s],[%s] <-> [%s],[%s] \n", conn1.LocalAddr().String(), conn1.RemoteAddr().String(), conn2.LocalAddr().String(), conn2.RemoteAddr().String())
|
||||
var wg sync.WaitGroup
|
||||
// wait tow goroutines
|
||||
@ -158,6 +163,8 @@ func (c *ProxyRelayConfig) Start() error {
|
||||
err = c.Port2port(c.PortA, c.PortB, stopChan)
|
||||
} else if c.Mode == ProxyMode_Starter {
|
||||
err = c.Host2host(c.PortA, c.PortB, stopChan)
|
||||
} else if c.Mode == ProxyMode_UDP {
|
||||
err = c.ForwardUDP(c.PortA, c.PortB, stopChan)
|
||||
}
|
||||
if err != nil {
|
||||
c.Running = false
|
||||
|
@ -3,6 +3,8 @@ package tcpprox
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"imuslab.com/zoraxy/mod/database"
|
||||
@ -20,6 +22,7 @@ const (
|
||||
ProxyMode_Listen = 0
|
||||
ProxyMode_Transport = 1
|
||||
ProxyMode_Starter = 2
|
||||
ProxyMode_UDP = 3
|
||||
)
|
||||
|
||||
type ProxyRelayOptions struct {
|
||||
@ -31,16 +34,16 @@ type ProxyRelayOptions struct {
|
||||
}
|
||||
|
||||
type ProxyRelayConfig struct {
|
||||
UUID string //A UUIDv4 representing this config
|
||||
Name string //Name of the config
|
||||
Running bool //If the service is running
|
||||
PortA string //Ports A (config depends on mode)
|
||||
PortB string //Ports B (config depends on mode)
|
||||
Mode int //Operation Mode
|
||||
Timeout int //Timeout for connection in sec
|
||||
stopChan chan bool //Stop channel to stop the listener
|
||||
aTobAccumulatedByteTransfer int64 //Accumulated byte transfer from A to B
|
||||
bToaAccumulatedByteTransfer int64 //Accumulated byte transfer from B to A
|
||||
UUID string //A UUIDv4 representing this config
|
||||
Name string //Name of the config
|
||||
Running bool //If the service is running
|
||||
PortA string //Ports A (config depends on mode)
|
||||
PortB string //Ports B (config depends on mode)
|
||||
Mode int //Operation Mode
|
||||
Timeout int //Timeout for connection in sec
|
||||
stopChan chan bool //Stop channel to stop the listener
|
||||
aTobAccumulatedByteTransfer atomic.Int64 //Accumulated byte transfer from A to B
|
||||
bToaAccumulatedByteTransfer atomic.Int64 //Accumulated byte transfer from B to A
|
||||
|
||||
parent *Manager `json:"-"`
|
||||
}
|
||||
@ -57,7 +60,8 @@ type Manager struct {
|
||||
Configs []*ProxyRelayConfig
|
||||
|
||||
//Realtime Statistics
|
||||
Connections int //currently connected connect counts
|
||||
Connections int //currently connected connect counts
|
||||
UDPClientMap sync.Map //map storing the UDP client-server connections
|
||||
}
|
||||
|
||||
func NewTCProxy(options *Options) *Manager {
|
||||
@ -94,6 +98,11 @@ func NewTCProxy(options *Options) *Manager {
|
||||
}
|
||||
|
||||
func (m *Manager) NewConfig(config *ProxyRelayOptions) string {
|
||||
//Generate two zero value for atomic int64
|
||||
aAcc := atomic.Int64{}
|
||||
bAcc := atomic.Int64{}
|
||||
aAcc.Store(0)
|
||||
bAcc.Store(0)
|
||||
//Generate a new config from options
|
||||
configUUID := uuid.New().String()
|
||||
thisConfig := ProxyRelayConfig{
|
||||
@ -105,8 +114,8 @@ func (m *Manager) NewConfig(config *ProxyRelayOptions) string {
|
||||
Mode: config.Mode,
|
||||
Timeout: config.Timeout,
|
||||
stopChan: nil,
|
||||
aTobAccumulatedByteTransfer: 0,
|
||||
bToaAccumulatedByteTransfer: 0,
|
||||
aTobAccumulatedByteTransfer: aAcc,
|
||||
bToaAccumulatedByteTransfer: bAcc,
|
||||
|
||||
parent: m,
|
||||
}
|
||||
|
89
src/mod/tcpprox/udpprox.go
Normal file
89
src/mod/tcpprox/udpprox.go
Normal file
@ -0,0 +1,89 @@
|
||||
package tcpprox
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
/*
|
||||
UDP Proxy Module
|
||||
*/
|
||||
|
||||
// Information maintained for each client/server connection
|
||||
type udpClientServerConn struct {
|
||||
ClientAddr *net.UDPAddr // Address of the client
|
||||
ServerConn *net.UDPConn // UDP connection to server
|
||||
}
|
||||
|
||||
// Generate a new connection by opening a UDP connection to the server
|
||||
func createNewUDPConn(srvAddr, cliAddr *net.UDPAddr) *udpClientServerConn {
|
||||
conn := new(udpClientServerConn)
|
||||
conn.ClientAddr = cliAddr
|
||||
srvudp, err := net.DialUDP("udp", nil, srvAddr)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
conn.ServerConn = srvudp
|
||||
return conn
|
||||
}
|
||||
|
||||
// Start listener, return inbound lisener and proxy target UDP address
|
||||
func initUDPConnections(listenAddr string, targetAddress string) (*net.UDPConn, *net.UDPAddr, error) {
|
||||
// Set up Proxy
|
||||
saddr, err := net.ResolveUDPAddr("udp", listenAddr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
inboundConn, err := net.ListenUDP("udp", saddr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
log.Println("Proxy serving on port %s\n", listenAddr)
|
||||
|
||||
outboundConn, err := net.ResolveUDPAddr("udp", targetAddress)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return inboundConn, outboundConn, nil
|
||||
}
|
||||
|
||||
func (c *ProxyRelayConfig) ForwardUDP(address1, address2 string, stopChan chan bool) error {
|
||||
lisener, targetAddr, err := initUDPConnections(address1, address2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var buffer [1500]byte
|
||||
for {
|
||||
n, cliaddr, err := lisener.ReadFromUDP(buffer[0:])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
c.aTobAccumulatedByteTransfer.Add(int64(n))
|
||||
saddr := cliaddr.String()
|
||||
dlock()
|
||||
conn, found := ClientDict[saddr]
|
||||
if !found {
|
||||
conn = createNewUDPConn(targetAddr, cliaddr)
|
||||
if conn == nil {
|
||||
dunlock()
|
||||
continue
|
||||
}
|
||||
ClientDict[saddr] = conn
|
||||
dunlock()
|
||||
Vlogf(2, "Created new connection for client %s\n", saddr)
|
||||
// Fire up routine to manage new connection
|
||||
go RunConnection(conn)
|
||||
} else {
|
||||
Vlogf(5, "Found connection for client %s\n", saddr)
|
||||
dunlock()
|
||||
}
|
||||
// Relay to server
|
||||
_, err = conn.ServerConn.Write(buffer[0:n])
|
||||
if checkreport(1, err) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
@ -258,7 +258,7 @@
|
||||
|
||||
setTimeout(function(){
|
||||
//Update the checkbox
|
||||
msgbox("Proxy Root Updated");
|
||||
msgbox("Default Site Updated");
|
||||
}, 100);
|
||||
|
||||
})
|
||||
|
1512
src/web/img/logo_white.ai
Normal file
1512
src/web/img/logo_white.ai
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/web/img/logo_white.png
Normal file
BIN
src/web/img/logo_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
38
src/web/img/logo_white.svg
Normal file
38
src/web/img/logo_white.svg
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="600px" height="200px" viewBox="0 0 600 200" enable-background="new 0 0 600 200" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#EFEFEF" d="M138.761,47.403l-16.064,17.87c9.504,8.549,15.48,20.94,15.48,34.728c0,13.785-5.976,26.179-15.48,34.726
|
||||
l16.063,17.871c14.393-12.945,23.445-31.717,23.445-52.597C162.206,79.115,153.155,60.351,138.761,47.403z"/>
|
||||
<path fill="#EFEFEF" d="M44.198,152.596l16.064-17.869c-9.503-8.547-15.48-20.941-15.48-34.726c0-13.79,5.978-26.179,15.48-34.728
|
||||
l-16.063-17.87C29.807,60.351,20.753,79.115,20.753,100C20.753,120.881,29.807,139.652,44.198,152.596z"/>
|
||||
</g>
|
||||
<polygon fill="#A9D1F3" points="106.581,38.326 91.48,56.48 76.38,38.326 "/>
|
||||
<polygon fill="#A9D1F3" points="106.581,143.52 91.48,161.674 76.379,143.52 "/>
|
||||
<circle fill="#A9D1F3" cx="91.48" cy="100" r="22.422"/>
|
||||
<g>
|
||||
<path fill="#F7F7F7" d="M194.194,132.898l43.232-66.846h-39.238V54.539h56.155v8.224l-43.233,66.729h43.703v11.629h-60.619V132.898
|
||||
z"/>
|
||||
<path fill="#F7F7F7" d="M263.038,108.814c0-21.499,14.45-33.951,30.544-33.951c15.977,0,30.31,12.452,30.31,33.951
|
||||
c0,21.498-14.333,33.951-30.31,33.951C277.488,142.766,263.038,130.313,263.038,108.814z M310.029,108.814
|
||||
c0-13.627-6.344-22.791-16.447-22.791c-10.221,0-16.564,9.164-16.564,22.791c0,13.744,6.344,22.674,16.564,22.674
|
||||
C303.686,131.488,310.029,122.559,310.029,108.814z"/>
|
||||
<path fill="#F7F7F7" d="M339.869,76.391h11.042l1.176,11.629h0.234c4.582-8.223,11.396-13.156,18.444-13.156
|
||||
c3.173,0,5.169,0.471,7.166,1.293l-2.35,11.863c-2.349-0.704-3.877-1.057-6.578-1.057c-5.287,0-11.632,3.643-15.626,13.981v40.177
|
||||
h-13.509V76.391z"/>
|
||||
<path fill="#F7F7F7" d="M380.868,123.969c0-13.98,11.748-21.146,38.649-24.082c-0.115-7.402-2.819-13.98-12.334-13.98
|
||||
c-6.813,0-13.158,3.056-18.68,6.578l-5.052-9.162c6.696-4.23,15.742-8.459,26.08-8.459c16.096,0,23.497,10.104,23.497,27.374
|
||||
v38.884h-11.044l-1.058-7.4h-0.469c-5.875,5.051-12.806,9.045-20.56,9.045C388.739,142.766,380.868,135.365,380.868,123.969z
|
||||
M419.518,124.322V108.58c-19.147,2.23-25.61,7.166-25.61,14.332c0,6.461,4.348,9.047,10.104,9.047
|
||||
C409.649,131.959,414.231,129.256,419.518,124.322z"/>
|
||||
<path fill="#F7F7F7" d="M464.63,107.405l-19.383-31.015h14.686l7.636,13.039c1.996,3.643,3.995,7.285,6.109,10.927h0.587
|
||||
c1.645-3.642,3.406-7.284,5.287-10.927l6.813-13.039h14.099l-19.386,32.424l20.795,32.307h-14.685l-8.459-13.744
|
||||
c-2.115-3.76-4.346-7.754-6.697-11.396h-0.586c-1.997,3.643-3.995,7.52-5.992,11.396l-7.518,13.744h-14.098L464.63,107.405z"/>
|
||||
<path fill="#F7F7F7" d="M508.096,166.85l2.586-10.574c1.176,0.354,3.054,0.939,4.815,0.939c6.932,0,11.045-5.168,13.394-12.1
|
||||
l1.41-4.463l-25.611-64.262h13.746l11.865,33.363c1.996,5.758,3.993,12.1,5.991,18.209h0.587
|
||||
c1.645-5.992,3.406-12.334,5.053-18.209l10.456-33.363h13.038l-23.73,68.607c-5.051,13.863-11.865,23.143-25.375,23.143
|
||||
C512.914,168.141,510.329,167.672,508.096,166.85z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.1 KiB |
Loading…
x
Reference in New Issue
Block a user