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

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
lixin9311 committed Jan 21, 2017
2 parents 6f7f790 + 9b9860f commit 97a5c71
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 52 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
1.2.1 (2017-01-22)
* Fix bug in handling of UDP OTA packets

1.2.0 (2017-01-20)
* Support UDP reley on server side, and OTA
* Support UDP relay on server side, and OTA
* Support "aes-[128/192/256]-ctr" encryption method (Thanks for @slurin)
* Support "chacha20-ietf" encryption method
* Improve performance of "chacha20" encryption method
* Corrently close connection if handshake failed
* Correctly close connection if handshake failed

1.1.5 (2016-05-04)
* Support OTA (Thanks for @ayanamist for implementing this feature)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# shadowsocks-go

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

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).

Expand Down
23 changes: 3 additions & 20 deletions shadowsocks/udp.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func (c *SecurePacketConn) WriteTo(b []byte, dst net.Addr) (n int, err error) {
packetLen := len(b) + len(iv)

if c.ota {
b[idType] |= OneTimeAuthMask
packetLen += lenHmacSha1
key := cipher.key
actualHmacSha1Buf := HmacSha1(append(iv, key...), b)
Expand Down Expand Up @@ -129,24 +130,6 @@ func (c *SecurePacketConn) IsOta() bool {
return c.ota
}

func (c *SecurePacketConn) ForceOTAWriteTo(b []byte, dst net.Addr) (n int, err error) {
cipher := c.Copy()
iv, err := cipher.initEncrypt()
if err != nil {
return
}
packetLen := len(b) + len(iv)

packetLen += lenHmacSha1
key := cipher.key
actualHmacSha1Buf := HmacSha1(append(iv, key...), b)
b = append(b, actualHmacSha1Buf...)

cipherData := make([]byte, packetLen)
copy(cipherData, iv)

cipher.encrypt(cipherData[len(iv):], b)
n, err = c.PacketConn.WriteTo(cipherData, dst)
n -= lenHmacSha1
return
func (c *SecurePacketConn) ForceOTA() net.PacketConn {
return NewSecurePacketConn(c.PacketConn, c.Cipher.Copy(), true)
}
58 changes: 29 additions & 29 deletions shadowsocks/udprelay.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,15 @@ func newNatTable() *natTable {
return &natTable{conns: map[string]net.PacketConn{}}
}

func (table *natTable) DeleteAndClose(index string) {
func (table *natTable) Delete(index string) net.PacketConn {
table.Lock()
defer table.Unlock()
c, ok := table.conns[index]
if ok {
c.Close()
delete(table.conns, index)
return c
}
return nil
}

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

type ReqList struct {
type requestHeaderList struct {
sync.Mutex
List map[string]([]byte)
}

func newReqList() *ReqList {
ret := &ReqList{List: map[string]([]byte){}}
func newReqList() *requestHeaderList {
ret := &requestHeaderList{List: map[string]([]byte){}}
go func() {
for {
time.Sleep(reqListRefreshTime)
Expand All @@ -83,29 +84,29 @@ func newReqList() *ReqList {
return ret
}

func (r *ReqList) Refresh() {
func (r *requestHeaderList) Refresh() {
r.Lock()
defer r.Unlock()
for k, _ := range r.List {
delete(r.List, k)
}
}

func (r *ReqList) Get(dstaddr string) (req []byte, ok bool) {
func (r *requestHeaderList) Get(dstaddr string) (req []byte, ok bool) {
r.Lock()
defer r.Unlock()
req, ok = r.List[dstaddr]
return
}

func (r *ReqList) Put(dstaddr string, req []byte) {
func (r *requestHeaderList) Put(dstaddr string, req []byte) {
r.Lock()
defer r.Unlock()
r.List[dstaddr] = req
return
}

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

func Pipeloop(ss *SecurePacketConn, addr net.Addr, in net.PacketConn, compatiblemode bool) {
func Pipeloop(write net.PacketConn, writeAddr net.Addr, readClose net.PacketConn) {
buf := leakyBuf.Get()
defer leakyBuf.Put(buf)
defer in.Close()
defer readClose.Close()
for {
in.SetDeadline(time.Now().Add(udpTimeout))
n, raddr, err := in.ReadFrom(buf)
readClose.SetDeadline(time.Now().Add(udpTimeout))
n, raddr, err := readClose.ReadFrom(buf)
if err != nil {
if ne, ok := err.(*net.OpError); ok {
if ne.Err == syscall.EMFILE || ne.Err == syscall.ENFILE {
Expand All @@ -144,24 +145,15 @@ func Pipeloop(ss *SecurePacketConn, addr net.Addr, in net.PacketConn, compatible
Debug.Println("[udp]read error:", err)
}
}
Debug.Printf("[udp]closed pipe %s<-%s\n", addr, in.LocalAddr())
Debug.Printf("[udp]closed pipe %s<-%s\n", writeAddr, readClose.LocalAddr())
return
}
// need improvement here
if req, ok := reqList.Get(raddr.String()); ok {
if compatiblemode {
ss.ForceOTAWriteTo(append(req, buf[:n]...), addr)
} else {
ss.WriteTo(append(req, buf[:n]...), addr)
}
write.WriteTo(append(req, buf[:n]...), writeAddr)
} else {
header, hlen := ParseHeader(raddr)
if compatiblemode {
ss.ForceOTAWriteTo(append(header[:hlen], buf[:n]...), addr)
} else {
ss.WriteTo(append(header[:hlen], buf[:n]...), addr)
}

header, hlen := parseHeaderFromAddr(raddr)
write.WriteTo(append(header[:hlen], buf[:n]...), writeAddr)
}
}
}
Expand All @@ -176,6 +168,7 @@ func handleUDPConnection(handle *SecurePacketConn, n int, src net.Addr, receive
if addrType&OneTimeAuthMask > 0 {
ota = true
}
receive[idType] &= ^OneTimeAuthMask
compatiblemode := !handle.IsOta() && ota

switch addrType & AddrMask {
Expand Down Expand Up @@ -229,8 +222,13 @@ func handleUDPConnection(handle *SecurePacketConn, n int, src net.Addr, receive
if !exist {
Debug.Printf("[udp]new client %s->%s via %s ota=%v\n", src, dst, remote.LocalAddr(), ota)
go func() {
Pipeloop(handle, src, remote, compatiblemode)
natlist.DeleteAndClose(src.String())
if compatiblemode {
Pipeloop(handle.ForceOTA(), src, remote)
} else {
Pipeloop(handle, src, remote)
}

natlist.Delete(src.String())
}()
} else {
Debug.Printf("[udp]using cached client %s->%s via %s ota=%v\n", src, dst, remote.LocalAddr(), ota)
Expand All @@ -248,7 +246,9 @@ func handleUDPConnection(handle *SecurePacketConn, n int, src net.Addr, receive
} else {
Debug.Println("[udp]error connecting to:", dst, err)
}
natlist.DeleteAndClose(src.String())
if conn := natlist.Delete(src.String()); conn != nil {
conn.Close()
}
}
// Pipeloop
return
Expand Down

0 comments on commit 97a5c71

Please sign in to comment.