fix udp over tcp

This commit is contained in:
rui.zheng 2016-02-04 18:01:14 +08:00
parent 59e7057fe9
commit a482f258da
3 changed files with 76 additions and 75 deletions

View File

@ -119,7 +119,7 @@ gost -L=:8080 -F=socks://server_ip:1080
如果两端都是gost(如上)则数据传输会被加密(使用tls或tls-auth方法)否则使用标准socks5进行通讯(no-auth或user/pass方法)。
#### shadowsocks
gost对shadowsocks的支持是基于[shadowsocks-go](https://github.com/shadowsocks/shadowsocks-go)库。
gost对shadowsocks加密方法的支持是基于[shadowsocks-go](https://github.com/shadowsocks/shadowsocks-go)库。
服务端:
```bash
@ -130,7 +130,7 @@ gost -L=ss://aes-128-cfb:123456@:8338
gost -L=:8080 -F=ss://aes-128-cfb:123456@server_ip:8338
```
gost内置了tls证书如果需要使用其他tls证书在gost目录放置key.pem(公钥)和cert.pem(私钥)两个文件即可。
gost内置了tls证书如果需要使用其他tls证书在gost目录放置cert.pem(公钥)和key.pem(私钥)两个文件即可。
SOCKS5 UDP数据处理
------

20
conn.go
View File

@ -16,6 +16,7 @@ import (
"net/url"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
)
@ -24,6 +25,21 @@ var (
connCounter int32
)
var (
// tcp buffer pool
tcpPool = sync.Pool{
New: func() interface{} {
return make([]byte, 16*1024)
},
}
// udp buffer pool
udpPool = sync.Pool{
New: func() interface{} {
return make([]byte, 64*1024+262)
},
}
)
func listenAndServe(arg Args) error {
var ln net.Listener
var err error
@ -120,7 +136,9 @@ func handleConn(conn net.Conn, arg Args) {
// http + socks5
b := make([]byte, 16*1024)
//b := make([]byte, 16*1024)
b := tcpPool.Get().([]byte)
defer tcpPool.Put(b)
n, err := io.ReadAtLeast(conn, b, 2)
if err != nil {

113
socks.go
View File

@ -7,6 +7,7 @@ import (
"github.com/ginuerzh/gosocks5"
"github.com/golang/glog"
"io"
"io/ioutil"
"net"
"net/url"
"strconv"
@ -18,6 +19,10 @@ const (
MethodTLSAuth uint8 = 0x82 // extended method for tls+auth
)
const (
CmdUdpTun uint8 = 0xf3 // extended method for udp over tcp
)
type clientSelector struct {
methods []uint8
user *url.Userinfo
@ -193,7 +198,7 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
} else {
serveBind(conn)
}
case gosocks5.CmdUdp:
case gosocks5.CmdUdp, CmdUdpTun:
glog.V(LINFO).Infoln("[socks5] UDP ASSOCIATE", req.Addr)
uconn, err := net.ListenUDP("udp", nil)
if err != nil {
@ -211,7 +216,6 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
addr := ToSocksAddr(uconn.LocalAddr())
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
glog.V(LINFO).Infoln("[socks5] UDP listen on", addr)
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
if err := rep.Write(conn); err != nil {
@ -219,42 +223,67 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
return
} else {
glog.V(LDEBUG).Infoln(rep)
glog.V(LINFO).Infoln("[socks5] UDP listen on", addr)
}
cc, dgram, err := createClientConn(conn, uconn)
var cc *UDPConn
var dgram *gosocks5.UDPDatagram
if req.Cmd == CmdUdpTun {
dgram, err = gosocks5.ReadUDPDatagram(conn)
if err != nil {
glog.V(LWARNING).Infoln("socks5 udp:", err)
return
}
glog.V(LINFO).Infof("[udp] to %s, length %d", dgram.Header.Addr, len(dgram.Data))
cc = Client(conn, nil)
glog.V(LINFO).Infof("[udp] tunnel to %s, length %d", dgram.Header.Addr, len(dgram.Data))
} else {
b := udpPool.Get().([]byte)
defer udpPool.Put(b)
raddr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String())
n, raddr, err := uconn.ReadFromUDP(b)
if err != nil {
glog.V(LWARNING).Infoln("socks5 udp:", err)
return
}
sc, err := createServerConn(uconn, raddr)
dgram, err = gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n]))
if err != nil {
glog.V(LWARNING).Infoln("socks5 udp:", err)
return
}
cc = Client(uconn, raddr)
glog.V(LINFO).Infof("[udp] %s -> %s, length %d", raddr, dgram.Header.Addr, len(dgram.Data))
}
sc, err := createServerConn(uconn)
if err != nil {
glog.V(LWARNING).Infoln("socks5 udp:", err)
return
}
if err = sc.WriteUDPTimeout(dgram, time.Second*30); err != nil {
if err = sc.WriteUDPTimeout(dgram, time.Second*60); err != nil {
glog.V(LWARNING).Infoln("socks5 udp:", err)
return
}
dgram, err = sc.ReadUDPTimeout(time.Second * 30)
dgram, err = sc.ReadUDPTimeout(time.Second * 60)
if err != nil {
glog.V(LWARNING).Infoln("socks5 udp:", err)
return
}
glog.V(LINFO).Infof("[udp] from %s, length %d", dgram.Header.Addr, len(dgram.Data))
if err = cc.WriteUDPTimeout(dgram, time.Second*30); err != nil {
if err = cc.WriteUDPTimeout(dgram, time.Second*60); err != nil {
glog.V(LWARNING).Infoln("socks5 udp:", err)
return
}
if req.Cmd == gosocks5.CmdUdp {
go func() {
ioutil.ReadAll(conn)
cc.Close()
sc.Close()
glog.V(LINFO).Infoln("[udp] transfer done")
}()
}
TransportUDP(cc, sc)
default:
glog.V(LWARNING).Infoln("Unrecognized request: ", req)
@ -334,7 +363,7 @@ func forwardBind(req *gosocks5.Request, conn net.Conn) error {
defer fconn.Close()
if err := req.Write(fconn); err != nil {
glog.V(LWARNING).Infoln("[socks5] BIND(forward)", err)
glog.V(LWARNING).Infoln("[socks5] BIND forward", err)
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
return err
}
@ -377,53 +406,7 @@ func peekReply(dst io.Writer, src io.Reader) (rep *gosocks5.Reply, err error) {
return
}
func createClientConn(conn net.Conn, uconn *net.UDPConn) (c *UDPConn, dgram *gosocks5.UDPDatagram, err error) {
var raddr *net.UDPAddr
dgramChan := make(chan *gosocks5.UDPDatagram, 1)
errChan := make(chan error, 1)
go func() {
b := make([]byte, 64*1024+262)
n, addr, err := uconn.ReadFromUDP(b)
if err != nil {
errChan <- err
return
}
raddr = addr
dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n]))
if err != nil {
errChan <- err
return
}
dgramChan <- dgram
}()
go func() {
dgram, err := gosocks5.ReadUDPDatagram(conn)
if err != nil {
errChan <- err
return
}
dgramChan <- dgram
}()
select {
case dgram = <-dgramChan:
if raddr != nil {
glog.V(LINFO).Infoln("[udp] client", raddr)
c = Client(uconn, raddr)
} else {
glog.V(LINFO).Infoln("[udp] tunnel")
c = Client(conn, nil)
}
case err = <-errChan:
}
return
}
func createServerConn(uconn *net.UDPConn, addr net.Addr) (c *UDPConn, err error) {
func createServerConn(uconn *net.UDPConn) (c *UDPConn, err error) {
if len(forwardArgs) == 0 {
c = Server(uconn)
return
@ -436,9 +419,9 @@ func createServerConn(uconn *net.UDPConn, addr net.Addr) (c *UDPConn, err error)
}
return
}
glog.V(LINFO).Infoln("forward udp associate")
glog.V(LINFO).Infoln("[udp] forward associate")
req := gosocks5.NewRequest(gosocks5.CmdUdp, nil)
req := gosocks5.NewRequest(CmdUdpTun, nil)
if err = req.Write(fconn); err != nil {
fconn.Close()
return
@ -455,7 +438,7 @@ func createServerConn(uconn *net.UDPConn, addr net.Addr) (c *UDPConn, err error)
fconn.Close()
return nil, errors.New("Failure")
}
glog.V(LINFO).Infoln("forward udp associate, on", rep.Addr, "OK")
glog.V(LINFO).Infoln("[udp] forward associate on", rep.Addr, "OK")
c = Server(fconn)
return
@ -477,13 +460,13 @@ func PipeUDP(src, dst *UDPConn, ch chan<- error) {
for {
var dgram *gosocks5.UDPDatagram
dgram, err = src.ReadUDP()
dgram, err = src.ReadUDPTimeout(time.Second * 60)
if err != nil {
break
}
// glog.V(LDEBUG).Infof("[udp] addr %s, length %d", dgram.Header.Addr, len(dgram.Data))
glog.V(LDEBUG).Infof("[udp] addr %s, length %d", dgram.Header.Addr, len(dgram.Data))
if err = dst.WriteUDP(dgram); err != nil {
if err = dst.WriteUDPTimeout(dgram, time.Second*60); err != nil {
break
}
}
@ -501,9 +484,9 @@ func TransportUDP(cc, sc *UDPConn) (err error) {
select {
case err = <-wChan:
//log.Println("w exit", err)
// glog.V(LDEBUG).Infoln("w exit", err)
case err = <-rChan:
//log.Println("r exit", err)
// glog.V(LDEBUG).Infoln("r exit", err)
}
return