fix udp over tcp
This commit is contained in:
parent
59e7057fe9
commit
a482f258da
@ -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
20
conn.go
@ -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 {
|
||||
|
127
socks.go
127
socks.go
@ -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)
|
||||
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))
|
||||
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
|
||||
}
|
||||
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())
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||
return
|
||||
n, raddr, err := uconn.ReadFromUDP(b)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||
return
|
||||
}
|
||||
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, raddr)
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user