diff --git a/CHANGELOG.md b/CHANGELOG.md index 4032cfa..2f886b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 1.3.5 + +- Add VT color support for Windows +- Fix a bug where UDP did not work when using only port in SOCKS5 listen address (e.g. ":1080") +- Fix a bug in handling SOCKS5 UDP packets with domain address +- Updated quic-go to v0.34.0 + ## 1.3.4 - Eliminate unnecessary DNS lookups when using SOCKS5 outbound with ACL disabled @@ -57,7 +64,8 @@ ## 1.1.0 -- Super major CPU performance improvements (~30% to several times faster, depending on the circumstances) by optimizing several data structures in quic-go (changes upstreamed) +- Super major CPU performance improvements (~30% to several times faster, depending on the circumstances) by optimizing + several data structures in quic-go (changes upstreamed) ## 1.0.5 diff --git a/app/auth/external.go b/app/auth/external.go index 768e331..62843ce 100644 --- a/app/auth/external.go +++ b/app/auth/external.go @@ -17,7 +17,7 @@ type CmdAuthProvider struct { Cmd string } -func (p *CmdAuthProvider) Auth(addr net.Addr, auth []byte, sSend uint64, sRecv uint64) (bool, string) { +func (p *CmdAuthProvider) Auth(addr net.Addr, auth []byte, sSend, sRecv uint64) (bool, string) { cmd := exec.Command(p.Cmd, addr.String(), string(auth), strconv.Itoa(int(sSend)), strconv.Itoa(int(sRecv))) out, err := cmd.Output() if err != nil { @@ -51,7 +51,7 @@ type authResp struct { Msg string `json:"msg"` } -func (p *HTTPAuthProvider) Auth(addr net.Addr, auth []byte, sSend uint64, sRecv uint64) (bool, string) { +func (p *HTTPAuthProvider) Auth(addr net.Addr, auth []byte, sSend, sRecv uint64) (bool, string) { jbs, err := json.Marshal(&authReq{ Addr: addr.String(), Payload: auth, diff --git a/app/auth/funcs.go b/app/auth/funcs.go index 63d3f50..cfe296e 100644 --- a/app/auth/funcs.go +++ b/app/auth/funcs.go @@ -24,7 +24,7 @@ func PasswordAuthFunc(rawMsg json5.RawMessage) (cs.ConnectFunc, error) { // yes it is pwds = []string{pwdConfig["password"]} } - return func(addr net.Addr, auth []byte, sSend uint64, sRecv uint64) (bool, string) { + return func(addr net.Addr, auth []byte, sSend, sRecv uint64) (bool, string) { for _, pwd := range pwds { if string(auth) == pwd { return true, "Welcome" diff --git a/app/cmd/acme.go b/app/cmd/acme.go index 9b2a26a..88784e6 100644 --- a/app/cmd/acme.go +++ b/app/cmd/acme.go @@ -12,8 +12,8 @@ import ( "github.com/caddyserver/certmagic" ) -func acmeTLSConfig(domains []string, email string, disableHTTP bool, disableTLSALPN bool, - altHTTPPort int, altTLSALPNPort int, +func acmeTLSConfig(domains []string, email string, disableHTTP, disableTLSALPN bool, + altHTTPPort, altTLSALPNPort int, ) (*tls.Config, error) { cfg := &certmagic.Config{ RenewalWindowRatio: certmagic.DefaultRenewalWindowRatio, diff --git a/app/cmd/main.go b/app/cmd/main.go index 36ef82c..33a33bf 100644 --- a/app/cmd/main.go +++ b/app/cmd/main.go @@ -157,6 +157,8 @@ func fakeFlags() { } func init() { + openWinVT() + // compatible with old flag format fakeFlags() diff --git a/app/cmd/server.go b/app/cmd/server.go index c6909d3..9612cfc 100644 --- a/app/cmd/server.go +++ b/app/cmd/server.go @@ -99,7 +99,7 @@ func server(config *serverConfig) { logrus.Warn("Neither authentication nor obfuscation is turned on. " + "Your server could be used by anyone! Are you sure this is what you want?") } - authFunc = func(addr net.Addr, auth []byte, sSend uint64, sRecv uint64) (bool, string) { + authFunc = func(addr net.Addr, auth []byte, sSend, sRecv uint64) (bool, string) { return true, "Welcome" } case "password", "passwords": @@ -123,7 +123,7 @@ func server(config *serverConfig) { default: logrus.WithField("mode", config.Auth.Mode).Fatal("Unsupported authentication mode") } - connectFunc := func(addr net.Addr, auth []byte, sSend uint64, sRecv uint64) (bool, string) { + connectFunc := func(addr net.Addr, auth []byte, sSend, sRecv uint64) (bool, string) { ok, msg := authFunc(addr, auth, sSend, sRecv) if !ok { logrus.WithFields(logrus.Fields{ diff --git a/app/cmd/winvt.go b/app/cmd/winvt.go new file mode 100644 index 0000000..a0eafad --- /dev/null +++ b/app/cmd/winvt.go @@ -0,0 +1,22 @@ +//go:build windows +// +build windows + +package main + +import ( + "os" + + "golang.org/x/sys/windows" +) + +// Add console VT color mode +func openWinVT() { + stdout := windows.Handle(os.Stdout.Fd()) + + var mode uint32 + windows.GetConsoleMode(stdout, &mode) + + mode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING // Add VT Color Support + + windows.SetConsoleMode(stdout, mode) +} diff --git a/app/cmd/winvt_stub.go b/app/cmd/winvt_stub.go new file mode 100644 index 0000000..91c4545 --- /dev/null +++ b/app/cmd/winvt_stub.go @@ -0,0 +1,7 @@ +//go:build !windows +// +build !windows + +package main + +func openWinVT() { +} diff --git a/app/redirect/getsockopt_linux.go b/app/redirect/getsockopt_linux.go index 33c8cf4..b84593e 100644 --- a/app/redirect/getsockopt_linux.go +++ b/app/redirect/getsockopt_linux.go @@ -8,7 +8,7 @@ import ( "unsafe" ) -func getsockopt(s uintptr, level uintptr, name uintptr, val unsafe.Pointer, vallen *uint32) (err error) { +func getsockopt(s, level, name uintptr, val unsafe.Pointer, vallen *uint32) (err error) { _, _, e := syscall.Syscall6(syscall.SYS_GETSOCKOPT, s, level, name, uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) if e != 0 { err = e diff --git a/app/redirect/getsockopt_linux_386.go b/app/redirect/getsockopt_linux_386.go index de930ec..4adefce 100644 --- a/app/redirect/getsockopt_linux_386.go +++ b/app/redirect/getsockopt_linux_386.go @@ -13,7 +13,7 @@ const ( // we have to call syscall.socketcall with this trick. func syscall_socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err syscall.Errno) -func getsockopt(s uintptr, level uintptr, name uintptr, val unsafe.Pointer, vallen *uint32) (err error) { +func getsockopt(s, level, name uintptr, val unsafe.Pointer, vallen *uint32) (err error) { _, e := syscall_socketcall(SYS_GETSOCKOPT, s, level, name, uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) if e != 0 { err = e diff --git a/app/socks5/server.go b/app/socks5/server.go index 58255d8..11cc7bc 100644 --- a/app/socks5/server.go +++ b/app/socks5/server.go @@ -254,9 +254,11 @@ func (s *Server) handleUDP(c *net.TCPConn, r *socks5.Request) error { s.UDPErrorFunc(c.RemoteAddr(), closeErr) }() // Start local UDP server + // Bind to the same address that the incoming TCP connection is sending to udpConn, err := net.ListenUDP("udp", &net.UDPAddr{ - IP: s.TCPAddr.IP, - Zone: s.TCPAddr.Zone, + IP: c.LocalAddr().(*net.TCPAddr).IP, + Zone: c.LocalAddr().(*net.TCPAddr).Zone, + Port: 0, // Random port }) if err != nil { _ = sendReply(c, socks5.RepServerFailure) @@ -320,7 +322,7 @@ func (s *Server) handleUDP(c *net.TCPConn, r *socks5.Request) error { return nil } -func (s *Server) udpServer(clientConn *net.UDPConn, localRelayConn *net.UDPConn, hyUDP cs.HyUDPConn) { +func (s *Server) udpServer(clientConn, localRelayConn *net.UDPConn, hyUDP cs.HyUDPConn) { var clientAddr *net.UDPAddr buf := make([]byte, udpBufferSize) // Local to remote @@ -348,6 +350,9 @@ func (s *Server) udpServer(clientConn *net.UDPConn, localRelayConn *net.UDPConn, if err != nil { continue } + if atyp == socks5.ATYPDomain { + addr = addr[1:] // Remove the leading length byte + } d := socks5.NewDatagram(atyp, addr, port, bs) _, _ = clientConn.WriteToUDP(d.Bytes(), clientAddr) } @@ -362,6 +367,9 @@ func (s *Server) udpServer(clientConn *net.UDPConn, localRelayConn *net.UDPConn, if err != nil { continue } + if atyp == socks5.ATYPDomain { + addr = addr[1:] // Remove the leading length byte + } d := socks5.NewDatagram(atyp, addr, port, buf[:n]) _, _ = clientConn.WriteToUDP(d.Bytes(), clientAddr) } diff --git a/build.sh b/build.sh index 48c5a94..d55bfc1 100755 --- a/build.sh +++ b/build.sh @@ -71,7 +71,7 @@ platform_to_env() { } make_ldflags() { - local ldflags="-s -w -X 'main.appDate=$(date -u '+%F %T')'" + local ldflags="-buildid= -s -w -X 'main.appDate=$(date -u '+%F %T')'" if [ -n "$HY_APP_VERSION" ]; then ldflags="$ldflags -X 'main.appVersion=$HY_APP_VERSION'" else diff --git a/core/cs/client.go b/core/cs/client.go index 93d3249..896edca 100644 --- a/core/cs/client.go +++ b/core/cs/client.go @@ -49,7 +49,7 @@ type Client struct { } func NewClient(serverAddr string, auth []byte, tlsConfig *tls.Config, quicConfig *quic.Config, - pktConnFunc pktconns.ClientPacketConnFunc, sendBPS uint64, recvBPS uint64, fastOpen bool, lazyStart bool, + pktConnFunc pktconns.ClientPacketConnFunc, sendBPS, recvBPS uint64, fastOpen, lazyStart bool, quicReconnectFunc func(err error), ) (*Client, error) { quicConfig.DisablePathMTUDiscovery = quicConfig.DisablePathMTUDiscovery || pmtud.DisablePathMTUDiscovery diff --git a/core/cs/server.go b/core/cs/server.go index 4922c13..0d68124 100644 --- a/core/cs/server.go +++ b/core/cs/server.go @@ -17,7 +17,7 @@ import ( ) type ( - ConnectFunc func(addr net.Addr, auth []byte, sSend uint64, sRecv uint64) (bool, string) + ConnectFunc func(addr net.Addr, auth []byte, sSend, sRecv uint64) (bool, string) DisconnectFunc func(addr net.Addr, auth []byte, err error) TCPRequestFunc func(addr net.Addr, auth []byte, reqAddr string, action acl.Action, arg string) TCPErrorFunc func(addr net.Addr, auth []byte, reqAddr string, err error) @@ -53,7 +53,7 @@ type Server struct { func NewServer(tlsConfig *tls.Config, quicConfig *quic.Config, pktConn net.PacketConn, transport *transport.ServerTransport, - sendBPS uint64, recvBPS uint64, disableUDP bool, aclEngine *acl.Engine, + sendBPS, recvBPS uint64, disableUDP bool, aclEngine *acl.Engine, connectFunc ConnectFunc, disconnectFunc DisconnectFunc, tcpRequestFunc TCPRequestFunc, tcpErrorFunc TCPErrorFunc, udpRequestFunc UDPRequestFunc, udpErrorFunc UDPErrorFunc, diff --git a/core/pktconns/obfs/obfs.go b/core/pktconns/obfs/obfs.go index 2829560..29375b8 100644 --- a/core/pktconns/obfs/obfs.go +++ b/core/pktconns/obfs/obfs.go @@ -8,8 +8,8 @@ import ( ) type Obfuscator interface { - Deobfuscate(in []byte, out []byte) int - Obfuscate(in []byte, out []byte) int + Deobfuscate(in, out []byte) int + Obfuscate(in, out []byte) int } const xpSaltLen = 16 @@ -30,7 +30,7 @@ func NewXPlusObfuscator(key []byte) *XPlusObfuscator { } } -func (x *XPlusObfuscator) Deobfuscate(in []byte, out []byte) int { +func (x *XPlusObfuscator) Deobfuscate(in, out []byte) int { outLen := len(in) - xpSaltLen if outLen <= 0 || len(out) < outLen { return 0 @@ -42,7 +42,7 @@ func (x *XPlusObfuscator) Deobfuscate(in []byte, out []byte) int { return outLen } -func (x *XPlusObfuscator) Obfuscate(in []byte, out []byte) int { +func (x *XPlusObfuscator) Obfuscate(in, out []byte) int { outLen := len(in) + xpSaltLen if len(out) < outLen { return 0 diff --git a/core/transport/socks5.go b/core/transport/socks5.go index 43d5c6b..112a68b 100644 --- a/core/transport/socks5.go +++ b/core/transport/socks5.go @@ -21,7 +21,7 @@ type SOCKS5Client struct { Password string } -func NewSOCKS5Client(serverAddr string, username string, password string) *SOCKS5Client { +func NewSOCKS5Client(serverAddr, username, password string) *SOCKS5Client { return &SOCKS5Client{ Dialer: &net.Dialer{ Timeout: 8 * time.Second, @@ -215,7 +215,7 @@ func (c *socks5UDPConn) Close() error { return nil } -func socks5AddrToUDPAddr(atyp byte, addr []byte, port []byte) (*net.UDPAddr, error) { +func socks5AddrToUDPAddr(atyp byte, addr, port []byte) (*net.UDPAddr, error) { clone := func(b []byte) []byte { c := make([]byte, len(b)) copy(c, b)