From 414869fd9635deff8ba5fc5761fa5e40e4f30fa9 Mon Sep 17 00:00:00 2001 From: NNdroid <99177648+NNdroid@users.noreply.github.com> Date: Fri, 14 Jul 2023 18:37:46 +0800 Subject: [PATCH] optimise code. --- common/xcrypto/xcrypto.go | 14 ++++++- h1/conn.go | 11 ------ h1/h1client.go | 10 +++++ h1/h1server.go | 7 +++- h1/httpc_tls.go | 10 +++++ h1/httpd.go | 47 +++------------------- h1/utils.go | 83 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 126 insertions(+), 56 deletions(-) create mode 100644 h1/utils.go diff --git a/common/xcrypto/xcrypto.go b/common/xcrypto/xcrypto.go index d48d22a..4873226 100644 --- a/common/xcrypto/xcrypto.go +++ b/common/xcrypto/xcrypto.go @@ -5,6 +5,7 @@ import ( "crypto/cipher" "crypto/sha1" "crypto/sha256" + "hash/fnv" ) type XCrypto struct { @@ -25,10 +26,21 @@ func (x *XCrypto) LoadKey(key string) { } func (x *XCrypto) LoadNonce(key string) { + n := 2 * 2 * 3 h := sha1.New() h.Write([]byte(key)) b := h.Sum(nil) - x.Nonce = b[:12] + ia := int(String2Int64(key) % int64(len(b)-n)) + x.Nonce = b[ia : ia+n] +} + +func String2Int64(s string) int64 { + h := fnv.New32a() + _, err := h.Write([]byte(s)) + if err != nil { + return 0 + } + return int64(h.Sum32()) } func (x *XCrypto) Init(key string) error { diff --git a/h1/conn.go b/h1/conn.go index 2c9993e..d2b0bf9 100644 --- a/h1/conn.go +++ b/h1/conn.go @@ -3,7 +3,6 @@ package h1 import ( "bytes" "io" - "math/rand" "net" "time" ) @@ -117,13 +116,3 @@ func mkConnAddr(p1 net.Conn, address string) net.Conn { } return p1 } - -const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/-_" - -func randStringBytes(n int) string { - b := make([]byte, n) - for i := range b { - b[i] = letterBytes[rand.Intn(len(letterBytes))] - } - return string(b) -} diff --git a/h1/h1client.go b/h1/h1client.go index cb8fe49..b8ccd79 100644 --- a/h1/h1client.go +++ b/h1/h1client.go @@ -22,6 +22,10 @@ import ( func StartClient(iFace *water.Interface, config config.Config) { log.Println("vtun h1 client started") var cl *Client + tcA := RandomStringByStringNonce(16, config.Key, 123) + tcB := RandomStringByStringNonce(32, config.Key, 456) + tcC := RandomStringByStringNonce(64, config.Key, 789) + ua := RandomUserAgent(config.Key) go tunToH1(config, iFace) for { if config.Protocol == "https" { @@ -29,6 +33,12 @@ func StartClient(iFace *water.Interface, config config.Config) { } else { cl = NewClient(config.ServerAddr) } + cl.TokenCookieA = tcA + cl.TokenCookieB = tcB + cl.TokenCookieC = tcC + cl.Url = "/" + RandomStringByInt64(64, time.Now().UnixMilli()) + cl.Host = "www.microsoft.com" + cl.UserAgent = ua conn, err := cl.Dial() if err != nil { time.Sleep(3 * time.Second) diff --git a/h1/h1server.go b/h1/h1server.go index dc11e41..dfb97b2 100644 --- a/h1/h1server.go +++ b/h1/h1server.go @@ -23,13 +23,16 @@ import ( func StartServer(iFace *water.Interface, config config.Config) { log.Printf("vtun h1 server started on %v", config.LocalAddr) webSrv := NewHandle(netutil.GetDefaultHttpHandleFunc()) + webSrv.TokenCookieA = RandomStringByStringNonce(16, config.Key, 123) + webSrv.TokenCookieB = RandomStringByStringNonce(32, config.Key, 456) + webSrv.TokenCookieC = RandomStringByStringNonce(64, config.Key, 789) http.Handle("/", webSrv) srv := &http.Server{Addr: config.LocalAddr, Handler: nil} go func(srv *http.Server) { var err error if config.Protocol == "https" { tlsConfig := &tls.Config{ - MinVersion: tls.VersionTLS12, + MinVersion: tls.VersionTLS13, CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256}, CipherSuites: []uint16{ tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, @@ -45,7 +48,7 @@ func StartServer(iFace *water.Interface, config config.Config) { } else { err = srv.ListenAndServe() } - if err != ErrServerClose { + if err != http.ErrServerClosed { panic(err) } }(srv) diff --git a/h1/httpc_tls.go b/h1/httpc_tls.go index 1744671..c64a4c8 100644 --- a/h1/httpc_tls.go +++ b/h1/httpc_tls.go @@ -38,6 +38,16 @@ func NewTLSClient(config config.Config) *Client { cl := NewClient(config.ServerAddr) tlsConfig := &tls.Config{ + MinVersion: tls.VersionTLS13, + CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256}, + CipherSuites: []uint16{ + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + }, InsecureSkipVerify: config.TLSInsecureSkipVerify, } diff --git a/h1/httpd.go b/h1/httpd.go index 9deabe2..dbf168e 100644 --- a/h1/httpd.go +++ b/h1/httpd.go @@ -80,9 +80,7 @@ func NewHandle(handler http.Handler) *Server { HttpHandler: handler, TokenTTL: tokenTTL, } - srv.startTokenCleaner() - return srv } @@ -97,9 +95,7 @@ func (srv *Server) StartServer() { if srv.lis == nil { return } - srv.startTokenCleaner() - http.HandleFunc("/", srv.ServeHTTP) go http.Serve(srv.lis, nil) } @@ -122,7 +118,6 @@ func (srv *Server) Addr() net.Addr { func (srv *Server) Close() error { srv.dieLock.Lock() - select { case <-srv.die: srv.dieLock.Unlock() @@ -137,38 +132,28 @@ func (srv *Server) Close() error { } } -// set cookie: TokenCookieA = XXXX -// try get cookie: TokenCookieB = XXXX func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { var cc *state var ok bool var err error var c, ct *http.Cookie - - c, err = r.Cookie(srv.TokenCookieB) // token + c, err = r.Cookie(srv.TokenCookieB) if err != nil { - goto FILE } - - ct, err = r.Cookie(srv.TokenCookieC) // flag + ct, err = r.Cookie(srv.TokenCookieC) if err != nil { - goto FILE } - cc, ok = srv.checkToken(c.Value) if ok { if r.Method == srv.RxMethod || r.Method == srv.TxMethod { - } else { goto FILE } - srv.handleNonWs(w, r, c.Value, ct.Value, cc) return } - FILE: srv.handleBase(w, r) } @@ -176,42 +161,33 @@ FILE: func (srv *Server) handleBase(w http.ResponseWriter, r *http.Request) { header := w.Header() header.Set("Server", srv.HeaderServer) - token := randStringBytes(16) + token := RandomString(16) expiration := time.Now().AddDate(0, 0, 3) cookie := http.Cookie{Name: srv.TokenCookieA, Value: token, Expires: expiration} http.SetCookie(w, &cookie) srv.regToken(token) - srv.HttpHandler.ServeHTTP(w, r) } func (srv *Server) handleWs(w http.ResponseWriter, r *http.Request, token string, flag string, cc *state) { - ip := r.Header.Get("Cf-Connecting-Ip") - hj, ok := w.(http.Hijacker) if !ok { return } - conn, bufRW, err := hj.Hijack() if err != nil { return } - bufRW.Flush() - conn.Write([]byte("HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: " + token + "\r\n\r\n")) - cc.mx.Lock() defer cc.mx.Unlock() if r.Method == srv.RxMethod && flag == srv.RxFlag { - srv.rmToken(token) srv.accepts <- mkConnAddr(conn, ip) } - } func (srv *Server) handleNonWs(w http.ResponseWriter, r *http.Request, token string, flag string, cc *state) { @@ -224,19 +200,15 @@ func (srv *Server) handleNonWs(w http.ResponseWriter, r *http.Request, token str header.Set("Cache-Control", "private, no-store, no-cache, max-age=0") header.Set("Content-Encoding", "gzip") flusher.Flush() - hj, ok := w.(http.Hijacker) if !ok { return } - conn, bufRW, err := hj.Hijack() if err != nil { return } - bufRW.Flush() - cc.mx.Lock() defer cc.mx.Unlock() if r.Method == srv.RxMethod && flag == srv.RxFlag { @@ -254,25 +226,22 @@ func (srv *Server) handleNonWs(w http.ResponseWriter, r *http.Request, token str cc.bufR.Reader.Read(buf[:n]) srv.accepts <- mkConn(cc.connR, cc.connW, buf[:n]) } - } func (srv *Server) regToken(token string) { srv.mx.Lock() defer srv.mx.Unlock() - _, ok := srv.states[token] if ok { - } srv.states[token] = &state{ ttl: time.Now().Add(srv.TokenTTL), } } + func (srv *Server) checkToken(token string) (*state, bool) { srv.mx.Lock() defer srv.mx.Unlock() - c, ok := srv.states[token] if !ok { return nil, false @@ -283,17 +252,15 @@ func (srv *Server) checkToken(token string) (*state, bool) { } return c, true } + func (srv *Server) rmToken(token string) { srv.mx.Lock() defer srv.mx.Unlock() - _, ok := srv.states[token] if !ok { return } - delete(srv.states, token) - return } @@ -306,9 +273,7 @@ func (srv *Server) tokenCleaner() { return case <-ticker.C: } - list := make([]*state, 0) - srv.mx.Lock() for idx, c := range srv.states { if time.Now().After(c.ttl) { @@ -318,8 +283,6 @@ func (srv *Server) tokenCleaner() { } } srv.mx.Unlock() - - // check and close half open connection for _, cc := range list { cc.mx.Lock() if cc.connR == nil && cc.connW != nil { diff --git a/h1/utils.go b/h1/utils.go new file mode 100644 index 0000000..5716f03 --- /dev/null +++ b/h1/utils.go @@ -0,0 +1,83 @@ +package h1 + +import ( + "hash/fnv" + "math/rand" +) + +var letter = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") + +func RandomString(n int) string { + b := make([]rune, n) + for i := range b { + b[i] = letter[rand.Intn(len(letter))] + } + return string(b) +} + +func RandomStringByInt64(n int, seed int64) string { + r := rand.New(rand.NewSource(seed)) + b := make([]rune, n) + for i := range b { + b[i] = letter[r.Intn(len(letter))] + } + return string(b) +} + +func String2Int64(s string) int64 { + h := fnv.New32a() + _, err := h.Write([]byte(s)) + if err != nil { + return 0 + } + return int64(h.Sum32()) +} + +func RandomStringByStringNonce(n int, seed string, nonce int64) string { + return RandomStringByInt64(n, String2Int64(seed)*nonce) +} + +func RandomStringByString(n int, seed string) string { + return RandomStringByInt64(n, String2Int64(seed)) +} + +var userAgentList = []string{ + "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;", + "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv,2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (Windows NT 6.1; rv,2.0.1) Gecko/20100101 Firefox/4.0.1", + "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11", + "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11", + "Mozilla/5.0 (Macintosh; Intel Mac OS X…TML, like Gecko) Chrome/17.0.963.56 Safari/535.11", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS….50 (KHTML, like Gecko) Version/5.1 Safari/534.50", + "Mozilla/5.0 (Windows; U; Windows NT 6.1….50 (KHTML, like Gecko) Version/5.1 Safari/534.50", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)", + "Mozilla/4.0 (compatible; MSIE 7.0; Win…etaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4… Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5", + "Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3… Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5", + "Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like… Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5", + "Mozilla/5.0 (Linux; U; Android 2.3.7; …HTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "MQQBrowser/26 Mozilla/5.0 (Linux; U; A…HTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Opera/9.80 (Android 2.3.4; Linux; Oper…107180945; U; en-GB) Presto/2.8.149 Version/11.10", + "Mozilla/5.0 (Linux; U; Android 3.0; en….13 (KHTML, like Gecko) Version/4.0 Safari/534.13", + "Mozilla/5.0 (BlackBerry; U; BlackBerry…ike Gecko) Version/6.0.0.337 Mobile Safari/534.1+", + "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3…ecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0", + "Mozilla/5.0 (SymbianOS/9.4; Series60/5…ebKit/525 (KHTML, like Gecko) BrowserNG/7.1.18124", + "Mozilla/5.0 (compatible; MSIE 9.0; Win…ne OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)", + "UCWEB7.0.2.37/28/999", + "NOKIA5700/ UCWEB7.0.2.37/28/999", + "Openwave/ UCWEB7.0.2.37/28/999", + "Mozilla/4.0 (compatible; MSIE 6.0; ) Opera/UCWEB7.0.2.37/28/999", +} + +func RandomUserAgent(seed string) string { + return userAgentList[rand.New(rand.NewSource(String2Int64(seed))).Intn(len(userAgentList))] +}