Skip to content

Commit

Permalink
2024-06-03
Browse files Browse the repository at this point in the history
新增TLS指纹随机
  • Loading branch information
qtgolang committed Jun 3, 2024
1 parent fb8d0e2 commit 208be61
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 31 deletions.
61 changes: 45 additions & 16 deletions Api/OtherCommands.go
Original file line number Diff line number Diff line change
@@ -1,30 +1,59 @@
package Api

import "github.com/qtgolang/SunnyNet/SunnyNet"
import (
"github.com/qtgolang/SunnyNet/SunnyNet"
"github.com/qtgolang/SunnyNet/public"
"strconv"
)

const (
//OtherCommandDisable_TCP 禁用TCP 返回0失败 返回1成功
//OtherCommandDisable_TCP 禁用TCP 返回0失败 返回1成功 [参数1 SunnyNetContext 参数2 是否禁用]
OtherCommandDisable_TCP = uintptr(1001)
// OtherCommandRandomTLSSet 是否使用随机TLS指纹 注意如果关闭后将会同时取消设置的固定TLS指纹[参数1 SunnyNetContext 参数2 是否打开]
OtherCommandRandomTLSSet = uintptr(1002)
//OtherCommandRandomFixedTLSSet 使用固定的TLS指纹 [参数1 SunnyNetContext 参数2 RandomTLSList]
OtherCommandRandomFixedTLSSet = uintptr(1003)
//OtherCommandRandomFixedTLSGet 是否使用固定的TLS指纹 [参数1 SunnyNetContext] 返回 String
OtherCommandRandomFixedTLSGet = uintptr(1004)
)

