Skip to content

Commit 6447a85

Browse files
author
Ben Schwartz
committed
Avoid creating NAT mappings for rejected packets
Currently, each valid shadowsocks packet causes a NAT mapping to be created (if there isn't a matching one already), even if that packet is rejected due to a malformed or disallowed destination address. This is a regression due to #83. The regression results in a significant memory leak, because unused mappings are never cleaned up.
1 parent 264ddf9 commit 6447a85

File tree

1 file changed

+35
-16
lines changed

1 file changed

+35
-16
lines changed

service/udp.go

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ func (s *udpService) Serve(clientConn net.PacketConn) error {
169169
}
170170

171171
cipherData := cipherBuf[:clientProxyBytes]
172-
var textData []byte
172+
var payload []byte
173+
var tgtUDPAddr *net.UDPAddr
173174
targetConn := nm.Get(clientAddr.String())
174175
if targetConn == nil {
175176
clientLocation, locErr := s.m.GetLocation(clientAddr)
@@ -179,6 +180,7 @@ func (s *udpService) Serve(clientConn net.PacketConn) error {
179180
debugUDPAddr(clientAddr, "Got location \"%s\"", clientLocation)
180181

181182
ip := clientAddr.(*net.UDPAddr).IP
183+
var textData []byte
182184
var cipher *ss.Cipher
183185
unpackStart := time.Now()
184186
textData, keyID, cipher, err = findAccessKeyUDP(ip, textBuf, cipherData, s.ciphers)
@@ -188,36 +190,32 @@ func (s *udpService) Serve(clientConn net.PacketConn) error {
188190
return onet.NewConnectionError("ERR_CIPHER", "Failed to unpack initial packet", err)
189191
}
190192

193+
var onetErr *onet.ConnectionError
194+
if payload, tgtUDPAddr, onetErr = s.parsePacket(textData); onetErr != nil {
195+
return onetErr
196+
}
197+
191198
udpConn, err := net.ListenPacket("udp", "")
192199
if err != nil {
193200
return onet.NewConnectionError("ERR_CREATE_SOCKET", "Failed to create UDP socket", err)
194201
}
195202
targetConn = nm.Add(clientAddr, clientConn, cipher, udpConn, clientLocation, keyID)
196203
} else {
197204
unpackStart := time.Now()
198-
textData, err = ss.Unpack(nil, cipherData, targetConn.cipher)
205+
textData, err := ss.Unpack(nil, cipherData, targetConn.cipher)
199206
timeToCipher = time.Now().Sub(unpackStart)
200207
if err != nil {
201208
return onet.NewConnectionError("ERR_CIPHER", "Failed to unpack data from client", err)
202209
}
203-
}
204-
clientLocation = targetConn.clientLocation
205210

206-
tgtAddr := socks.SplitAddr(textData)
207-
if tgtAddr == nil {
208-
return onet.NewConnectionError("ERR_READ_ADDRESS", "Failed to get target address", nil)
209-
}
210-
211-
tgtUDPAddr, err := net.ResolveUDPAddr("udp", tgtAddr.String())
212-
if err != nil {
213-
return onet.NewConnectionError("ERR_RESOLVE_ADDRESS", fmt.Sprintf("Failed to resolve target address %v", tgtAddr), err)
214-
}
215-
if err := s.targetIPValidator(tgtUDPAddr.IP); err != nil {
216-
return err
211+
var onetErr *onet.ConnectionError
212+
if payload, tgtUDPAddr, onetErr = s.parsePacket(textData); onetErr != nil {
213+
return onetErr
214+
}
217215
}
216+
clientLocation = targetConn.clientLocation
218217

219218
debugUDPAddr(clientAddr, "Proxy exit %v", targetConn.LocalAddr())
220-
payload := textData[len(tgtAddr):]
221219
proxyTargetBytes, err = targetConn.WriteTo(payload, tgtUDPAddr) // accept only UDPAddr despite the signature
222220
if err != nil {
223221
return onet.NewConnectionError("ERR_WRITE", "Failed to write to target", err)
@@ -228,6 +226,27 @@ func (s *udpService) Serve(clientConn net.PacketConn) error {
228226
return nil
229227
}
230228

229+
// Given the decrypted contents of a UDP packet, return
230+
// the payload and the destination address, or an error if
231+
// this packet cannot or should not be forwarded.
232+
func (s *udpService) parsePacket(textData []byte) ([]byte, *net.UDPAddr, *onet.ConnectionError) {
233+
tgtAddr := socks.SplitAddr(textData)
234+
if tgtAddr == nil {
235+
return nil, nil, onet.NewConnectionError("ERR_READ_ADDRESS", "Failed to get target address", nil)
236+
}
237+
238+
tgtUDPAddr, err := net.ResolveUDPAddr("udp", tgtAddr.String())
239+
if err != nil {
240+
return nil, nil, onet.NewConnectionError("ERR_RESOLVE_ADDRESS", fmt.Sprintf("Failed to resolve target address %v", tgtAddr), err)
241+
}
242+
if err := s.targetIPValidator(tgtUDPAddr.IP); err != nil {
243+
return nil, nil, err
244+
}
245+
246+
payload := textData[len(tgtAddr):]
247+
return payload, tgtUDPAddr, nil
248+
}
249+
231250
func (s *udpService) Stop() error {
232251
s.mu.Lock()
233252
defer s.mu.Unlock()

0 commit comments

Comments
 (0)