├── .github ├── update_dependencies.sh └── workflows │ ├── lint.yml │ └── test.yml ├── .gitignore ├── .golangci.yml ├── LICENSE ├── Makefile ├── README.md ├── go.mod ├── go.sum ├── none.go ├── shadowaead ├── aead.go ├── protocol.go ├── service.go └── service_multi.go ├── shadowaead_2022 ├── protocol.go ├── relay.go ├── service.go ├── service_multi.go ├── service_multi_test.go ├── service_test.go ├── slidingwindow.go ├── xor.go └── xor_go119.go ├── shadowimpl └── fetcher.go ├── shadowsocks.go └── shadowstream └── protocol.go /.github/update_dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROJECTS=$(dirname "$0")/../.. 4 | 5 | go get -x github.com/sagernet/sing@$(git -C $PROJECTS/sing rev-parse HEAD) 6 | go mod tidy 7 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: lint 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - dev 8 | paths-ignore: 9 | - '**.md' 10 | - '.github/**' 11 | - '!.github/workflows/lint.yml' 12 | pull_request: 13 | branches: 14 | - main 15 | - dev 16 | 17 | jobs: 18 | build: 19 | name: Build 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | with: 25 | fetch-depth: 0 26 | - name: Setup Go 27 | uses: actions/setup-go@v5 28 | with: 29 | go-version: ^1.22 30 | - name: Cache go module 31 | uses: actions/cache@v4 32 | with: 33 | path: | 34 | ~/go/pkg/mod 35 | key: go-${{ hashFiles('**/go.sum') }} 36 | - name: golangci-lint 37 | uses: golangci/golangci-lint-action@v6 38 | with: 39 | version: latest -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - dev 8 | paths-ignore: 9 | - '**.md' 10 | - '.github/**' 11 | - '!.github/workflows/debug.yml' 12 | pull_request: 13 | branches: 14 | - main 15 | - dev 16 | 17 | jobs: 18 | build: 19 | name: Linux 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | with: 25 | fetch-depth: 0 26 | - name: Setup Go 27 | uses: actions/setup-go@v5 28 | with: 29 | go-version: ^1.22 30 | - name: Build 31 | run: | 32 | make test 33 | build_go118: 34 | name: Linux (Go 1.18) 35 | runs-on: ubuntu-latest 36 | steps: 37 | - name: Checkout 38 | uses: actions/checkout@v4 39 | with: 40 | fetch-depth: 0 41 | - name: Setup Go 42 | uses: actions/setup-go@v5 43 | with: 44 | go-version: ~1.18 45 | continue-on-error: true 46 | - name: Build 47 | run: | 48 | make test 49 | build_go120: 50 | name: Linux (Go 1.20) 51 | runs-on: ubuntu-latest 52 | steps: 53 | - name: Checkout 54 | uses: actions/checkout@v4 55 | with: 56 | fetch-depth: 0 57 | - name: Setup Go 58 | uses: actions/setup-go@v5 59 | with: 60 | go-version: ~1.20 61 | continue-on-error: true 62 | - name: Build 63 | run: | 64 | make test 65 | build_go121: 66 | name: Linux (Go 1.21) 67 | runs-on: ubuntu-latest 68 | steps: 69 | - name: Checkout 70 | uses: actions/checkout@v4 71 | with: 72 | fetch-depth: 0 73 | - name: Setup Go 74 | uses: actions/setup-go@v5 75 | with: 76 | go-version: ~1.21 77 | continue-on-error: true 78 | - name: Build 79 | run: | 80 | make test 81 | build_windows: 82 | name: Windows 83 | runs-on: windows-latest 84 | steps: 85 | - name: Checkout 86 | uses: actions/checkout@v4 87 | with: 88 | fetch-depth: 0 89 | - name: Setup Go 90 | uses: actions/setup-go@v5 91 | with: 92 | go-version: ^1.22 93 | continue-on-error: true 94 | - name: Build 95 | run: | 96 | make test 97 | build_darwin: 98 | name: macOS 99 | runs-on: macos-latest 100 | steps: 101 | - name: Checkout 102 | uses: actions/checkout@v4 103 | with: 104 | fetch-depth: 0 105 | - name: Setup Go 106 | uses: actions/setup-go@v5 107 | with: 108 | go-version: ^1.22 109 | continue-on-error: true 110 | - name: Build 111 | run: | 112 | make test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /vendor/ 3 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | linters: 2 | disable-all: true 3 | enable: 4 | - gofumpt 5 | - govet 6 | - gci 7 | - staticcheck 8 | 9 | linters-settings: 10 | gci: 11 | custom-order: true 12 | sections: 13 | - standard 14 | - prefix(github.com/sagernet/) 15 | - default 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2022 by nekohasekai 2 | 3 | This program is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program. If not, see . -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | fmt: 2 | @gofumpt -l -w . 3 | @gofmt -s -w . 4 | @gci write --custom-order -s standard -s "prefix(github.com/sagernet/)" -s "default" . 5 | 6 | fmt_install: 7 | go install -v mvdan.cc/gofumpt@latest 8 | go install -v github.com/daixiang0/gci@latest 9 | 10 | lint: 11 | GOOS=linux golangci-lint run ./... 12 | GOOS=android golangci-lint run ./... 13 | GOOS=windows golangci-lint run ./... 14 | GOOS=darwin golangci-lint run ./... 15 | GOOS=freebsd golangci-lint run ./... 16 | 17 | lint_install: 18 | go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest 19 | 20 | test: 21 | go test -v ./... -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sing-shadowsocks 2 | 3 | Lightweight and efficient shadowsocks implementation with sing. -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sagernet/sing-shadowsocks 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/sagernet/sing v0.6.10 7 | golang.org/x/crypto v0.23.0 8 | lukechampine.com/blake3 v1.3.0 9 | ) 10 | 11 | require ( 12 | github.com/klauspost/cpuid/v2 v2.0.12 // indirect 13 | golang.org/x/sys v0.21.0 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE= 3 | github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= 4 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 5 | github.com/sagernet/sing v0.6.10 h1:Jey1tePgH9bjFuK1fQI3D9T+bPOQ4SdHMjuS4sYjDv4= 6 | github.com/sagernet/sing v0.6.10/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= 7 | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= 8 | golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= 9 | golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= 10 | golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= 11 | golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 12 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 13 | lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= 14 | lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= 15 | -------------------------------------------------------------------------------- /none.go: -------------------------------------------------------------------------------- 1 | package shadowsocks 2 | 3 | import ( 4 | "context" 5 | "net" 6 | "net/netip" 7 | 8 | "github.com/sagernet/sing/common" 9 | "github.com/sagernet/sing/common/buf" 10 | M "github.com/sagernet/sing/common/metadata" 11 | N "github.com/sagernet/sing/common/network" 12 | "github.com/sagernet/sing/common/udpnat" 13 | ) 14 | 15 | const MethodNone = "none" 16 | 17 | type NoneMethod struct{} 18 | 19 | func NewNone() Method { 20 | return &NoneMethod{} 21 | } 22 | 23 | func (m *NoneMethod) Name() string { 24 | return MethodNone 25 | } 26 | 27 | func (m *NoneMethod) DialConn(conn net.Conn, destination M.Socksaddr) (net.Conn, error) { 28 | shadowsocksConn := &noneConn{ 29 | Conn: conn, 30 | handshake: true, 31 | destination: destination, 32 | } 33 | return shadowsocksConn, shadowsocksConn.clientHandshake() 34 | } 35 | 36 | func (m *NoneMethod) DialEarlyConn(conn net.Conn, destination M.Socksaddr) net.Conn { 37 | return &noneConn{ 38 | Conn: conn, 39 | destination: destination, 40 | } 41 | } 42 | 43 | func (m *NoneMethod) DialPacketConn(conn net.Conn) N.NetPacketConn { 44 | return &nonePacketConn{conn} 45 | } 46 | 47 | type noneConn struct { 48 | net.Conn 49 | 50 | handshake bool 51 | destination M.Socksaddr 52 | } 53 | 54 | func (c *noneConn) clientHandshake() error { 55 | err := M.SocksaddrSerializer.WriteAddrPort(c.Conn, c.destination) 56 | if err != nil { 57 | return err 58 | } 59 | c.handshake = true 60 | return nil 61 | } 62 | 63 | func (c *noneConn) Write(b []byte) (n int, err error) { 64 | if c.handshake { 65 | return c.Conn.Write(b) 66 | } 67 | err = M.SocksaddrSerializer.WriteAddrPort(c.Conn, c.destination) 68 | if err != nil { 69 | return 70 | } 71 | c.handshake = true 72 | return c.Conn.Write(b) 73 | } 74 | 75 | func (c *noneConn) WriteBuffer(buffer *buf.Buffer) error { 76 | defer buffer.Release() 77 | if c.handshake { 78 | return common.Error(c.Conn.Write(buffer.Bytes())) 79 | } 80 | 81 | header := buf.With(buffer.ExtendHeader(M.SocksaddrSerializer.AddrPortLen(c.destination))) 82 | err := M.SocksaddrSerializer.WriteAddrPort(header, c.destination) 83 | if err != nil { 84 | return err 85 | } 86 | c.handshake = true 87 | return common.Error(c.Conn.Write(buffer.Bytes())) 88 | } 89 | 90 | func (c *noneConn) FrontHeadroom() int { 91 | if !c.handshake { 92 | return M.SocksaddrSerializer.AddrPortLen(c.destination) 93 | } 94 | return 0 95 | } 96 | 97 | func (c *noneConn) RemoteAddr() net.Addr { 98 | return c.destination.TCPAddr() 99 | } 100 | 101 | func (c *noneConn) Upstream() any { 102 | return c.Conn 103 | } 104 | 105 | func (c *noneConn) ReaderReplaceable() bool { 106 | return true 107 | } 108 | 109 | func (c *noneConn) WriterReplaceable() bool { 110 | return c.handshake 111 | } 112 | 113 | type nonePacketConn struct { 114 | net.Conn 115 | } 116 | 117 | func (c *nonePacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) { 118 | _, err := buffer.ReadOnceFrom(c) 119 | if err != nil { 120 | return M.Socksaddr{}, err 121 | } 122 | return M.SocksaddrSerializer.ReadAddrPort(buffer) 123 | } 124 | 125 | func (c *nonePacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { 126 | defer buffer.Release() 127 | header := buf.With(buffer.ExtendHeader(M.SocksaddrSerializer.AddrPortLen(destination))) 128 | err := M.SocksaddrSerializer.WriteAddrPort(header, destination) 129 | if err != nil { 130 | return err 131 | } 132 | return common.Error(buffer.WriteTo(c)) 133 | } 134 | 135 | func (c *nonePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { 136 | n, err = c.Read(p) 137 | if err != nil { 138 | return 139 | } 140 | buffer := buf.As(p[:n]) 141 | destination, err := M.SocksaddrSerializer.ReadAddrPort(buffer) 142 | if err != nil { 143 | return 144 | } 145 | if destination.IsFqdn() { 146 | addr = destination 147 | } else { 148 | addr = destination.UDPAddr() 149 | } 150 | n = copy(p, buffer.Bytes()) 151 | return 152 | } 153 | 154 | func (c *nonePacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { 155 | destination := M.SocksaddrFromNet(addr) 156 | buffer := buf.NewSize(M.SocksaddrSerializer.AddrPortLen(destination) + len(p)) 157 | defer buffer.Release() 158 | err = M.SocksaddrSerializer.WriteAddrPort(buffer, destination) 159 | if err != nil { 160 | return 161 | } 162 | _, err = buffer.Write(p) 163 | if err != nil { 164 | return 165 | } 166 | return len(p), nil 167 | } 168 | 169 | func (c *nonePacketConn) Headroom() int { 170 | return M.MaxSocksaddrLength 171 | } 172 | 173 | type NoneService struct { 174 | handler Handler 175 | udpNat *udpnat.Service[netip.AddrPort] 176 | } 177 | 178 | func NewNoneService(udpTimeout int64, handler Handler) Service { 179 | s := &NoneService{ 180 | handler: handler, 181 | } 182 | s.udpNat = udpnat.New[netip.AddrPort](udpTimeout, handler) 183 | return s 184 | } 185 | 186 | func (s *NoneService) Name() string { 187 | return MethodNone 188 | } 189 | 190 | func (s *NoneService) Password() string { 191 | return "" 192 | } 193 | 194 | func (s *NoneService) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 195 | destination, err := M.SocksaddrSerializer.ReadAddrPort(conn) 196 | if err != nil { 197 | return err 198 | } 199 | metadata.Protocol = "shadowsocks" 200 | metadata.Destination = destination 201 | return s.handler.NewConnection(ctx, conn, metadata) 202 | } 203 | 204 | func (s *NoneService) WriteIsThreadUnsafe() { 205 | } 206 | 207 | func (s *NoneService) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 208 | destination, err := M.SocksaddrSerializer.ReadAddrPort(buffer) 209 | if err != nil { 210 | return err 211 | } 212 | metadata.Protocol = "shadowsocks" 213 | metadata.Destination = destination 214 | s.udpNat.NewPacket(ctx, metadata.Source.AddrPort(), buffer, metadata, func(natConn N.PacketConn) N.PacketWriter { 215 | return &nonePacketWriter{conn, natConn} 216 | }) 217 | return nil 218 | } 219 | 220 | type nonePacketWriter struct { 221 | source N.PacketConn 222 | nat N.PacketConn 223 | } 224 | 225 | func (w *nonePacketWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { 226 | header := buf.With(buffer.ExtendHeader(M.SocksaddrSerializer.AddrPortLen(destination))) 227 | err := M.SocksaddrSerializer.WriteAddrPort(header, destination) 228 | if err != nil { 229 | buffer.Release() 230 | return err 231 | } 232 | return w.source.WritePacket(buffer, M.SocksaddrFromNet(w.nat.LocalAddr())) 233 | } 234 | 235 | func (w *nonePacketWriter) Upstream() any { 236 | return w.source 237 | } 238 | 239 | func (w *nonePacketWriter) FrontHeadroom() int { 240 | return M.MaxSocksaddrLength 241 | } 242 | 243 | func (s *NoneService) NewError(ctx context.Context, err error) { 244 | s.handler.NewError(ctx, err) 245 | } 246 | -------------------------------------------------------------------------------- /shadowaead/aead.go: -------------------------------------------------------------------------------- 1 | package shadowaead 2 | 3 | import ( 4 | "crypto/cipher" 5 | "encoding/binary" 6 | "io" 7 | "sync" 8 | 9 | "github.com/sagernet/sing/common/buf" 10 | ) 11 | 12 | // https://shadowsocks.org/en/wiki/AEAD-Ciphers.html 13 | const ( 14 | MaxPacketSize = 16*1024 - 1 15 | PacketLengthBufferSize = 2 16 | ) 17 | 18 | const ( 19 | // Overhead 20 | // crypto/cipher.gcmTagSize 21 | // golang.org/x/crypto/chacha20poly1305.Overhead 22 | Overhead = 16 23 | ) 24 | 25 | type Reader struct { 26 | upstream io.Reader 27 | cipher cipher.AEAD 28 | buffer []byte 29 | nonce []byte 30 | index int 31 | cached int 32 | } 33 | 34 | func NewReader(upstream io.Reader, cipher cipher.AEAD, maxPacketSize int) *Reader { 35 | return &Reader{ 36 | upstream: upstream, 37 | cipher: cipher, 38 | buffer: make([]byte, maxPacketSize+Overhead), 39 | nonce: make([]byte, cipher.NonceSize()), 40 | } 41 | } 42 | 43 | func NewRawReader(upstream io.Reader, cipher cipher.AEAD, buffer []byte, nonce []byte) *Reader { 44 | return &Reader{ 45 | upstream: upstream, 46 | cipher: cipher, 47 | buffer: buffer, 48 | nonce: nonce, 49 | } 50 | } 51 | 52 | func (r *Reader) Upstream() any { 53 | return r.upstream 54 | } 55 | 56 | func (r *Reader) WriteTo(writer io.Writer) (n int64, err error) { 57 | if r.cached > 0 { 58 | writeN, writeErr := writer.Write(r.buffer[r.index : r.index+r.cached]) 59 | if writeErr != nil { 60 | return int64(writeN), writeErr 61 | } 62 | n += int64(writeN) 63 | } 64 | for { 65 | start := PacketLengthBufferSize + Overhead 66 | _, err = io.ReadFull(r.upstream, r.buffer[:start]) 67 | if err != nil { 68 | return 69 | } 70 | _, err = r.cipher.Open(r.buffer[:0], r.nonce, r.buffer[:start], nil) 71 | if err != nil { 72 | return 73 | } 74 | increaseNonce(r.nonce) 75 | length := int(binary.BigEndian.Uint16(r.buffer[:PacketLengthBufferSize])) 76 | end := length + Overhead 77 | _, err = io.ReadFull(r.upstream, r.buffer[:end]) 78 | if err != nil { 79 | return 80 | } 81 | _, err = r.cipher.Open(r.buffer[:0], r.nonce, r.buffer[:end], nil) 82 | if err != nil { 83 | return 84 | } 85 | increaseNonce(r.nonce) 86 | writeN, writeErr := writer.Write(r.buffer[:length]) 87 | if writeErr != nil { 88 | return int64(writeN), writeErr 89 | } 90 | n += int64(writeN) 91 | } 92 | } 93 | 94 | func (r *Reader) readInternal() (err error) { 95 | start := PacketLengthBufferSize + Overhead 96 | _, err = io.ReadFull(r.upstream, r.buffer[:start]) 97 | if err != nil { 98 | return err 99 | } 100 | _, err = r.cipher.Open(r.buffer[:0], r.nonce, r.buffer[:start], nil) 101 | if err != nil { 102 | return err 103 | } 104 | increaseNonce(r.nonce) 105 | length := int(binary.BigEndian.Uint16(r.buffer[:PacketLengthBufferSize])) 106 | end := length + Overhead 107 | _, err = io.ReadFull(r.upstream, r.buffer[:end]) 108 | if err != nil { 109 | return err 110 | } 111 | _, err = r.cipher.Open(r.buffer[:0], r.nonce, r.buffer[:end], nil) 112 | if err != nil { 113 | return err 114 | } 115 | increaseNonce(r.nonce) 116 | r.cached = length 117 | r.index = 0 118 | return nil 119 | } 120 | 121 | func (r *Reader) ReadByte() (byte, error) { 122 | if r.cached == 0 { 123 | err := r.readInternal() 124 | if err != nil { 125 | return 0, err 126 | } 127 | } 128 | index := r.index 129 | r.index++ 130 | r.cached-- 131 | return r.buffer[index], nil 132 | } 133 | 134 | func (r *Reader) Read(b []byte) (n int, err error) { 135 | if r.cached > 0 { 136 | n = copy(b, r.buffer[r.index:r.index+r.cached]) 137 | r.cached -= n 138 | r.index += n 139 | return 140 | } 141 | start := PacketLengthBufferSize + Overhead 142 | _, err = io.ReadFull(r.upstream, r.buffer[:start]) 143 | if err != nil { 144 | return 0, err 145 | } 146 | _, err = r.cipher.Open(r.buffer[:0], r.nonce, r.buffer[:start], nil) 147 | if err != nil { 148 | return 0, err 149 | } 150 | increaseNonce(r.nonce) 151 | length := int(binary.BigEndian.Uint16(r.buffer[:PacketLengthBufferSize])) 152 | end := length + Overhead 153 | 154 | if len(b) >= end { 155 | data := b[:end] 156 | _, err = io.ReadFull(r.upstream, data) 157 | if err != nil { 158 | return 0, err 159 | } 160 | _, err = r.cipher.Open(b[:0], r.nonce, data, nil) 161 | if err != nil { 162 | return 0, err 163 | } 164 | increaseNonce(r.nonce) 165 | return length, nil 166 | } else { 167 | _, err = io.ReadFull(r.upstream, r.buffer[:end]) 168 | if err != nil { 169 | return 0, err 170 | } 171 | _, err = r.cipher.Open(r.buffer[:0], r.nonce, r.buffer[:end], nil) 172 | if err != nil { 173 | return 0, err 174 | } 175 | increaseNonce(r.nonce) 176 | n = copy(b, r.buffer[:length]) 177 | r.cached = length - n 178 | r.index = n 179 | return 180 | } 181 | } 182 | 183 | func (r *Reader) Discard(n int) error { 184 | for { 185 | if r.cached >= n { 186 | r.cached -= n 187 | r.index += n 188 | return nil 189 | } else if r.cached > 0 { 190 | n -= r.cached 191 | r.cached = 0 192 | r.index = 0 193 | } 194 | err := r.readInternal() 195 | if err != nil { 196 | return err 197 | } 198 | } 199 | } 200 | 201 | func (r *Reader) Buffer() *buf.Buffer { 202 | buffer := buf.With(r.buffer) 203 | buffer.Resize(r.index, r.cached) 204 | return buffer 205 | } 206 | 207 | func (r *Reader) Cached() int { 208 | return r.cached 209 | } 210 | 211 | func (r *Reader) CachedSlice() []byte { 212 | return r.buffer[r.index : r.index+r.cached] 213 | } 214 | 215 | func (r *Reader) ReadWithLengthChunk(lengthChunk []byte) error { 216 | _, err := r.cipher.Open(r.buffer[:0], r.nonce, lengthChunk, nil) 217 | if err != nil { 218 | return err 219 | } 220 | increaseNonce(r.nonce) 221 | length := int(binary.BigEndian.Uint16(r.buffer[:PacketLengthBufferSize])) 222 | end := length + Overhead 223 | _, err = io.ReadFull(r.upstream, r.buffer[:end]) 224 | if err != nil { 225 | return err 226 | } 227 | _, err = r.cipher.Open(r.buffer[:0], r.nonce, r.buffer[:end], nil) 228 | if err != nil { 229 | return err 230 | } 231 | increaseNonce(r.nonce) 232 | r.cached = length 233 | r.index = 0 234 | return nil 235 | } 236 | 237 | func (r *Reader) ReadWithLength(length uint16) error { 238 | end := int(length) + Overhead 239 | _, err := io.ReadFull(r.upstream, r.buffer[:end]) 240 | if err != nil { 241 | return err 242 | } 243 | _, err = r.cipher.Open(r.buffer[:0], r.nonce, r.buffer[:end], nil) 244 | if err != nil { 245 | return err 246 | } 247 | increaseNonce(r.nonce) 248 | r.cached = int(length) 249 | r.index = 0 250 | return nil 251 | } 252 | 253 | func (r *Reader) ReadExternalChunk(chunk []byte) error { 254 | bb, err := r.cipher.Open(r.buffer[:0], r.nonce, chunk, nil) 255 | if err != nil { 256 | return err 257 | } 258 | increaseNonce(r.nonce) 259 | r.cached = len(bb) 260 | r.index = 0 261 | return nil 262 | } 263 | 264 | func (r *Reader) ReadChunk(buffer *buf.Buffer, chunk []byte) error { 265 | bb, err := r.cipher.Open(buffer.Index(buffer.Len()), r.nonce, chunk, nil) 266 | if err != nil { 267 | return err 268 | } 269 | increaseNonce(r.nonce) 270 | buffer.Extend(len(bb)) 271 | return nil 272 | } 273 | 274 | type Writer struct { 275 | upstream io.Writer 276 | cipher cipher.AEAD 277 | maxPacketSize int 278 | buffer []byte 279 | nonce []byte 280 | access sync.Mutex 281 | } 282 | 283 | func NewWriter(upstream io.Writer, cipher cipher.AEAD, maxPacketSize int) *Writer { 284 | return &Writer{ 285 | upstream: upstream, 286 | cipher: cipher, 287 | buffer: make([]byte, maxPacketSize+PacketLengthBufferSize+Overhead*2), 288 | nonce: make([]byte, cipher.NonceSize()), 289 | maxPacketSize: maxPacketSize, 290 | } 291 | } 292 | 293 | func NewRawWriter(upstream io.Writer, cipher cipher.AEAD, maxPacketSize int, buffer []byte, nonce []byte) *Writer { 294 | return &Writer{ 295 | upstream: upstream, 296 | cipher: cipher, 297 | maxPacketSize: maxPacketSize, 298 | buffer: buffer, 299 | nonce: nonce, 300 | } 301 | } 302 | 303 | func (w *Writer) Upstream() any { 304 | return w.upstream 305 | } 306 | 307 | func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) { 308 | for { 309 | offset := Overhead + PacketLengthBufferSize 310 | readN, readErr := r.Read(w.buffer[offset : offset+w.maxPacketSize]) 311 | if readErr != nil { 312 | return 0, readErr 313 | } 314 | binary.BigEndian.PutUint16(w.buffer[:PacketLengthBufferSize], uint16(readN)) 315 | w.cipher.Seal(w.buffer[:0], w.nonce, w.buffer[:PacketLengthBufferSize], nil) 316 | increaseNonce(w.nonce) 317 | packet := w.cipher.Seal(w.buffer[offset:offset], w.nonce, w.buffer[offset:offset+readN], nil) 318 | increaseNonce(w.nonce) 319 | _, err = w.upstream.Write(w.buffer[:offset+len(packet)]) 320 | if err != nil { 321 | return 322 | } 323 | n += int64(readN) 324 | } 325 | } 326 | 327 | func (w *Writer) Write(p []byte) (n int, err error) { 328 | if len(p) == 0 { 329 | return 330 | } 331 | 332 | for pLen := len(p); pLen > 0; { 333 | var data []byte 334 | if pLen > w.maxPacketSize { 335 | data = p[:w.maxPacketSize] 336 | p = p[w.maxPacketSize:] 337 | pLen -= w.maxPacketSize 338 | } else { 339 | data = p 340 | pLen = 0 341 | } 342 | w.access.Lock() 343 | binary.BigEndian.PutUint16(w.buffer[:PacketLengthBufferSize], uint16(len(data))) 344 | w.cipher.Seal(w.buffer[:0], w.nonce, w.buffer[:PacketLengthBufferSize], nil) 345 | increaseNonce(w.nonce) 346 | offset := Overhead + PacketLengthBufferSize 347 | packet := w.cipher.Seal(w.buffer[offset:offset], w.nonce, data, nil) 348 | increaseNonce(w.nonce) 349 | w.access.Unlock() 350 | _, err = w.upstream.Write(w.buffer[:offset+len(packet)]) 351 | if err != nil { 352 | return 353 | } 354 | n += len(data) 355 | } 356 | 357 | return 358 | } 359 | 360 | func (w *Writer) WriteVectorised(buffers []*buf.Buffer) error { 361 | defer buf.ReleaseMulti(buffers) 362 | var index int 363 | var err error 364 | for _, buffer := range buffers { 365 | pLen := buffer.Len() 366 | if pLen > w.maxPacketSize { 367 | _, err = w.Write(buffer.Bytes()) 368 | if err != nil { 369 | return err 370 | } 371 | } else { 372 | if cap(w.buffer) < index+PacketLengthBufferSize+pLen+2*Overhead { 373 | _, err = w.upstream.Write(w.buffer[:index]) 374 | index = 0 375 | if err != nil { 376 | return err 377 | } 378 | } 379 | w.access.Lock() 380 | binary.BigEndian.PutUint16(w.buffer[index:index+PacketLengthBufferSize], uint16(pLen)) 381 | w.cipher.Seal(w.buffer[index:index], w.nonce, w.buffer[index:index+PacketLengthBufferSize], nil) 382 | increaseNonce(w.nonce) 383 | offset := index + Overhead + PacketLengthBufferSize 384 | w.cipher.Seal(w.buffer[offset:offset], w.nonce, buffer.Bytes(), nil) 385 | increaseNonce(w.nonce) 386 | w.access.Unlock() 387 | index = offset + pLen + Overhead 388 | } 389 | } 390 | if index > 0 { 391 | _, err = w.upstream.Write(w.buffer[:index]) 392 | } 393 | return err 394 | } 395 | 396 | func (w *Writer) Buffer() *buf.Buffer { 397 | return buf.With(w.buffer) 398 | } 399 | 400 | func (w *Writer) WriteChunk(buffer *buf.Buffer, chunk []byte) { 401 | bb := w.cipher.Seal(buffer.Index(buffer.Len()), w.nonce, chunk, nil) 402 | buffer.Extend(len(bb)) 403 | increaseNonce(w.nonce) 404 | } 405 | 406 | func (w *Writer) BufferedWriter(reversed int) *BufferedWriter { 407 | return &BufferedWriter{ 408 | upstream: w, 409 | reversed: reversed, 410 | data: w.buffer[PacketLengthBufferSize+Overhead : len(w.buffer)-Overhead], 411 | } 412 | } 413 | 414 | type BufferedWriter struct { 415 | upstream *Writer 416 | data []byte 417 | reversed int 418 | index int 419 | } 420 | 421 | func (w *BufferedWriter) Write(p []byte) (n int, err error) { 422 | for { 423 | cachedN := copy(w.data[w.reversed+w.index:], p[n:]) 424 | w.index += cachedN 425 | if cachedN == len(p[n:]) { 426 | n += cachedN 427 | return 428 | } 429 | err = w.Flush() 430 | if err != nil { 431 | return 432 | } 433 | n += cachedN 434 | } 435 | } 436 | 437 | func (w *BufferedWriter) Flush() error { 438 | if w.index == 0 { 439 | if w.reversed > 0 { 440 | _, err := w.upstream.upstream.Write(w.upstream.buffer[:w.reversed]) 441 | w.reversed = 0 442 | return err 443 | } 444 | return nil 445 | } 446 | buffer := w.upstream.buffer[w.reversed:] 447 | binary.BigEndian.PutUint16(buffer[:PacketLengthBufferSize], uint16(w.index)) 448 | w.upstream.cipher.Seal(buffer[:0], w.upstream.nonce, buffer[:PacketLengthBufferSize], nil) 449 | increaseNonce(w.upstream.nonce) 450 | offset := Overhead + PacketLengthBufferSize 451 | packet := w.upstream.cipher.Seal(buffer[offset:offset], w.upstream.nonce, buffer[offset:offset+w.index], nil) 452 | increaseNonce(w.upstream.nonce) 453 | _, err := w.upstream.upstream.Write(w.upstream.buffer[:w.reversed+offset+len(packet)]) 454 | w.reversed = 0 455 | w.index = 0 456 | return err 457 | } 458 | 459 | func increaseNonce(nonce []byte) { 460 | for i := range nonce { 461 | nonce[i]++ 462 | if nonce[i] != 0 { 463 | return 464 | } 465 | } 466 | } 467 | -------------------------------------------------------------------------------- /shadowaead/protocol.go: -------------------------------------------------------------------------------- 1 | package shadowaead 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/sha1" 7 | "io" 8 | "net" 9 | 10 | "github.com/sagernet/sing-shadowsocks" 11 | "github.com/sagernet/sing/common" 12 | "github.com/sagernet/sing/common/buf" 13 | M "github.com/sagernet/sing/common/metadata" 14 | N "github.com/sagernet/sing/common/network" 15 | "github.com/sagernet/sing/common/rw" 16 | 17 | "golang.org/x/crypto/chacha20poly1305" 18 | "golang.org/x/crypto/hkdf" 19 | ) 20 | 21 | var List = []string{ 22 | "aes-128-gcm", 23 | "aes-192-gcm", 24 | "aes-256-gcm", 25 | "chacha20-ietf-poly1305", 26 | "xchacha20-ietf-poly1305", 27 | } 28 | 29 | var _ shadowsocks.Method = (*Method)(nil) 30 | 31 | func New(method string, key []byte, password string) (*Method, error) { 32 | m := &Method{ 33 | name: method, 34 | } 35 | switch method { 36 | case "aes-128-gcm": 37 | m.keySaltLength = 16 38 | m.constructor = aeadCipher(aes.NewCipher, cipher.NewGCM) 39 | case "aes-192-gcm": 40 | m.keySaltLength = 24 41 | m.constructor = aeadCipher(aes.NewCipher, cipher.NewGCM) 42 | case "aes-256-gcm": 43 | m.keySaltLength = 32 44 | m.constructor = aeadCipher(aes.NewCipher, cipher.NewGCM) 45 | case "chacha20-ietf-poly1305": 46 | m.keySaltLength = 32 47 | m.constructor = chacha20poly1305.New 48 | case "xchacha20-ietf-poly1305": 49 | m.keySaltLength = 32 50 | m.constructor = chacha20poly1305.NewX 51 | } 52 | if len(key) == m.keySaltLength { 53 | m.key = key 54 | } else if len(key) > 0 { 55 | return nil, shadowsocks.ErrBadKey 56 | } else if password == "" { 57 | return nil, shadowsocks.ErrMissingPassword 58 | } else { 59 | m.key = shadowsocks.Key([]byte(password), m.keySaltLength) 60 | } 61 | return m, nil 62 | } 63 | 64 | func Kdf(key, iv []byte, buffer *buf.Buffer) { 65 | kdf := hkdf.New(sha1.New, key, iv, []byte("ss-subkey")) 66 | common.Must1(buffer.ReadFullFrom(kdf, buffer.FreeLen())) 67 | } 68 | 69 | func aeadCipher(block func(key []byte) (cipher.Block, error), aead func(block cipher.Block) (cipher.AEAD, error)) func(key []byte) (cipher.AEAD, error) { 70 | return func(key []byte) (cipher.AEAD, error) { 71 | b, err := block(key) 72 | if err != nil { 73 | return nil, err 74 | } 75 | return aead(b) 76 | } 77 | } 78 | 79 | type Method struct { 80 | name string 81 | keySaltLength int 82 | constructor func(key []byte) (cipher.AEAD, error) 83 | key []byte 84 | } 85 | 86 | func (m *Method) Name() string { 87 | return m.name 88 | } 89 | 90 | func (m *Method) DialConn(conn net.Conn, destination M.Socksaddr) (net.Conn, error) { 91 | shadowsocksConn := &clientConn{ 92 | Conn: conn, 93 | Method: m, 94 | destination: destination, 95 | } 96 | return shadowsocksConn, shadowsocksConn.writeRequest(nil) 97 | } 98 | 99 | func (m *Method) DialEarlyConn(conn net.Conn, destination M.Socksaddr) net.Conn { 100 | return &clientConn{ 101 | Conn: conn, 102 | Method: m, 103 | destination: destination, 104 | } 105 | } 106 | 107 | func (m *Method) DialPacketConn(conn net.Conn) N.NetPacketConn { 108 | return &clientPacketConn{m, conn} 109 | } 110 | 111 | type clientConn struct { 112 | net.Conn 113 | *Method 114 | destination M.Socksaddr 115 | reader *Reader 116 | writer *Writer 117 | } 118 | 119 | func (c *clientConn) writeRequest(payload []byte) error { 120 | salt := buf.NewSize(c.keySaltLength) 121 | defer salt.Release() 122 | salt.WriteRandom(c.keySaltLength) 123 | 124 | key := buf.NewSize(c.keySaltLength) 125 | 126 | Kdf(c.key, salt.Bytes(), key) 127 | writeCipher, err := c.constructor(key.Bytes()) 128 | key.Release() 129 | if err != nil { 130 | return err 131 | } 132 | writer := NewWriter(c.Conn, writeCipher, MaxPacketSize) 133 | header := writer.Buffer() 134 | common.Must1(header.Write(salt.Bytes())) 135 | bufferedWriter := writer.BufferedWriter(header.Len()) 136 | 137 | if len(payload) > 0 { 138 | err = M.SocksaddrSerializer.WriteAddrPort(bufferedWriter, c.destination) 139 | if err != nil { 140 | return err 141 | } 142 | 143 | _, err = bufferedWriter.Write(payload) 144 | if err != nil { 145 | return err 146 | } 147 | } else { 148 | err = M.SocksaddrSerializer.WriteAddrPort(bufferedWriter, c.destination) 149 | if err != nil { 150 | return err 151 | } 152 | } 153 | 154 | err = bufferedWriter.Flush() 155 | if err != nil { 156 | return err 157 | } 158 | 159 | c.writer = writer 160 | return nil 161 | } 162 | 163 | func (c *clientConn) readResponse() error { 164 | salt := buf.NewSize(c.keySaltLength) 165 | defer salt.Release() 166 | _, err := salt.ReadFullFrom(c.Conn, c.keySaltLength) 167 | if err != nil { 168 | return err 169 | } 170 | key := buf.NewSize(c.keySaltLength) 171 | defer key.Release() 172 | Kdf(c.key, salt.Bytes(), key) 173 | readCipher, err := c.constructor(key.Bytes()) 174 | if err != nil { 175 | return err 176 | } 177 | c.reader = NewReader( 178 | c.Conn, 179 | readCipher, 180 | MaxPacketSize, 181 | ) 182 | return nil 183 | } 184 | 185 | func (c *clientConn) Read(p []byte) (n int, err error) { 186 | if c.reader == nil { 187 | if err = c.readResponse(); err != nil { 188 | return 189 | } 190 | } 191 | return c.reader.Read(p) 192 | } 193 | 194 | func (c *clientConn) WriteTo(w io.Writer) (n int64, err error) { 195 | if c.reader == nil { 196 | if err = c.readResponse(); err != nil { 197 | return 198 | } 199 | } 200 | return c.reader.WriteTo(w) 201 | } 202 | 203 | func (c *clientConn) Write(p []byte) (n int, err error) { 204 | if c.writer == nil { 205 | err = c.writeRequest(p) 206 | if err != nil { 207 | return 208 | } 209 | return len(p), nil 210 | } 211 | return c.writer.Write(p) 212 | } 213 | 214 | func (c *clientConn) NeedHandshake() bool { 215 | return c.writer == nil 216 | } 217 | 218 | func (c *clientConn) NeedAdditionalReadDeadline() bool { 219 | return true 220 | } 221 | 222 | func (c *clientConn) Upstream() any { 223 | return c.Conn 224 | } 225 | 226 | type clientPacketConn struct { 227 | *Method 228 | net.Conn 229 | } 230 | 231 | func (c *clientPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { 232 | defer buffer.Release() 233 | header := buf.With(buffer.ExtendHeader(c.keySaltLength + M.SocksaddrSerializer.AddrPortLen(destination))) 234 | header.WriteRandom(c.keySaltLength) 235 | err := M.SocksaddrSerializer.WriteAddrPort(header, destination) 236 | if err != nil { 237 | return err 238 | } 239 | key := buf.NewSize(c.keySaltLength) 240 | Kdf(c.key, buffer.To(c.keySaltLength), key) 241 | writeCipher, err := c.constructor(key.Bytes()) 242 | key.Release() 243 | if err != nil { 244 | return err 245 | } 246 | writeCipher.Seal(buffer.Index(c.keySaltLength), rw.ZeroBytes[:writeCipher.NonceSize()], buffer.From(c.keySaltLength), nil) 247 | buffer.Extend(Overhead) 248 | return common.Error(c.Write(buffer.Bytes())) 249 | } 250 | 251 | func (c *clientPacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) { 252 | n, err := c.Read(buffer.FreeBytes()) 253 | if err != nil { 254 | return M.Socksaddr{}, err 255 | } 256 | buffer.Truncate(n) 257 | if buffer.Len() < c.keySaltLength { 258 | return M.Socksaddr{}, io.ErrShortBuffer 259 | } 260 | key := buf.NewSize(c.keySaltLength) 261 | Kdf(c.key, buffer.To(c.keySaltLength), key) 262 | readCipher, err := c.constructor(key.Bytes()) 263 | key.Release() 264 | if err != nil { 265 | return M.Socksaddr{}, err 266 | } 267 | packet, err := readCipher.Open(buffer.Index(c.keySaltLength), rw.ZeroBytes[:readCipher.NonceSize()], buffer.From(c.keySaltLength), nil) 268 | if err != nil { 269 | return M.Socksaddr{}, err 270 | } 271 | buffer.Advance(c.keySaltLength) 272 | buffer.Truncate(len(packet)) 273 | if err != nil { 274 | return M.Socksaddr{}, err 275 | } 276 | return M.SocksaddrSerializer.ReadAddrPort(buffer) 277 | } 278 | 279 | func (c *clientPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { 280 | buffer := buf.With(p) 281 | destination, err := c.ReadPacket(buffer) 282 | if err != nil { 283 | return 284 | } 285 | if destination.IsFqdn() { 286 | addr = destination 287 | } else { 288 | addr = destination.UDPAddr() 289 | } 290 | n = copy(p, buffer.Bytes()) 291 | return 292 | } 293 | 294 | func (c *clientPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { 295 | destination := M.SocksaddrFromNet(addr) 296 | buffer := buf.NewSize(c.keySaltLength + M.SocksaddrSerializer.AddrPortLen(destination) + len(p) + Overhead) 297 | defer buffer.Release() 298 | buffer.Resize(c.keySaltLength+M.SocksaddrSerializer.AddrPortLen(destination), 0) 299 | common.Must1(buffer.Write(p)) 300 | err = c.WritePacket(buffer, destination) 301 | if err != nil { 302 | return 303 | } 304 | return len(p), nil 305 | } 306 | 307 | func (c *clientPacketConn) FrontHeadroom() int { 308 | return c.keySaltLength + M.MaxSocksaddrLength 309 | } 310 | 311 | func (c *clientPacketConn) RearHeadroom() int { 312 | return Overhead 313 | } 314 | 315 | func (c *clientPacketConn) ReaderMTU() int { 316 | return MaxPacketSize 317 | } 318 | 319 | func (c *clientPacketConn) WriterMTU() int { 320 | return MaxPacketSize 321 | } 322 | 323 | func (c *clientPacketConn) Upstream() any { 324 | return c.Conn 325 | } 326 | -------------------------------------------------------------------------------- /shadowaead/service.go: -------------------------------------------------------------------------------- 1 | package shadowaead 2 | 3 | import ( 4 | "context" 5 | "crypto/rand" 6 | "io" 7 | "net" 8 | "net/netip" 9 | "sync" 10 | 11 | "github.com/sagernet/sing-shadowsocks" 12 | "github.com/sagernet/sing/common" 13 | "github.com/sagernet/sing/common/buf" 14 | E "github.com/sagernet/sing/common/exceptions" 15 | M "github.com/sagernet/sing/common/metadata" 16 | N "github.com/sagernet/sing/common/network" 17 | "github.com/sagernet/sing/common/rw" 18 | "github.com/sagernet/sing/common/udpnat" 19 | ) 20 | 21 | var ErrBadHeader = E.New("bad header") 22 | 23 | var _ shadowsocks.Service = (*Service)(nil) 24 | 25 | type Service struct { 26 | *Method 27 | password string 28 | handler shadowsocks.Handler 29 | udpNat *udpnat.Service[netip.AddrPort] 30 | } 31 | 32 | func NewService(method string, key []byte, password string, udpTimeout int64, handler shadowsocks.Handler) (*Service, error) { 33 | m, err := New(method, key, password) 34 | if err != nil { 35 | return nil, err 36 | } 37 | s := &Service{ 38 | Method: m, 39 | handler: handler, 40 | udpNat: udpnat.New[netip.AddrPort](udpTimeout, handler), 41 | } 42 | return s, nil 43 | } 44 | 45 | func (s *Service) Name() string { 46 | return s.name 47 | } 48 | 49 | func (s *Service) Password() string { 50 | return s.password 51 | } 52 | 53 | func (s *Service) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 54 | err := s.newConnection(ctx, conn, metadata) 55 | if err != nil { 56 | err = &shadowsocks.ServerConnError{Conn: conn, Source: metadata.Source, Cause: err} 57 | } 58 | return err 59 | } 60 | 61 | func (s *Service) newConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 62 | header := buf.NewSize(s.keySaltLength + PacketLengthBufferSize + Overhead) 63 | defer header.Release() 64 | 65 | _, err := header.ReadFullFrom(conn, header.FreeLen()) 66 | if err != nil { 67 | return E.Cause(err, "read header") 68 | } else if !header.IsFull() { 69 | return ErrBadHeader 70 | } 71 | 72 | key := buf.NewSize(s.keySaltLength) 73 | Kdf(s.key, header.To(s.keySaltLength), key) 74 | readCipher, err := s.constructor(key.Bytes()) 75 | key.Release() 76 | if err != nil { 77 | return err 78 | } 79 | reader := NewReader(conn, readCipher, MaxPacketSize) 80 | 81 | err = reader.ReadWithLengthChunk(header.From(s.keySaltLength)) 82 | if err != nil { 83 | return err 84 | } 85 | 86 | destination, err := M.SocksaddrSerializer.ReadAddrPort(reader) 87 | if err != nil { 88 | return err 89 | } 90 | 91 | metadata.Protocol = "shadowsocks" 92 | metadata.Destination = destination 93 | 94 | return s.handler.NewConnection(ctx, &serverConn{ 95 | Method: s.Method, 96 | Conn: conn, 97 | reader: reader, 98 | }, metadata) 99 | } 100 | 101 | func (s *Service) NewError(ctx context.Context, err error) { 102 | s.handler.NewError(ctx, err) 103 | } 104 | 105 | type serverConn struct { 106 | *Method 107 | net.Conn 108 | access sync.Mutex 109 | reader *Reader 110 | writer *Writer 111 | } 112 | 113 | func (c *serverConn) writeResponse(payload []byte) (n int, err error) { 114 | salt := buf.NewSize(c.keySaltLength) 115 | salt.WriteRandom(c.keySaltLength) 116 | 117 | key := buf.NewSize(c.keySaltLength) 118 | 119 | Kdf(c.key, salt.Bytes(), key) 120 | writeCipher, err := c.constructor(key.Bytes()) 121 | key.Release() 122 | if err != nil { 123 | salt.Release() 124 | return 125 | } 126 | writer := NewWriter(c.Conn, writeCipher, MaxPacketSize) 127 | 128 | header := writer.Buffer() 129 | common.Must1(header.Write(salt.Bytes())) 130 | salt.Release() 131 | 132 | bufferedWriter := writer.BufferedWriter(header.Len()) 133 | if len(payload) > 0 { 134 | n, err = bufferedWriter.Write(payload) 135 | if err != nil { 136 | return 137 | } 138 | } 139 | 140 | err = bufferedWriter.Flush() 141 | if err != nil { 142 | return 143 | } 144 | 145 | c.writer = writer 146 | return 147 | } 148 | 149 | func (c *serverConn) Read(b []byte) (n int, err error) { 150 | return c.reader.Read(b) 151 | } 152 | 153 | func (c *serverConn) Write(p []byte) (n int, err error) { 154 | if c.writer != nil { 155 | return c.writer.Write(p) 156 | } 157 | c.access.Lock() 158 | if c.writer != nil { 159 | c.access.Unlock() 160 | return c.writer.Write(p) 161 | } 162 | defer c.access.Unlock() 163 | return c.writeResponse(p) 164 | } 165 | 166 | func (c *serverConn) WriteTo(w io.Writer) (n int64, err error) { 167 | return c.reader.WriteTo(w) 168 | } 169 | 170 | func (c *serverConn) NeedAdditionalReadDeadline() bool { 171 | return true 172 | } 173 | 174 | func (c *serverConn) Upstream() any { 175 | return c.Conn 176 | } 177 | 178 | func (c *serverConn) ReaderMTU() int { 179 | return MaxPacketSize 180 | } 181 | 182 | func (c *Service) WriteIsThreadUnsafe() { 183 | } 184 | 185 | func (s *Service) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 186 | err := s.newPacket(ctx, conn, buffer, metadata) 187 | if err != nil { 188 | err = &shadowsocks.ServerPacketError{Source: metadata.Source, Cause: err} 189 | } 190 | return err 191 | } 192 | 193 | func (s *Service) newPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 194 | if buffer.Len() < s.keySaltLength { 195 | return io.ErrShortBuffer 196 | } 197 | key := buf.NewSize(s.keySaltLength) 198 | Kdf(s.key, buffer.To(s.keySaltLength), key) 199 | readCipher, err := s.constructor(key.Bytes()) 200 | key.Release() 201 | if err != nil { 202 | return err 203 | } 204 | packet, err := readCipher.Open(buffer.Index(s.keySaltLength), rw.ZeroBytes[:readCipher.NonceSize()], buffer.From(s.keySaltLength), nil) 205 | if err != nil { 206 | return err 207 | } 208 | buffer.Advance(s.keySaltLength) 209 | buffer.Truncate(len(packet)) 210 | 211 | destination, err := M.SocksaddrSerializer.ReadAddrPort(buffer) 212 | if err != nil { 213 | return err 214 | } 215 | 216 | metadata.Protocol = "shadowsocks" 217 | metadata.Destination = destination 218 | s.udpNat.NewPacket(ctx, metadata.Source.AddrPort(), buffer, metadata, func(natConn N.PacketConn) N.PacketWriter { 219 | return &serverPacketWriter{s.Method, conn, natConn} 220 | }) 221 | return nil 222 | } 223 | 224 | type serverPacketWriter struct { 225 | *Method 226 | source N.PacketConn 227 | nat N.PacketConn 228 | } 229 | 230 | func (w *serverPacketWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { 231 | header := buffer.ExtendHeader(w.keySaltLength + M.SocksaddrSerializer.AddrPortLen(destination)) 232 | common.Must1(io.ReadFull(rand.Reader, header[:w.keySaltLength])) 233 | err := M.SocksaddrSerializer.WriteAddrPort(buf.With(header[w.keySaltLength:]), destination) 234 | if err != nil { 235 | buffer.Release() 236 | return err 237 | } 238 | key := buf.NewSize(w.keySaltLength) 239 | Kdf(w.key, buffer.To(w.keySaltLength), key) 240 | writeCipher, err := w.constructor(key.Bytes()) 241 | key.Release() 242 | if err != nil { 243 | return err 244 | } 245 | writeCipher.Seal(buffer.From(w.keySaltLength)[:0], rw.ZeroBytes[:writeCipher.NonceSize()], buffer.From(w.keySaltLength), nil) 246 | buffer.Extend(Overhead) 247 | return w.source.WritePacket(buffer, M.SocksaddrFromNet(w.nat.LocalAddr())) 248 | } 249 | 250 | func (w *serverPacketWriter) FrontHeadroom() int { 251 | return w.keySaltLength + M.MaxSocksaddrLength 252 | } 253 | 254 | func (w *serverPacketWriter) RearHeadroom() int { 255 | return Overhead 256 | } 257 | 258 | func (w *serverPacketWriter) WriterMTU() int { 259 | return MaxPacketSize 260 | } 261 | 262 | func (w *serverPacketWriter) Upstream() any { 263 | return w.source 264 | } 265 | 266 | func (w *serverPacketWriter) ReaderMTU() int { 267 | return MaxPacketSize 268 | } 269 | 270 | func (w *serverPacketWriter) WriteIsThreadUnsafe() { 271 | } 272 | -------------------------------------------------------------------------------- /shadowaead/service_multi.go: -------------------------------------------------------------------------------- 1 | package shadowaead 2 | 3 | import ( 4 | "context" 5 | "crypto/cipher" 6 | "io" 7 | "net" 8 | "net/netip" 9 | 10 | "github.com/sagernet/sing-shadowsocks" 11 | "github.com/sagernet/sing/common/auth" 12 | "github.com/sagernet/sing/common/buf" 13 | E "github.com/sagernet/sing/common/exceptions" 14 | M "github.com/sagernet/sing/common/metadata" 15 | N "github.com/sagernet/sing/common/network" 16 | "github.com/sagernet/sing/common/rw" 17 | "github.com/sagernet/sing/common/udpnat" 18 | ) 19 | 20 | var _ shadowsocks.MultiService[int] = (*MultiService[int])(nil) 21 | 22 | type MultiService[U comparable] struct { 23 | name string 24 | methodMap map[U]*Method 25 | handler shadowsocks.Handler 26 | udpNat *udpnat.Service[netip.AddrPort] 27 | } 28 | 29 | func NewMultiService[U comparable](method string, udpTimeout int64, handler shadowsocks.Handler) (*MultiService[U], error) { 30 | s := &MultiService[U]{ 31 | name: method, 32 | handler: handler, 33 | udpNat: udpnat.New[netip.AddrPort](udpTimeout, handler), 34 | } 35 | return s, nil 36 | } 37 | 38 | func (s *MultiService[U]) Name() string { 39 | return s.name 40 | } 41 | 42 | func (s *MultiService[U]) UpdateUsers(userList []U, keyList [][]byte) error { 43 | s.methodMap = make(map[U]*Method) 44 | for i, user := range userList { 45 | key := keyList[i] 46 | method, err := New(s.name, key, "") 47 | if err != nil { 48 | return err 49 | } 50 | s.methodMap[user] = method 51 | } 52 | return nil 53 | } 54 | 55 | func (s *MultiService[U]) UpdateUsersWithPasswords(userList []U, passwordList []string) error { 56 | s.methodMap = make(map[U]*Method) 57 | for i, user := range userList { 58 | password := passwordList[i] 59 | method, err := New(s.name, nil, password) 60 | if err != nil { 61 | return err 62 | } 63 | s.methodMap[user] = method 64 | } 65 | return nil 66 | } 67 | 68 | func (s *MultiService[U]) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 69 | err := s.newConnection(ctx, conn, metadata) 70 | if err != nil { 71 | err = &shadowsocks.ServerConnError{Conn: conn, Source: metadata.Source, Cause: err} 72 | } 73 | return err 74 | } 75 | 76 | func (s *MultiService[U]) newConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 77 | var user U 78 | var method *Method 79 | for u, m := range s.methodMap { 80 | user, method = u, m 81 | break 82 | } 83 | if method == nil { 84 | return shadowsocks.ErrNoUsers 85 | } 86 | header := buf.NewSize(method.keySaltLength + PacketLengthBufferSize + Overhead) 87 | defer header.Release() 88 | 89 | _, err := header.ReadFullFrom(conn, header.FreeLen()) 90 | if err != nil { 91 | return E.Cause(err, "read header") 92 | } else if !header.IsFull() { 93 | return ErrBadHeader 94 | } 95 | 96 | var reader *Reader 97 | var readCipher cipher.AEAD 98 | for u, m := range s.methodMap { 99 | key := buf.NewSize(method.keySaltLength) 100 | Kdf(m.key, header.To(m.keySaltLength), key) 101 | readCipher, err = m.constructor(key.Bytes()) 102 | key.Release() 103 | if err != nil { 104 | return err 105 | } 106 | reader = NewReader(conn, readCipher, MaxPacketSize) 107 | 108 | err = reader.ReadWithLengthChunk(header.From(method.keySaltLength)) 109 | if err != nil { 110 | continue 111 | } 112 | 113 | user, method = u, m 114 | break 115 | } 116 | if err != nil { 117 | return err 118 | } 119 | 120 | destination, err := M.SocksaddrSerializer.ReadAddrPort(reader) 121 | if err != nil { 122 | return err 123 | } 124 | 125 | metadata.Protocol = "shadowsocks" 126 | metadata.Destination = destination 127 | 128 | return s.handler.NewConnection(auth.ContextWithUser(ctx, user), &serverConn{ 129 | Method: method, 130 | Conn: conn, 131 | reader: reader, 132 | }, metadata) 133 | } 134 | 135 | func (s *MultiService[U]) WriteIsThreadUnsafe() { 136 | } 137 | 138 | func (s *MultiService[U]) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 139 | err := s.newPacket(ctx, conn, buffer, metadata) 140 | if err != nil { 141 | err = &shadowsocks.ServerPacketError{Source: metadata.Source, Cause: err} 142 | } 143 | return err 144 | } 145 | 146 | func (s *MultiService[U]) newPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 147 | var user U 148 | var method *Method 149 | for u, m := range s.methodMap { 150 | user, method = u, m 151 | break 152 | } 153 | if method == nil { 154 | return shadowsocks.ErrNoUsers 155 | } 156 | if buffer.Len() < method.keySaltLength { 157 | return io.ErrShortBuffer 158 | } 159 | var readCipher cipher.AEAD 160 | var err error 161 | decrypted := make([]byte, 0, buffer.Len()) 162 | for u, m := range s.methodMap { 163 | key := buf.NewSize(m.keySaltLength) 164 | Kdf(m.key, buffer.To(m.keySaltLength), key) 165 | readCipher, err = m.constructor(key.Bytes()) 166 | key.Release() 167 | if err != nil { 168 | return err 169 | } 170 | var packet []byte 171 | packet, err = readCipher.Open(decrypted, rw.ZeroBytes[:readCipher.NonceSize()], buffer.From(m.keySaltLength), nil) 172 | if err != nil { 173 | continue 174 | } 175 | 176 | buffer.Advance(m.keySaltLength) 177 | buffer.Truncate(len(packet)) 178 | copy(buffer.Bytes(), packet) 179 | 180 | user, method = u, m 181 | break 182 | } 183 | if err != nil { 184 | return err 185 | } 186 | 187 | destination, err := M.SocksaddrSerializer.ReadAddrPort(buffer) 188 | if err != nil { 189 | return err 190 | } 191 | 192 | metadata.Protocol = "shadowsocks" 193 | metadata.Destination = destination 194 | s.udpNat.NewPacket(auth.ContextWithUser(ctx, user), metadata.Source.AddrPort(), buffer, metadata, func(natConn N.PacketConn) N.PacketWriter { 195 | return &serverPacketWriter{method, conn, natConn} 196 | }) 197 | return nil 198 | } 199 | 200 | func (s *MultiService[U]) NewError(ctx context.Context, err error) { 201 | s.handler.NewError(ctx, err) 202 | } 203 | -------------------------------------------------------------------------------- /shadowaead_2022/protocol.go: -------------------------------------------------------------------------------- 1 | package shadowaead_2022 2 | 3 | import ( 4 | "bytes" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | "crypto/rand" 8 | "crypto/sha256" 9 | "encoding/base64" 10 | "encoding/binary" 11 | "io" 12 | "math" 13 | mRand "math/rand" 14 | "net" 15 | "os" 16 | "strings" 17 | "sync/atomic" 18 | "time" 19 | 20 | "github.com/sagernet/sing-shadowsocks" 21 | "github.com/sagernet/sing-shadowsocks/shadowaead" 22 | "github.com/sagernet/sing/common" 23 | "github.com/sagernet/sing/common/buf" 24 | "github.com/sagernet/sing/common/bufio" 25 | E "github.com/sagernet/sing/common/exceptions" 26 | M "github.com/sagernet/sing/common/metadata" 27 | N "github.com/sagernet/sing/common/network" 28 | "github.com/sagernet/sing/common/random" 29 | "github.com/sagernet/sing/common/rw" 30 | 31 | "golang.org/x/crypto/chacha20poly1305" 32 | "lukechampine.com/blake3" 33 | ) 34 | 35 | const ( 36 | HeaderTypeClient = 0 37 | HeaderTypeServer = 1 38 | MaxPaddingLength = 900 39 | PacketNonceSize = 24 40 | MaxPacketSize = 65535 41 | RequestHeaderFixedChunkLength = 1 + 8 + 2 42 | PacketMinimalHeaderSize = 30 43 | ) 44 | 45 | var ( 46 | ErrMissingPSK = E.New("missing psk") 47 | ErrBadHeaderType = E.New("bad header type") 48 | ErrBadTimestamp = E.New("bad timestamp") 49 | ErrBadRequestSalt = E.New("bad request salt") 50 | ErrSaltNotUnique = E.New("salt not unique") 51 | ErrBadClientSessionId = E.New("bad client session id") 52 | ErrPacketIdNotUnique = E.New("packet id not unique") 53 | ErrTooManyServerSessions = E.New("server session changed more than once during the last minute") 54 | ErrPacketTooShort = E.New("packet too short") 55 | ) 56 | 57 | var List = []string{ 58 | "2022-blake3-aes-128-gcm", 59 | "2022-blake3-aes-256-gcm", 60 | "2022-blake3-chacha20-poly1305", 61 | } 62 | 63 | func init() { 64 | random.InitializeSeed() 65 | } 66 | 67 | func NewWithPassword(method string, password string, timeFunc func() time.Time) (shadowsocks.Method, error) { 68 | var pskList [][]byte 69 | if password == "" { 70 | return nil, ErrMissingPSK 71 | } 72 | keyStrList := strings.Split(password, ":") 73 | pskList = make([][]byte, len(keyStrList)) 74 | for i, keyStr := range keyStrList { 75 | kb, err := base64.StdEncoding.DecodeString(keyStr) 76 | if err != nil { 77 | return nil, E.Cause(err, "decode key") 78 | } 79 | pskList[i] = kb 80 | } 81 | return New(method, pskList, timeFunc) 82 | } 83 | 84 | func New(method string, pskList [][]byte, timeFunc func() time.Time) (shadowsocks.Method, error) { 85 | m := &Method{ 86 | name: method, 87 | timeFunc: timeFunc, 88 | } 89 | 90 | switch method { 91 | case "2022-blake3-aes-128-gcm": 92 | m.keySaltLength = 16 93 | m.constructor = aeadCipher(aes.NewCipher, cipher.NewGCM) 94 | m.blockConstructor = aes.NewCipher 95 | case "2022-blake3-aes-256-gcm": 96 | m.keySaltLength = 32 97 | m.constructor = aeadCipher(aes.NewCipher, cipher.NewGCM) 98 | m.blockConstructor = aes.NewCipher 99 | case "2022-blake3-chacha20-poly1305": 100 | if len(pskList) > 1 { 101 | return nil, os.ErrInvalid 102 | } 103 | m.keySaltLength = 32 104 | m.constructor = chacha20poly1305.New 105 | } 106 | 107 | if len(pskList) == 0 { 108 | return nil, ErrMissingPSK 109 | } 110 | 111 | for i, psk := range pskList { 112 | if len(psk) < m.keySaltLength { 113 | return nil, shadowsocks.ErrBadKey 114 | } else if len(psk) > m.keySaltLength { 115 | pskList[i] = Key(psk, m.keySaltLength) 116 | } 117 | } 118 | 119 | if len(pskList) > 1 { 120 | pskHash := make([]byte, (len(pskList)-1)*aes.BlockSize) 121 | for i, psk := range pskList { 122 | if i == 0 { 123 | continue 124 | } 125 | hash := blake3.Sum512(psk) 126 | copy(pskHash[aes.BlockSize*(i-1):aes.BlockSize*i], hash[:aes.BlockSize]) 127 | } 128 | m.pskHash = pskHash 129 | } 130 | 131 | var err error 132 | switch method { 133 | case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 134 | m.udpBlockEncryptCipher, err = aes.NewCipher(pskList[0]) 135 | if err != nil { 136 | return nil, err 137 | } 138 | m.udpBlockDecryptCipher, err = aes.NewCipher(pskList[len(pskList)-1]) 139 | if err != nil { 140 | return nil, err 141 | } 142 | case "2022-blake3-chacha20-poly1305": 143 | m.udpCipher, err = chacha20poly1305.NewX(pskList[0]) 144 | if err != nil { 145 | return nil, err 146 | } 147 | } 148 | 149 | m.pskList = pskList 150 | return m, nil 151 | } 152 | 153 | func Key(key []byte, keyLength int) []byte { 154 | psk := sha256.Sum256(key) 155 | return psk[:keyLength] 156 | } 157 | 158 | func SessionKey(psk []byte, salt []byte, keyLength int) []byte { 159 | sessionKey := make([]byte, len(psk)+len(salt)) 160 | copy(sessionKey, psk) 161 | copy(sessionKey[len(psk):], salt) 162 | outKey := make([]byte, keyLength) 163 | blake3.DeriveKey(outKey, "shadowsocks 2022 session subkey", sessionKey) 164 | return outKey 165 | } 166 | 167 | func aeadCipher(block func(key []byte) (cipher.Block, error), aead func(block cipher.Block) (cipher.AEAD, error)) func(key []byte) (cipher.AEAD, error) { 168 | return func(key []byte) (cipher.AEAD, error) { 169 | b, err := block(key) 170 | if err != nil { 171 | return nil, err 172 | } 173 | return aead(b) 174 | } 175 | } 176 | 177 | type Method struct { 178 | name string 179 | keySaltLength int 180 | timeFunc func() time.Time 181 | 182 | constructor func(key []byte) (cipher.AEAD, error) 183 | blockConstructor func(key []byte) (cipher.Block, error) 184 | udpCipher cipher.AEAD 185 | udpBlockEncryptCipher cipher.Block 186 | udpBlockDecryptCipher cipher.Block 187 | pskList [][]byte 188 | pskHash []byte 189 | } 190 | 191 | func (m *Method) Name() string { 192 | return m.name 193 | } 194 | 195 | func (m *Method) DialConn(conn net.Conn, destination M.Socksaddr) (net.Conn, error) { 196 | shadowsocksConn := &clientConn{ 197 | Method: m, 198 | Conn: conn, 199 | destination: destination, 200 | } 201 | return shadowsocksConn, shadowsocksConn.writeRequest(nil) 202 | } 203 | 204 | func (m *Method) DialEarlyConn(conn net.Conn, destination M.Socksaddr) net.Conn { 205 | return &clientConn{ 206 | Method: m, 207 | Conn: conn, 208 | destination: destination, 209 | } 210 | } 211 | 212 | func (m *Method) DialPacketConn(conn net.Conn) N.NetPacketConn { 213 | return &clientPacketConn{m, conn, m.newUDPSession()} 214 | } 215 | 216 | type clientConn struct { 217 | *Method 218 | net.Conn 219 | destination M.Socksaddr 220 | requestSalt []byte 221 | reader *shadowaead.Reader 222 | writer *shadowaead.Writer 223 | } 224 | 225 | func (m *Method) time() time.Time { 226 | if m.timeFunc != nil { 227 | return m.timeFunc() 228 | } else { 229 | return time.Now() 230 | } 231 | } 232 | 233 | func (m *Method) writeExtendedIdentityHeaders(request *buf.Buffer, salt []byte) error { 234 | pskLen := len(m.pskList) 235 | if pskLen < 2 { 236 | return nil 237 | } 238 | for i, psk := range m.pskList { 239 | keyMaterial := make([]byte, m.keySaltLength*2) 240 | copy(keyMaterial, psk) 241 | copy(keyMaterial[m.keySaltLength:], salt) 242 | identitySubkey := buf.NewSize(m.keySaltLength) 243 | identitySubkey.Extend(identitySubkey.FreeLen()) 244 | blake3.DeriveKey(identitySubkey.Bytes(), "shadowsocks 2022 identity subkey", keyMaterial) 245 | 246 | pskHash := m.pskHash[aes.BlockSize*i : aes.BlockSize*(i+1)] 247 | 248 | header := request.Extend(16) 249 | b, err := m.blockConstructor(identitySubkey.Bytes()) 250 | if err != nil { 251 | return err 252 | } 253 | b.Encrypt(header, pskHash) 254 | identitySubkey.Release() 255 | if i == pskLen-2 { 256 | break 257 | } 258 | } 259 | return nil 260 | } 261 | 262 | func (c *clientConn) writeRequest(payload []byte) error { 263 | salt := make([]byte, c.keySaltLength) 264 | common.Must1(io.ReadFull(rand.Reader, salt)) 265 | 266 | key := SessionKey(c.pskList[len(c.pskList)-1], salt, c.keySaltLength) 267 | writeCipher, err := c.constructor(key) 268 | if err != nil { 269 | return err 270 | } 271 | writer := shadowaead.NewWriter( 272 | c.Conn, 273 | writeCipher, 274 | MaxPacketSize, 275 | ) 276 | 277 | header := writer.Buffer() 278 | header.Write(salt) 279 | 280 | err = c.writeExtendedIdentityHeaders(header, salt) 281 | if err != nil { 282 | return err 283 | } 284 | 285 | var _fixedLengthBuffer [RequestHeaderFixedChunkLength]byte 286 | fixedLengthBuffer := buf.With(_fixedLengthBuffer[:]) 287 | common.Must(fixedLengthBuffer.WriteByte(HeaderTypeClient)) 288 | common.Must(binary.Write(fixedLengthBuffer, binary.BigEndian, uint64(c.time().Unix()))) 289 | var paddingLen int 290 | if len(payload) < MaxPaddingLength { 291 | paddingLen = mRand.Intn(MaxPaddingLength) + 1 292 | } 293 | variableLengthHeaderLen := M.SocksaddrSerializer.AddrPortLen(c.destination) + 2 + paddingLen 294 | payloadLen := len(payload) 295 | variableLengthHeaderLen += payloadLen 296 | common.Must(binary.Write(fixedLengthBuffer, binary.BigEndian, uint16(variableLengthHeaderLen))) 297 | writer.WriteChunk(header, fixedLengthBuffer.Bytes()) 298 | 299 | variableLengthBuffer := buf.NewSize(variableLengthHeaderLen) 300 | err = M.SocksaddrSerializer.WriteAddrPort(variableLengthBuffer, c.destination) 301 | if err != nil { 302 | return err 303 | } 304 | common.Must(binary.Write(variableLengthBuffer, binary.BigEndian, uint16(paddingLen))) 305 | if paddingLen > 0 { 306 | variableLengthBuffer.Extend(paddingLen) 307 | } 308 | if payloadLen > 0 { 309 | common.Must1(variableLengthBuffer.Write(payload[:payloadLen])) 310 | } 311 | writer.WriteChunk(header, variableLengthBuffer.Bytes()) 312 | variableLengthBuffer.Release() 313 | 314 | err = writer.BufferedWriter(header.Len()).Flush() 315 | if err != nil { 316 | return E.Cause(err, "client handshake") 317 | } 318 | 319 | c.requestSalt = salt 320 | c.writer = writer 321 | return nil 322 | } 323 | 324 | func (c *clientConn) readResponse() error { 325 | if c.reader != nil { 326 | return nil 327 | } 328 | 329 | salt := buf.NewSize(c.keySaltLength) 330 | 331 | _, err := salt.ReadFullFrom(c.Conn, salt.FreeLen()) 332 | if err != nil { 333 | salt.Release() 334 | return err 335 | } 336 | 337 | key := SessionKey(c.pskList[len(c.pskList)-1], salt.Bytes(), c.keySaltLength) 338 | salt.Release() 339 | 340 | readCipher, err := c.constructor(key) 341 | if err != nil { 342 | return err 343 | } 344 | reader := shadowaead.NewReader( 345 | c.Conn, 346 | readCipher, 347 | MaxPacketSize, 348 | ) 349 | 350 | err = reader.ReadWithLength(uint16(1 + 8 + c.keySaltLength + 2)) 351 | if err != nil { 352 | return E.Cause(err, "read response fixed length chunk") 353 | } 354 | 355 | headerType, err := rw.ReadByte(reader) 356 | if err != nil { 357 | return err 358 | } 359 | if headerType != HeaderTypeServer /* && headerType != HeaderTypeServerEncrypted*/ { 360 | return E.Extend(ErrBadHeaderType, "expected ", HeaderTypeServer, ", got ", headerType) 361 | } 362 | 363 | var epoch uint64 364 | err = binary.Read(reader, binary.BigEndian, &epoch) 365 | if err != nil { 366 | return err 367 | } 368 | 369 | diff := int(math.Abs(float64(c.time().Unix() - int64(epoch)))) 370 | if diff > 30 { 371 | return E.Extend(ErrBadTimestamp, "received ", epoch, ", diff ", diff, "s") 372 | } 373 | 374 | requestSalt := buf.NewSize(c.keySaltLength) 375 | _, err = requestSalt.ReadFullFrom(reader, requestSalt.FreeLen()) 376 | if err != nil { 377 | return err 378 | } 379 | 380 | if bytes.Compare(requestSalt.Bytes(), c.requestSalt) > 0 { 381 | return ErrBadRequestSalt 382 | } 383 | requestSalt.Release() 384 | c.requestSalt = nil 385 | 386 | var length uint16 387 | err = binary.Read(reader, binary.BigEndian, &length) 388 | if err != nil { 389 | return err 390 | } 391 | 392 | err = reader.ReadWithLength(length) 393 | if err != nil { 394 | return err 395 | } 396 | if headerType == HeaderTypeServer { 397 | c.reader = reader 398 | } 399 | return nil 400 | } 401 | 402 | func (c *clientConn) Read(p []byte) (n int, err error) { 403 | if err = c.readResponse(); err != nil { 404 | return 405 | } 406 | return c.reader.Read(p) 407 | } 408 | 409 | func (c *clientConn) WriteTo(w io.Writer) (n int64, err error) { 410 | if err = c.readResponse(); err != nil { 411 | return 412 | } 413 | return bufio.Copy(w, c.reader) 414 | } 415 | 416 | func (c *clientConn) Write(p []byte) (n int, err error) { 417 | if c.writer == nil { 418 | err = c.writeRequest(p) 419 | if err == nil { 420 | n = len(p) 421 | } 422 | return 423 | } 424 | return c.writer.Write(p) 425 | } 426 | 427 | var _ N.VectorisedWriter = (*clientConn)(nil) 428 | 429 | func (c *clientConn) WriteVectorised(buffers []*buf.Buffer) error { 430 | if c.writer != nil { 431 | return c.writer.WriteVectorised(buffers) 432 | } 433 | err := c.writeRequest(buffers[0].Bytes()) 434 | if err != nil { 435 | buf.ReleaseMulti(buffers) 436 | return err 437 | } 438 | buffers[0].Release() 439 | return c.writer.WriteVectorised(buffers[1:]) 440 | } 441 | 442 | func (c *clientConn) NeedHandshake() bool { 443 | return c.writer == nil 444 | } 445 | 446 | func (c *clientConn) NeedAdditionalReadDeadline() bool { 447 | return true 448 | } 449 | 450 | func (c *clientConn) Upstream() any { 451 | return c.Conn 452 | } 453 | 454 | func (c *clientConn) Close() error { 455 | return common.Close( 456 | c.Conn, 457 | common.PtrOrNil(c.reader), 458 | common.PtrOrNil(c.writer), 459 | ) 460 | } 461 | 462 | type clientPacketConn struct { 463 | *Method 464 | net.Conn 465 | session *udpSession 466 | } 467 | 468 | func (c *clientPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { 469 | defer buffer.Release() 470 | var hdrLen int 471 | if c.udpCipher != nil { 472 | hdrLen = PacketNonceSize 473 | } 474 | 475 | var paddingLen int 476 | if destination.Port == 53 && buffer.Len() < MaxPaddingLength { 477 | paddingLen = mRand.Intn(MaxPaddingLength-buffer.Len()) + 1 478 | } 479 | 480 | hdrLen += 16 // packet header 481 | pskLen := len(c.pskList) 482 | if c.udpCipher == nil && pskLen > 1 { 483 | hdrLen += (pskLen - 1) * aes.BlockSize 484 | } 485 | hdrLen += 1 // header type 486 | hdrLen += 8 // timestamp 487 | hdrLen += 2 // padding length 488 | hdrLen += paddingLen 489 | hdrLen += M.SocksaddrSerializer.AddrPortLen(destination) 490 | header := buf.With(buffer.ExtendHeader(hdrLen)) 491 | 492 | var dataIndex int 493 | if c.udpCipher != nil { 494 | common.Must1(header.ReadFullFrom(c.session.rng, PacketNonceSize)) 495 | if pskLen > 1 { 496 | panic("unsupported chacha extended header") 497 | } 498 | dataIndex = PacketNonceSize 499 | } else { 500 | dataIndex = aes.BlockSize 501 | } 502 | 503 | common.Must( 504 | binary.Write(header, binary.BigEndian, c.session.sessionId), 505 | binary.Write(header, binary.BigEndian, c.session.nextPacketId()), 506 | ) 507 | 508 | if c.udpCipher == nil && pskLen > 1 { 509 | for i, psk := range c.pskList { 510 | dataIndex += aes.BlockSize 511 | pskHash := c.pskHash[aes.BlockSize*i : aes.BlockSize*(i+1)] 512 | 513 | identityHeader := header.Extend(aes.BlockSize) 514 | xorWords(identityHeader, pskHash, header.To(aes.BlockSize)) 515 | b, err := c.blockConstructor(psk) 516 | if err != nil { 517 | return err 518 | } 519 | b.Encrypt(identityHeader, identityHeader) 520 | 521 | if i == pskLen-2 { 522 | break 523 | } 524 | } 525 | } 526 | common.Must( 527 | header.WriteByte(HeaderTypeClient), 528 | binary.Write(header, binary.BigEndian, uint64(c.time().Unix())), 529 | binary.Write(header, binary.BigEndian, uint16(paddingLen)), // padding length 530 | ) 531 | 532 | if paddingLen > 0 { 533 | header.Extend(paddingLen) 534 | } 535 | 536 | err := M.SocksaddrSerializer.WriteAddrPort(header, destination) 537 | if err != nil { 538 | return err 539 | } 540 | if c.udpCipher != nil { 541 | c.udpCipher.Seal(buffer.Index(dataIndex), buffer.To(dataIndex), buffer.From(dataIndex), nil) 542 | buffer.Extend(shadowaead.Overhead) 543 | } else { 544 | packetHeader := buffer.To(aes.BlockSize) 545 | c.session.cipher.Seal(buffer.Index(dataIndex), packetHeader[4:16], buffer.From(dataIndex), nil) 546 | buffer.Extend(shadowaead.Overhead) 547 | c.udpBlockEncryptCipher.Encrypt(packetHeader, packetHeader) 548 | } 549 | return common.Error(c.Write(buffer.Bytes())) 550 | } 551 | 552 | func (c *clientPacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) { 553 | n, err := c.Read(buffer.FreeBytes()) 554 | if err != nil { 555 | return M.Socksaddr{}, err 556 | } 557 | buffer.Truncate(n) 558 | 559 | var packetHeader []byte 560 | if c.udpCipher != nil { 561 | if buffer.Len() < PacketNonceSize+PacketMinimalHeaderSize { 562 | return M.Socksaddr{}, ErrPacketTooShort 563 | } 564 | _, err = c.udpCipher.Open(buffer.Index(PacketNonceSize), buffer.To(PacketNonceSize), buffer.From(PacketNonceSize), nil) 565 | if err != nil { 566 | return M.Socksaddr{}, E.Cause(err, "decrypt packet") 567 | } 568 | buffer.Advance(PacketNonceSize) 569 | buffer.Truncate(buffer.Len() - shadowaead.Overhead) 570 | } else { 571 | if buffer.Len() < PacketMinimalHeaderSize { 572 | return M.Socksaddr{}, ErrPacketTooShort 573 | } 574 | packetHeader = buffer.To(aes.BlockSize) 575 | c.udpBlockDecryptCipher.Decrypt(packetHeader, packetHeader) 576 | } 577 | 578 | var sessionId, packetId uint64 579 | err = binary.Read(buffer, binary.BigEndian, &sessionId) 580 | if err != nil { 581 | return M.Socksaddr{}, err 582 | } 583 | err = binary.Read(buffer, binary.BigEndian, &packetId) 584 | if err != nil { 585 | return M.Socksaddr{}, err 586 | } 587 | 588 | if sessionId == c.session.remoteSessionId { 589 | if !c.session.window.Check(packetId) { 590 | return M.Socksaddr{}, ErrPacketIdNotUnique 591 | } 592 | } else if sessionId == c.session.lastRemoteSessionId { 593 | if !c.session.lastWindow.Check(packetId) { 594 | return M.Socksaddr{}, ErrPacketIdNotUnique 595 | } 596 | } 597 | 598 | var remoteCipher cipher.AEAD 599 | if packetHeader != nil { 600 | if sessionId == c.session.remoteSessionId { 601 | remoteCipher = c.session.remoteCipher 602 | } else if sessionId == c.session.lastRemoteSessionId { 603 | remoteCipher = c.session.lastRemoteCipher 604 | } else { 605 | key := SessionKey(c.pskList[len(c.pskList)-1], packetHeader[:8], c.keySaltLength) 606 | remoteCipher, err = c.constructor(key) 607 | if err != nil { 608 | return M.Socksaddr{}, err 609 | } 610 | } 611 | _, err = remoteCipher.Open(buffer.Index(0), packetHeader[4:16], buffer.Bytes(), nil) 612 | if err != nil { 613 | return M.Socksaddr{}, E.Cause(err, "decrypt packet") 614 | } 615 | buffer.Truncate(buffer.Len() - shadowaead.Overhead) 616 | } 617 | 618 | var headerType byte 619 | headerType, err = buffer.ReadByte() 620 | if err != nil { 621 | return M.Socksaddr{}, err 622 | } 623 | if headerType != HeaderTypeServer { 624 | return M.Socksaddr{}, E.Extend(ErrBadHeaderType, "expected ", HeaderTypeServer, ", got ", headerType) 625 | } 626 | 627 | var epoch uint64 628 | err = binary.Read(buffer, binary.BigEndian, &epoch) 629 | if err != nil { 630 | return M.Socksaddr{}, err 631 | } 632 | 633 | diff := int(math.Abs(float64(c.time().Unix() - int64(epoch)))) 634 | if diff > 30 { 635 | return M.Socksaddr{}, E.Extend(ErrBadTimestamp, "received ", epoch, ", diff ", diff, "s") 636 | } 637 | 638 | if sessionId == c.session.remoteSessionId { 639 | c.session.window.Add(packetId) 640 | } else if sessionId == c.session.lastRemoteSessionId { 641 | c.session.lastWindow.Add(packetId) 642 | c.session.lastRemoteSeen = c.time().Unix() 643 | } else { 644 | if c.session.remoteSessionId != 0 { 645 | if c.time().Unix()-c.session.lastRemoteSeen < 60 { 646 | return M.Socksaddr{}, ErrTooManyServerSessions 647 | } else { 648 | c.session.lastRemoteSessionId = c.session.remoteSessionId 649 | c.session.lastWindow = c.session.window 650 | c.session.lastRemoteSeen = c.time().Unix() 651 | c.session.lastRemoteCipher = c.session.remoteCipher 652 | c.session.window = SlidingWindow{} 653 | } 654 | } 655 | c.session.remoteSessionId = sessionId 656 | c.session.remoteCipher = remoteCipher 657 | c.session.window.Add(packetId) 658 | } 659 | 660 | var clientSessionId uint64 661 | err = binary.Read(buffer, binary.BigEndian, &clientSessionId) 662 | if err != nil { 663 | return M.Socksaddr{}, err 664 | } 665 | 666 | if clientSessionId != c.session.sessionId { 667 | return M.Socksaddr{}, ErrBadClientSessionId 668 | } 669 | 670 | var paddingLen uint16 671 | err = binary.Read(buffer, binary.BigEndian, &paddingLen) 672 | if err != nil { 673 | return M.Socksaddr{}, E.Cause(err, "read padding length") 674 | } 675 | buffer.Advance(int(paddingLen)) 676 | 677 | destination, err := M.SocksaddrSerializer.ReadAddrPort(buffer) 678 | if err != nil { 679 | return M.Socksaddr{}, err 680 | } 681 | return destination, nil 682 | } 683 | 684 | func (c *clientPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { 685 | buffer := buf.With(p) 686 | destination, err := c.ReadPacket(buffer) 687 | if err != nil { 688 | return 689 | } 690 | if destination.IsFqdn() { 691 | addr = destination 692 | } else { 693 | addr = destination.UDPAddr() 694 | } 695 | n = copy(p, buffer.Bytes()) 696 | return 697 | } 698 | 699 | func (c *clientPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { 700 | destination := M.SocksaddrFromNet(addr) 701 | var overHead int 702 | if c.udpCipher != nil { 703 | overHead = PacketNonceSize + shadowaead.Overhead 704 | } else { 705 | overHead = shadowaead.Overhead 706 | } 707 | overHead += 16 // packet header 708 | pskLen := len(c.pskList) 709 | if c.udpCipher == nil && pskLen > 1 { 710 | overHead += (pskLen - 1) * aes.BlockSize 711 | } 712 | var paddingLen int 713 | if destination.Port == 53 && len(p) < MaxPaddingLength { 714 | paddingLen = mRand.Intn(MaxPaddingLength-len(p)) + 1 715 | } 716 | overHead += 1 // header type 717 | overHead += 8 // timestamp 718 | overHead += 2 // padding length 719 | overHead += paddingLen 720 | overHead += M.SocksaddrSerializer.AddrPortLen(destination) 721 | 722 | buffer := buf.NewSize(overHead + len(p)) 723 | defer buffer.Release() 724 | 725 | var dataIndex int 726 | if c.udpCipher != nil { 727 | common.Must1(buffer.ReadFullFrom(c.session.rng, PacketNonceSize)) 728 | if pskLen > 1 { 729 | panic("unsupported chacha extended header") 730 | } 731 | dataIndex = PacketNonceSize 732 | } else { 733 | dataIndex = aes.BlockSize 734 | } 735 | 736 | common.Must( 737 | binary.Write(buffer, binary.BigEndian, c.session.sessionId), 738 | binary.Write(buffer, binary.BigEndian, c.session.nextPacketId()), 739 | ) 740 | 741 | if c.udpCipher == nil && pskLen > 1 { 742 | for i, psk := range c.pskList { 743 | dataIndex += aes.BlockSize 744 | pskHash := c.pskHash[aes.BlockSize*i : aes.BlockSize*(i+1)] 745 | 746 | identityHeader := buffer.Extend(aes.BlockSize) 747 | xorWords(identityHeader, pskHash, buffer.To(aes.BlockSize)) 748 | b, err := c.blockConstructor(psk) 749 | if err != nil { 750 | return 0, err 751 | } 752 | b.Encrypt(identityHeader, identityHeader) 753 | 754 | if i == pskLen-2 { 755 | break 756 | } 757 | } 758 | } 759 | common.Must( 760 | buffer.WriteByte(HeaderTypeClient), 761 | binary.Write(buffer, binary.BigEndian, uint64(c.time().Unix())), 762 | binary.Write(buffer, binary.BigEndian, uint16(paddingLen)), // padding length 763 | ) 764 | 765 | if paddingLen > 0 { 766 | buffer.Extend(paddingLen) 767 | } 768 | 769 | err = M.SocksaddrSerializer.WriteAddrPort(buffer, destination) 770 | if err != nil { 771 | return 772 | } 773 | common.Must1(buffer.Write(p)) 774 | if c.udpCipher != nil { 775 | c.udpCipher.Seal(buffer.Index(dataIndex), buffer.To(dataIndex), buffer.From(dataIndex), nil) 776 | buffer.Extend(shadowaead.Overhead) 777 | } else { 778 | packetHeader := buffer.To(aes.BlockSize) 779 | c.session.cipher.Seal(buffer.Index(dataIndex), packetHeader[4:16], buffer.From(dataIndex), nil) 780 | buffer.Extend(shadowaead.Overhead) 781 | c.udpBlockEncryptCipher.Encrypt(packetHeader, packetHeader) 782 | } 783 | err = common.Error(c.Write(buffer.Bytes())) 784 | if err != nil { 785 | return 786 | } 787 | return len(p), nil 788 | } 789 | 790 | func (c *clientPacketConn) FrontHeadroom() int { 791 | var overHead int 792 | if c.udpCipher != nil { 793 | overHead = PacketNonceSize + shadowaead.Overhead 794 | } else { 795 | overHead = shadowaead.Overhead 796 | } 797 | overHead += 16 // packet header 798 | pskLen := len(c.pskList) 799 | if c.udpCipher == nil && pskLen > 1 { 800 | overHead += (pskLen - 1) * aes.BlockSize 801 | } 802 | overHead += 1 // header type 803 | overHead += 8 // timestamp 804 | overHead += 2 // padding length 805 | overHead += MaxPaddingLength 806 | overHead += M.MaxSocksaddrLength 807 | return overHead 808 | } 809 | 810 | func (c *clientPacketConn) RearHeadroom() int { 811 | return shadowaead.Overhead 812 | } 813 | 814 | type udpSession struct { 815 | sessionId uint64 816 | packetId uint64 817 | remoteSessionId uint64 818 | lastRemoteSessionId uint64 819 | lastRemoteSeen int64 820 | cipher cipher.AEAD 821 | remoteCipher cipher.AEAD 822 | lastRemoteCipher cipher.AEAD 823 | window SlidingWindow 824 | lastWindow SlidingWindow 825 | rng io.Reader 826 | } 827 | 828 | func (s *udpSession) nextPacketId() uint64 { 829 | return atomic.AddUint64(&s.packetId, 1) 830 | } 831 | 832 | func (m *Method) newUDPSession() *udpSession { 833 | session := &udpSession{} 834 | if m.udpCipher != nil { 835 | session.rng = Blake3KeyedHash(rand.Reader) 836 | common.Must(binary.Read(session.rng, binary.BigEndian, &session.sessionId)) 837 | } else { 838 | common.Must(binary.Read(rand.Reader, binary.BigEndian, &session.sessionId)) 839 | } 840 | session.packetId-- 841 | if m.udpCipher == nil { 842 | sessionId := make([]byte, 8) 843 | binary.BigEndian.PutUint64(sessionId, session.sessionId) 844 | key := SessionKey(m.pskList[len(m.pskList)-1], sessionId, m.keySaltLength) 845 | var err error 846 | session.cipher, err = m.constructor(key) 847 | if err != nil { 848 | return nil 849 | } 850 | } 851 | return session 852 | } 853 | 854 | func (c *clientPacketConn) Upstream() any { 855 | return c.Conn 856 | } 857 | 858 | func (c *clientPacketConn) Close() error { 859 | return common.Close(c.Conn) 860 | } 861 | 862 | func Blake3KeyedHash(reader io.Reader) io.Reader { 863 | key := make([]byte, 32) 864 | common.Must1(io.ReadFull(reader, key)) 865 | h := blake3.New(1024, key) 866 | return h.XOF() 867 | } 868 | -------------------------------------------------------------------------------- /shadowaead_2022/relay.go: -------------------------------------------------------------------------------- 1 | package shadowaead_2022 2 | 3 | import ( 4 | "context" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | "encoding/base64" 8 | "encoding/binary" 9 | "net" 10 | "os" 11 | 12 | "github.com/sagernet/sing-shadowsocks" 13 | "github.com/sagernet/sing-shadowsocks/shadowaead" 14 | "github.com/sagernet/sing/common/auth" 15 | "github.com/sagernet/sing/common/buf" 16 | "github.com/sagernet/sing/common/bufio" 17 | E "github.com/sagernet/sing/common/exceptions" 18 | M "github.com/sagernet/sing/common/metadata" 19 | N "github.com/sagernet/sing/common/network" 20 | "github.com/sagernet/sing/common/udpnat" 21 | 22 | "lukechampine.com/blake3" 23 | ) 24 | 25 | var _ shadowsocks.Service = (*RelayService[int])(nil) 26 | 27 | type RelayService[U comparable] struct { 28 | name string 29 | keySaltLength int 30 | handler shadowsocks.Handler 31 | 32 | constructor func(key []byte) (cipher.AEAD, error) 33 | blockConstructor func(key []byte) (cipher.Block, error) 34 | udpBlockCipher cipher.Block 35 | 36 | iPSK []byte 37 | uPSKHash map[[aes.BlockSize]byte]U 38 | uDestination map[U]M.Socksaddr 39 | uCipher map[U]cipher.Block 40 | udpNat *udpnat.Service[uint64] 41 | } 42 | 43 | func (s *RelayService[U]) Name() string { 44 | return s.name 45 | } 46 | 47 | func (s *RelayService[U]) Password() string { 48 | return base64.StdEncoding.EncodeToString(s.iPSK) 49 | } 50 | 51 | func (s *RelayService[U]) UpdateUsers(userList []U, keyList [][]byte, destinationList []M.Socksaddr) error { 52 | uPSKHash := make(map[[aes.BlockSize]byte]U) 53 | uDestination := make(map[U]M.Socksaddr) 54 | uCipher := make(map[U]cipher.Block) 55 | for i, user := range userList { 56 | key := keyList[i] 57 | destination := destinationList[i] 58 | if len(key) < s.keySaltLength { 59 | return shadowsocks.ErrBadKey 60 | } else if len(key) > s.keySaltLength { 61 | key = Key(key, s.keySaltLength) 62 | } 63 | 64 | var hash [aes.BlockSize]byte 65 | hash512 := blake3.Sum512(key) 66 | copy(hash[:], hash512[:]) 67 | 68 | uPSKHash[hash] = user 69 | uDestination[user] = destination 70 | var err error 71 | uCipher[user], err = s.blockConstructor(key) 72 | if err != nil { 73 | return err 74 | } 75 | } 76 | 77 | s.uPSKHash = uPSKHash 78 | s.uDestination = uDestination 79 | s.uCipher = uCipher 80 | return nil 81 | } 82 | 83 | func (s *RelayService[U]) UpdateUsersWithPasswords(userList []U, passwordList []string, destinationList []M.Socksaddr) error { 84 | keyList := make([][]byte, 0, len(passwordList)) 85 | for _, password := range passwordList { 86 | if password == "" { 87 | return shadowsocks.ErrMissingPassword 88 | } 89 | uPSK, err := base64.StdEncoding.DecodeString(password) 90 | if err != nil { 91 | return E.Cause(err, "decode psk") 92 | } 93 | keyList = append(keyList, uPSK) 94 | } 95 | return s.UpdateUsers(userList, keyList, destinationList) 96 | } 97 | 98 | func NewRelayServiceWithPassword[U comparable](method string, password string, udpTimeout int64, handler shadowsocks.Handler) (*RelayService[U], error) { 99 | if password == "" { 100 | return nil, ErrMissingPSK 101 | } 102 | iPSK, err := base64.StdEncoding.DecodeString(password) 103 | if err != nil { 104 | return nil, E.Cause(err, "decode psk") 105 | } 106 | return NewRelayService[U](method, iPSK, udpTimeout, handler) 107 | } 108 | 109 | func NewRelayService[U comparable](method string, psk []byte, udpTimeout int64, handler shadowsocks.Handler) (*RelayService[U], error) { 110 | s := &RelayService[U]{ 111 | name: method, 112 | handler: handler, 113 | 114 | uPSKHash: make(map[[aes.BlockSize]byte]U), 115 | uDestination: make(map[U]M.Socksaddr), 116 | uCipher: make(map[U]cipher.Block), 117 | 118 | udpNat: udpnat.New[uint64](udpTimeout, handler), 119 | } 120 | 121 | switch method { 122 | case "2022-blake3-aes-128-gcm": 123 | s.keySaltLength = 16 124 | s.constructor = aeadCipher(aes.NewCipher, cipher.NewGCM) 125 | s.blockConstructor = aes.NewCipher 126 | case "2022-blake3-aes-256-gcm": 127 | s.keySaltLength = 32 128 | s.constructor = aeadCipher(aes.NewCipher, cipher.NewGCM) 129 | s.blockConstructor = aes.NewCipher 130 | default: 131 | return nil, os.ErrInvalid 132 | } 133 | if len(psk) != s.keySaltLength { 134 | if len(psk) < s.keySaltLength { 135 | return nil, shadowsocks.ErrBadKey 136 | } else { 137 | psk = Key(psk, s.keySaltLength) 138 | } 139 | } 140 | s.iPSK = psk 141 | var err error 142 | s.udpBlockCipher, err = s.blockConstructor(psk) 143 | return s, err 144 | } 145 | 146 | func (s *RelayService[U]) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 147 | err := s.newConnection(ctx, conn, metadata) 148 | if err != nil { 149 | err = &shadowsocks.ServerConnError{Conn: conn, Source: metadata.Source, Cause: err} 150 | } 151 | return err 152 | } 153 | 154 | func (s *RelayService[U]) newConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 155 | requestHeader := buf.New() 156 | defer requestHeader.Release() 157 | n, err := requestHeader.ReadOnceFrom(conn) 158 | if err != nil { 159 | return err 160 | } else if int(n) < s.keySaltLength+aes.BlockSize { 161 | return shadowaead.ErrBadHeader 162 | } 163 | requestSalt := requestHeader.To(s.keySaltLength) 164 | var _eiHeader [aes.BlockSize]byte 165 | eiHeader := _eiHeader[:] 166 | copy(eiHeader, requestHeader.Range(s.keySaltLength, s.keySaltLength+aes.BlockSize)) 167 | 168 | keyMaterial := make([]byte, s.keySaltLength*2) 169 | copy(keyMaterial, s.iPSK) 170 | copy(keyMaterial[s.keySaltLength:], requestSalt) 171 | identitySubkey := buf.NewSize(s.keySaltLength) 172 | identitySubkey.Extend(identitySubkey.FreeLen()) 173 | blake3.DeriveKey(identitySubkey.Bytes(), "shadowsocks 2022 identity subkey", keyMaterial) 174 | b, err := s.blockConstructor(identitySubkey.Bytes()) 175 | identitySubkey.Release() 176 | if err != nil { 177 | return err 178 | } 179 | b.Decrypt(eiHeader, eiHeader) 180 | 181 | var user U 182 | if u, loaded := s.uPSKHash[_eiHeader]; loaded { 183 | user = u 184 | } else { 185 | return E.New("invalid request") 186 | } 187 | 188 | copy(requestHeader.Range(aes.BlockSize, aes.BlockSize+s.keySaltLength), requestHeader.To(s.keySaltLength)) 189 | requestHeader.Advance(aes.BlockSize) 190 | 191 | metadata.Protocol = "shadowsocks-relay" 192 | metadata.Destination = s.uDestination[user] 193 | conn = bufio.NewCachedConn(conn, requestHeader) 194 | return s.handler.NewConnection(auth.ContextWithUser(ctx, user), conn, metadata) 195 | } 196 | 197 | func (s *RelayService[U]) WriteIsThreadUnsafe() { 198 | } 199 | 200 | func (s *RelayService[U]) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 201 | err := s.newPacket(ctx, conn, buffer, metadata) 202 | if err != nil { 203 | err = &shadowsocks.ServerPacketError{Source: metadata.Source, Cause: err} 204 | } 205 | return err 206 | } 207 | 208 | func (s *RelayService[U]) newPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 209 | packetHeader := buffer.To(aes.BlockSize) 210 | s.udpBlockCipher.Decrypt(packetHeader, packetHeader) 211 | 212 | sessionId := binary.BigEndian.Uint64(packetHeader) 213 | 214 | var _eiHeader [aes.BlockSize]byte 215 | eiHeader := _eiHeader[:] 216 | s.udpBlockCipher.Decrypt(eiHeader, buffer.Range(aes.BlockSize, 2*aes.BlockSize)) 217 | xorWords(eiHeader, eiHeader, packetHeader) 218 | 219 | var user U 220 | if u, loaded := s.uPSKHash[_eiHeader]; loaded { 221 | user = u 222 | } else { 223 | return E.New("invalid request") 224 | } 225 | 226 | s.uCipher[user].Encrypt(packetHeader, packetHeader) 227 | copy(buffer.Range(aes.BlockSize, 2*aes.BlockSize), packetHeader) 228 | buffer.Advance(aes.BlockSize) 229 | 230 | metadata.Protocol = "shadowsocks-relay" 231 | metadata.Destination = s.uDestination[user] 232 | s.udpNat.NewContextPacket(ctx, sessionId, buffer, metadata, func(natConn N.PacketConn) (context.Context, N.PacketWriter) { 233 | return auth.ContextWithUser(ctx, user), &udpnat.DirectBackWriter{Source: conn, Nat: natConn} 234 | }) 235 | return nil 236 | } 237 | 238 | func (s *RelayService[U]) NewError(ctx context.Context, err error) { 239 | s.handler.NewError(ctx, err) 240 | } 241 | -------------------------------------------------------------------------------- /shadowaead_2022/service.go: -------------------------------------------------------------------------------- 1 | package shadowaead_2022 2 | 3 | import ( 4 | "context" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | "crypto/rand" 8 | "encoding/base64" 9 | "encoding/binary" 10 | "io" 11 | "math" 12 | mRand "math/rand" 13 | "net" 14 | "os" 15 | "sync" 16 | "sync/atomic" 17 | "time" 18 | 19 | "github.com/sagernet/sing-shadowsocks" 20 | "github.com/sagernet/sing-shadowsocks/shadowaead" 21 | "github.com/sagernet/sing/common" 22 | "github.com/sagernet/sing/common/buf" 23 | "github.com/sagernet/sing/common/cache" 24 | E "github.com/sagernet/sing/common/exceptions" 25 | M "github.com/sagernet/sing/common/metadata" 26 | N "github.com/sagernet/sing/common/network" 27 | "github.com/sagernet/sing/common/replay" 28 | "github.com/sagernet/sing/common/udpnat" 29 | 30 | "golang.org/x/crypto/chacha20poly1305" 31 | ) 32 | 33 | var ( 34 | ErrInvalidRequest = E.New("invalid request") 35 | ErrNoPadding = E.New("bad request: missing payload or padding") 36 | ErrBadPadding = E.New("bad request: damaged padding") 37 | ) 38 | 39 | var _ shadowsocks.Service = (*Service)(nil) 40 | 41 | type Service struct { 42 | name string 43 | keySaltLength int 44 | handler shadowsocks.Handler 45 | timeFunc func() time.Time 46 | 47 | constructor func(key []byte) (cipher.AEAD, error) 48 | blockConstructor func(key []byte) (cipher.Block, error) 49 | udpCipher cipher.AEAD 50 | udpBlockCipher cipher.Block 51 | psk []byte 52 | 53 | replayFilter replay.Filter 54 | udpNat *udpnat.Service[uint64] 55 | udpSessions *cache.LruCache[uint64, *serverUDPSession] 56 | } 57 | 58 | func NewServiceWithPassword(method string, password string, udpTimeout int64, handler shadowsocks.Handler, timeFunc func() time.Time) (shadowsocks.Service, error) { 59 | if password == "" { 60 | return nil, ErrMissingPSK 61 | } 62 | psk, err := base64.StdEncoding.DecodeString(password) 63 | if err != nil { 64 | return nil, E.Cause(err, "decode psk") 65 | } 66 | return NewService(method, psk, udpTimeout, handler, timeFunc) 67 | } 68 | 69 | func NewService(method string, psk []byte, udpTimeout int64, handler shadowsocks.Handler, timeFunc func() time.Time) (shadowsocks.Service, error) { 70 | s := &Service{ 71 | name: method, 72 | handler: handler, 73 | timeFunc: timeFunc, 74 | 75 | replayFilter: replay.NewSimple(60 * time.Second), 76 | udpNat: udpnat.New[uint64](udpTimeout, handler), 77 | udpSessions: cache.New[uint64, *serverUDPSession]( 78 | cache.WithAge[uint64, *serverUDPSession](udpTimeout), 79 | cache.WithUpdateAgeOnGet[uint64, *serverUDPSession](), 80 | ), 81 | } 82 | 83 | switch method { 84 | case "2022-blake3-aes-128-gcm": 85 | s.keySaltLength = 16 86 | s.constructor = aeadCipher(aes.NewCipher, cipher.NewGCM) 87 | s.blockConstructor = aes.NewCipher 88 | case "2022-blake3-aes-256-gcm": 89 | s.keySaltLength = 32 90 | s.constructor = aeadCipher(aes.NewCipher, cipher.NewGCM) 91 | s.blockConstructor = aes.NewCipher 92 | case "2022-blake3-chacha20-poly1305": 93 | s.keySaltLength = 32 94 | s.constructor = chacha20poly1305.New 95 | default: 96 | return nil, os.ErrInvalid 97 | } 98 | 99 | if len(psk) != s.keySaltLength { 100 | if len(psk) < s.keySaltLength { 101 | return nil, shadowsocks.ErrBadKey 102 | } else if len(psk) > s.keySaltLength { 103 | psk = Key(psk, s.keySaltLength) 104 | } else { 105 | return nil, ErrMissingPSK 106 | } 107 | } 108 | 109 | var err error 110 | switch method { 111 | case "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm": 112 | s.udpBlockCipher, err = aes.NewCipher(psk) 113 | case "2022-blake3-chacha20-poly1305": 114 | s.udpCipher, err = chacha20poly1305.NewX(psk) 115 | } 116 | if err != nil { 117 | return nil, err 118 | } 119 | 120 | s.psk = psk 121 | return s, nil 122 | } 123 | 124 | func (s *Service) Name() string { 125 | return s.name 126 | } 127 | 128 | func (s *Service) Password() string { 129 | return base64.StdEncoding.EncodeToString(s.psk) 130 | } 131 | 132 | func (s *Service) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 133 | err := s.newConnection(ctx, conn, metadata) 134 | if err != nil { 135 | err = &shadowsocks.ServerConnError{Conn: conn, Source: metadata.Source, Cause: err} 136 | } 137 | return err 138 | } 139 | 140 | func (s *Service) time() time.Time { 141 | if s.timeFunc != nil { 142 | return s.timeFunc() 143 | } else { 144 | return time.Now() 145 | } 146 | } 147 | 148 | func (s *Service) newConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 149 | header := make([]byte, s.keySaltLength+shadowaead.Overhead+RequestHeaderFixedChunkLength) 150 | 151 | n, err := conn.Read(header) 152 | if err != nil { 153 | return E.Cause(err, "read header") 154 | } else if n < len(header) { 155 | return shadowaead.ErrBadHeader 156 | } 157 | 158 | requestSalt := header[:s.keySaltLength] 159 | 160 | if !s.replayFilter.Check(requestSalt) { 161 | return ErrSaltNotUnique 162 | } 163 | 164 | requestKey := SessionKey(s.psk, requestSalt, s.keySaltLength) 165 | readCipher, err := s.constructor(requestKey) 166 | if err != nil { 167 | return err 168 | } 169 | reader := shadowaead.NewReader( 170 | conn, 171 | readCipher, 172 | MaxPacketSize, 173 | ) 174 | 175 | err = reader.ReadExternalChunk(header[s.keySaltLength:]) 176 | if err != nil { 177 | return err 178 | } 179 | 180 | headerType, err := reader.ReadByte() 181 | if err != nil { 182 | return E.Cause(err, "read header") 183 | } 184 | 185 | if headerType != HeaderTypeClient { 186 | return E.Extend(ErrBadHeaderType, "expected ", HeaderTypeClient, ", got ", headerType) 187 | } 188 | 189 | var epoch uint64 190 | err = binary.Read(reader, binary.BigEndian, &epoch) 191 | if err != nil { 192 | return err 193 | } 194 | 195 | diff := int(math.Abs(float64(s.time().Unix() - int64(epoch)))) 196 | if diff > 30 { 197 | return E.Extend(ErrBadTimestamp, "received ", epoch, ", diff ", diff, "s") 198 | } 199 | 200 | var length uint16 201 | err = binary.Read(reader, binary.BigEndian, &length) 202 | if err != nil { 203 | return err 204 | } 205 | 206 | err = reader.ReadWithLength(length) 207 | if err != nil { 208 | return err 209 | } 210 | 211 | destination, err := M.SocksaddrSerializer.ReadAddrPort(reader) 212 | if err != nil { 213 | return err 214 | } 215 | 216 | var paddingLen uint16 217 | err = binary.Read(reader, binary.BigEndian, &paddingLen) 218 | if err != nil { 219 | return err 220 | } 221 | 222 | if uint16(reader.Cached()) < paddingLen { 223 | return ErrNoPadding 224 | } 225 | 226 | if paddingLen > 0 { 227 | err = reader.Discard(int(paddingLen)) 228 | if err != nil { 229 | return E.Cause(err, "discard padding") 230 | } 231 | } else if reader.Cached() == 0 { 232 | return ErrNoPadding 233 | } 234 | 235 | protocolConn := &serverConn{ 236 | Service: s, 237 | Conn: conn, 238 | uPSK: s.psk, 239 | headerType: headerType, 240 | requestSalt: requestSalt, 241 | } 242 | 243 | protocolConn.reader = reader 244 | 245 | metadata.Protocol = "shadowsocks" 246 | metadata.Destination = destination 247 | return s.handler.NewConnection(ctx, protocolConn, metadata) 248 | } 249 | 250 | type serverConn struct { 251 | *Service 252 | net.Conn 253 | uPSK []byte 254 | access sync.Mutex 255 | headerType byte 256 | reader *shadowaead.Reader 257 | writer *shadowaead.Writer 258 | requestSalt []byte 259 | } 260 | 261 | func (c *serverConn) writeResponse(payload []byte) (n int, err error) { 262 | salt := buf.NewSize(c.keySaltLength) 263 | salt.WriteRandom(salt.FreeLen()) 264 | 265 | key := SessionKey(c.uPSK, salt.Bytes(), c.keySaltLength) 266 | writeCipher, err := c.constructor(key) 267 | if err != nil { 268 | salt.Release() 269 | return 270 | } 271 | writer := shadowaead.NewWriter( 272 | c.Conn, 273 | writeCipher, 274 | MaxPacketSize, 275 | ) 276 | header := writer.Buffer() 277 | header.Write(salt.Bytes()) 278 | 279 | salt.Release() 280 | 281 | headerType := byte(HeaderTypeServer) 282 | payloadLen := len(payload) 283 | 284 | headerFixedChunk := buf.NewSize(1 + 8 + c.keySaltLength + 2) 285 | common.Must(headerFixedChunk.WriteByte(headerType)) 286 | common.Must(binary.Write(headerFixedChunk, binary.BigEndian, uint64(c.time().Unix()))) 287 | common.Must1(headerFixedChunk.Write(c.requestSalt)) 288 | common.Must(binary.Write(headerFixedChunk, binary.BigEndian, uint16(payloadLen))) 289 | 290 | writer.WriteChunk(header, headerFixedChunk.Bytes()) 291 | headerFixedChunk.Release() 292 | c.requestSalt = nil 293 | 294 | if payloadLen > 0 { 295 | writer.WriteChunk(header, payload[:payloadLen]) 296 | } 297 | 298 | err = writer.BufferedWriter(header.Len()).Flush() 299 | if err != nil { 300 | return 301 | } 302 | 303 | switch headerType { 304 | case HeaderTypeServer: 305 | c.writer = writer 306 | // case HeaderTypeServerEncrypted: 307 | // encryptedWriter := NewTLSEncryptedStreamWriter(writer) 308 | // if payloadLen < len(payload) { 309 | // _, err = encryptedWriter.Write(payload[payloadLen:]) 310 | // if err != nil { 311 | // return 312 | // } 313 | // } 314 | // c.writer = encryptedWriter 315 | } 316 | 317 | n = len(payload) 318 | return 319 | } 320 | 321 | func (c *serverConn) Read(b []byte) (n int, err error) { 322 | return c.reader.Read(b) 323 | } 324 | 325 | func (c *serverConn) Write(p []byte) (n int, err error) { 326 | if c.writer != nil { 327 | return c.writer.Write(p) 328 | } 329 | c.access.Lock() 330 | if c.writer != nil { 331 | c.access.Unlock() 332 | return c.writer.Write(p) 333 | } 334 | defer c.access.Unlock() 335 | return c.writeResponse(p) 336 | } 337 | 338 | func (c *serverConn) WriteVectorised(buffers []*buf.Buffer) error { 339 | if c.writer != nil { 340 | return c.writer.WriteVectorised(buffers) 341 | } 342 | c.access.Lock() 343 | if c.writer != nil { 344 | c.access.Unlock() 345 | return c.writer.WriteVectorised(buffers) 346 | } 347 | defer c.access.Unlock() 348 | _, err := c.writeResponse(buffers[0].Bytes()) 349 | if err != nil { 350 | buf.ReleaseMulti(buffers) 351 | return err 352 | } 353 | buffers[0].Release() 354 | return c.writer.WriteVectorised(buffers[1:]) 355 | } 356 | 357 | func (c *serverConn) Close() error { 358 | return common.Close( 359 | c.Conn, 360 | common.PtrOrNil(c.reader), 361 | common.PtrOrNil(c.writer), 362 | ) 363 | } 364 | 365 | func (c *serverConn) NeedAdditionalReadDeadline() bool { 366 | return true 367 | } 368 | 369 | func (c *serverConn) Upstream() any { 370 | return c.Conn 371 | } 372 | 373 | func (s *Service) WriteIsThreadUnsafe() { 374 | } 375 | 376 | func (s *Service) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 377 | err := s.newPacket(ctx, conn, buffer, metadata) 378 | if err != nil { 379 | err = &shadowsocks.ServerPacketError{Source: metadata.Source, Cause: err} 380 | } 381 | return err 382 | } 383 | 384 | func (s *Service) newPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 385 | var packetHeader []byte 386 | if s.udpCipher != nil { 387 | if buffer.Len() < PacketNonceSize+PacketMinimalHeaderSize { 388 | return ErrPacketTooShort 389 | } 390 | _, err := s.udpCipher.Open(buffer.Index(PacketNonceSize), buffer.To(PacketNonceSize), buffer.From(PacketNonceSize), nil) 391 | if err != nil { 392 | return E.Cause(err, "decrypt packet header") 393 | } 394 | buffer.Advance(PacketNonceSize) 395 | buffer.Truncate(buffer.Len() - shadowaead.Overhead) 396 | } else { 397 | if buffer.Len() < PacketMinimalHeaderSize { 398 | return ErrPacketTooShort 399 | } 400 | packetHeader = buffer.To(aes.BlockSize) 401 | s.udpBlockCipher.Decrypt(packetHeader, packetHeader) 402 | } 403 | 404 | var sessionId, packetId uint64 405 | err := binary.Read(buffer, binary.BigEndian, &sessionId) 406 | if err != nil { 407 | return err 408 | } 409 | err = binary.Read(buffer, binary.BigEndian, &packetId) 410 | if err != nil { 411 | return err 412 | } 413 | 414 | session, loaded := s.udpSessions.LoadOrStore(sessionId, s.newUDPSession) 415 | if !loaded { 416 | session.remoteSessionId = sessionId 417 | if packetHeader != nil { 418 | key := SessionKey(s.psk, packetHeader[:8], s.keySaltLength) 419 | session.remoteCipher, err = s.constructor(key) 420 | if err != nil { 421 | return err 422 | } 423 | } 424 | } 425 | goto process 426 | 427 | returnErr: 428 | if !loaded { 429 | s.udpSessions.Delete(sessionId) 430 | } 431 | return err 432 | 433 | process: 434 | if !session.window.Check(packetId) { 435 | err = ErrPacketIdNotUnique 436 | goto returnErr 437 | } 438 | 439 | if packetHeader != nil { 440 | _, err = session.remoteCipher.Open(buffer.Index(0), packetHeader[4:16], buffer.Bytes(), nil) 441 | if err != nil { 442 | err = E.Cause(err, "decrypt packet") 443 | goto returnErr 444 | } 445 | buffer.Truncate(buffer.Len() - shadowaead.Overhead) 446 | } 447 | 448 | session.window.Add(packetId) 449 | 450 | var headerType byte 451 | headerType, err = buffer.ReadByte() 452 | if err != nil { 453 | err = E.Cause(err, "decrypt packet") 454 | goto returnErr 455 | } 456 | if headerType != HeaderTypeClient { 457 | err = E.Extend(ErrBadHeaderType, "expected ", HeaderTypeClient, ", got ", headerType) 458 | goto returnErr 459 | } 460 | 461 | var epoch uint64 462 | err = binary.Read(buffer, binary.BigEndian, &epoch) 463 | if err != nil { 464 | goto returnErr 465 | } 466 | diff := int(math.Abs(float64(s.time().Unix() - int64(epoch)))) 467 | if diff > 30 { 468 | err = E.Extend(ErrBadTimestamp, "received ", epoch, ", diff ", diff, "s") 469 | goto returnErr 470 | } 471 | 472 | var paddingLen uint16 473 | err = binary.Read(buffer, binary.BigEndian, &paddingLen) 474 | if err != nil { 475 | err = E.Cause(err, "read padding length") 476 | goto returnErr 477 | } 478 | buffer.Advance(int(paddingLen)) 479 | 480 | destination, err := M.SocksaddrSerializer.ReadAddrPort(buffer) 481 | if err != nil { 482 | goto returnErr 483 | } 484 | metadata.Protocol = "shadowsocks" 485 | metadata.Destination = destination 486 | s.udpNat.NewPacket(ctx, sessionId, buffer, metadata, func(natConn N.PacketConn) N.PacketWriter { 487 | return &serverPacketWriter{s, conn, natConn, session, s.udpBlockCipher} 488 | }) 489 | return nil 490 | } 491 | 492 | func (s *Service) NewError(ctx context.Context, err error) { 493 | s.handler.NewError(ctx, err) 494 | } 495 | 496 | type serverPacketWriter struct { 497 | *Service 498 | source N.PacketConn 499 | nat N.PacketConn 500 | session *serverUDPSession 501 | udpBlockCipher cipher.Block 502 | } 503 | 504 | func (w *serverPacketWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { 505 | var hdrLen int 506 | if w.udpCipher != nil { 507 | hdrLen = PacketNonceSize 508 | } 509 | 510 | var paddingLen int 511 | if destination.Port == 53 && buffer.Len() < MaxPaddingLength { 512 | paddingLen = mRand.Intn(MaxPaddingLength-buffer.Len()) + 1 513 | } 514 | 515 | hdrLen += 16 // packet header 516 | hdrLen += 1 // header type 517 | hdrLen += 8 // timestamp 518 | hdrLen += 8 // remote session id 519 | hdrLen += 2 // padding length 520 | hdrLen += paddingLen 521 | hdrLen += M.SocksaddrSerializer.AddrPortLen(destination) 522 | header := buf.With(buffer.ExtendHeader(hdrLen)) 523 | 524 | var dataIndex int 525 | if w.udpCipher != nil { 526 | common.Must1(header.ReadFullFrom(w.session.rng, PacketNonceSize)) 527 | dataIndex = PacketNonceSize 528 | } else { 529 | dataIndex = aes.BlockSize 530 | } 531 | 532 | common.Must( 533 | binary.Write(header, binary.BigEndian, w.session.sessionId), 534 | binary.Write(header, binary.BigEndian, w.session.nextPacketId()), 535 | header.WriteByte(HeaderTypeServer), 536 | binary.Write(header, binary.BigEndian, uint64(w.time().Unix())), 537 | binary.Write(header, binary.BigEndian, w.session.remoteSessionId), 538 | binary.Write(header, binary.BigEndian, uint16(paddingLen)), // padding length 539 | ) 540 | 541 | if paddingLen > 0 { 542 | header.Extend(paddingLen) 543 | } 544 | 545 | err := M.SocksaddrSerializer.WriteAddrPort(header, destination) 546 | if err != nil { 547 | buffer.Release() 548 | return err 549 | } 550 | 551 | if w.udpCipher != nil { 552 | w.udpCipher.Seal(buffer.Index(dataIndex), buffer.To(dataIndex), buffer.From(dataIndex), nil) 553 | buffer.Extend(shadowaead.Overhead) 554 | } else { 555 | packetHeader := buffer.To(aes.BlockSize) 556 | w.session.cipher.Seal(buffer.Index(dataIndex), packetHeader[4:16], buffer.From(dataIndex), nil) 557 | buffer.Extend(shadowaead.Overhead) 558 | w.udpBlockCipher.Encrypt(packetHeader, packetHeader) 559 | } 560 | return w.source.WritePacket(buffer, M.SocksaddrFromNet(w.nat.LocalAddr())) 561 | } 562 | 563 | func (w *serverPacketWriter) FrontHeadroom() int { 564 | var hdrLen int 565 | if w.udpCipher != nil { 566 | hdrLen = PacketNonceSize 567 | } 568 | hdrLen += 16 // packet header 569 | hdrLen += 1 // header type 570 | hdrLen += 8 // timestamp 571 | hdrLen += 8 // remote session id 572 | hdrLen += 2 // padding length 573 | hdrLen += MaxPaddingLength 574 | hdrLen += M.MaxSocksaddrLength 575 | return hdrLen 576 | } 577 | 578 | func (w *serverPacketWriter) RearHeadroom() int { 579 | return shadowaead.Overhead 580 | } 581 | 582 | func (w *serverPacketWriter) Upstream() any { 583 | return w.source 584 | } 585 | 586 | type serverUDPSession struct { 587 | sessionId uint64 588 | remoteSessionId uint64 589 | packetId uint64 590 | cipher cipher.AEAD 591 | remoteCipher cipher.AEAD 592 | window SlidingWindow 593 | rng io.Reader 594 | } 595 | 596 | func (s *serverUDPSession) nextPacketId() uint64 { 597 | return atomic.AddUint64(&s.packetId, 1) 598 | } 599 | 600 | func (s *Service) newUDPSession() *serverUDPSession { 601 | session := &serverUDPSession{} 602 | if s.udpCipher != nil { 603 | session.rng = Blake3KeyedHash(rand.Reader) 604 | common.Must(binary.Read(session.rng, binary.BigEndian, &session.sessionId)) 605 | } else { 606 | common.Must(binary.Read(rand.Reader, binary.BigEndian, &session.sessionId)) 607 | } 608 | session.packetId-- 609 | if s.udpCipher == nil { 610 | sessionId := make([]byte, 8) 611 | binary.BigEndian.PutUint64(sessionId, session.sessionId) 612 | key := SessionKey(s.psk, sessionId, s.keySaltLength) 613 | var err error 614 | session.cipher, err = s.constructor(key) 615 | common.Must(err) 616 | } 617 | return session 618 | } 619 | -------------------------------------------------------------------------------- /shadowaead_2022/service_multi.go: -------------------------------------------------------------------------------- 1 | package shadowaead_2022 2 | 3 | import ( 4 | "context" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | "crypto/rand" 8 | "encoding/base64" 9 | "encoding/binary" 10 | "io" 11 | "math" 12 | "net" 13 | "os" 14 | "time" 15 | 16 | "github.com/sagernet/sing-shadowsocks" 17 | "github.com/sagernet/sing-shadowsocks/shadowaead" 18 | "github.com/sagernet/sing/common" 19 | "github.com/sagernet/sing/common/auth" 20 | "github.com/sagernet/sing/common/buf" 21 | E "github.com/sagernet/sing/common/exceptions" 22 | M "github.com/sagernet/sing/common/metadata" 23 | N "github.com/sagernet/sing/common/network" 24 | "github.com/sagernet/sing/common/rw" 25 | 26 | "lukechampine.com/blake3" 27 | ) 28 | 29 | var _ shadowsocks.MultiService[int] = (*MultiService[int])(nil) 30 | 31 | type MultiService[U comparable] struct { 32 | *Service 33 | 34 | uPSK map[U][]byte 35 | uPSKHash map[[aes.BlockSize]byte]U 36 | uCipher map[U]cipher.Block 37 | } 38 | 39 | func NewMultiServiceWithPassword[U comparable](method string, password string, udpTimeout int64, handler shadowsocks.Handler, timeFunc func() time.Time) (*MultiService[U], error) { 40 | if password == "" { 41 | return nil, ErrMissingPSK 42 | } 43 | iPSK, err := base64.StdEncoding.DecodeString(password) 44 | if err != nil { 45 | return nil, E.Cause(err, "decode psk") 46 | } 47 | return NewMultiService[U](method, iPSK, udpTimeout, handler, timeFunc) 48 | } 49 | 50 | func NewMultiService[U comparable](method string, iPSK []byte, udpTimeout int64, handler shadowsocks.Handler, timeFunc func() time.Time) (*MultiService[U], error) { 51 | switch method { 52 | case "2022-blake3-aes-128-gcm": 53 | case "2022-blake3-aes-256-gcm": 54 | default: 55 | return nil, os.ErrInvalid 56 | } 57 | 58 | ss, err := NewService(method, iPSK, udpTimeout, handler, timeFunc) 59 | if err != nil { 60 | return nil, err 61 | } 62 | 63 | s := &MultiService[U]{ 64 | Service: ss.(*Service), 65 | 66 | uPSK: make(map[U][]byte), 67 | uPSKHash: make(map[[aes.BlockSize]byte]U), 68 | } 69 | return s, nil 70 | } 71 | 72 | func (s *MultiService[U]) UpdateUsers(userList []U, keyList [][]byte) error { 73 | uPSK := make(map[U][]byte) 74 | uPSKHash := make(map[[aes.BlockSize]byte]U) 75 | uCipher := make(map[U]cipher.Block) 76 | for i, user := range userList { 77 | key := keyList[i] 78 | if len(key) < s.keySaltLength { 79 | return shadowsocks.ErrBadKey 80 | } else if len(key) > s.keySaltLength { 81 | key = Key(key, s.keySaltLength) 82 | } 83 | 84 | var hash [aes.BlockSize]byte 85 | hash512 := blake3.Sum512(key) 86 | copy(hash[:], hash512[:]) 87 | 88 | uPSKHash[hash] = user 89 | uPSK[user] = key 90 | var err error 91 | uCipher[user], err = s.blockConstructor(key) 92 | if err != nil { 93 | return err 94 | } 95 | } 96 | 97 | s.uPSK = uPSK 98 | s.uPSKHash = uPSKHash 99 | s.uCipher = uCipher 100 | return nil 101 | } 102 | 103 | func (s *MultiService[U]) UpdateUsersWithPasswords(userList []U, passwordList []string) error { 104 | keyList := make([][]byte, 0, len(passwordList)) 105 | for _, password := range passwordList { 106 | if password == "" { 107 | return shadowsocks.ErrMissingPassword 108 | } 109 | uPSK, err := base64.StdEncoding.DecodeString(password) 110 | if err != nil { 111 | return E.Cause(err, "decode psk") 112 | } 113 | keyList = append(keyList, uPSK) 114 | } 115 | return s.UpdateUsers(userList, keyList) 116 | } 117 | 118 | func (s *MultiService[U]) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 119 | err := s.NewConnection0(ctx, conn, metadata, conn, nil) 120 | if err != nil { 121 | err = &shadowsocks.ServerConnError{Conn: conn, Source: metadata.Source, Cause: err} 122 | } 123 | return err 124 | } 125 | 126 | func (s *MultiService[U]) NewConnection0(ctx context.Context, conn net.Conn, metadata M.Metadata, handshakeReader io.Reader, handshakeSuccess func()) error { 127 | requestHeader := make([]byte, s.keySaltLength+aes.BlockSize+shadowaead.Overhead+RequestHeaderFixedChunkLength) 128 | var ( 129 | n int 130 | err error 131 | ) 132 | if handshakeSuccess != nil { 133 | n, err = io.ReadFull(handshakeReader, requestHeader) 134 | } else { 135 | n, err = handshakeReader.Read(requestHeader) 136 | } 137 | if err != nil { 138 | return err 139 | } else if n < len(requestHeader) { 140 | return shadowaead.ErrBadHeader 141 | } 142 | requestSalt := requestHeader[:s.keySaltLength] 143 | if !s.replayFilter.Check(requestSalt) { 144 | return ErrSaltNotUnique 145 | } 146 | 147 | var _eiHeader [aes.BlockSize]byte 148 | eiHeader := _eiHeader[:] 149 | copy(eiHeader, requestHeader[s.keySaltLength:s.keySaltLength+aes.BlockSize]) 150 | 151 | keyMaterial := make([]byte, s.keySaltLength*2) 152 | copy(keyMaterial, s.psk) 153 | copy(keyMaterial[s.keySaltLength:], requestSalt) 154 | identitySubkey := buf.NewSize(s.keySaltLength) 155 | identitySubkey.Extend(identitySubkey.FreeLen()) 156 | blake3.DeriveKey(identitySubkey.Bytes(), "shadowsocks 2022 identity subkey", keyMaterial) 157 | b, err := s.blockConstructor(identitySubkey.Bytes()) 158 | identitySubkey.Release() 159 | if err != nil { 160 | return err 161 | } 162 | b.Decrypt(eiHeader, eiHeader) 163 | 164 | var user U 165 | var uPSK []byte 166 | if u, loaded := s.uPSKHash[_eiHeader]; loaded { 167 | user = u 168 | uPSK = s.uPSK[u] 169 | } else { 170 | return ErrInvalidRequest 171 | } 172 | 173 | if handshakeSuccess != nil { 174 | handshakeSuccess() 175 | } 176 | 177 | requestKey := SessionKey(uPSK, requestSalt, s.keySaltLength) 178 | readCipher, err := s.constructor(requestKey) 179 | if err != nil { 180 | return err 181 | } 182 | reader := shadowaead.NewReader( 183 | conn, 184 | readCipher, 185 | MaxPacketSize, 186 | ) 187 | 188 | err = reader.ReadExternalChunk(requestHeader[s.keySaltLength+aes.BlockSize:]) 189 | if err != nil { 190 | return err 191 | } 192 | 193 | headerType, err := rw.ReadByte(reader) 194 | if err != nil { 195 | return E.Cause(err, "read header") 196 | } 197 | 198 | if headerType != HeaderTypeClient { 199 | return E.Extend(ErrBadHeaderType, "expected ", HeaderTypeClient, ", got ", headerType) 200 | } 201 | 202 | var epoch uint64 203 | err = binary.Read(reader, binary.BigEndian, &epoch) 204 | if err != nil { 205 | return E.Cause(err, "read timestamp") 206 | } 207 | diff := int(math.Abs(float64(s.time().Unix() - int64(epoch)))) 208 | if diff > 30 { 209 | return E.Extend(ErrBadTimestamp, "received ", epoch, ", diff ", diff, "s") 210 | } 211 | var length uint16 212 | err = binary.Read(reader, binary.BigEndian, &length) 213 | if err != nil { 214 | return E.Cause(err, "read length") 215 | } 216 | 217 | err = reader.ReadWithLength(length) 218 | if err != nil { 219 | return err 220 | } 221 | 222 | destination, err := M.SocksaddrSerializer.ReadAddrPort(reader) 223 | if err != nil { 224 | return E.Cause(err, "read destination") 225 | } 226 | 227 | var paddingLen uint16 228 | err = binary.Read(reader, binary.BigEndian, &paddingLen) 229 | if err != nil { 230 | return E.Cause(err, "read padding length") 231 | } 232 | 233 | if reader.Cached() < int(paddingLen) { 234 | return ErrBadPadding 235 | } else if paddingLen > 0 { 236 | err = reader.Discard(int(paddingLen)) 237 | if err != nil { 238 | return E.Cause(err, "discard padding") 239 | } 240 | } else if reader.Cached() == 0 { 241 | return ErrNoPadding 242 | } 243 | 244 | protocolConn := &serverConn{ 245 | Service: s.Service, 246 | Conn: conn, 247 | uPSK: uPSK, 248 | headerType: headerType, 249 | requestSalt: requestSalt, 250 | } 251 | 252 | protocolConn.reader = reader 253 | metadata.Protocol = "shadowsocks" 254 | metadata.Destination = destination 255 | return s.handler.NewConnection(auth.ContextWithUser(ctx, user), protocolConn, metadata) 256 | } 257 | 258 | func (s *MultiService[U]) WriteIsThreadUnsafe() { 259 | } 260 | 261 | func (s *MultiService[U]) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 262 | err := s.newPacket(ctx, conn, buffer, metadata) 263 | if err != nil { 264 | err = &shadowsocks.ServerPacketError{Source: metadata.Source, Cause: err} 265 | } 266 | return err 267 | } 268 | 269 | func (s *MultiService[U]) newPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 270 | if buffer.Len() < PacketMinimalHeaderSize { 271 | return ErrPacketTooShort 272 | } 273 | 274 | packetHeader := buffer.To(aes.BlockSize) 275 | s.udpBlockCipher.Decrypt(packetHeader, packetHeader) 276 | 277 | var _eiHeader [aes.BlockSize]byte 278 | eiHeader := _eiHeader[:] 279 | s.udpBlockCipher.Decrypt(eiHeader, buffer.Range(aes.BlockSize, 2*aes.BlockSize)) 280 | xorWords(eiHeader, eiHeader, packetHeader) 281 | 282 | var user U 283 | var uPSK []byte 284 | if u, loaded := s.uPSKHash[_eiHeader]; loaded { 285 | user = u 286 | uPSK = s.uPSK[u] 287 | } else { 288 | return E.New("invalid request") 289 | } 290 | 291 | var sessionId, packetId uint64 292 | err := binary.Read(buffer, binary.BigEndian, &sessionId) 293 | if err != nil { 294 | return err 295 | } 296 | err = binary.Read(buffer, binary.BigEndian, &packetId) 297 | if err != nil { 298 | return err 299 | } 300 | 301 | buffer.Advance(aes.BlockSize) 302 | 303 | session, loaded := s.udpSessions.LoadOrStore(sessionId, func() *serverUDPSession { 304 | return s.newUDPSession(uPSK) 305 | }) 306 | if !loaded { 307 | session.remoteSessionId = sessionId 308 | key := SessionKey(uPSK, packetHeader[:8], s.keySaltLength) 309 | session.remoteCipher, err = s.constructor(key) 310 | if err != nil { 311 | return err 312 | } 313 | } 314 | 315 | goto process 316 | 317 | returnErr: 318 | if !loaded { 319 | s.udpSessions.Delete(sessionId) 320 | } 321 | return err 322 | 323 | process: 324 | if !session.window.Check(packetId) { 325 | err = ErrPacketIdNotUnique 326 | goto returnErr 327 | } 328 | 329 | if packetHeader != nil { 330 | _, err = session.remoteCipher.Open(buffer.Index(0), packetHeader[4:16], buffer.Bytes(), nil) 331 | if err != nil { 332 | err = E.Cause(err, "decrypt packet") 333 | goto returnErr 334 | } 335 | buffer.Truncate(buffer.Len() - shadowaead.Overhead) 336 | } 337 | 338 | session.window.Add(packetId) 339 | 340 | var headerType byte 341 | headerType, err = buffer.ReadByte() 342 | if err != nil { 343 | err = E.Cause(err, "decrypt packet") 344 | goto returnErr 345 | } 346 | if headerType != HeaderTypeClient { 347 | err = E.Extend(ErrBadHeaderType, "expected ", HeaderTypeClient, ", got ", headerType) 348 | goto returnErr 349 | } 350 | 351 | var epoch uint64 352 | err = binary.Read(buffer, binary.BigEndian, &epoch) 353 | if err != nil { 354 | goto returnErr 355 | } 356 | diff := int(math.Abs(float64(s.time().Unix() - int64(epoch)))) 357 | if diff > 30 { 358 | err = E.Extend(ErrBadTimestamp, "received ", epoch, ", diff ", diff, "s") 359 | goto returnErr 360 | } 361 | 362 | var paddingLen uint16 363 | err = binary.Read(buffer, binary.BigEndian, &paddingLen) 364 | if err != nil { 365 | err = E.Cause(err, "read padding length") 366 | goto returnErr 367 | } 368 | buffer.Advance(int(paddingLen)) 369 | 370 | destination, err := M.SocksaddrSerializer.ReadAddrPort(buffer) 371 | if err != nil { 372 | goto returnErr 373 | } 374 | 375 | metadata.Protocol = "shadowsocks" 376 | metadata.Destination = destination 377 | s.udpNat.NewContextPacket(ctx, sessionId, buffer, metadata, func(natConn N.PacketConn) (context.Context, N.PacketWriter) { 378 | return auth.ContextWithUser(ctx, user), &serverPacketWriter{s.Service, conn, natConn, session, s.uCipher[user]} 379 | }) 380 | return nil 381 | } 382 | 383 | func (s *MultiService[U]) newUDPSession(uPSK []byte) *serverUDPSession { 384 | session := &serverUDPSession{} 385 | if s.udpCipher != nil { 386 | session.rng = Blake3KeyedHash(rand.Reader) 387 | common.Must(binary.Read(session.rng, binary.BigEndian, &session.sessionId)) 388 | } else { 389 | common.Must(binary.Read(rand.Reader, binary.BigEndian, &session.sessionId)) 390 | } 391 | session.packetId-- 392 | sessionId := make([]byte, 8) 393 | binary.BigEndian.PutUint64(sessionId, session.sessionId) 394 | key := SessionKey(uPSK, sessionId, s.keySaltLength) 395 | var err error 396 | session.cipher, err = s.constructor(key) 397 | common.Must(err) 398 | return session 399 | } 400 | -------------------------------------------------------------------------------- /shadowaead_2022/service_multi_test.go: -------------------------------------------------------------------------------- 1 | package shadowaead_2022_test 2 | 3 | import ( 4 | "context" 5 | "crypto/rand" 6 | "net" 7 | "sync" 8 | "testing" 9 | 10 | "github.com/sagernet/sing-shadowsocks/shadowaead_2022" 11 | "github.com/sagernet/sing/common" 12 | E "github.com/sagernet/sing/common/exceptions" 13 | M "github.com/sagernet/sing/common/metadata" 14 | N "github.com/sagernet/sing/common/network" 15 | ) 16 | 17 | func TestMultiService(t *testing.T) { 18 | t.Parallel() 19 | method := "2022-blake3-aes-128-gcm" 20 | var iPSK [16]byte 21 | rand.Reader.Read(iPSK[:]) 22 | 23 | var wg sync.WaitGroup 24 | 25 | multiService, err := shadowaead_2022.NewMultiService[string](method, iPSK[:], 500, &multiHandler{t, &wg}, nil) 26 | if err != nil { 27 | t.Fatal(err) 28 | } 29 | 30 | var uPSK [16]byte 31 | rand.Reader.Read(uPSK[:]) 32 | multiService.UpdateUsers([]string{"my user"}, [][]byte{uPSK[:]}) 33 | 34 | client, err := shadowaead_2022.New(method, [][]byte{iPSK[:], uPSK[:]}, nil) 35 | if err != nil { 36 | t.Fatal(err) 37 | } 38 | wg.Add(1) 39 | 40 | serverConn, clientConn := net.Pipe() 41 | defer common.Close(serverConn, clientConn) 42 | go func() { 43 | err := multiService.NewConnection(context.Background(), serverConn, M.Metadata{}) 44 | if err != nil { 45 | serverConn.Close() 46 | t.Error(E.Cause(err, "server")) 47 | return 48 | } 49 | }() 50 | _, err = client.DialConn(clientConn, M.ParseSocksaddr("test.com:443")) 51 | if err != nil { 52 | t.Fatal(err) 53 | } 54 | wg.Wait() 55 | } 56 | 57 | type multiHandler struct { 58 | t *testing.T 59 | wg *sync.WaitGroup 60 | } 61 | 62 | func (h *multiHandler) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 63 | if metadata.Destination.String() != "test.com:443" { 64 | h.t.Error("bad destination") 65 | } 66 | h.wg.Done() 67 | return nil 68 | } 69 | 70 | func (h *multiHandler) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error { 71 | return nil 72 | } 73 | 74 | func (h *multiHandler) NewError(ctx context.Context, err error) { 75 | h.t.Error(ctx, err) 76 | } 77 | -------------------------------------------------------------------------------- /shadowaead_2022/service_test.go: -------------------------------------------------------------------------------- 1 | package shadowaead_2022_test 2 | 3 | import ( 4 | "context" 5 | "crypto/rand" 6 | "net" 7 | "sync" 8 | "testing" 9 | 10 | "github.com/sagernet/sing-shadowsocks/shadowaead_2022" 11 | "github.com/sagernet/sing/common" 12 | E "github.com/sagernet/sing/common/exceptions" 13 | M "github.com/sagernet/sing/common/metadata" 14 | ) 15 | 16 | func TestService(t *testing.T) { 17 | t.Parallel() 18 | method := "2022-blake3-aes-128-gcm" 19 | var psk [16]byte 20 | rand.Reader.Read(psk[:]) 21 | 22 | var wg sync.WaitGroup 23 | 24 | service, err := shadowaead_2022.NewService(method, psk[:], 500, &multiHandler{t, &wg}, nil) 25 | if err != nil { 26 | t.Fatal(err) 27 | } 28 | 29 | client, err := shadowaead_2022.New(method, [][]byte{psk[:]}, nil) 30 | if err != nil { 31 | t.Fatal(err) 32 | } 33 | wg.Add(1) 34 | 35 | serverConn, clientConn := net.Pipe() 36 | defer common.Close(serverConn, clientConn) 37 | go func() { 38 | err := service.NewConnection(context.Background(), serverConn, M.Metadata{}) 39 | if err != nil { 40 | serverConn.Close() 41 | t.Error(E.Cause(err, "server")) 42 | return 43 | } 44 | }() 45 | _, err = client.DialConn(clientConn, M.ParseSocksaddr("test.com:443")) 46 | if err != nil { 47 | t.Fatal(err) 48 | } 49 | wg.Wait() 50 | } 51 | -------------------------------------------------------------------------------- /shadowaead_2022/slidingwindow.go: -------------------------------------------------------------------------------- 1 | package shadowaead_2022 2 | 3 | const ( 4 | swBlockBitLog = 6 // 1<<6 == 64 bits 5 | swBlockBits = 1 << swBlockBitLog // must be power of 2 6 | swRingBlocks = 1 << 7 // must be power of 2 7 | swBlockMask = swRingBlocks - 1 8 | swBitMask = swBlockBits - 1 9 | swSize = (swRingBlocks - 1) * swBlockBits 10 | ) 11 | 12 | // SlidingWindow maintains a sliding window of uint64 counters. 13 | type SlidingWindow struct { 14 | last uint64 15 | ring [swRingBlocks]uint64 16 | } 17 | 18 | // Reset resets the filter to its initial state. 19 | func (f *SlidingWindow) Reset() { 20 | f.last = 0 21 | f.ring[0] = 0 22 | } 23 | 24 | // Check checks whether counter can be accepted by the sliding window filter. 25 | func (f *SlidingWindow) Check(counter uint64) bool { 26 | switch { 27 | case counter > f.last: // ahead of window 28 | return true 29 | case f.last-counter > swSize: // behind window 30 | return false 31 | } 32 | 33 | // In window. Check bit. 34 | blockIndex := counter >> swBlockBitLog & swBlockMask 35 | bitIndex := counter & swBitMask 36 | return f.ring[blockIndex]>>bitIndex&1 == 0 37 | } 38 | 39 | // Add adds counter to the sliding window without checking if the counter is valid. 40 | // Call Check beforehand to make sure the counter is valid. 41 | func (f *SlidingWindow) Add(counter uint64) { 42 | blockIndex := counter >> swBlockBitLog 43 | 44 | // Check if counter is ahead of window. 45 | if counter > f.last { 46 | lastBlockIndex := f.last >> swBlockBitLog 47 | diff := int(blockIndex - lastBlockIndex) 48 | if diff > swRingBlocks { 49 | diff = swRingBlocks 50 | } 51 | 52 | for i := 0; i < diff; i++ { 53 | lastBlockIndex = (lastBlockIndex + 1) & swBlockMask 54 | f.ring[lastBlockIndex] = 0 55 | } 56 | 57 | f.last = counter 58 | } 59 | 60 | blockIndex &= swBlockMask 61 | bitIndex := counter & swBitMask 62 | f.ring[blockIndex] |= 1 << bitIndex 63 | } 64 | -------------------------------------------------------------------------------- /shadowaead_2022/xor.go: -------------------------------------------------------------------------------- 1 | //go:build go1.20 2 | 3 | package shadowaead_2022 4 | 5 | import "crypto/subtle" 6 | 7 | var xorWords = subtle.XORBytes 8 | -------------------------------------------------------------------------------- /shadowaead_2022/xor_go119.go: -------------------------------------------------------------------------------- 1 | //go:build !go1.20 2 | 3 | package shadowaead_2022 4 | 5 | import _ "unsafe" 6 | 7 | //go:linkname xorWords crypto/cipher.xorWords 8 | //go:noescape 9 | func xorWords(dst, a, b []byte) 10 | -------------------------------------------------------------------------------- /shadowimpl/fetcher.go: -------------------------------------------------------------------------------- 1 | package shadowimpl 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/sagernet/sing-shadowsocks" 7 | "github.com/sagernet/sing-shadowsocks/shadowaead" 8 | "github.com/sagernet/sing-shadowsocks/shadowaead_2022" 9 | "github.com/sagernet/sing-shadowsocks/shadowstream" 10 | "github.com/sagernet/sing/common" 11 | E "github.com/sagernet/sing/common/exceptions" 12 | ) 13 | 14 | func FetchMethod(method string, password string, timeFunc func() time.Time) (shadowsocks.Method, error) { 15 | if method == "none" || method == "plain" || method == "dummy" { 16 | return shadowsocks.NewNone(), nil 17 | } else if common.Contains(shadowstream.List, method) { 18 | return shadowstream.New(method, nil, password) 19 | } else if common.Contains(shadowaead.List, method) { 20 | return shadowaead.New(method, nil, password) 21 | } else if common.Contains(shadowaead_2022.List, method) { 22 | return shadowaead_2022.NewWithPassword(method, password, timeFunc) 23 | } else { 24 | return nil, E.New("shadowsocks: unsupported method ", method) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /shadowsocks.go: -------------------------------------------------------------------------------- 1 | package shadowsocks 2 | 3 | import ( 4 | "crypto/md5" 5 | "net" 6 | 7 | "github.com/sagernet/sing/common" 8 | E "github.com/sagernet/sing/common/exceptions" 9 | F "github.com/sagernet/sing/common/format" 10 | M "github.com/sagernet/sing/common/metadata" 11 | N "github.com/sagernet/sing/common/network" 12 | ) 13 | 14 | var ( 15 | ErrBadKey = E.New("bad key") 16 | ErrMissingPassword = E.New("missing password") 17 | ErrNoUsers = E.New("no users") 18 | ) 19 | 20 | type Method interface { 21 | Name() string 22 | DialConn(conn net.Conn, destination M.Socksaddr) (net.Conn, error) 23 | DialEarlyConn(conn net.Conn, destination M.Socksaddr) net.Conn 24 | DialPacketConn(conn net.Conn) N.NetPacketConn 25 | } 26 | 27 | type Service interface { 28 | Name() string 29 | Password() string 30 | N.TCPConnectionHandler 31 | N.UDPHandler 32 | E.Handler 33 | } 34 | 35 | type MultiService[U comparable] interface { 36 | Name() string 37 | UpdateUsers(userList []U, keyList [][]byte) error 38 | UpdateUsersWithPasswords(userList []U, passwordList []string) error 39 | N.TCPConnectionHandler 40 | N.UDPHandler 41 | E.Handler 42 | } 43 | 44 | type Handler interface { 45 | N.TCPConnectionHandler 46 | N.UDPConnectionHandler 47 | E.Handler 48 | } 49 | 50 | type ServerConnError struct { 51 | net.Conn 52 | Source M.Socksaddr 53 | Cause error 54 | } 55 | 56 | func (e *ServerConnError) Close() error { 57 | if conn, ok := common.Cast[*net.TCPConn](e.Conn); ok { 58 | conn.SetLinger(0) 59 | } 60 | return e.Conn.Close() 61 | } 62 | 63 | func (e *ServerConnError) Unwrap() error { 64 | return e.Cause 65 | } 66 | 67 | func (e *ServerConnError) Error() string { 68 | return F.ToString("shadowsocks: serve TCP from ", e.Source, ": ", e.Cause) 69 | } 70 | 71 | type ServerPacketError struct { 72 | Source M.Socksaddr 73 | Cause error 74 | } 75 | 76 | func (e *ServerPacketError) Unwrap() error { 77 | return e.Cause 78 | } 79 | 80 | func (e *ServerPacketError) Error() string { 81 | return F.ToString("shadowsocks: serve UDP from ", e.Source, ": ", e.Cause) 82 | } 83 | 84 | func Key(password []byte, keySize int) []byte { 85 | var b, prev []byte 86 | h := md5.New() 87 | for len(b) < keySize { 88 | h.Write(prev) 89 | h.Write(password) 90 | b = h.Sum(b) 91 | prev = b[len(b)-h.Size():] 92 | h.Reset() 93 | } 94 | return b[:keySize] 95 | } 96 | -------------------------------------------------------------------------------- /shadowstream/protocol.go: -------------------------------------------------------------------------------- 1 | package shadowstream 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/md5" 7 | "crypto/rand" 8 | "crypto/rc4" 9 | "io" 10 | "net" 11 | "os" 12 | 13 | "github.com/sagernet/sing-shadowsocks" 14 | "github.com/sagernet/sing/common" 15 | "github.com/sagernet/sing/common/buf" 16 | M "github.com/sagernet/sing/common/metadata" 17 | N "github.com/sagernet/sing/common/network" 18 | 19 | "golang.org/x/crypto/chacha20" 20 | ) 21 | 22 | var List = []string{ 23 | "aes-128-ctr", 24 | "aes-192-ctr", 25 | "aes-256-ctr", 26 | "aes-128-cfb", 27 | "aes-192-cfb", 28 | "aes-256-cfb", 29 | "rc4-md5", 30 | "chacha20-ietf", 31 | "xchacha20", 32 | } 33 | 34 | type Method struct { 35 | name string 36 | keyLength int 37 | saltLength int 38 | encryptConstructor func(key []byte, salt []byte) (cipher.Stream, error) 39 | decryptConstructor func(key []byte, salt []byte) (cipher.Stream, error) 40 | key []byte 41 | } 42 | 43 | func New(method string, key []byte, password string) (shadowsocks.Method, error) { 44 | m := &Method{ 45 | name: method, 46 | } 47 | switch method { 48 | case "aes-128-ctr": 49 | m.keyLength = 16 50 | m.saltLength = aes.BlockSize 51 | m.encryptConstructor = blockStream(aes.NewCipher, cipher.NewCTR) 52 | m.decryptConstructor = blockStream(aes.NewCipher, cipher.NewCTR) 53 | case "aes-192-ctr": 54 | m.keyLength = 24 55 | m.saltLength = aes.BlockSize 56 | m.encryptConstructor = blockStream(aes.NewCipher, cipher.NewCTR) 57 | m.decryptConstructor = blockStream(aes.NewCipher, cipher.NewCTR) 58 | case "aes-256-ctr": 59 | m.keyLength = 32 60 | m.saltLength = aes.BlockSize 61 | m.encryptConstructor = blockStream(aes.NewCipher, cipher.NewCTR) 62 | m.decryptConstructor = blockStream(aes.NewCipher, cipher.NewCTR) 63 | case "aes-128-cfb": 64 | m.keyLength = 16 65 | m.saltLength = aes.BlockSize 66 | m.encryptConstructor = blockStream(aes.NewCipher, cipher.NewCFBEncrypter) 67 | m.decryptConstructor = blockStream(aes.NewCipher, cipher.NewCFBDecrypter) 68 | case "aes-192-cfb": 69 | m.keyLength = 24 70 | m.saltLength = aes.BlockSize 71 | m.encryptConstructor = blockStream(aes.NewCipher, cipher.NewCFBEncrypter) 72 | m.decryptConstructor = blockStream(aes.NewCipher, cipher.NewCFBDecrypter) 73 | case "aes-256-cfb": 74 | m.keyLength = 32 75 | m.saltLength = aes.BlockSize 76 | m.encryptConstructor = blockStream(aes.NewCipher, cipher.NewCFBEncrypter) 77 | m.decryptConstructor = blockStream(aes.NewCipher, cipher.NewCFBDecrypter) 78 | case "rc4-md5": 79 | m.keyLength = 16 80 | m.saltLength = 16 81 | m.encryptConstructor = func(key []byte, salt []byte) (cipher.Stream, error) { 82 | h := md5.New() 83 | h.Write(key) 84 | h.Write(salt) 85 | return rc4.NewCipher(h.Sum(nil)) 86 | } 87 | m.decryptConstructor = func(key []byte, salt []byte) (cipher.Stream, error) { 88 | h := md5.New() 89 | h.Write(key) 90 | h.Write(salt) 91 | return rc4.NewCipher(h.Sum(nil)) 92 | } 93 | case "chacha20-ietf": 94 | m.keyLength = chacha20.KeySize 95 | m.saltLength = chacha20.NonceSize 96 | m.encryptConstructor = func(key []byte, salt []byte) (cipher.Stream, error) { 97 | return chacha20.NewUnauthenticatedCipher(key, salt) 98 | } 99 | m.decryptConstructor = func(key []byte, salt []byte) (cipher.Stream, error) { 100 | return chacha20.NewUnauthenticatedCipher(key, salt) 101 | } 102 | case "xchacha20": 103 | m.keyLength = chacha20.KeySize 104 | m.saltLength = chacha20.NonceSizeX 105 | m.encryptConstructor = func(key []byte, salt []byte) (cipher.Stream, error) { 106 | return chacha20.NewUnauthenticatedCipher(key, salt) 107 | } 108 | m.decryptConstructor = func(key []byte, salt []byte) (cipher.Stream, error) { 109 | return chacha20.NewUnauthenticatedCipher(key, salt) 110 | } 111 | default: 112 | return nil, os.ErrInvalid 113 | } 114 | if len(key) == m.keyLength { 115 | m.key = key 116 | } else if len(key) > 0 { 117 | return nil, shadowsocks.ErrBadKey 118 | } else if password != "" { 119 | m.key = shadowsocks.Key([]byte(password), m.keyLength) 120 | } else { 121 | return nil, shadowsocks.ErrMissingPassword 122 | } 123 | return m, nil 124 | } 125 | 126 | func blockStream(blockCreator func(key []byte) (cipher.Block, error), streamCreator func(block cipher.Block, iv []byte) cipher.Stream) func([]byte, []byte) (cipher.Stream, error) { 127 | return func(key []byte, iv []byte) (cipher.Stream, error) { 128 | block, err := blockCreator(key) 129 | if err != nil { 130 | return nil, err 131 | } 132 | return streamCreator(block, iv), err 133 | } 134 | } 135 | 136 | func (m *Method) Name() string { 137 | return m.name 138 | } 139 | 140 | func (m *Method) DialConn(conn net.Conn, destination M.Socksaddr) (net.Conn, error) { 141 | shadowsocksConn := &clientConn{ 142 | Method: m, 143 | Conn: conn, 144 | destination: destination, 145 | } 146 | return shadowsocksConn, shadowsocksConn.writeRequest() 147 | } 148 | 149 | func (m *Method) DialEarlyConn(conn net.Conn, destination M.Socksaddr) net.Conn { 150 | return &clientConn{ 151 | Method: m, 152 | Conn: conn, 153 | destination: destination, 154 | } 155 | } 156 | 157 | func (m *Method) DialPacketConn(conn net.Conn) N.NetPacketConn { 158 | return &clientPacketConn{m, conn} 159 | } 160 | 161 | type clientConn struct { 162 | *Method 163 | net.Conn 164 | destination M.Socksaddr 165 | readStream cipher.Stream 166 | writeStream cipher.Stream 167 | } 168 | 169 | func (c *clientConn) writeRequest() error { 170 | buffer := buf.NewSize(c.saltLength + M.SocksaddrSerializer.AddrPortLen(c.destination)) 171 | defer buffer.Release() 172 | 173 | salt := buffer.Extend(c.saltLength) 174 | common.Must1(io.ReadFull(rand.Reader, salt)) 175 | 176 | stream, err := c.encryptConstructor(c.key, salt) 177 | if err != nil { 178 | return err 179 | } 180 | 181 | err = M.SocksaddrSerializer.WriteAddrPort(buffer, c.destination) 182 | if err != nil { 183 | return err 184 | } 185 | 186 | stream.XORKeyStream(buffer.From(c.saltLength), buffer.From(c.saltLength)) 187 | 188 | _, err = c.Conn.Write(buffer.Bytes()) 189 | if err != nil { 190 | return err 191 | } 192 | 193 | c.writeStream = stream 194 | return nil 195 | } 196 | 197 | func (c *clientConn) readResponse() error { 198 | if c.readStream != nil { 199 | return nil 200 | } 201 | salt := make([]byte, c.saltLength) 202 | _, err := io.ReadFull(c.Conn, salt) 203 | if err != nil { 204 | return err 205 | } 206 | c.readStream, err = c.decryptConstructor(c.key, salt) 207 | return err 208 | } 209 | 210 | func (c *clientConn) Read(p []byte) (n int, err error) { 211 | if c.readStream == nil { 212 | err = c.readResponse() 213 | if err != nil { 214 | return 215 | } 216 | } 217 | n, err = c.Conn.Read(p) 218 | if err != nil { 219 | return 220 | } 221 | c.readStream.XORKeyStream(p[:n], p[:n]) 222 | return 223 | } 224 | 225 | func (c *clientConn) Write(p []byte) (n int, err error) { 226 | if c.writeStream == nil { 227 | err = c.writeRequest() 228 | if err != nil { 229 | return 230 | } 231 | } 232 | 233 | c.writeStream.XORKeyStream(p, p) 234 | return c.Conn.Write(p) 235 | } 236 | 237 | func (c *clientConn) NeedAdditionalReadDeadline() bool { 238 | return true 239 | } 240 | 241 | func (c *clientConn) Upstream() any { 242 | return c.Conn 243 | } 244 | 245 | type clientPacketConn struct { 246 | *Method 247 | net.Conn 248 | } 249 | 250 | func (c *clientPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { 251 | defer buffer.Release() 252 | header := buf.With(buffer.ExtendHeader(c.saltLength + M.SocksaddrSerializer.AddrPortLen(destination))) 253 | common.Must1(header.ReadFullFrom(rand.Reader, c.saltLength)) 254 | err := M.SocksaddrSerializer.WriteAddrPort(header, destination) 255 | if err != nil { 256 | return err 257 | } 258 | stream, err := c.encryptConstructor(c.key, buffer.To(c.saltLength)) 259 | if err != nil { 260 | return err 261 | } 262 | stream.XORKeyStream(buffer.From(c.saltLength), buffer.From(c.saltLength)) 263 | return common.Error(c.Write(buffer.Bytes())) 264 | } 265 | 266 | func (c *clientPacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) { 267 | n, err := c.Read(buffer.FreeBytes()) 268 | if err != nil { 269 | return M.Socksaddr{}, err 270 | } 271 | buffer.Truncate(n) 272 | stream, err := c.decryptConstructor(c.key, buffer.To(c.saltLength)) 273 | if err != nil { 274 | return M.Socksaddr{}, err 275 | } 276 | stream.XORKeyStream(buffer.From(c.saltLength), buffer.From(c.saltLength)) 277 | buffer.Advance(c.saltLength) 278 | return M.SocksaddrSerializer.ReadAddrPort(buffer) 279 | } 280 | 281 | func (c *clientPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { 282 | n, err = c.Read(p) 283 | if err != nil { 284 | return 285 | } 286 | stream, err := c.decryptConstructor(c.key, p[:c.saltLength]) 287 | if err != nil { 288 | return 289 | } 290 | buffer := buf.As(p[c.saltLength:n]) 291 | stream.XORKeyStream(buffer.Bytes(), buffer.Bytes()) 292 | destination, err := M.SocksaddrSerializer.ReadAddrPort(buffer) 293 | if err != nil { 294 | return 295 | } 296 | if destination.IsFqdn() { 297 | addr = destination 298 | } else { 299 | addr = destination.UDPAddr() 300 | } 301 | n = copy(p, buffer.Bytes()) 302 | return 303 | } 304 | 305 | func (c *clientPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { 306 | destination := M.SocksaddrFromNet(addr) 307 | buffer := buf.NewSize(c.saltLength + M.SocksaddrSerializer.AddrPortLen(destination) + len(p)) 308 | defer buffer.Release() 309 | common.Must1(buffer.ReadFullFrom(rand.Reader, c.saltLength)) 310 | err = M.SocksaddrSerializer.WriteAddrPort(buffer, M.SocksaddrFromNet(addr)) 311 | if err != nil { 312 | return 313 | } 314 | _, err = buffer.Write(p) 315 | if err != nil { 316 | return 317 | } 318 | stream, err := c.encryptConstructor(c.key, buffer.To(c.saltLength)) 319 | if err != nil { 320 | return 321 | } 322 | stream.XORKeyStream(buffer.From(c.saltLength), buffer.From(c.saltLength)) 323 | _, err = c.Write(buffer.Bytes()) 324 | if err != nil { 325 | return 326 | } 327 | return len(p), nil 328 | } 329 | 330 | func (c *clientPacketConn) FrontHeadroom() int { 331 | return c.saltLength + M.MaxSocksaddrLength 332 | } 333 | 334 | func (c *clientPacketConn) Upstream() any { 335 | return c.Conn 336 | } 337 | --------------------------------------------------------------------------------