4 Commits

Author SHA1 Message Date
Toby Chui
1faaae21d7 Merge pull request #827 from Saeraphinx/webui-style-changes
Update Sidebar CSS
2025-09-20 12:32:42 +08:00
Saera
53c73e1e77 update styling 2025-09-19 11:44:20 -05:00
Toby Chui
0805da9d13 Added more test cases for netutil ipmatch 2025-09-19 21:14:20 +08:00
Toby Chui
52f652fbaf Enable SNI offload in HTTPS proxy connections
Updated the ReverseProxy's ProxyHTTPS method to use tls.Dial with SNI support when connecting to upstream servers. Also incremented SYSTEM_VERSION to 3.2.7.
2025-09-17 07:37:21 +08:00
7 changed files with 95 additions and 11 deletions

View File

@@ -44,7 +44,7 @@ import (
const ( const (
/* Build Constants */ /* Build Constants */
SYSTEM_NAME = "Zoraxy" SYSTEM_NAME = "Zoraxy"
SYSTEM_VERSION = "3.2.6" SYSTEM_VERSION = "3.2.7"
DEVELOPMENT_BUILD = false DEVELOPMENT_BUILD = false
/* System Constants */ /* System Constants */

View File

@@ -2,10 +2,10 @@ package dpcore
import ( import (
"context" "context"
"crypto/tls"
"errors" "errors"
"io" "io"
"log" "log"
"net"
"net/http" "net/http"
"net/url" "net/url"
"strings" "strings"
@@ -391,7 +391,6 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr
return res.StatusCode, nil return res.StatusCode, nil
} }
func (p *ReverseProxy) ProxyHTTPS(rw http.ResponseWriter, req *http.Request) (int, error) { func (p *ReverseProxy) ProxyHTTPS(rw http.ResponseWriter, req *http.Request) (int, error) {
hij, ok := rw.(http.Hijacker) hij, ok := rw.(http.Hijacker)
if !ok { if !ok {
@@ -407,12 +406,23 @@ func (p *ReverseProxy) ProxyHTTPS(rw http.ResponseWriter, req *http.Request) (in
return http.StatusInternalServerError, err return http.StatusInternalServerError, err
} }
proxyConn, err := net.Dial("tcp", req.URL.Host) // Extract SNI/hostname for TLS handshake
host := req.URL.Host
if !strings.Contains(host, ":") {
host += ":443"
}
serverName := req.URL.Hostname()
// Connect with SNI offload
tlsConfig := &tls.Config{
ServerName: serverName,
}
proxyConn, err := tls.Dial("tcp", host, tlsConfig)
if err != nil { if err != nil {
if p.Verbal { if p.Verbal {
p.logf("http: proxy error: %v", err) p.logf("http: proxy error: %v", err)
} }
clientConn.Close()
return http.StatusInternalServerError, err return http.StatusInternalServerError, err
} }

View File

@@ -108,14 +108,24 @@ func MatchIpCIDR(ip string, cidr string) bool {
// Check if a ip is private IP range // Check if a ip is private IP range
func IsPrivateIP(ipStr string) bool { func IsPrivateIP(ipStr string) bool {
if ipStr == "127.0.0.1" || ipStr == "::1" { if ipStr == "127.0.0.1" || ipStr == "::1" {
//local loopback // local loopback
return true return true
} }
ip := net.ParseIP(ipStr) ip := net.ParseIP(ipStr)
if ip == nil { if ip == nil {
return false return false
} }
return ip.IsPrivate() if ip.IsPrivate() {
return true
}
// Check for IPv6 link-local addresses (fe80::/10)
if ip.To16() != nil && ip.To4() == nil {
// IPv6 only
if ip[0] == 0xfe && (ip[1]&0xc0) == 0x80 {
return true
}
}
return false
} }
// Check if an Ip string is ipv6 // Check if an Ip string is ipv6

View File

@@ -26,3 +26,56 @@ func TestHandlePing(t *testing.T) {
t.Log(realIP, pingTime, ttl) t.Log(realIP, pingTime, ttl)
} }
func TestMatchIpWildcard_IPv6(t *testing.T) {
// IPv6 wildcards are not supported by MatchIpWildcard, so these should all return false
tests := []struct {
ip string
wildcard string
want bool
}{
{"fd7a:115c:a1e0::e101:6f0f", "fd7a:115c:a1e0::e101:6f0f", false}, // not supported
{"fd7a:115c:a1e0::e101:6f0f", "*:*:*:*:*:*:*:*", false},
}
for _, tt := range tests {
got := netutils.MatchIpWildcard(tt.ip, tt.wildcard)
if got != tt.want {
t.Errorf("MatchIpWildcard(%q, %q) = %v, want %v", tt.ip, tt.wildcard, got, tt.want)
}
}
}
func TestMatchIpCIDR_IPv6(t *testing.T) {
tests := []struct {
ip string
cidr string
want bool
}{
{"fd7a:115c:a1e0::e101:6f0f", "fd7a:115c:a1e0::/48", true},
{"fd7a:115c:a1e0::e101:6f0f", "fd7a:115c:a1e0::/64", true},
{"fd7a:115c:a1e0::e101:6f0f", "fd7a:115c:a1e1::/48", false},
{"fd7a:115c:a1e0::e101:6f0f", "fd7a:115c:a1e0::/128", false},
}
for _, tt := range tests {
got := netutils.MatchIpCIDR(tt.ip, tt.cidr)
if got != tt.want {
t.Errorf("MatchIpCIDR(%q, %q) = %v, want %v", tt.ip, tt.cidr, got, tt.want)
}
}
}
func TestIsPrivateIP_IPv6(t *testing.T) {
tests := []struct {
ip string
want bool
}{
{"fd7a:115c:a1e0::e101:6f0f", true}, // Unique local address (fc00::/7)
{"fe80::1", true}, // Link-local
{"2001:db8::1", false}, // Documentation address
}
for _, tt := range tests {
got := netutils.IsPrivateIP(tt.ip)
if got != tt.want {
t.Errorf("IsPrivateIP(%q) = %v, want %v", tt.ip, got, tt.want)
}
}
}

View File

@@ -336,7 +336,7 @@ body.darkTheme .ui.segment.advanceoptions {
body.darkTheme .ui.segment{ body.darkTheme .ui.segment{
background-color: transparent !important; background-color: transparent !important;
color: var(--text_color) !important; color: var(--text_color) !important;
border: 1px solid transparent !important; border: 0 /*solid transparent*/ !important;
} }
body.darkTheme .sub.header { body.darkTheme .sub.header {

View File

@@ -173,7 +173,7 @@
</div> </div>
<br><br> <br><br>
<div class="ui divider"></div> <div class="ui divider"></div>
<div class="ui container" style="color: grey; font-size: 90%"> <div class="ui container" style="color: grey; font-size: 90%; padding-bottom: 1em;">
<p><a href="https://zoraxy.aroz.org" target="_blank">Zoraxy</a> <span class="zrversion"></span> © 2021 - <span class="year"></span> tobychui. Licensed under AGPL</p> <p><a href="https://zoraxy.aroz.org" target="_blank">Zoraxy</a> <span class="zrversion"></span> © 2021 - <span class="year"></span> tobychui. Licensed under AGPL</p>
</div> </div>

View File

@@ -72,15 +72,17 @@ body.darkTheme .menubar{
width: 240px; width: 240px;
position: sticky; position: sticky;
top: 4em; top: 4em;
padding: 0 1em;
} }
.contentWindow{ .contentWindow{
display: inline-block; display: inline-block;
width: calc(100% - 240px); width: calc(100% - 244px);
vertical-align: top; vertical-align: top;
background-color: var(--theme_bg_primary); background-color: var(--theme_bg_primary);
border-radius: 1em; border-radius: 1em;
margin-right: 2em; margin-right: 1em;
flex-shrink: 0;
} }
.menutoggle{ .menutoggle{
@@ -309,8 +311,17 @@ body.darkTheme .menubar{
font-size: 0.8em !important; font-size: 0.8em !important;
color: #9c9c9c !important; color: #9c9c9c !important;
padding-left: 0.6em; padding-left: 0.6em;
/* fix the divider being really weird in the sidebar menu */
margin: 1rem 0 0.25rem 0 !important;
height: 2em !important;
border-bottom: 1px solid rgba(34,36,38,.15) !important;
border-top: 1px solid rgba(255,255,255,.1) !important;
} }
body.darkTheme .menudivider{
border-bottom: 1px solid rgba(255,255,255,.15) !important;
border-top: 1px solid rgba(34,36,38,.1) !important;
}
/* /*
Global rules overwrite Global rules overwrite
*/ */