func OtherCommands(Cmd uintptr, Command ...uintptr) uintptr {
switch Cmd {
case OtherCommandDisable_TCP:
{
if len(Command) < 1 {
return 0
}
SunnyContext := int(Command[0])
disable := int(Command[1]) == 1
SunnyNet.SunnyStorageLock.Lock()
w := SunnyNet.SunnyStorage[SunnyContext]
SunnyNet.SunnyStorageLock.Unlock()
if w == nil {
return 0
case OtherCommandDisable_TCP, OtherCommandRandomTLSSet, OtherCommandRandomFixedTLSSet, OtherCommandRandomFixedTLSGet:
if len(Command) < 1 {
return 0
}
SunnyContext := int(Command[0])
state := int(Command[1]) == 1
SunnyNet.SunnyStorageLock.Lock()
w := SunnyNet.SunnyStorage[SunnyContext]
SunnyNet.SunnyStorageLock.Unlock()
if w == nil {
return 0
}
switch Cmd {
case OtherCommandDisable_TCP:
w.DisableTCP(state)
return 1
case OtherCommandRandomTLSSet:
w.SetRandomTLS(state)
return 1
case OtherCommandRandomFixedTLSSet:
w.SetRandomFixedTLS(string(public.CStringToBytes(Command[1], int(Command[2]))))
return 1
case OtherCommandRandomFixedTLSGet:
r := w.GetTLSTestValues()
s := ""
for _, v := range r {
if s == "" {
s = strconv.Itoa(int(v))
} else {
s += "," + strconv.Itoa(int(v))
}
}
w.DisableTCP(disable)
return public.PointerPtr(s)
}
return 1
return 0

}
return 0
Expand Down
Binary file modified BuildLibrary/Library/Android/arm64-v8a/libSunny.so
Binary file not shown.
Binary file modified BuildLibrary/Library/Android/armeabi-v7a/libSunny.so
Binary file not shown.
Binary file modified BuildLibrary/Library/Android/x86/libSunny.so
Binary file not shown.
Binary file modified BuildLibrary/Library/Linux/amd64/Sunny.so
Binary file not shown.
Binary file modified BuildLibrary/Library/Linux/x86/Sunny.so
Binary file not shown.
Binary file modified BuildLibrary/Library/windows/x32/Sunny.dll
Binary file not shown.
Binary file modified BuildLibrary/Library/windows/x64/Sunny64.dll
Binary file not shown.
110 changes: 98 additions & 12 deletions SunnyNet/SunnyNet.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/qtgolang/SunnyNet/src/websocket"
"io"
"io/ioutil"
mrand "math/rand"
"net"
"net/http"
"net/url"
Expand Down Expand Up @@ -187,8 +188,8 @@ func (s *ProxyRequest) setSocket5User(user string) {
sL.Unlock()
}
func (s *ProxyRequest) IsMustTcpRules(Host string) bool {
s.Global.connListLock.Lock()
defer s.Global.connListLock.Unlock()
s.Global.lock.Lock()
defer s.Global.lock.Unlock()
if s.Global.mustTcpRegexp == nil {
return false
}
Expand Down Expand Up @@ -629,6 +630,10 @@ func (s *ProxyRequest) MustTcpProcessing(aheadData []byte, Tag string) {
}
fig := &tls.Config{Certificates: []tls.Certificate{*certificate}, ServerName: HttpCertificate.ParsingHost(s.Target.String())}
fig.InsecureSkipVerify = true
obj := s.Global.GetTLSValues()
if obj != nil {
fig.CipherSuites = obj
}
tlsConn := tls.Client(RemoteTCP, fig)
err = tlsConn.Handshake()
RemoteTCP = tlsConn
Expand Down Expand Up @@ -878,7 +883,12 @@ func (s *ProxyRequest) transparentProcessing() {
//将数据全部取出,稍后重新放进去
_bytes, _ := s.RwObj.Peek(s.RwObj.Reader.Buffered())
//升级到TLS客户端
T := tls.Client(s.Conn, &tls.Config{InsecureSkipVerify: true})
fig := &tls.Config{InsecureSkipVerify: true}
obj := s.Global.GetTLSValues()
if obj != nil {
fig.CipherSuites = obj
}
T := tls.Client(s.Conn, fig)
//将数据重新写进去
T.Reset(_bytes)
//进行握手处理
Expand Down Expand Up @@ -1134,6 +1144,7 @@ func (s *ProxyRequest) doRequest() error {
if s.WinHttp == nil {
s.WinHttp = GoWinHttp.NewGoWinHttp()
}
s.WinHttp.GetTLSValues = s.Global.GetTLSValues
s.WinHttp.SetTlsConfig(cfg)
s.WinHttp.SetProxy(s.Proxy)
A, B := s.WinHttp.Do(s.Request)
Expand Down Expand Up @@ -1299,6 +1310,10 @@ func (s *ProxyRequest) handleWss() bool {
}
cfg.ServerName = HttpCertificate.ParsingHost(s.Request.URL.Host)
cfg.InsecureSkipVerify = true
obj := s.Global.GetTLSValues()
if obj != nil {
cfg.CipherSuites = obj
}
dialer = &websocket.Dialer{TLSClientConfig: cfg}
} else {
dialer = &websocket.Dialer{}
Expand Down Expand Up @@ -1713,7 +1728,7 @@ type Sunny struct {
tcpSocket *net.Listener //TcpSocket服务器
udpSocket *net.UDPConn //UdpSocket服务器
connList map[int64]net.Conn //会话连接客户端、停止服务器时可以全部关闭
connListLock sync.Mutex //会话连接互斥锁
lock sync.Mutex //会话连接互斥锁
socket5VerifyUser bool //S5代理是否需要验证账号密码
socket5VerifyUserList map[string]string //S5代理需要验证的账号密码列表
socket5VerifyUserLock sync.Mutex //S5代理验证时的锁
Expand All @@ -1730,6 +1745,9 @@ type Sunny struct {
proxyRegexp *regexp.Regexp //上游代理使用规则
mustTcpRegexp *regexp.Regexp //强制走TCP规则,如果 isMustTcp 打开状态,本功能则无效
isRun bool //是否在运行中
fixedTLS []uint16 //固定的TLS指纹
isRandomTLS bool //是否随机使用TLS指纹
randomTLSValue []uint16 //tls 指纹选项合集
SunnyContext int
}

Expand All @@ -1748,17 +1766,85 @@ func NewSunny() *Sunny {
SunnyContext := NewMessageId()
a, _ := regexp.Compile("ALL")
s := &Sunny{SunnyContext: SunnyContext, certCache: NewCache(), connList: make(map[int64]net.Conn), socket5VerifyUserList: make(map[string]string), proxy: &GoWinHttp.Proxy{}, proxyRegexp: a}
s.randomTLSValue = make([]uint16, public.RandomTLSValueArrayLen)
copy(s.randomTLSValue, public.RandomTLSValueArray)
s.SetCert(defaultManager)
SunnyStorageLock.Lock()
SunnyStorage[s.SunnyContext] = s
SunnyStorageLock.Unlock()
return s
}

// SetRandomTLS 是否使用随机TLS指纹
func (s *Sunny) SetRandomTLS(open bool) {
if s == nil {
return
}
s.lock.Lock()
s.isRandomTLS = open
s.fixedTLS = nil
s.lock.Unlock()
}

// GetTLSValues 获取固定的TLS指纹列表或随机TLS指纹列表,如果未开启使用随机TLS指纹,并且未设置固定TLS指纹,则返回nil
func (s *Sunny) GetTLSValues() []uint16 {
if s == nil {
return nil
}
s.lock.Lock()
if !s.isRandomTLS {
if len(s.fixedTLS) > 0 {
s.lock.Unlock()
return s.fixedTLS
}
s.lock.Unlock()
return nil
}
n := mrand.Intn(public.RandomTLSValueArrayLen) + 1
for i := public.RandomTLSValueArrayLen - 1; i > 0; i-- {
j := mrand.Intn(i + 1)
s.randomTLSValue[i], s.randomTLSValue[j] = s.randomTLSValue[j], s.randomTLSValue[i]
}
shuffledArray := make([]uint16, n)
copy(shuffledArray, s.randomTLSValue[:n])
s.lock.Unlock()
return shuffledArray
}

// GetTLSTestValues 随机生成一个TLS指纹列表
func (s *Sunny) GetTLSTestValues() []uint16 {
if s == nil {
return nil
}
s.lock.Lock()
n := mrand.Intn(public.RandomTLSValueArrayLen) + 1
for i := public.RandomTLSValueArrayLen - 1; i > 0; i-- {
j := mrand.Intn(i + 1)
s.randomTLSValue[i], s.randomTLSValue[j] = s.randomTLSValue[j], s.randomTLSValue[i]
}
shuffledArray := make([]uint16, n)
copy(shuffledArray, s.randomTLSValue[:n])
s.lock.Unlock()
return shuffledArray
}

// SetRandomFixedTLS 是否使用固定的TLS指纹 请注意这个函数是一个全局函数
func (s *Sunny) SetRandomFixedTLS(value string) {
m := strings.Split(value, ",")
array := make([]uint16, 0)
for _, v := range m {
zm, _ := strconv.Atoi(strings.TrimSpace(v))
array = append(array, uint16(zm))
}
s.lock.Lock()
s.fixedTLS = array
s.lock.Unlock()
}

// SetMustTcpRegexp 设置强制走TCP规则,如果 打开了全部强制走TCP状态,本功能则无效
func (s *Sunny) SetMustTcpRegexp(RegexpList string) error {
s.connListLock.Lock()
defer s.connListLock.Unlock()
s.lock.Lock()
defer s.lock.Unlock()
r := strings.ReplaceAll("^"+strings.ReplaceAll(RegexpList, " ", "")+"$", "\r", "")
r = strings.ReplaceAll(r, "\t", "")
r = strings.ReplaceAll(r, "\n", ";")
Expand Down Expand Up @@ -2130,15 +2216,15 @@ func (s *Sunny) Close() *Sunny {
if s.udpSocket != nil {
_ = s.udpSocket.Close()
}
s.connListLock.Lock()
s.lock.Lock()
for k, conn := range s.connList {
_ = conn.Close()
delete(s.connList, k)
}
if CrossCompiled.NFapi_SunnyPointer() == uintptr(unsafe.Pointer(s)) {
CrossCompiled.NFapi_ProcessPortInt(0)
}
s.connListLock.Unlock()
s.lock.Unlock()
return s
}

Expand All @@ -2165,18 +2251,18 @@ func (s *Sunny) listenTcpGo() {
func (s *Sunny) handleClientConn(conn net.Conn, tgt *TargetInfo) {
Theoni := atomic.AddInt64(&public.Theology, 1)
//存入会话列表 方便停止时,将所以连接断开
s.connListLock.Lock()
s.lock.Lock()
s.connList[Theoni] = conn
s.connListLock.Unlock()
s.lock.Unlock()
//构造一个请求中间件
req := &ProxyRequest{Global: s, TcpCall: s.tcpCallback, HttpCall: s.httpCallback, wsCall: s.websocketCallback, TcpGoCall: s.goTcpCallback, HttpGoCall: s.goHttpCallback, wsGoCall: s.goWebsocketCallback} //原始请求对象
defer req.delSocket5User()
defer func() {
//当 handleClientConn 函数 即将退出时 从会话列表中删除当前会话
_ = conn.Close()
s.connListLock.Lock()
s.lock.Lock()
delete(s.connList, Theoni)
s.connListLock.Unlock()
s.lock.Unlock()
//当 handleClientConn 函数 即将退出时 销毁 请求中间件 中的一些信息,避免内存泄漏
req.RwObj = nil
req.Conn = nil
Expand Down
10 changes: 9 additions & 1 deletion public/constobj.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ package public

import "C"
import (
"math/rand"
"time"
)

const SunnyVersion = "2024-06-01"
const SunnyVersion = "2024-06-03"

// TCP请求相关
const (
Expand Down Expand Up @@ -113,6 +114,13 @@ const (
Socks5typeIpv6 = uint8(0x04)
)

var RandomTLSValueArray = []uint16{0x0005, 0x000a, 0x002f, 0x0035, 0x003c, 0x009c, 0x009d, 0xc007, 0xc009, 0xc00a, 0xc011, 0xc012, 0xc013, 0xc014, 0xc023, 0xc027, 0xc02f, 0xc02b, 0xc030, 0xc02c, 0xcca8, 0xcca9, 0x1301, 0x1302, 0x1303, 0x5600}
var RandomTLSValueArrayLen = len(RandomTLSValueArray)

func init() {
rand.Seed(time.Now().UnixNano())
}

// Sunny中间件自带默认证书
const (
RootCa = `-----BEGIN CERTIFICATE-----
Expand Down
7 changes: 7 additions & 0 deletions src/GoWinHttp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ type WinHttp struct {
cfg *tls.Config
WinPool *PoolInfo
PoolName string
GetTLSValues func() []uint16
}
type Proxy struct {
S5TypeProxy bool
Expand Down Expand Up @@ -957,6 +958,12 @@ func (w *WinHttp) connect() (_a bool, _b bool, _c *http.Response, _d error) {
if cfg.ServerName == "" {
cfg.ServerName = fHost
}
if w.GetTLSValues != nil {
obj := w.GetTLSValues()
if len(obj) > 0 {
cfg.CipherSuites = obj
}
}
cfg.InsecureSkipVerify = true
tlsConn := tls.Client(w.WinPool.Conn, cfg)
err = tlsConn.Handshake()
Expand Down
6 changes: 4 additions & 2 deletions test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ func Test() {
//s.SetIeProxy(false)
//s.MustTcp(true)
Port := 2024
//s.SetMustTcpRegexp("*.bai
//du.com")
//s.SetMustTcpRegexp("*.baidu.com")
s = s.SetPort(Port).Start()
//开启随机TLS指纹
s.SetRandomTLS(true)

//fmt.Println(s.StartProcess())
// 请注意GoLang调试时候,请不要使用此(ProcessALLName)命令,因为不管开启或关闭,都会将当前所有TCP链接断开一次
// 因为如果不断开的一次的话,已经建立的TCP链接无法抓包。
Expand Down

0 comments on commit 208be61

Please sign in to comment.