diff --git a/cli/ss-server/main.go b/cli/ss-server/main.go index 0b34254..058a824 100644 --- a/cli/ss-server/main.go +++ b/cli/ss-server/main.go @@ -184,7 +184,7 @@ func newServer(f *flags) (*server, error) { } key = kb } - service, err := shadowaead.NewService(f.Method, key, []byte(f.Password), random.Blake3KeyedHash(), false, udpTimeout, s) + service, err := shadowaead.NewService(f.Method, key, []byte(f.Password), random.Default, false, udpTimeout, s) if err != nil { return nil, err } @@ -201,7 +201,7 @@ func newServer(f *flags) (*server, error) { } copy(key[:], kb) } - service, err := shadowaead_2022.NewService(f.Method, key, random.Blake3KeyedHash(), udpTimeout, s) + service, err := shadowaead_2022.NewService(f.Method, key, random.Default, udpTimeout, s) if err != nil { return nil, err } diff --git a/common/random/rng.go b/common/random/rng.go index 24374d7..62a897e 100644 --- a/common/random/rng.go +++ b/common/random/rng.go @@ -4,18 +4,32 @@ import ( "crypto/rand" "encoding/binary" "io" + "sync" "github.com/sagernet/sing/common" "lukechampine.com/blake3" ) -var System = rand.Reader +var System = &Source{rand.Reader} -func Blake3KeyedHash() Source { +var Default = Blake3KeyedHash() + +func Blake3KeyedHash() *Source { key := make([]byte, 32) common.Must1(io.ReadFull(System, key)) h := blake3.New(1024, key) - return Source{h.XOF()} + return &Source{&SyncReader{Reader: h.XOF()}} +} + +type SyncReader struct { + io.Reader + sync.Mutex +} + +func (r *SyncReader) Read(p []byte) (n int, err error) { + r.Lock() + defer r.Unlock() + return r.Reader.Read(p) } const ( diff --git a/protocol/shadowsocks/service.go b/protocol/shadowsocks/service.go index 37faebf..7c0fc5e 100644 --- a/protocol/shadowsocks/service.go +++ b/protocol/shadowsocks/service.go @@ -2,6 +2,8 @@ package shadowsocks import ( "context" + "fmt" + "net" E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" @@ -29,3 +31,31 @@ type UserContext[U comparable] struct { context.Context User U } + +type ServerConnError struct { + net.Conn + Source *M.AddrPort + Cause error +} + +func (e *ServerConnError) Unwrap() error { + return e.Cause +} + +func (e *ServerConnError) Error() string { + return fmt.Sprint("shadowsocks: serve TCP from ", e.Source, ": ", e.Cause) +} + +type ServerPacketError struct { + socks.PacketConn + Source *M.AddrPort + Cause error +} + +func (e *ServerPacketError) Unwrap() error { + return e.Cause +} + +func (e *ServerPacketError) Error() string { + return fmt.Sprint("shadowsocks: serve UDP from ", e.Source, ": ", e.Cause) +} diff --git a/protocol/shadowsocks/shadowaead/service.go b/protocol/shadowsocks/shadowaead/service.go index 9ac1b7e..0d929d7 100644 --- a/protocol/shadowsocks/shadowaead/service.go +++ b/protocol/shadowsocks/shadowaead/service.go @@ -79,6 +79,14 @@ func NewService(method string, key []byte, password []byte, secureRNG io.Reader, } func (s *Service) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { + err := s.newConnection(ctx, conn, metadata) + if err != nil { + err = &shadowsocks.ServerConnError{Conn: conn, Source: metadata.Source, Cause: err} + } + return err +} + +func (s *Service) newConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { _salt := buf.Make(s.keySaltLength) salt := common.Dup(_salt) @@ -191,6 +199,14 @@ func (c *serverConn) WriterReplaceable() bool { } func (s *Service) NewPacket(conn socks.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { + err := s.newPacket(conn, buffer, metadata) + if err != nil { + err = &shadowsocks.ServerPacketError{PacketConn: conn, Source: metadata.Source, Cause: err} + } + return err +} + +func (s *Service) newPacket(conn socks.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { if buffer.Len() < s.keySaltLength { return E.New("bad packet") } diff --git a/protocol/shadowsocks/shadowaead_2022/service.go b/protocol/shadowsocks/shadowaead_2022/service.go index 2e7dac3..505bdb6 100644 --- a/protocol/shadowsocks/shadowaead_2022/service.go +++ b/protocol/shadowsocks/shadowaead_2022/service.go @@ -73,6 +73,14 @@ func NewService(method string, psk [KeySaltSize]byte, secureRNG io.Reader, udpTi } func (s *Service) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { + err := s.newConnection(ctx, conn, metadata) + if err != nil { + err = &shadowsocks.ServerConnError{Conn: conn, Source: metadata.Source, Cause: err} + } + return err +} + +func (s *Service) newConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { requestSalt := make([]byte, KeySaltSize) _, err := io.ReadFull(conn, requestSalt) if err != nil { @@ -230,6 +238,14 @@ func (c *serverConn) WriterReplaceable() bool { } func (s *Service) NewPacket(conn socks.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { + err := s.newPacket(conn, buffer, metadata) + if err != nil { + err = &shadowsocks.ServerPacketError{PacketConn: conn, Source: metadata.Source, Cause: err} + } + return err +} + +func (s *Service) newPacket(conn socks.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { var packetHeader []byte if s.udpCipher != nil { _, err := s.udpCipher.Open(buffer.Index(PacketNonceSize), buffer.To(PacketNonceSize), buffer.From(PacketNonceSize), nil) diff --git a/protocol/shadowsocks/shadowaead_2022/service_multi.go b/protocol/shadowsocks/shadowaead_2022/service_multi.go index 5da4aef..561448f 100644 --- a/protocol/shadowsocks/shadowaead_2022/service_multi.go +++ b/protocol/shadowsocks/shadowaead_2022/service_multi.go @@ -73,6 +73,14 @@ func NewMultiService[U comparable](method string, iPSK [KeySaltSize]byte, secure } func (s *MultiService[U]) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { + err := s.newConnection(ctx, conn, metadata) + if err != nil { + err = &shadowsocks.ServerConnError{Conn: conn, Source: metadata.Source, Cause: err} + } + return err +} + +func (s *MultiService[U]) newConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { requestSalt := make([]byte, KeySaltSize) _, err := io.ReadFull(conn, requestSalt) if err != nil { @@ -166,6 +174,14 @@ func (s *MultiService[U]) NewConnection(ctx context.Context, conn net.Conn, meta } func (s *MultiService[U]) NewPacket(conn socks.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { + err := s.newPacket(conn, buffer, metadata) + if err != nil { + err = &shadowsocks.ServerPacketError{PacketConn: conn, Source: metadata.Source, Cause: err} + } + return err +} + +func (s *MultiService[U]) newPacket(conn socks.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { packetHeader := buffer.To(aes.BlockSize) s.udpBlockCipher.Decrypt(packetHeader, packetHeader) diff --git a/protocol/socks/packet_conn.go b/protocol/socks/packet_conn.go index 7438a12..125c6e0 100644 --- a/protocol/socks/packet_conn.go +++ b/protocol/socks/packet_conn.go @@ -27,6 +27,7 @@ type PacketConn interface { Close() error LocalAddr() net.Addr + RemoteAddr() net.Addr SetDeadline(t time.Time) error SetReadDeadline(t time.Time) error SetWriteDeadline(t time.Time) error @@ -42,6 +43,10 @@ type UDPConnectionHandler interface { type PacketConnStub struct{} +func (s *PacketConnStub) RemoteAddr() net.Addr { + return &common.DummyAddr{} +} + func (s *PacketConnStub) SetDeadline(t time.Time) error { return os.ErrInvalid } @@ -113,3 +118,7 @@ func (p *PacketConnWrapper) ReadPacket(buffer *buf.Buffer) (*M.AddrPort, error) func (p *PacketConnWrapper) WritePacket(buffer *buf.Buffer, destination *M.AddrPort) error { return common.Error(p.WriteTo(buffer.Bytes(), destination.UDPAddr())) } + +func (p *PacketConnWrapper) RemoteAddr() net.Addr { + return &common.DummyAddr{} +} diff --git a/transport/tls/cert.go b/transport/tls/cert.go index 0f08ba6..468dcb1 100644 --- a/transport/tls/cert.go +++ b/transport/tls/cert.go @@ -16,7 +16,7 @@ import ( ) func GenerateCertificate(hosts ...string) (*tls.Certificate, error) { - rng := random.Blake3KeyedHash() + rng := random.System r := rand.New(rng) privateKey, err := rsa.GenerateKey(rng, 2048)