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方法)。
|
如果两端都是gost(如上)则数据传输会被加密(使用tls或tls-auth方法),否则使用标准socks5进行通讯(no-auth或user/pass方法)。
|
||||||
|
|
||||||
#### shadowsocks
|
#### shadowsocks
|
||||||
gost对shadowsocks的支持是基于[shadowsocks-go](https://github.com/shadowsocks/shadowsocks-go)库。
|
gost对shadowsocks加密方法的支持是基于[shadowsocks-go](https://github.com/shadowsocks/shadowsocks-go)库。
|
||||||
|
|
||||||
服务端:
|
服务端:
|
||||||
```bash
|
```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 -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数据处理
|
SOCKS5 UDP数据处理
|
||||||
------
|
------
|
||||||
|
20
conn.go
20
conn.go
@ -16,6 +16,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -24,6 +25,21 @@ var (
|
|||||||
connCounter int32
|
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 {
|
func listenAndServe(arg Args) error {
|
||||||
var ln net.Listener
|
var ln net.Listener
|
||||||
var err error
|
var err error
|
||||||
@ -120,7 +136,9 @@ func handleConn(conn net.Conn, arg Args) {
|
|||||||
|
|
||||||
// http + socks5
|
// 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)
|
n, err := io.ReadAtLeast(conn, b, 2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
113
socks.go
113
socks.go
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/ginuerzh/gosocks5"
|
"github.com/ginuerzh/gosocks5"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -18,6 +19,10 @@ const (
|
|||||||
MethodTLSAuth uint8 = 0x82 // extended method for tls+auth
|
MethodTLSAuth uint8 = 0x82 // extended method for tls+auth
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CmdUdpTun uint8 = 0xf3 // extended method for udp over tcp
|
||||||
|
)
|
||||||
|
|
||||||
type clientSelector struct {
|
type clientSelector struct {
|
||||||
methods []uint8
|
methods []uint8
|
||||||
user *url.Userinfo
|
user *url.Userinfo
|
||||||
@ -193,7 +198,7 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
|||||||
} else {
|
} else {
|
||||||
serveBind(conn)
|
serveBind(conn)
|
||||||
}
|
}
|
||||||
case gosocks5.CmdUdp:
|
case gosocks5.CmdUdp, CmdUdpTun:
|
||||||
glog.V(LINFO).Infoln("[socks5] UDP ASSOCIATE", req.Addr)
|
glog.V(LINFO).Infoln("[socks5] UDP ASSOCIATE", req.Addr)
|
||||||
uconn, err := net.ListenUDP("udp", nil)
|
uconn, err := net.ListenUDP("udp", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -211,7 +216,6 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
|||||||
|
|
||||||
addr := ToSocksAddr(uconn.LocalAddr())
|
addr := ToSocksAddr(uconn.LocalAddr())
|
||||||
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||||
glog.V(LINFO).Infoln("[socks5] UDP listen on", addr)
|
|
||||||
|
|
||||||
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
||||||
if err := rep.Write(conn); err != nil {
|
if err := rep.Write(conn); err != nil {
|
||||||
@ -219,42 +223,67 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
|||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
glog.V(LDEBUG).Infoln(rep)
|
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 {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
return
|
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 {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
return
|
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 {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
return
|
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)
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dgram, err = sc.ReadUDPTimeout(time.Second * 30)
|
dgram, err = sc.ReadUDPTimeout(time.Second * 60)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
glog.V(LINFO).Infof("[udp] from %s, length %d", dgram.Header.Addr, len(dgram.Data))
|
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)
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
return
|
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)
|
TransportUDP(cc, sc)
|
||||||
default:
|
default:
|
||||||
glog.V(LWARNING).Infoln("Unrecognized request: ", req)
|
glog.V(LWARNING).Infoln("Unrecognized request: ", req)
|
||||||
@ -334,7 +363,7 @@ func forwardBind(req *gosocks5.Request, conn net.Conn) error {
|
|||||||
defer fconn.Close()
|
defer fconn.Close()
|
||||||
|
|
||||||
if err := req.Write(fconn); err != nil {
|
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)
|
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -377,53 +406,7 @@ func peekReply(dst io.Writer, src io.Reader) (rep *gosocks5.Reply, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func createClientConn(conn net.Conn, uconn *net.UDPConn) (c *UDPConn, dgram *gosocks5.UDPDatagram, err error) {
|
func createServerConn(uconn *net.UDPConn) (c *UDPConn, 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) {
|
|
||||||
if len(forwardArgs) == 0 {
|
if len(forwardArgs) == 0 {
|
||||||
c = Server(uconn)
|
c = Server(uconn)
|
||||||
return
|
return
|
||||||
@ -436,9 +419,9 @@ func createServerConn(uconn *net.UDPConn, addr net.Addr) (c *UDPConn, err error)
|
|||||||
}
|
}
|
||||||
return
|
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 {
|
if err = req.Write(fconn); err != nil {
|
||||||
fconn.Close()
|
fconn.Close()
|
||||||
return
|
return
|
||||||
@ -455,7 +438,7 @@ func createServerConn(uconn *net.UDPConn, addr net.Addr) (c *UDPConn, err error)
|
|||||||
fconn.Close()
|
fconn.Close()
|
||||||
return nil, errors.New("Failure")
|
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)
|
c = Server(fconn)
|
||||||
return
|
return
|
||||||
@ -477,13 +460,13 @@ func PipeUDP(src, dst *UDPConn, ch chan<- error) {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
var dgram *gosocks5.UDPDatagram
|
var dgram *gosocks5.UDPDatagram
|
||||||
dgram, err = src.ReadUDP()
|
dgram, err = src.ReadUDPTimeout(time.Second * 60)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
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
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -501,9 +484,9 @@ func TransportUDP(cc, sc *UDPConn) (err error) {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case err = <-wChan:
|
case err = <-wChan:
|
||||||
//log.Println("w exit", err)
|
// glog.V(LDEBUG).Infoln("w exit", err)
|
||||||
case err = <-rChan:
|
case err = <-rChan:
|
||||||
//log.Println("r exit", err)
|
// glog.V(LDEBUG).Infoln("r exit", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
Loading…
Reference in New Issue
Block a user