mirror of https://github.com/ginuerzh/gost
14 changed files with 1065 additions and 71 deletions
@ -0,0 +1,121 @@ |
|||
package gost |
|||
|
|||
import ( |
|||
"bytes" |
|||
"crypto/tls" |
|||
"fmt" |
|||
"io" |
|||
"net" |
|||
"net/http" |
|||
"sync" |
|||
) |
|||
|
|||
func init() { |
|||
// SetLogger(&LogLogger{})
|
|||
// Debug = true
|
|||
|
|||
cert, err := GenCertificate() |
|||
if err != nil { |
|||
panic(err) |
|||
} |
|||
DefaultTLSConfig = &tls.Config{ |
|||
Certificates: []tls.Certificate{cert}, |
|||
} |
|||
} |
|||
|
|||
var ( |
|||
httpTestHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|||
io.Copy(w, r.Body) |
|||
}) |
|||
|
|||
udpTestHandler = udpHandlerFunc(func(w io.Writer, r *udpRequest) { |
|||
io.Copy(w, r.Body) |
|||
}) |
|||
) |
|||
|
|||
type udpRequest struct { |
|||
Body io.Reader |
|||
RemoteAddr string |
|||
} |
|||
|
|||
type udpResponseWriter struct { |
|||
conn net.PacketConn |
|||
addr net.Addr |
|||
} |
|||
|
|||
func (w *udpResponseWriter) Write(p []byte) (int, error) { |
|||
return w.conn.WriteTo(p, w.addr) |
|||
} |
|||
|
|||
type udpHandlerFunc func(w io.Writer, r *udpRequest) |
|||
|
|||
// udpTestServer is a UDP server for test.
|
|||
type udpTestServer struct { |
|||
ln net.PacketConn |
|||
handler udpHandlerFunc |
|||
wg sync.WaitGroup |
|||
mu sync.Mutex // guards closed and conns
|
|||
closed bool |
|||
} |
|||
|
|||
func newUDPTestServer(handler udpHandlerFunc) *udpTestServer { |
|||
laddr, _ := net.ResolveUDPAddr("udp", "127.0.0.1:0") |
|||
ln, err := net.ListenUDP("udp", laddr) |
|||
if err != nil { |
|||
panic(fmt.Sprintf("udptest: failed to listen on a port: %v", err)) |
|||
} |
|||
return &udpTestServer{ |
|||
ln: ln, |
|||
handler: handler, |
|||
} |
|||
} |
|||
|
|||
func (s *udpTestServer) Start() { |
|||
go s.serve() |
|||
} |
|||
|
|||
func (s *udpTestServer) serve() { |
|||
for { |
|||
data := make([]byte, 1024) |
|||
n, raddr, err := s.ln.ReadFrom(data) |
|||
if err != nil { |
|||
return |
|||
} |
|||
if s.handler != nil { |
|||
s.wg.Add(1) |
|||
go func() { |
|||
defer s.wg.Done() |
|||
w := &udpResponseWriter{ |
|||
conn: s.ln, |
|||
addr: raddr, |
|||
} |
|||
r := &udpRequest{ |
|||
Body: bytes.NewReader(data[:n]), |
|||
RemoteAddr: raddr.String(), |
|||
} |
|||
s.handler(w, r) |
|||
}() |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (s *udpTestServer) Addr() string { |
|||
return s.ln.LocalAddr().String() |
|||
} |
|||
|
|||
func (s *udpTestServer) Close() error { |
|||
s.mu.Lock() |
|||
|
|||
if s.closed { |
|||
s.mu.Unlock() |
|||
return nil |
|||
} |
|||
|
|||
err := s.ln.Close() |
|||
s.closed = true |
|||
s.mu.Unlock() |
|||
|
|||
s.wg.Wait() |
|||
|
|||
return err |
|||
} |
|||
@ -0,0 +1,333 @@ |
|||
package gost |
|||
|
|||
import ( |
|||
"bytes" |
|||
"crypto/rand" |
|||
"fmt" |
|||
"net/http/httptest" |
|||
"net/url" |
|||
"testing" |
|||
"time" |
|||
) |
|||
|
|||
func tcpDirectForwardRoundtrip(targetURL string, data []byte) error { |
|||
ln, err := TCPListener("") |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
u, err := url.Parse(targetURL) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
client := &Client{ |
|||
Connector: ForwardConnector(), |
|||
Transporter: TCPTransporter(), |
|||
} |
|||
|
|||
server := &Server{ |
|||
Listener: ln, |
|||
Handler: TCPDirectForwardHandler(u.Host), |
|||
} |
|||
|
|||
go server.Run() |
|||
defer server.Close() |
|||
|
|||
return proxyRoundtrip(client, server, targetURL, data) |
|||
} |
|||
|
|||
func TestTCPDirectForward(t *testing.T) { |
|||
httpSrv := httptest.NewServer(httpTestHandler) |
|||
defer httpSrv.Close() |
|||
|
|||
sendData := make([]byte, 128) |
|||
rand.Read(sendData) |
|||
|
|||
err := tcpDirectForwardRoundtrip(httpSrv.URL, sendData) |
|||
if err != nil { |
|||
t.Error(err) |
|||
} |
|||
} |
|||
|
|||
func BenchmarkTCPDirectForward(b *testing.B) { |
|||
httpSrv := httptest.NewServer(httpTestHandler) |
|||
defer httpSrv.Close() |
|||
|
|||
sendData := make([]byte, 128) |
|||
rand.Read(sendData) |
|||
|
|||
ln, err := TCPListener("") |
|||
if err != nil { |
|||
b.Error(err) |
|||
} |
|||
|
|||
client := &Client{ |
|||
Connector: ForwardConnector(), |
|||
Transporter: TCPTransporter(), |
|||
} |
|||
|
|||
u, err := url.Parse(httpSrv.URL) |
|||
if err != nil { |
|||
b.Error(err) |
|||
} |
|||
server := &Server{ |
|||
Listener: ln, |
|||
Handler: TCPDirectForwardHandler(u.Host), |
|||
} |
|||
go server.Run() |
|||
defer server.Close() |
|||
|
|||
for i := 0; i < b.N; i++ { |
|||
if err := proxyRoundtrip(client, server, httpSrv.URL, sendData); err != nil { |
|||
b.Error(err) |
|||
} |
|||
} |
|||
} |
|||
|
|||
func BenchmarkTCPDirectForwardParallel(b *testing.B) { |
|||
httpSrv := httptest.NewServer(httpTestHandler) |
|||
defer httpSrv.Close() |
|||
|
|||
sendData := make([]byte, 128) |
|||
rand.Read(sendData) |
|||
|
|||
ln, err := TCPListener("") |
|||
if err != nil { |
|||
b.Error(err) |
|||
} |
|||
|
|||
client := &Client{ |
|||
Connector: ForwardConnector(), |
|||
Transporter: TCPTransporter(), |
|||
} |
|||
|
|||
u, err := url.Parse(httpSrv.URL) |
|||
if err != nil { |
|||
b.Error(err) |
|||
} |
|||
server := &Server{ |
|||
Listener: ln, |
|||
Handler: TCPDirectForwardHandler(u.Host), |
|||
} |
|||
go server.Run() |
|||
defer server.Close() |
|||
|
|||
b.RunParallel(func(pb *testing.PB) { |
|||
for pb.Next() { |
|||
if err := proxyRoundtrip(client, server, httpSrv.URL, sendData); err != nil { |
|||
b.Error(err) |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
|
|||
func udpRoundtrip(client *Client, server *Server, host string, data []byte) (err error) { |
|||
conn, err := proxyConn(client, server) |
|||
if err != nil { |
|||
return |
|||
} |
|||
defer conn.Close() |
|||
|
|||
conn.SetDeadline(time.Now().Add(1 * time.Second)) |
|||
defer conn.SetDeadline(time.Time{}) |
|||
|
|||
conn, err = client.Connect(conn, host) |
|||
if err != nil { |
|||
return |
|||
} |
|||
|
|||
if _, err = conn.Write(data); err != nil { |
|||
return |
|||
} |
|||
|
|||
recv := make([]byte, len(data)) |
|||
if _, err = conn.Read(recv); err != nil { |
|||
return |
|||
} |
|||
|
|||
if !bytes.Equal(data, recv) { |
|||
return fmt.Errorf("data not equal") |
|||
} |
|||
|
|||
return |
|||
} |
|||
|
|||
func udpDirectForwardRoundtrip(host string, data []byte) error { |
|||
ln, err := UDPDirectForwardListener("localhost:0", 0) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
client := &Client{ |
|||
Connector: ForwardConnector(), |
|||
Transporter: UDPTransporter(), |
|||
} |
|||
|
|||
server := &Server{ |
|||
Listener: ln, |
|||
Handler: UDPDirectForwardHandler(host), |
|||
} |
|||
|
|||
go server.Run() |
|||
defer server.Close() |
|||
|
|||
return udpRoundtrip(client, server, host, data) |
|||
} |
|||
|
|||
func TestUDPDirectForward(t *testing.T) { |
|||
udpSrv := newUDPTestServer(udpTestHandler) |
|||
udpSrv.Start() |
|||
defer udpSrv.Close() |
|||
|
|||
sendData := make([]byte, 128) |
|||
rand.Read(sendData) |
|||
err := udpDirectForwardRoundtrip(udpSrv.Addr(), sendData) |
|||
if err != nil { |
|||
t.Error(err) |
|||
} |
|||
} |
|||
|
|||
func BenchmarkUDPDirectForward(b *testing.B) { |
|||
udpSrv := newUDPTestServer(udpTestHandler) |
|||
udpSrv.Start() |
|||
defer udpSrv.Close() |
|||
|
|||
sendData := make([]byte, 128) |
|||
rand.Read(sendData) |
|||
|
|||
ln, err := UDPDirectForwardListener("localhost:0", 0) |
|||
if err != nil { |
|||
b.Error(err) |
|||
} |
|||
|
|||
client := &Client{ |
|||
Connector: ForwardConnector(), |
|||
Transporter: UDPTransporter(), |
|||
} |
|||
|
|||
server := &Server{ |
|||
Listener: ln, |
|||
Handler: UDPDirectForwardHandler(udpSrv.Addr()), |
|||
} |
|||
|
|||
go server.Run() |
|||
defer server.Close() |
|||
|
|||
for i := 0; i < b.N; i++ { |
|||
if err := udpRoundtrip(client, server, udpSrv.Addr(), sendData); err != nil { |
|||
b.Error(err) |
|||
} |
|||
} |
|||
} |
|||
|
|||
func BenchmarkUDPDirectForwardParallel(b *testing.B) { |
|||
udpSrv := newUDPTestServer(udpTestHandler) |
|||
udpSrv.Start() |
|||
defer udpSrv.Close() |
|||
|
|||
sendData := make([]byte, 128) |
|||
rand.Read(sendData) |
|||
|
|||
ln, err := UDPDirectForwardListener("localhost:0", 0) |
|||
if err != nil { |
|||
b.Error(err) |
|||
} |
|||
|
|||
client := &Client{ |
|||
Connector: ForwardConnector(), |
|||
Transporter: UDPTransporter(), |
|||
} |
|||
|
|||
server := &Server{ |
|||
Listener: ln, |
|||
Handler: UDPDirectForwardHandler(udpSrv.Addr()), |
|||
} |
|||
|
|||
go server.Run() |
|||
defer server.Close() |
|||
|
|||
b.RunParallel(func(pb *testing.PB) { |
|||
for pb.Next() { |
|||
if err := udpRoundtrip(client, server, udpSrv.Addr(), sendData); err != nil { |
|||
b.Error(err) |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
|
|||
func tcpRemoteForwardRoundtrip(t *testing.T, targetURL string, data []byte) error { |
|||
ln, err := TCPRemoteForwardListener("localhost:0", nil) // listening on localhost
|
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
u, err := url.Parse(targetURL) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
client := &Client{ |
|||
Connector: ForwardConnector(), |
|||
Transporter: TCPTransporter(), |
|||
} |
|||
|
|||
server := &Server{ |
|||
Listener: ln, |
|||
Handler: TCPRemoteForwardHandler(u.Host), // forward to u.Host
|
|||
} |
|||
|
|||
go server.Run() |
|||
defer server.Close() |
|||
|
|||
return proxyRoundtrip(client, server, targetURL, data) |
|||
} |
|||
|
|||
func TestTCPRemoteForward(t *testing.T) { |
|||
httpSrv := httptest.NewServer(httpTestHandler) |
|||
defer httpSrv.Close() |
|||
|
|||
sendData := make([]byte, 128) |
|||
rand.Read(sendData) |
|||
|
|||
err := tcpRemoteForwardRoundtrip(t, httpSrv.URL, sendData) |
|||
if err != nil { |
|||
t.Error(err) |
|||
} |
|||
} |
|||
|
|||
func udpRemoteForwardRoundtrip(t *testing.T, host string, data []byte) error { |
|||
ln, err := UDPRemoteForwardListener("localhost:0", nil, 0) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
client := &Client{ |
|||
Connector: ForwardConnector(), |
|||
Transporter: UDPTransporter(), |
|||
} |
|||
|
|||
server := &Server{ |
|||
Listener: ln, |
|||
Handler: UDPRemoteForwardHandler(host), |
|||
} |
|||
|
|||
go server.Run() |
|||
defer server.Close() |
|||
|
|||
return udpRoundtrip(client, server, host, data) |
|||
} |
|||
|
|||
func TestUDPRemoteForward(t *testing.T) { |
|||
udpSrv := newUDPTestServer(udpTestHandler) |
|||
udpSrv.Start() |
|||
defer udpSrv.Close() |
|||
|
|||
sendData := make([]byte, 128) |
|||
rand.Read(sendData) |
|||
|
|||
err := udpRemoteForwardRoundtrip(t, udpSrv.Addr(), sendData) |
|||
if err != nil { |
|||
t.Error(err) |
|||
} |
|||
} |
|||
Loading…
Reference in new issue