Skip to content
This repository was archived by the owner on Jun 12, 2022. It is now read-only.

Commit 2c88f6d

Browse files
committed
⚙️ Fix client UDP
1 parent e87c802 commit 2c88f6d

File tree

11 files changed

+247
-141
lines changed

11 files changed

+247
-141
lines changed

client/client.go

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ type ShadowsocksPacketConn interface {
202202
net.PacketConn
203203

204204
// ReadFromZeroCopy eliminates copying by requiring that a big enough buffer is passed for reading.
205-
ReadFromZeroCopy(b []byte) (payload []byte, address string, err error)
205+
ReadFromZeroCopy(b []byte) (socksAddrStart, payloadStart, payloadLength int, err error)
206206

207207
// WriteToZeroCopy minimizes copying by requiring that enough space is reserved in b.
208208
// The socks address is still being copied into the buffer.
@@ -368,7 +368,12 @@ func (c *packetConn) ReadFrom(b []byte) (int, net.Addr, error) {
368368
}
369369

370370
// Decrypt in-place.
371-
payload, address, err := ss.UnpackAndValidatePacket(c.cipher, c.aead, c.filter, c.sid, nil, cipherBuf[:n])
371+
_, socksAddr, payload, err := ss.UnpackAndValidatePacket(c.cipher, c.aead, c.filter, c.sid, nil, cipherBuf[:n])
372+
if err != nil {
373+
return 0, nil, err
374+
}
375+
376+
addr, err := socksAddr.Addr("udp")
372377
if err != nil {
373378
return 0, nil, err
374379
}
@@ -378,37 +383,17 @@ func (c *packetConn) ReadFrom(b []byte) (int, net.Addr, error) {
378383
err = io.ErrShortBuffer
379384
}
380385

381-
return n, NewAddr(address, "udp"), err
386+
return n, addr, err
382387
}
383388

