Skip to content
This repository was archived by the owner on Apr 9, 2020. It is now read-only.

Commit 97a5c71

Browse files
committed
Merge branch 'develop'
2 parents 6f7f790 + 9b9860f commit 97a5c71

File tree

4 files changed

+38
-52
lines changed

4 files changed

+38
-52
lines changed

CHANGELOG

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
1.2.1 (2017-01-22)
2+
* Fix bug in handling of UDP OTA packets
3+
14
1.2.0 (2017-01-20)
2-
* Support UDP reley on server side, and OTA
5+
* Support UDP relay on server side, and OTA
36
* Support "aes-[128/192/256]-ctr" encryption method (Thanks for @slurin)
47
* Support "chacha20-ietf" encryption method
58
* Improve performance of "chacha20" encryption method
6-
* Corrently close connection if handshake failed
9+
* Correctly close connection if handshake failed
710

811
1.1.5 (2016-05-04)
912
* Support OTA (Thanks for @ayanamist for implementing this feature)

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# shadowsocks-go
22

3-
Current version: 1.2.0 [![Build Status](https://travis-ci.org/shadowsocks/shadowsocks-go.png?branch=master)](https://travis-ci.org/shadowsocks/shadowsocks-go)
3+
Current version: 1.2.1 [![Build Status](https://travis-ci.org/shadowsocks/shadowsocks-go.png?branch=master)](https://travis-ci.org/shadowsocks/shadowsocks-go)
44

55
shadowsocks-go is a lightweight tunnel proxy which can help you get through firewalls. It is a port of [shadowsocks](https://github.com/clowwindy/shadowsocks).
66

shadowsocks/udp.go

+3-20
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ func (c *SecurePacketConn) WriteTo(b []byte, dst net.Addr) (n int, err error) {
9292
packetLen := len(b) + len(iv)
9393

9494
if c.ota {
95+
b[idType] |= OneTimeAuthMask
9596
packetLen += lenHmacSha1
9697
key := cipher.key
9798
actualHmacSha1Buf := HmacSha1(append(iv, key...), b)
@@ -129,24 +130,6 @@ func (c *SecurePacketConn) IsOta() bool {
129130
return c.ota
130131
}
131132

132-
func (c *SecurePacketConn) ForceOTAWriteTo(b []byte, dst net.Addr) (n int, err error) {
133-
cipher := c.Copy()
134-
iv, err := cipher.initEncrypt()
135-
if err != nil {
136-
return
137-
}
138-
packetLen := len(b) + len(iv)
139-
140-
packetLen += lenHmacSha1
141-
key := cipher.key
142-
actualHmacSha1Buf := HmacSha1(append(iv, key...), b)
143-
b = append(b, actualHmacSha1Buf...)
144-
145-
cipherData := make([]byte, packetLen)
146-
copy(cipherData, iv)
147-
148-
cipher.encrypt(cipherData[len(iv):], b)
149-
n, err = c.PacketConn.WriteTo(cipherData, dst)
150-
n -= lenHmacSha1
151-
return
133+
func (c *SecurePacketConn) ForceOTA() net.PacketConn {
134+
return NewSecurePacketConn(c.PacketConn, c.Cipher.Copy(), true)
152135
}

shadowsocks/udprelay.go

+29-29
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,15 @@ func newNatTable() *natTable {
4343
return &natTable{conns: map[string]net.PacketConn{}}
4444
}
4545

46-
func (table *natTable) DeleteAndClose(index string) {
46+
func (table *natTable) Delete(index string) net.PacketConn {
4747
table.Lock()
4848
defer table.Unlock()
4949
c, ok := table.conns[index]
5050
if ok {
51-
c.Close()
5251
delete(table.conns, index)
52+
return c
5353
}
54+
return nil
5455
}
5556

5657
func (table *natTable) Get(index string) (c net.PacketConn, ok bool, err error) {
@@ -67,13 +68,13 @@ func (table *natTable) Get(index string) (c net.PacketConn, ok bool, err error)
6768
return
6869
}
6970

70-
type ReqList struct {
71+
type requestHeaderList struct {
7172
sync.Mutex
7273
List map[string]([]byte)
7374
}
7475

75-
func newReqList() *ReqList {
76-
ret := &ReqList{List: map[string]([]byte){}}
76+
func newReqList() *requestHeaderList {
77+
ret := &requestHeaderList{List: map[string]([]byte){}}
7778
go func() {
7879
for {
7980
time.Sleep(reqListRefreshTime)
@@ -83,29 +84,29 @@ func newReqList() *ReqList {
8384
return ret
8485
}
8586

86-
func (r *ReqList) Refresh() {
87+
func (r *requestHeaderList) Refresh() {
8788
r.Lock()
8889
defer r.Unlock()
8990
for k, _ := range r.List {
9091
delete(r.List, k)
9192
}
9293
}
9394

94-
func (r *ReqList) Get(dstaddr string) (req []byte, ok bool) {
95+
func (r *requestHeaderList) Get(dstaddr string) (req []byte, ok bool) {
9596
r.Lock()
9697
defer r.Unlock()
9798
req, ok = r.List[dstaddr]
9899
return
99100
}
100101

101-
func (r *ReqList) Put(dstaddr string, req []byte) {
102+
func (r *requestHeaderList) Put(dstaddr string, req []byte) {
102103
r.Lock()
103104
defer r.Unlock()
104105
r.List[dstaddr] = req
105106
return
106107
}
107108

108-
func ParseHeader(addr net.Addr) ([]byte, int) {
109+
func parseHeaderFromAddr(addr net.Addr) ([]byte, int) {
109110
// if the request address type is domain, it cannot be reverselookuped
110111
ip, port, err := net.SplitHostPort(addr.String())
111112
if err != nil {
@@ -129,13 +130,13 @@ func ParseHeader(addr net.Addr) ([]byte, int) {
129130
return buf[:1+iplen+2], 1 + iplen + 2
130131
}
131132

132-
func Pipeloop(ss *SecurePacketConn, addr net.Addr, in net.PacketConn, compatiblemode bool) {
133+
func Pipeloop(write net.PacketConn, writeAddr net.Addr, readClose net.PacketConn) {
133134
buf := leakyBuf.Get()
134135
defer leakyBuf.Put(buf)
135-
defer in.Close()
136+
defer readClose.Close()
136137
for {
137-
in.SetDeadline(time.Now().Add(udpTimeout))
138-
n, raddr, err := in.ReadFrom(buf)
138+
readClose.SetDeadline(time.Now().Add(udpTimeout))
139+
n, raddr, err := readClose.ReadFrom(buf)
139140
if err != nil {
140141
if ne, ok := err.(*net.OpError); ok {
141142
if ne.Err == syscall.EMFILE || ne.Err == syscall.ENFILE {
@@ -144,24 +145,15 @@ func Pipeloop(ss *SecurePacketConn, addr net.Addr, in net.PacketConn, compatible
144145
Debug.Println("[udp]read error:", err)
145146
}
146147
}
147-
Debug.Printf("[udp]closed pipe %s<-%s\n", addr, in.LocalAddr())
148+
Debug.Printf("[udp]closed pipe %s<-%s\n", writeAddr, readClose.LocalAddr())
148149
return
149150
}
150151
// need improvement here
151152
if req, ok := reqList.Get(raddr.String()); ok {
152-
if compatiblemode {
153-
ss.ForceOTAWriteTo(append(req, buf[:n]...), addr)
154-
} else {
155-
ss.WriteTo(append(req, buf[:n]...), addr)
156-
}
153+
write.WriteTo(append(req, buf[:n]...), writeAddr)
157154
} else {
158-
header, hlen := ParseHeader(raddr)
159-
if compatiblemode {
160-
ss.ForceOTAWriteTo(append(header[:hlen], buf[:n]...), addr)
161-
} else {
162-
ss.WriteTo(append(header[:hlen], buf[:n]...), addr)
163-
}
164-
155+
header, hlen := parseHeaderFromAddr(raddr)
156+
write.WriteTo(append(header[:hlen], buf[:n]...), writeAddr)
165157
}
166158
}
167159
}
@@ -176,6 +168,7 @@ func handleUDPConnection(handle *SecurePacketConn, n int, src net.Addr, receive
176168
if addrType&OneTimeAuthMask > 0 {
177169
ota = true
178170
}
171+
receive[idType] &= ^OneTimeAuthMask
179172
compatiblemode := !handle.IsOta() && ota
180173

181174
switch addrType & AddrMask {
@@ -229,8 +222,13 @@ func handleUDPConnection(handle *SecurePacketConn, n int, src net.Addr, receive
229222
if !exist {
230223
Debug.Printf("[udp]new client %s->%s via %s ota=%v\n", src, dst, remote.LocalAddr(), ota)
231224
go func() {
232-
Pipeloop(handle, src, remote, compatiblemode)
233-
natlist.DeleteAndClose(src.String())
225+
if compatiblemode {
226+
Pipeloop(handle.ForceOTA(), src, remote)
227+
} else {
228+
Pipeloop(handle, src, remote)
229+
}
230+
231+
natlist.Delete(src.String())
234232
}()
235233
} else {
236234
Debug.Printf("[udp]using cached client %s->%s via %s ota=%v\n", src, dst, remote.LocalAddr(), ota)
@@ -248,7 +246,9 @@ func handleUDPConnection(handle *SecurePacketConn, n int, src net.Addr, receive
248246
} else {
249247
Debug.Println("[udp]error connecting to:", dst, err)
250248
}
251-
natlist.DeleteAndClose(src.String())
249+
if conn := natlist.Delete(src.String()); conn != nil {
250+
conn.Close()
251+
}
252252
}
253253
// Pipeloop
254254
return

0 commit comments

Comments
 (0)