2025-04-26

This commit is contained in:
Qin tian
2025-04-26 19:31:33 +08:00
parent 64c9dad6cb
commit e922684525
10 changed files with 153 additions and 47 deletions

View File

@@ -314,7 +314,7 @@ func SetRequestUrl(MessageId int, URI string) bool {
k.Request.Host = Host
k.Request.URL = _u
k.Request.RequestURI = ""
k.UpdateRawTarget(0)
k.Request.SetContext(public.Connect_Raw_Address, func() string { return Host })
if k.Request.Header.Get("host") != "" {
k.Request.Header.Set("host", k.Request.Host)

View File

@@ -39,7 +39,7 @@ const (
localCert
)
var httpTypeMap = make(map[string]*httpTypeInfo)
var httpTypeMap = make(map[uint32]*httpTypeInfo)
const whoisUndefined = 0
const whoisNoHTTPS = 1
@@ -49,7 +49,6 @@ const whoisHTTPS2 = 3
type httpTypeInfo struct {
_type byte
_time time.Time
_lock sync.Mutex
_cert *x509.Certificate
}
@@ -69,9 +68,10 @@ func init() {
go clean()
}
func ClientIsHttps(server string) (byte, *x509.Certificate) {
hashCode := public.SumHashCode(server)
whoisLock.Lock()
defer whoisLock.Unlock()
res := httpTypeMap[server]
res := httpTypeMap[hashCode]
if res == nil {
return whoisUndefined, nil
}
@@ -87,27 +87,30 @@ ClientRequestIsHttps
*/
func ClientRequestIsHttps(Sunny *Sunny, targetAddr string, serverName string) (res byte, cert *x509.Certificate) {
var obj *httpTypeInfo
hashCode := public.SumHashCode(targetAddr)
whoisLock.Lock()
if httpTypeMap[targetAddr] == nil {
if httpTypeMap[hashCode] == nil {
obj = &httpTypeInfo{_time: time.Now()}
httpTypeMap[targetAddr] = obj
httpTypeMap[hashCode] = obj
} else {
obj = httpTypeMap[targetAddr]
obj = httpTypeMap[hashCode]
}
whoisLock.Unlock()
obj._lock.Lock()
if obj._type != whoisUndefined {
obj._lock.Unlock()
return obj._type, obj._cert
}
defer func() {
if res != whoisUndefined {
whoisLock.Lock()
if obj._type != whoisUndefined && obj._type != whoisNoHTTPS {
obj._time = time.Now()
whoisLock.Unlock()
return
}
obj._type = res
obj._cert = cert
obj._time = time.Now()
whoisLock.Unlock()
obj._lock.Unlock()
}
}()
proxyHost, proxyPort, e := net.SplitHostPort(targetAddr)

View File

@@ -127,6 +127,9 @@ func (s *proxyRequest) CallbackTCPRequest(callType int, _msg *public.TcpMsg, Rem
}
Call.Call(s.TcpCall, s.Global.SunnyContext, LocalAddr, hostname, int(callType), MessageId, msg.Data.Bytes(), msg.Data.Len(), s.Theology, pid)
}
func (s *proxyRequest) UpdateRawTarget(i uint32) {
s.rawTarget = i
}
// CallbackBeforeRequest HTTP发起请求处理回调
func (s *proxyRequest) CallbackBeforeRequest() {
@@ -181,6 +184,7 @@ func (s *proxyRequest) CallbackBeforeRequest() {
_serverIP: s.Response.ServerIP,
_localAddress: s.Conn.LocalAddr().String(),
_OutRouterIPFunc: s.SetOutRouterIP,
updateRawTarget: s.UpdateRawTarget,
}
s.Global.scriptHTTPCall(m)
s.TlsConfig = m._tls
@@ -249,6 +253,7 @@ func (s *proxyRequest) CallbackBeforeResponse() {
_serverIP: s.Response.ServerIP,
_localAddress: s.Conn.LocalAddr().String(),
_OutRouterIPFunc: s.SetOutRouterIP,
updateRawTarget: s.UpdateRawTarget,
}
s.Global.scriptHTTPCall(m)
s.Response.Response = m._response
@@ -351,6 +356,7 @@ func (s *proxyRequest) CallbackError(err string) {
_serverIP: s.Response.ServerIP,
_localAddress: s.Conn.LocalAddr().String(),
_OutRouterIPFunc: s.SetOutRouterIP,
updateRawTarget: s.UpdateRawTarget,
}
s.Global.scriptHTTPCall(m)
if s._Display == false {

View File

@@ -34,6 +34,7 @@ type httpConn struct {
_isRandomCipherSuites bool
_localAddress string
_OutRouterIPFunc func(string) bool
updateRawTarget func(int uint32)
}
func (k *httpConn) SetOutRouterIP(way string) bool {
@@ -81,6 +82,9 @@ func (h *httpConn) UpdateURL(NewUrl string) bool {
h._request.URL = a
h._request.Host = h._request.URL.Host
h._request.RequestURI = ""
if h.updateRawTarget != nil {
h.updateRawTarget(0)
}
h._request.SetContext(public.Connect_Raw_Address, func() string { return a.Host })
if h._request.Header.Get("host") != "" {
h._request.Header.Set("host", h._request.URL.Host)

View File

@@ -210,6 +210,7 @@ type proxyRequest struct {
_isRandomCipherSuites bool
_SocksUser string
outRouterIP *net.TCPAddr
rawTarget uint32
}
var sUser = make(map[int]string)
@@ -1016,6 +1017,27 @@ func (s *proxyRequest) doRequest() error {
var err error
var Close func()
do, n, err, Close = httpClient.Do(s.Request, s.Proxy, false, s.TlsConfig, s.SendTimeout, s.getTLSValues, s.Conn)
if err == nil && do != nil {
if s.rawTarget != 0 {
whoisLock.Lock()
obj := httpTypeMap[s.rawTarget]
if obj != nil {
if obj._type == whoisUndefined {
obj._time = time.Now()
if s.Request.URL.Scheme != "https" {
obj._type = whoisNoHTTPS
} else {
if do.ProtoMajor == 2 {
obj._type = whoisHTTPS2
} else {
obj._type = whoisHTTPS1
}
}
}
}
whoisLock.Unlock()
}
}
s.Response.Conn = n
ip, _ := s.Request.Context().Value(public.SunnyNetServerIpTags).(string)
if ip != "" {
@@ -1093,9 +1115,11 @@ func (s *proxyRequest) https() {
if res == whoisUndefined {
res, cert = ClientRequestIsHttps(s.Global, s.Target.String(), serverName)
}
if res == whoisNoHTTPS || res == whoisUndefined {
if res == whoisNoHTTPS {
_ = s.RwObj.Close()
return
} else if res == whoisUndefined {
s.rawTarget = public.SumHashCode(s.Target.String())
}
if res == whoisHTTPS1 {
tlsConfig.NextProtos = public.HTTP1NextProtos
@@ -1720,6 +1744,7 @@ func (s *proxyRequest) CompleteRequest(req *http.Request) {
}
//验证处理是否websocket请求,如果是直接处理
if s.handleWss() {
return
}
//为了保证在请求完成时,还能获取到到请求的提交信息,先备份数据
@@ -2677,6 +2702,7 @@ func (s *proxyRequest) clone() *proxyRequest {
NoRepairHttp: s.NoRepairHttp,
defaultScheme: s.defaultScheme,
SendTimeout: s.SendTimeout,
rawTarget: s.rawTarget,
}
if s.outRouterIP != nil {
req.outRouterIP = &net.TCPAddr{IP: s.outRouterIP.IP}

View File

@@ -4,12 +4,51 @@
package CrossCompiled
import (
"fmt"
"github.com/qtgolang/SunnyNet/src/ProcessDrv/Info"
"os"
"os/exec"
"strconv"
"strings"
)
func runBatchWithPrivileges_lod(commands []string) (error, string) {
// 用 && 拼接多个命令(注意引号转义)
joined := strings.Join(commands, " && ")
escaped := strings.ReplaceAll(joined, `"`, `\"`)
script := fmt.Sprintf(`do shell script "%s" with administrator privileges`, escaped)
out, err := exec.Command("osascript", "-e", script).CombinedOutput()
s := string(out)
return err, s
}
func runBatchWithPrivileges(commands []string) (error, string) {
prompt := "SunnyNetV4-请求操作系统代理"
// 拼接多条命令
joined := strings.Join(commands, " && ")
// 获取用户目录
homeDir, _ := os.UserHomeDir()
appSupportDir := homeDir + "/Library/Application Support/SunnyNetProV4"
os.MkdirAll(appSupportDir, 0755)
// 写入临时脚本
bashPath := appSupportDir + "/run_as_admin.sh"
bashScript := "#!/bin/bash\n" + joined + "\n"
err := os.WriteFile(bashPath, []byte(bashScript), 0755)
if err != nil {
return fmt.Errorf("写入脚本失败: %v", err), ""
}
// 构造 AppleScript 脚本(自定义提示语)
escapedPath := strings.ReplaceAll(bashPath, `"`, `\"`)
escapedPrompt := strings.ReplaceAll(prompt, `"`, `\"`)
appleScript := fmt.Sprintf(`do shell script "bash \"%s\"" with prompt "%s" with administrator privileges`, escapedPath, escapedPrompt)
// 执行 osascript
out, err := exec.Command("osascript", "-e", appleScript).CombinedOutput()
return err, string(out)
}
type netInterface struct{}
// 获取所有网络接口名称
@@ -37,21 +76,14 @@ func (c *netInterface) SetProxy(proxyHost string, Port int) bool {
if len(AllInterfaceName) < 1 {
return false
}
proxyPort := strconv.Itoa(Port)
var array []string
for _, interfaceName := range AllInterfaceName {
// 设置 HTTP 代理
setWebProxyCmd := exec.Command("networksetup", "-setwebproxy", interfaceName, proxyHost, proxyPort)
_ = setWebProxyCmd.Run()
// 设置 HTTPS 代理
setSecureWebProxyCmd := exec.Command("networksetup", "-setsecurewebproxy", interfaceName, proxyHost, proxyPort)
_ = setSecureWebProxyCmd.Run()
// 设置 SOCKS 代理
setSocksProxyCmd := exec.Command("networksetup", "-setsocksfirewallproxy", interfaceName, proxyHost, proxyPort)
_ = setSocksProxyCmd.Run()
array = append(array, fmt.Sprintf("networksetup -setwebproxy \"%s\" %s %d", interfaceName, proxyHost, Port))
array = append(array, fmt.Sprintf("networksetup -setsecurewebproxy \"%s\" %s %d", interfaceName, proxyHost, Port))
array = append(array, fmt.Sprintf("networksetup -setsocksfirewallproxy \"%s\" %s %d", interfaceName, proxyHost, Port))
}
return true
err, _ := runBatchWithPrivileges(array)
return err == nil
}
func (c *netInterface) DisableProxy() bool {
@@ -59,18 +91,14 @@ func (c *netInterface) DisableProxy() bool {
if len(AllInterfaceName) < 1 {
return false
}
var array []string
for _, interfaceName := range AllInterfaceName {
// 关闭 HTTP 代理
disableWebProxyCmd := exec.Command("networksetup", "-setwebproxystate", interfaceName, "off")
_ = disableWebProxyCmd.Run()
// 关闭 HTTPS 代理
disableSecureWebProxyCmd := exec.Command("networksetup", "-setsecurewebproxystate", interfaceName, "off")
_ = disableSecureWebProxyCmd.Run()
// 关闭 SOCKS 代理
disableSocksProxyCmd := exec.Command("networksetup", "-setsocksfirewallproxystate", interfaceName, "off")
_ = disableSocksProxyCmd.Run()
array = append(array, fmt.Sprintf("networksetup -setwebproxystate \"%s\" off", interfaceName))
array = append(array, fmt.Sprintf("networksetup -setsecurewebproxystate \"%s\" off", interfaceName))
array = append(array, fmt.Sprintf("networksetup -setsocksfirewallproxystate \"%s\" off", interfaceName))
}
return true
err, _ := runBatchWithPrivileges(array)
return err == nil
}
func SetIeProxy(Off bool, Port int) bool {

View File

@@ -200,9 +200,9 @@ func (p *Proxy) Dial(network, addr string, OutRouterIP *net.TCPAddr) (net.Conn,
us = "Authorization: Basic " + ns + "\r\n"
//部分HTTP代理 需要 Proxy-Authorization
us += "Proxy-Authorization: Basic " + ns + "\r\n"
//部分HTTP代理 需要 Proxy-Connection
us += "Proxy-Connection: Keep-Alive\r\n"
}
//部分HTTP代理 需要 Proxy-Connection
us += "Proxy-Connection: Keep-Alive\r\n"
_, e = conn.Write([]byte("CONNECT " + addr + " HTTP/1.1\r\nHost: " + addr + "\r\n" + us + "\r\n"))
if e != nil {
return nil, e

View File

@@ -16,6 +16,24 @@ import (
"unsafe"
)
var _mustHTTP11 = make(map[uint32]*time.Time)
var _mustHTTP11_lock sync.Mutex
func init() {
go func() {
for {
time.Sleep(time.Minute)
_mustHTTP11_lock.Lock()
Nox := time.Now()
for key, value := range _mustHTTP11 {
if Nox.Sub(*value) > time.Minute*3 {
delete(_mustHTTP11, key)
}
}
_mustHTTP11_lock.Unlock()
}
}()
}
func Do(req *http.Request, RequestProxy *SunnyProxy.Proxy, CheckRedirect bool, config *tls.Config, outTime time.Duration, GetTLSValues func() []uint16, MConn net.Conn) (Response *http.Response, Conn net.Conn, err error, Close func()) {
if req.ProtoMajor == 2 {
Method := req.Method
@@ -50,6 +68,14 @@ func Do(req *http.Request, RequestProxy *SunnyProxy.Proxy, CheckRedirect bool, c
}
cfg.InsecureSkipVerify = true
}
_hashCode := public.SumHashCode(req.Host)
_mustHTTP11_lock.Lock()
if _mustHTTP11[_hashCode] != nil {
cfg.NextProtos = public.HTTP1NextProtos
x := time.Now()
_mustHTTP11[_hashCode] = &x
}
_mustHTTP11_lock.Unlock()
handshakeCount := 0
for {
if cfg != nil && GetTLSValues != nil {
@@ -63,7 +89,20 @@ func Do(req *http.Request, RequestProxy *SunnyProxy.Proxy, CheckRedirect bool, c
if Conn != nil {
_ = Conn.Close()
}
ers := err.Error()
if strings.Contains(ers, "stream error: stream ID") && len(cfg.NextProtos) == 2 {
cfg.NextProtos = public.HTTP1NextProtos
_mustHTTP11_lock.Lock()
x := time.Now()
_mustHTTP11[_hashCode] = &x
_mustHTTP11_lock.Unlock()
continue
}
//Get "https://www.zjwubei.com:520/": stream error: stream ID 1; CANCEL; received from peer
if strings.Contains(ers, "handshake") || strings.Contains(ers, "connection") || strings.Contains(ers, "EOF") {
handshakeCount++
if handshakeCount > 10 {
@@ -156,18 +195,11 @@ var httpClientMap map[uint32]clientList
type clientList map[uintptr]*clientPart
func hashCode(s string) uint32 {
var hash int32 = 0
for _, ch := range s {
hash = 31*hash + ch
}
return uint32(hash)
}
func httpClientGet(req *http.Request, Proxy *SunnyProxy.Proxy, cfg *tls.Config, timeout time.Duration) *clientPart {
httpLock.Lock()
defer httpLock.Unlock()
outRouterIP, _ := req.Context().Value(public.OutRouterIPKey).(*net.TCPAddr)
s := ""
s := dns.GetDnsServer()
if outRouterIP != nil {
s += outRouterIP.String() + "|"
} else {
@@ -183,7 +215,7 @@ func httpClientGet(req *http.Request, Proxy *SunnyProxy.Proxy, cfg *tls.Config,
}
s += strings.Join(cfg.NextProtos, "-")
}
hash := hashCode(s)
hash := public.SumHashCode(s)
if clients, ok := httpClientMap[hash]; ok {
if len(clients) > 0 {
for key, client := range clients {

View File

@@ -16,7 +16,7 @@ import (
"time"
)
const SunnyVersion = "2025-04-24"
const SunnyVersion = "2025-04-26"
const Information = `
------------------------------------------------------
欢迎使用 SunnyNet 网络中间件 - V` + SunnyVersion + `

View File

@@ -571,5 +571,12 @@ func IsLocalIP(ipStr string) (bool, net.IP) {
return false, nil
}
func SumHashCode(s string) uint32 {
var hash int32 = 0
for _, ch := range s {
hash = 31*hash + ch
}
return uint32(hash)
}
var RouterIPInspect = SunnyProxy.RouterIPInspect