384-
func (c *packetConn) ReadFromZeroCopy(b []byte) (payload []byte, address string, err error) {
389+
func (c *packetConn) ReadFromZeroCopy(b []byte) (socksAddrStart, payloadStart, payloadLength int, err error) {
385390
n, err := c.UDPConn.Read(b)
386391
if err != nil {
387392
return
388393
}
389394

390-
payload, address, err = ss.UnpackAndValidatePacket(c.cipher, c.aead, c.filter, c.sid, nil, b[:n])
395+
socksAddrStart, socksAddr, payload, err := ss.UnpackAndValidatePacket(c.cipher, c.aead, c.filter, c.sid, nil, b[:n])
396+
payloadStart = socksAddrStart + len(socksAddr)
397+
payloadLength = len(payload)
391398
return
392399
}
393-
394-
type addr struct {
395-
address string
396-
network string
397-
}
398-
399-
func (a *addr) String() string {
400-
return a.address
401-
}
402-
403-
func (a *addr) Network() string {
404-
return a.network
405-
}
406-
407-
// NewAddr returns a net.Addr that holds an address of the form `host:port` with a domain name or IP as host.
408-
// Used for SOCKS addressing.
409-
func NewAddr(address, network string) net.Addr {
410-
return &addr{
411-
address: address,
412-
network: network,
413-
}
414-
}

client/client_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func TestShadowsocksClient_ListenUDP(t *testing.T) {
121121
}
122122
defer conn.Close()
123123
conn.SetReadDeadline(time.Now().Add(time.Second * 5))
124-
pcrw := &packetConnReadWriter{PacketConn: conn, targetAddr: NewAddr(testTargetAddr, "udp")}
124+
pcrw := &packetConnReadWriter{PacketConn: conn, targetAddr: onet.NewAddr(testTargetAddr, "udp")}
125125
expectEchoPayload(pcrw, ss.MakeTestPayload(1024), make([]byte, 1024), t)
126126

127127
proxy.Close()
@@ -173,7 +173,7 @@ func BenchmarkShadowsocksClient_ListenUDP(b *testing.B) {
173173
buf := make([]byte, service.UDPPacketBufferSize)
174174
for n := 0; n < b.N; n++ {
175175
payload := ss.MakeTestPayload(1024)
176-
pcrw := &packetConnReadWriter{PacketConn: conn, targetAddr: NewAddr(testTargetAddr, "udp")}
176+
pcrw := &packetConnReadWriter{PacketConn: conn, targetAddr: onet.NewAddr(testTargetAddr, "udp")}
177177
b.StartTimer()
178178
expectEchoPayload(pcrw, payload, buf, b)
179179
b.StopTimer()
@@ -252,7 +252,7 @@ func startShadowsocksUDPEchoServer(expectedTgtAddr string, t testing.TB) (net.Co
252252
t.Logf("Failed to read from UDP conn: %v", err)
253253
return
254254
}
255-
buf, err := ss.Unpack(clientBuf, cipherBuf[:n], cipher)
255+
_, buf, err := ss.Unpack(clientBuf, cipherBuf[:n], cipher)
256256
if err != nil {
257257
t.Fatalf("Failed to decrypt: %v", err)
258258
}

client/nat.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ type natconn struct {
3636

3737
// The UDPConn where the last client packet was received from.
3838
clientConn onet.UDPPacketConn
39+
40+
// packetAdapter translates packets between clientConn and proxyConn.
41+
packetAdapter PacketAdapter
3942
}
4043

4144
func isDNS(addr *net.UDPAddr) bool {
@@ -79,8 +82,8 @@ func (c *natconn) WriteToZeroCopy(b []byte, start, length int, socksAddr []byte)
7982
return c.proxyConn.WriteToZeroCopy(b, start, length, socksAddr)
8083
}
8184

82-
func (c *natconn) ReadFromZeroCopy(b []byte) (payload []byte, address string, err error) {
83-
payload, address, err = c.proxyConn.ReadFromZeroCopy(b)
85+
func (c *natconn) ReadFromZeroCopy(b []byte) (socksAddrStart, payloadStart, payloadLength int, err error) {
86+
socksAddrStart, payloadStart, payloadLength, err = c.proxyConn.ReadFromZeroCopy(b)
8487
if err == nil {
8588
c.onRead(nil)
8689
}
@@ -104,7 +107,7 @@ func (c *natconn) timedCopy() {
104107
packetBuf := make([]byte, service.UDPPacketBufferSize)
105108

106109
for {
107-
payload, _, err := c.ReadFromZeroCopy(packetBuf)
110+
socksAddrStart, payloadStart, payloadLength, err := c.ReadFromZeroCopy(packetBuf)
108111
if err != nil {
109112
if errors.Is(err, os.ErrDeadlineExceeded) {
110113
return
@@ -113,7 +116,13 @@ func (c *natconn) timedCopy() {
113116
continue
114117
}
115118

116-
_, _, err = c.clientConn.WriteMsgUDP(payload, c.oobCache, c.clientAddr)
119+
writeBuf, err := c.packetAdapter.EncapsulatePacket(packetBuf, socksAddrStart, payloadStart, payloadLength)
120+
if err != nil {
121+
log.Print(err)
122+
continue
123+
}
124+
125+
_, _, err = c.clientConn.WriteMsgUDP(writeBuf, c.oobCache, c.clientAddr)
117126
if err != nil {
118127
log.Print(err)
119128
}
@@ -140,13 +149,14 @@ func (m *natmap) GetByClientAddress(key string) *natconn {
140149
return m.keyConn[key]
141150
}
142151

143-
func (m *natmap) set(clientAddr *net.UDPAddr, clientConn onet.UDPPacketConn, proxyConn ShadowsocksPacketConn, oobCache []byte) *natconn {
152+
func (m *natmap) set(clientAddr *net.UDPAddr, clientConn onet.UDPPacketConn, proxyConn ShadowsocksPacketConn, oobCache []byte, packetAdapter PacketAdapter) *natconn {
144153
entry := &natconn{
145154
proxyConn: proxyConn,
146155
defaultTimeout: m.timeout,
147156
oobCache: oobCache,
148157
clientAddr: clientAddr,
149158
clientConn: clientConn,
159+
packetAdapter: packetAdapter,
150160
}
151161

152162
m.Lock()
@@ -168,8 +178,8 @@ func (m *natmap) del(key string) *natconn {
168178
return nil
169179
}
170180

171-
func (m *natmap) Add(clientAddr *net.UDPAddr, clientConn onet.UDPPacketConn, oobCache []byte, proxyConn ShadowsocksPacketConn) *natconn {
172-
entry := m.set(clientAddr, clientConn, proxyConn, oobCache)
181+
func (m *natmap) Add(clientAddr *net.UDPAddr, clientConn onet.UDPPacketConn, oobCache []byte, proxyConn ShadowsocksPacketConn, packetAdapter PacketAdapter) *natconn {
182+
entry := m.set(clientAddr, clientConn, proxyConn, oobCache, packetAdapter)
173183
go func() {
174184
entry.timedCopy()
175185
if pc := m.del(clientAddr.String()); pc != nil {

client/tcp.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,19 @@ func (s *TCPTunnel) listen() {
6262

6363
socksaddr, err := s.handshaker.Handshake(clientConn)
6464
if err != nil {
65-
if socksaddr == nil {
66-
// Keep the connection open until EOF.
67-
// Example use case: SOCKS5 UDP ASSOCIATE command.
68-
b := make([]byte, 1)
69-
_, err = io.ReadFull(clientConn, b)
70-
if err == nil || err == io.ErrUnexpectedEOF {
71-
return
72-
}
73-
}
7465
log.Print(err)
7566
return
7667
}
68+
if socksaddr == nil {
69+
// Keep the connection open until EOF.
70+
// Example use case: SOCKS5 UDP ASSOCIATE command.
71+
b := make([]byte, 1)
72+
_, err = io.ReadFull(clientConn, b)
73+
if err != nil && err != io.ErrUnexpectedEOF {
74+
log.Print(err)
75+
}
76+
return
77+
}
7778

7879
proxyConn, err := s.client.DialTCP(nil, socksaddr, s.dialerTFO)
7980
if err != nil {

client/udp.go

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ type UDPTunnel struct {
1717
multiplexUDP bool
1818
natTimeout time.Duration
1919

20-
client Client
21-
conn *net.UDPConn
22-
packetParser PacketParser
20+
client Client
21+
conn *net.UDPConn
22+
packetAdapter PacketAdapter
2323
}
2424

2525
func (s *UDPTunnel) Name() string {
26-
return fmt.Sprint("UDP ", s.packetParser.Name(), " service")
26+
return fmt.Sprint("UDP ", s.packetAdapter.Name(), " service")
2727
}
2828

2929
func (s *UDPTunnel) Start() error {
@@ -61,7 +61,7 @@ func (s *UDPTunnel) listen() {
6161
continue
6262
}
6363

64-
payloadStart, payloadLength, detachedSocksAddr, err := s.packetParser.ParsePacket(packetBuf, ShadowsocksPacketConnFrontReserve, n)
64+
payloadStart, payloadLength, detachedSocksAddr, err := s.packetAdapter.ParsePacket(packetBuf, ShadowsocksPacketConnFrontReserve, n)
6565
if err != nil {
6666
log.Print(err)
6767
continue
@@ -76,7 +76,7 @@ func (s *UDPTunnel) listen() {
7676
continue
7777
}
7878

79-
proxyConn = nm.Add(clientAddr, s.conn, oobCache, spc)
79+
proxyConn = nm.Add(clientAddr, s.conn, oobCache, spc, s.packetAdapter)
8080
} else {
8181
proxyConn.oobCache = oobCache
8282
}
@@ -95,43 +95,54 @@ func (s *UDPTunnel) Stop() error {
9595
return nil
9696
}
9797

98-
// PacketParser parses an incoming packet and returns payload start index, payload length,
99-
// a detached socks address (if applicable), or an error.
100-
//
101-
// The detached socks address is only returned when the payload does not start with a socks address.
102-
type PacketParser interface {
98+
// PacketAdapter translates packets between a local interface and the proxy interface.
99+
type PacketAdapter interface {
103100
Name() string
101+
102+
// ParsePacket parses an incoming packet and returns payload start index, payload length,
103+
// a detached socks address (if applicable), or an error.
104+
//
105+
// The detached socks address is only returned when the payload does not start with a socks address.
104106
ParsePacket(pkt []byte, start, length int) (payloadStart, payloadLength int, detachedSocksAddr []byte, err error)
107+
108+
// EncapsulatePacket encapsulates the decrypted packet from proxy
109+
// into a new form so it's ready to be sent on the local interface.
110+
// The encapsulation must not extend beyond the range of the full decrypted packet.
111+
EncapsulatePacket(decryptedFullPacket []byte, socksAddrStart, payloadStart, payloadLength int) (pkt []byte, err error)
105112
}
106113

107-
// SimpleTunnelPacketParser simply relays packets between clientConn and proxyConn.
108-
type SimpleTunnelPacketParser struct {
114+
// SimpleTunnelPacketAdapter simply relays packets between clientConn and proxyConn.
115+
type SimpleTunnelPacketAdapter struct {
109116
remoteSocksAddr socks.Addr
110117
}
111118

112-
func NewSimpleTunnelPacketParser(remoteSocksAddr socks.Addr) *SimpleTunnelPacketParser {
113-
return &SimpleTunnelPacketParser{
119+
func NewSimpleTunnelPacketAdapter(remoteSocksAddr socks.Addr) *SimpleTunnelPacketAdapter {
120+
return &SimpleTunnelPacketAdapter{
114121
remoteSocksAddr: remoteSocksAddr,
115122
}
116123
}
117124

118-
func (p *SimpleTunnelPacketParser) Name() string {
125+
func (p *SimpleTunnelPacketAdapter) Name() string {
119126
return "simple tunnel"
120127
}
121128

122-
func (p *SimpleTunnelPacketParser) ParsePacket(_ []byte, start, length int) (payloadStart, payloadLength int, detachedSocksAddr []byte, err error) {
129+
func (p *SimpleTunnelPacketAdapter) ParsePacket(_ []byte, start, length int) (payloadStart, payloadLength int, detachedSocksAddr []byte, err error) {
123130
return start, length, p.remoteSocksAddr, nil
124131
}
125132

126-
// SimpleSocks5PacketParser is a minimal implementation of SOCKS5 UDP server.
133+
func (p *SimpleTunnelPacketAdapter) EncapsulatePacket(decryptedFullPacket []byte, _, payloadStart, payloadLength int) (pkt []byte, err error) {
134+
return decryptedFullPacket[payloadStart : payloadStart+payloadLength], nil
135+
}
136+
137+
// SimpleSocks5PacketAdapter is a minimal implementation of SOCKS5 UDP server.
127138
// It unconditionally accepts SOCKS5 UDP packets, no matter a corresponding UDP association exists or not.
128-
type SimpleSocks5PacketParser struct{}
139+
type SimpleSocks5PacketAdapter struct{}
129140

130-
func (p *SimpleSocks5PacketParser) Name() string {
141+
func (p *SimpleSocks5PacketAdapter) Name() string {
131142
return "simple SOCKS5"
132143
}
133144

134-
func (p *SimpleSocks5PacketParser) ParsePacket(pkt []byte, start, length int) (payloadStart, payloadLength int, detachedSocksAddr []byte, err error) {
145+
func (p *SimpleSocks5PacketAdapter) ParsePacket(pkt []byte, start, length int) (payloadStart, payloadLength int, detachedSocksAddr []byte, err error) {
135146
payloadStart = start + 3
136147
if len(pkt) <= payloadStart {
137148
return 0, 0, nil, ss.ErrShortPacket
@@ -152,14 +163,24 @@ func (p *SimpleSocks5PacketParser) ParsePacket(pkt []byte, start, length int) (p
152163
return
153164
}
154165

155-
// ShadowsocksNonePacketParser implements the 'none' mode of Shadowsocks.
156-
type ShadowsocksNonePacketParser struct{}
166+
func (p *SimpleSocks5PacketAdapter) EncapsulatePacket(decryptedFullPacket []byte, socksAddrStart, payloadStart, payloadLength int) (pkt []byte, err error) {
167+
start := socksAddrStart - 3
168+
// RSV
169+
decryptedFullPacket[start] = 0
170+
decryptedFullPacket[start+1] = 0
171+
// FRAG
172+
decryptedFullPacket[start+2] = 0
173+
return decryptedFullPacket[start : payloadStart+payloadLength], nil
174+
}
175+
176+
// ShadowsocksNonePacketAdapter implements the 'none' mode of Shadowsocks.
177+
type ShadowsocksNonePacketAdapter struct{}
157178

158-
func (p *ShadowsocksNonePacketParser) Name() string {
179+
func (p *ShadowsocksNonePacketAdapter) Name() string {
159180
return "Shadowsocks none"
160181
}
161182

162-
func (p *ShadowsocksNonePacketParser) ParsePacket(pkt []byte, start, length int) (payloadStart, payloadLength int, detachedSocksAddr []byte, err error) {
183+
func (p *ShadowsocksNonePacketAdapter) ParsePacket(pkt []byte, start, length int) (payloadStart, payloadLength int, detachedSocksAddr []byte, err error) {
163184
// Validate socks address.
164185
_, err = socks.SplitAddr(pkt[start:])
165186
if err != nil {
@@ -171,13 +192,17 @@ func (p *ShadowsocksNonePacketParser) ParsePacket(pkt []byte, start, length int)
171192
return
172193
}
173194

195+
func (p *ShadowsocksNonePacketAdapter) EncapsulatePacket(decryptedFullPacket []byte, socksAddrStart, payloadStart, payloadLength int) (pkt []byte, err error) {
196+
return decryptedFullPacket[socksAddrStart : payloadStart+payloadLength], nil
197+
}
198+
174199
func NewUDPSimpleTunnelService(tunnelListenAddress string, tunnelRemoteSocksAddr socks.Addr, multiplexUDP bool, natTimeout time.Duration, client Client) Service {
175200
return &UDPTunnel{
176201
listenAddress: tunnelListenAddress,
177202
multiplexUDP: multiplexUDP,
178203
natTimeout: natTimeout,
179204
client: client,
180-
packetParser: NewSimpleTunnelPacketParser(tunnelRemoteSocksAddr),
205+
packetAdapter: NewSimpleTunnelPacketAdapter(tunnelRemoteSocksAddr),
181206
}
182207
}
183208

@@ -187,7 +212,7 @@ func NewUDPSimpleSocks5Service(socks5ListenAddress string, multiplexUDP bool, na
187212
multiplexUDP: multiplexUDP,
188213
natTimeout: natTimeout,
189214
client: client,
190-
packetParser: &SimpleSocks5PacketParser{},
215+
packetAdapter: &SimpleSocks5PacketAdapter{},
191216
}
192217
}
193218

@@ -197,6 +222,6 @@ func NewUDPShadowsocksNoneService(ssNoneListenAddress string, multiplexUDP bool,
197222
multiplexUDP: multiplexUDP,
198223
natTimeout: natTimeout,
199224
client: client,
200-
packetParser: &ShadowsocksNonePacketParser{},
225+
packetAdapter: &ShadowsocksNonePacketAdapter{},
201226
}
202227
}

net/net.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,25 @@ type ConnectionError struct {
110110
func NewConnectionError(status, message string, cause error) *ConnectionError {
111111
return &ConnectionError{Status: status, Message: message, Cause: cause}
112112
}
113+
114+
type addr struct {
115+
address string
116+
network string
117+
}
118+
119+
func (a *addr) String() string {
120+
return a.address
121+
}
122+
123+
func (a *addr) Network() string {
124+
return a.network
125+
}
126+
127+
// NewAddr returns a net.Addr that holds an address of the form `host:port` with a domain name or IP as host.
128+
// Used for SOCKS addressing.
129+
func NewAddr(address, network string) net.Addr {
130+
return &addr{
131+
address: address,
132+
network: network,
133+
}
134+
}

service/nat.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func (c *natconn) timedCopy(ses *session, sm metrics.ShadowsocksMetrics) {
194194
ses.pid++
195195
default:
196196
headerStart = bodyStart - socksAddrLen
197-
ss.WriteUDPAddrToSocksAddr(pkt[headerStart:], raddr)
197+
socks.WriteUDPAddrAsSocksAddr(pkt[headerStart:], raddr)
198198
}
199199

200200
// `plainTextBuf` concatenates the SOCKS address and body:

0 commit comments

Comments
 (0)