merge branch 2.0

This commit is contained in:
rui.zheng 2016-02-05 15:31:38 +08:00
commit 10ca37d721
6 changed files with 103 additions and 92 deletions

View File

@ -121,7 +121,7 @@ gost -L=:8080 -F=socks://server_ip:1080
如果transport已经使用了加密模式(wss, tls)则socks5不会再使用加密方法防止不必要的双重加密。
#### shadowsocks
gost对shadowsocks的支持是基于[shadowsocks-go](https://github.com/shadowsocks/shadowsocks-go)库。
gost对shadowsocks加密方法的支持是基于[shadowsocks-go](https://github.com/shadowsocks/shadowsocks-go)库。
服务端:
```bash
@ -133,7 +133,8 @@ gost -L=:8080 -F=ss://aes-128-cfb:123456@server_ip:8338
```
#### TLS
gost内置了tls证书如果需要使用其他tls证书在gost目录放置key.pem(公钥)和cert.pem(私钥)两个文件即可。
gost内置了tls证书如果需要使用其他tls证书在gost目录放置cert.pem(公钥)和key.pem(私钥)两个文件即可。
SOCKS5 UDP数据处理
------

22
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 {
@ -214,7 +232,7 @@ func Connect(addr string) (conn net.Conn, err error) {
func forwardChain(chain ...Args) (conn net.Conn, end Args, err error) {
end = chain[0]
if conn, err = net.DialTimeout("tcp", end.Addr, time.Second*30); err != nil {
if conn, err = net.DialTimeout("tcp", end.Addr, time.Second*90); err != nil {
return
}
c, err := forward(conn, end)

View File

@ -18,7 +18,7 @@ const (
)
const (
Version = "2.0-rc2"
Version = "2.0-rc3"
)
var (

152
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,43 +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
}
cc = Client(conn, nil)
glog.V(LINFO).Infof("[udp] -> %s, length %d", dgram.Header.Addr, len(dgram.Data))
} else {
b := udpPool.Get().([]byte)
defer udpPool.Put(b)
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)
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))
defer sc.Close()
raddr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String())
if err = sc.WriteUDPTimeout(dgram, time.Second*90); err != nil {
glog.V(LWARNING).Infoln("socks5 udp:", err)
return
}
dgram, err = sc.ReadUDPTimeout(time.Second * 90)
if err != nil {
glog.V(LWARNING).Infoln("socks5 udp:", err)
return
}
sc, err := createServerConn(uconn, raddr)
if err != nil {
glog.V(LINFO).Infof("[udp] <- %s, length %d", dgram.Header.Addr, len(dgram.Data))
if err = cc.WriteUDPTimeout(dgram, time.Second*90); err != nil {
glog.V(LWARNING).Infoln("socks5 udp:", err)
return
}
if err = sc.WriteUDPTimeout(dgram, time.Second*30); err != nil {
glog.V(LWARNING).Infoln("socks5 udp:", err)
return
if req.Cmd == gosocks5.CmdUdp {
go TransportUDP(cc, sc)
ioutil.ReadAll(conn) // wait for client exit
glog.V(LINFO).Infoln("[udp] transfer done")
} else {
TransportUDP(cc, sc)
}
dgram, err = sc.ReadUDPTimeout(time.Second * 30)
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 {
glog.V(LWARNING).Infoln("socks5 udp:", err)
return
}
TransportUDP(cc, sc)
default:
glog.V(LWARNING).Infoln("Unrecognized request: ", req)
}
@ -288,6 +316,7 @@ func serveBind(conn net.Conn) error {
glog.V(LDEBUG).Infoln(rep)
glog.V(LINFO).Infoln("[socks5] BIND on", addr, "OK")
l.SetDeadline(time.Now().Add(time.Minute * 30)) // wait 30 minutes at most
tconn, err := l.AcceptTCP()
l.Close() // only accept one peer
if err != nil {
@ -319,7 +348,7 @@ func serveBind(conn net.Conn) error {
func forwardBind(req *gosocks5.Request, conn net.Conn) error {
fconn, _, err := forwardChain(forwardArgs...)
if err != nil {
glog.V(LWARNING).Infoln("[socks5] BIND(forward)", req.Addr, err)
glog.V(LWARNING).Infoln("[socks5] BIND forward", req.Addr, err)
if fconn != nil {
fconn.Close()
}
@ -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
}
@ -343,18 +372,18 @@ func forwardBind(req *gosocks5.Request, conn net.Conn) error {
// first reply
rep, err := peekReply(conn, fconn)
if err != nil {
glog.V(LWARNING).Infoln("[socks5] BIND(forward)", err)
glog.V(LWARNING).Infoln("[socks5] BIND forward", err)
return err
}
glog.V(LINFO).Infoln("[socks5] BIND(forward) on", rep.Addr, "OK")
glog.V(LINFO).Infoln("[socks5] BIND forward on", rep.Addr, "OK")
// second reply
rep, err = peekReply(conn, fconn)
if err != nil {
glog.V(LWARNING).Infoln("[socks5] BIND(forward) accept", err)
glog.V(LWARNING).Infoln("[socks5] BIND forward accept", err)
return err
}
glog.V(LINFO).Infoln("[socks5] BIND(forward) accept", rep.Addr)
glog.V(LINFO).Infoln("[socks5] BIND forward accept", rep.Addr)
return Transport(conn, fconn)
}
@ -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
@ -481,8 +464,11 @@ func PipeUDP(src, dst *UDPConn, ch chan<- error) {
if err != nil {
break
}
// glog.V(LDEBUG).Infof("[udp] addr %s, length %d", dgram.Header.Addr, len(dgram.Data))
if src.isClient {
glog.V(LDEBUG).Infof("[udp] -> %s, length %d", dgram.Header.Addr, len(dgram.Data))
} else {
glog.V(LDEBUG).Infof("[udp] <- %s, length %d", dgram.Header.Addr, len(dgram.Data))
}
if err = dst.WriteUDP(dgram); err != nil {
break
}
@ -501,9 +487,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

5
udp.go
View File

@ -72,7 +72,10 @@ func (c *UDPConn) readUDPClient() (*gosocks5.UDPDatagram, error) {
func (c *UDPConn) readUDPServer() (*gosocks5.UDPDatagram, error) {
if c.udp != nil {
b := make([]byte, 65535)
// b := make([]byte, 65535)
b := udpPool.Get().([]byte)
defer udpPool.Put(b)
n, addr, err := c.udp.ReadFrom(b)
if err != nil {
return nil, err

9
ws.go
View File

@ -129,15 +129,18 @@ func (s *ws) handle(w http.ResponseWriter, r *http.Request) {
}
func (s *ws) ListenAndServe() error {
http.HandleFunc("/ws", s.handle)
return http.ListenAndServe(s.arg.Addr, nil)
sm := http.NewServeMux()
sm.HandleFunc("/ws", s.handle)
return http.ListenAndServe(s.arg.Addr, sm)
}
func (s *ws) listenAndServeTLS() error {
http.HandleFunc("/ws", s.handle)
sm := http.NewServeMux()
sm.HandleFunc("/ws", s.handle)
server := &http.Server{
Addr: s.arg.Addr,
TLSConfig: &tls.Config{Certificates: []tls.Certificate{s.arg.Cert}},
Handler: sm,
}
return server.ListenAndServeTLS("", "")
}