feat(ss): support none/dummy cipher via no-op AEAD implementation

The go-gost fork of go-shadowsocks2 dropped built-in support for the
none/dummy cipher that was present in the original go-shadowsocks2.
Combined with the SS components' hard requirement for auth (and
therefore a valid cipher), this made gost fail to start with
method=none or method=dummy.

Add a no-op cipher in x/internal/util/ss/none/ that implements the
core.ShadowCipher interface using the standard go-shadowsocks2 AEAD
framing (salt + length-prefixed chunks, target address embedding)
without actual encryption.  SaltSize=16 ensures random salts on every
connection to avoid bloom-ring replay detection.

Update SS TCP connector/handler and SS UDP connector/handler to detect
method=none/dummy (case-insensitive) and use the no-op cipher instead
of utils.NewClientConfig/NewServerConfig.

Fixes go-gost/x#105
This commit is contained in:
ginuerzh
2026-06-17 22:18:23 +08:00
parent 183252f6ae
commit a86b5ab66b
6 changed files with 155 additions and 22 deletions
+30 -14
View File
@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"net"
"strings"
"sync"
"time"
@@ -20,6 +21,7 @@ import (
ictx "github.com/go-gost/x/internal/ctx"
"github.com/go-gost/x/internal/net/udp"
"github.com/go-gost/x/internal/util/relay"
"github.com/go-gost/x/internal/util/ss/none"
rate_limiter "github.com/go-gost/x/limiter/rate"
xrecorder "github.com/go-gost/x/recorder"
"github.com/go-gost/x/registry"
@@ -62,21 +64,35 @@ func (h *ssuHandler) Init(md md.Metadata) (err error) {
method := h.options.Auth.Username()
password, _ := h.options.Auth.Password()
serverConfig, err := utils.NewServerConfig(method, password, h.md.users)
if err != nil {
return err
}
serverConfig.UDPTimeout = time.Minute
h.udpServer = core.NewUDPServer(serverConfig)
err = h.udpServer.Init()
if err != nil {
return err
}
if strings.EqualFold(method, "none") || strings.EqualFold(method, "dummy") {
c := core.ServerConfig{Cipher: none.Cipher, Users: h.md.users, UDPTimeout: time.Minute}
h.udpServer = core.NewUDPServer(c)
err = h.udpServer.Init()
if err != nil {
return err
}
h.tcpServer = core.NewTCPServer(c)
err = h.tcpServer.Init()
if err != nil {
return err
}
} else {
serverConfig, err := utils.NewServerConfig(method, password, h.md.users)
if err != nil {
return err
}
serverConfig.UDPTimeout = time.Minute
h.udpServer = core.NewUDPServer(serverConfig)
err = h.udpServer.Init()
if err != nil {
return err
}
h.tcpServer = core.NewTCPServer(serverConfig)
err = h.tcpServer.Init()
if err != nil {
return err
h.tcpServer = core.NewTCPServer(serverConfig)
err = h.tcpServer.Init()
if err != nil {
return err
}
}
for _, ro := range h.options.Recorders {