mirror of
https://github.com/qtgolang/SunnyNet.git
synced 2026-08-30 22:11:29 -07:00
2025-04-26
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const SunnyVersion = "2025-04-24"
|
||||
const SunnyVersion = "2025-04-26"
|
||||
const Information = `
|
||||
------------------------------------------------------
|
||||
欢迎使用 SunnyNet 网络中间件 - V` + SunnyVersion + `
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user