merge branch 2.0
This commit is contained in:
commit
10ca37d721
@ -121,7 +121,7 @@ gost -L=:8080 -F=socks://server_ip:1080
|
|||||||
注:如果transport已经使用了加密模式(wss, tls),则socks5不会再使用加密方法,防止不必要的双重加密。
|
注:如果transport已经使用了加密模式(wss, tls),则socks5不会再使用加密方法,防止不必要的双重加密。
|
||||||
|
|
||||||
#### shadowsocks
|
#### shadowsocks
|
||||||
gost对shadowsocks的支持是基于[shadowsocks-go](https://github.com/shadowsocks/shadowsocks-go)库。
|
gost对shadowsocks加密方法的支持是基于[shadowsocks-go](https://github.com/shadowsocks/shadowsocks-go)库。
|
||||||
|
|
||||||
服务端:
|
服务端:
|
||||||
```bash
|
```bash
|
||||||
@ -133,7 +133,8 @@ gost -L=:8080 -F=ss://aes-128-cfb:123456@server_ip:8338
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### TLS
|
#### TLS
|
||||||
gost内置了tls证书,如果需要使用其他tls证书,在gost目录放置key.pem(公钥)和cert.pem(私钥)两个文件即可。
|
gost内置了tls证书,如果需要使用其他tls证书,在gost目录放置cert.pem(公钥)和key.pem(私钥)两个文件即可。
|
||||||
|
|
||||||
|
|
||||||
SOCKS5 UDP数据处理
|
SOCKS5 UDP数据处理
|
||||||
------
|
------
|
||||||
|
22
conn.go
22
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 {
|
||||||
@ -214,7 +232,7 @@ func Connect(addr string) (conn net.Conn, err error) {
|
|||||||
|
|
||||||
func forwardChain(chain ...Args) (conn net.Conn, end Args, err error) {
|
func forwardChain(chain ...Args) (conn net.Conn, end Args, err error) {
|
||||||
end = chain[0]
|
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
|
return
|
||||||
}
|
}
|
||||||
c, err := forward(conn, end)
|
c, err := forward(conn, end)
|
||||||
|
2
main.go
2
main.go
@ -18,7 +18,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = "2.0-rc2"
|
Version = "2.0-rc3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
152
socks.go
152
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,43 +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 {
|
||||||
|
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 {
|
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))
|
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 {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sc, err := createServerConn(uconn, raddr)
|
glog.V(LINFO).Infof("[udp] <- %s, length %d", dgram.Header.Addr, len(dgram.Data))
|
||||||
if err != nil {
|
|
||||||
|
if err = cc.WriteUDPTimeout(dgram, time.Second*90); 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 req.Cmd == gosocks5.CmdUdp {
|
||||||
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
go TransportUDP(cc, sc)
|
||||||
return
|
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:
|
default:
|
||||||
glog.V(LWARNING).Infoln("Unrecognized request: ", req)
|
glog.V(LWARNING).Infoln("Unrecognized request: ", req)
|
||||||
}
|
}
|
||||||
@ -288,6 +316,7 @@ func serveBind(conn net.Conn) error {
|
|||||||
glog.V(LDEBUG).Infoln(rep)
|
glog.V(LDEBUG).Infoln(rep)
|
||||||
glog.V(LINFO).Infoln("[socks5] BIND on", addr, "OK")
|
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()
|
tconn, err := l.AcceptTCP()
|
||||||
l.Close() // only accept one peer
|
l.Close() // only accept one peer
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -319,7 +348,7 @@ func serveBind(conn net.Conn) error {
|
|||||||
func forwardBind(req *gosocks5.Request, conn net.Conn) error {
|
func forwardBind(req *gosocks5.Request, conn net.Conn) error {
|
||||||
fconn, _, err := forwardChain(forwardArgs...)
|
fconn, _, err := forwardChain(forwardArgs...)
|
||||||
if err != nil {
|
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 {
|
if fconn != nil {
|
||||||
fconn.Close()
|
fconn.Close()
|
||||||
}
|
}
|
||||||
@ -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
|
||||||
}
|
}
|
||||||
@ -343,18 +372,18 @@ func forwardBind(req *gosocks5.Request, conn net.Conn) error {
|
|||||||
// first reply
|
// first reply
|
||||||
rep, err := peekReply(conn, fconn)
|
rep, err := peekReply(conn, fconn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("[socks5] BIND(forward)", err)
|
glog.V(LWARNING).Infoln("[socks5] BIND forward", err)
|
||||||
return 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
|
// second reply
|
||||||
rep, err = peekReply(conn, fconn)
|
rep, err = peekReply(conn, fconn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("[socks5] BIND(forward) accept", err)
|
glog.V(LWARNING).Infoln("[socks5] BIND forward accept", err)
|
||||||
return 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)
|
return Transport(conn, fconn)
|
||||||
}
|
}
|
||||||
@ -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
|
||||||
@ -481,8 +464,11 @@ func PipeUDP(src, dst *UDPConn, ch chan<- error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
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 {
|
if err = dst.WriteUDP(dgram); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -501,9 +487,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
|
||||||
|
5
udp.go
5
udp.go
@ -72,7 +72,10 @@ func (c *UDPConn) readUDPClient() (*gosocks5.UDPDatagram, error) {
|
|||||||
|
|
||||||
func (c *UDPConn) readUDPServer() (*gosocks5.UDPDatagram, error) {
|
func (c *UDPConn) readUDPServer() (*gosocks5.UDPDatagram, error) {
|
||||||
if c.udp != nil {
|
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)
|
n, addr, err := c.udp.ReadFrom(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
9
ws.go
9
ws.go
@ -129,15 +129,18 @@ func (s *ws) handle(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *ws) ListenAndServe() error {
|
func (s *ws) ListenAndServe() error {
|
||||||
http.HandleFunc("/ws", s.handle)
|
sm := http.NewServeMux()
|
||||||
return http.ListenAndServe(s.arg.Addr, nil)
|
sm.HandleFunc("/ws", s.handle)
|
||||||
|
return http.ListenAndServe(s.arg.Addr, sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ws) listenAndServeTLS() error {
|
func (s *ws) listenAndServeTLS() error {
|
||||||
http.HandleFunc("/ws", s.handle)
|
sm := http.NewServeMux()
|
||||||
|
sm.HandleFunc("/ws", s.handle)
|
||||||
server := &http.Server{
|
server := &http.Server{
|
||||||
Addr: s.arg.Addr,
|
Addr: s.arg.Addr,
|
||||||
TLSConfig: &tls.Config{Certificates: []tls.Certificate{s.arg.Cert}},
|
TLSConfig: &tls.Config{Certificates: []tls.Certificate{s.arg.Cert}},
|
||||||
|
Handler: sm,
|
||||||
}
|
}
|
||||||
return server.ListenAndServeTLS("", "")
|
return server.ListenAndServeTLS("", "")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user