add tests
This commit is contained in:
parent
d1cad3eb5b
commit
52a8626d4a
217
http_test.go
217
http_test.go
@ -4,56 +4,56 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var httpTestHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
var httpTestHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
io.Copy(w, r.Body)
|
io.Copy(w, r.Body)
|
||||||
})
|
})
|
||||||
|
|
||||||
func httpProxyRoundtrip(urlStr string, cliUser *url.Userinfo, srvUsers []*url.Userinfo, body io.Reader) (statusCode int, recv []byte, err error) {
|
func proxyRoundtrip(client *Client, server *Server, targetURL string, data []byte) (err error) {
|
||||||
ln, err := TCPListener("")
|
conn, err := client.Dial(server.Addr().String())
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
h := HTTPHandler(UsersHandlerOption(srvUsers...))
|
|
||||||
server := &Server{Listener: ln}
|
|
||||||
go server.Serve(h)
|
|
||||||
|
|
||||||
exitChan := make(chan struct{})
|
|
||||||
defer close(exitChan)
|
|
||||||
go func() {
|
|
||||||
defer server.Close()
|
|
||||||
<-exitChan
|
|
||||||
}()
|
|
||||||
|
|
||||||
client := &Client{
|
|
||||||
Connector: HTTPConnector(cliUser),
|
|
||||||
Transporter: TCPTransporter(),
|
|
||||||
}
|
|
||||||
conn, err := client.Dial(ln.Addr().String())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
|
conn.SetDeadline(time.Now().Add(1 * time.Second))
|
||||||
|
|
||||||
conn, err = client.Handshake(conn)
|
conn, err = client.Handshake(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
url, err := url.Parse(urlStr)
|
u, err := url.Parse(targetURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
conn, err = client.Connect(conn, url.Host)
|
conn, err = client.Connect(conn, u.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req, err := http.NewRequest(http.MethodGet, urlStr, body)
|
|
||||||
|
if u.Scheme == "https" {
|
||||||
|
conn = tls.Client(conn,
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
})
|
||||||
|
u.Scheme = "http"
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest(
|
||||||
|
http.MethodGet,
|
||||||
|
u.String(),
|
||||||
|
bytes.NewReader(data),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -65,63 +65,158 @@ func httpProxyRoundtrip(urlStr string, cliUser *url.Userinfo, srvUsers []*url.Us
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
statusCode = resp.StatusCode
|
|
||||||
recv, err = ioutil.ReadAll(resp.Body)
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return errors.New(resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
recv, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(data, recv) {
|
||||||
|
return fmt.Errorf("data not equal")
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var httpProxyTests = []struct {
|
var httpProxyTests = []struct {
|
||||||
url string
|
|
||||||
cliUser *url.Userinfo
|
cliUser *url.Userinfo
|
||||||
srvUsers []*url.Userinfo
|
srvUsers []*url.Userinfo
|
||||||
errStr string
|
errStr string
|
||||||
}{
|
}{
|
||||||
{"", nil, nil, ""},
|
{nil, nil, ""},
|
||||||
{"", nil, []*url.Userinfo{url.User("admin")}, "407 Proxy Authentication Required"},
|
{nil, []*url.Userinfo{url.User("admin")}, "407 Proxy Authentication Required"},
|
||||||
{"", nil, []*url.Userinfo{url.UserPassword("", "123456")}, "407 Proxy Authentication Required"},
|
{nil, []*url.Userinfo{url.UserPassword("", "123456")}, "407 Proxy Authentication Required"},
|
||||||
{"", url.User("admin"), []*url.Userinfo{url.User("test")}, "407 Proxy Authentication Required"},
|
{url.User("admin"), []*url.Userinfo{url.User("test")}, "407 Proxy Authentication Required"},
|
||||||
{"", url.User("admin"), []*url.Userinfo{url.UserPassword("admin", "123456")}, "407 Proxy Authentication Required"},
|
{url.User("admin"), []*url.Userinfo{url.UserPassword("admin", "123456")}, "407 Proxy Authentication Required"},
|
||||||
{"", url.User("admin"), []*url.Userinfo{url.User("admin")}, ""},
|
{url.User("admin"), []*url.Userinfo{url.User("admin")}, ""},
|
||||||
{"", url.User("admin"), []*url.Userinfo{url.UserPassword("admin", "")}, ""},
|
{url.User("admin"), []*url.Userinfo{url.UserPassword("admin", "")}, ""},
|
||||||
{"", url.UserPassword("admin", "123456"), nil, ""},
|
{url.UserPassword("admin", "123456"), nil, ""},
|
||||||
{"", url.UserPassword("admin", "123456"), []*url.Userinfo{url.User("admin")}, ""},
|
{url.UserPassword("admin", "123456"), []*url.Userinfo{url.User("admin")}, ""},
|
||||||
{"", url.UserPassword("admin", "123456"), []*url.Userinfo{url.UserPassword("", "123456")}, ""},
|
{url.UserPassword("admin", "123456"), []*url.Userinfo{url.UserPassword("", "123456")}, ""},
|
||||||
{"", url.UserPassword("", "123456"), []*url.Userinfo{url.UserPassword("", "123456")}, ""},
|
{url.UserPassword("", "123456"), []*url.Userinfo{url.UserPassword("", "123456")}, ""},
|
||||||
{"", url.UserPassword("admin", "123456"), []*url.Userinfo{url.UserPassword("admin", "123456")}, ""},
|
{url.UserPassword("admin", "123456"), []*url.Userinfo{url.UserPassword("admin", "123456")}, ""},
|
||||||
{"", url.UserPassword("admin", "123456"), []*url.Userinfo{url.UserPassword("user", "pass"), url.UserPassword("admin", "123456")}, ""},
|
{url.UserPassword("admin", "123456"), []*url.Userinfo{url.UserPassword("user", "pass"), url.UserPassword("admin", "123456")}, ""},
|
||||||
{"http://:0", nil, nil, "503 Service Unavailable"},
|
}
|
||||||
|
|
||||||
|
func httpProxyRoundtrip(targetURL string, data []byte, clientInfo *url.Userinfo, serverInfo []*url.Userinfo) error {
|
||||||
|
ln, err := TCPListener("")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: HTTPConnector(clientInfo),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: HTTPHandler(
|
||||||
|
UsersHandlerOption(serverInfo...),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
go server.Run()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
return proxyRoundtrip(client, server, targetURL, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHTTPProxy(t *testing.T) {
|
func TestHTTPProxy(t *testing.T) {
|
||||||
Debug = true
|
|
||||||
httpSrv := httptest.NewServer(httpTestHandler)
|
httpSrv := httptest.NewServer(httpTestHandler)
|
||||||
defer httpSrv.Close()
|
defer httpSrv.Close()
|
||||||
|
|
||||||
for _, test := range httpProxyTests {
|
sendData := make([]byte, 128)
|
||||||
send := make([]byte, 16)
|
rand.Read(sendData)
|
||||||
rand.Read(send)
|
|
||||||
urlStr := test.url
|
for i, tc := range httpProxyTests {
|
||||||
if urlStr == "" {
|
tc := tc
|
||||||
urlStr = httpSrv.URL
|
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
|
||||||
}
|
err := httpProxyRoundtrip(httpSrv.URL, sendData, tc.cliUser, tc.srvUsers)
|
||||||
_, recv, err := httpProxyRoundtrip(urlStr, test.cliUser, test.srvUsers, bytes.NewReader(send))
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if test.errStr != "" {
|
if tc.errStr != "" {
|
||||||
t.Errorf("HTTP proxy response should failed with error %s", test.errStr)
|
t.Errorf("#%d should failed with error %s", i, tc.errStr)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if test.errStr == "" {
|
if tc.errStr == "" {
|
||||||
t.Errorf("HTTP proxy got error %v", err)
|
t.Errorf("#%d got error %v", i, err)
|
||||||
}
|
}
|
||||||
if err.Error() != test.errStr {
|
if err.Error() != tc.errStr {
|
||||||
t.Errorf("HTTP proxy got error %v, want %v", err, test.errStr)
|
t.Errorf("#%d got error %v, want %v", i, err, tc.errStr)
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
if !bytes.Equal(send, recv) {
|
})
|
||||||
t.Errorf("got %v, want %v", recv, send)
|
}
|
||||||
continue
|
}
|
||||||
|
|
||||||
|
func BenchmarkHTTPProxy(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: HTTPConnector(url.UserPassword("admin", "123456")),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: HTTPHandler(
|
||||||
|
UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
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 BenchmarkHTTPProxyParallel(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: HTTPConnector(url.UserPassword("admin", "123456")),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: HTTPHandler(
|
||||||
|
UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
10
server.go
10
server.go
@ -12,6 +12,7 @@ import (
|
|||||||
// Server is a proxy server.
|
// Server is a proxy server.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
Listener Listener
|
Listener Listener
|
||||||
|
Handler Handler
|
||||||
options *ServerOptions
|
options *ServerOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +47,10 @@ func (s *Server) Serve(h Handler, opts ...ServerOption) error {
|
|||||||
}
|
}
|
||||||
s.Listener = ln
|
s.Listener = ln
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if h == nil {
|
||||||
|
h = s.Handler
|
||||||
|
}
|
||||||
if h == nil {
|
if h == nil {
|
||||||
h = HTTPHandler()
|
h = HTTPHandler()
|
||||||
}
|
}
|
||||||
@ -84,6 +89,11 @@ func (s *Server) Serve(h Handler, opts ...ServerOption) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run starts to serve.
|
||||||
|
func (s *Server) Run() error {
|
||||||
|
return s.Serve(s.Handler)
|
||||||
|
}
|
||||||
|
|
||||||
// ServerOptions holds the options for Server.
|
// ServerOptions holds the options for Server.
|
||||||
type ServerOptions struct {
|
type ServerOptions struct {
|
||||||
}
|
}
|
||||||
|
2
sni.go
2
sni.go
@ -93,7 +93,7 @@ func (h *sniHandler) Handle(conn net.Conn) {
|
|||||||
|
|
||||||
host = net.JoinHostPort(host, "443")
|
host = net.JoinHostPort(host, "443")
|
||||||
|
|
||||||
log.Logf("[ss] %s -> %s -> %s",
|
log.Logf("[sni] %s -> %s -> %s",
|
||||||
conn.RemoteAddr(), h.options.Node.String(), host)
|
conn.RemoteAddr(), h.options.Node.String(), host)
|
||||||
|
|
||||||
if !Can("tcp", host, h.options.Whitelist, h.options.Blacklist) {
|
if !Can("tcp", host, h.options.Whitelist, h.options.Blacklist) {
|
||||||
|
105
sni_test.go
Normal file
105
sni_test.go
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package gost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func sniRoundtrip(client *Client, server *Server, targetURL string, data []byte) (err error) {
|
||||||
|
conn, err := client.Dial(server.Addr().String())
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
conn.SetDeadline(time.Now().Add(3 * time.Second))
|
||||||
|
|
||||||
|
conn, err = client.Handshake(conn)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
u, err := url.Parse(targetURL)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
conn, err = client.Connect(conn, u.Host)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Scheme == "https" {
|
||||||
|
conn = tls.Client(conn,
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: false,
|
||||||
|
ServerName: u.Hostname(),
|
||||||
|
})
|
||||||
|
u.Scheme = "http"
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest(
|
||||||
|
http.MethodGet,
|
||||||
|
u.String(),
|
||||||
|
bytes.NewReader(data),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = req.Write(conn); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, err := http.ReadResponse(bufio.NewReader(conn), req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return errors.New(resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func sniProxyRoundtrip(targetURL string, data []byte, host string) error {
|
||||||
|
ln, err := TCPListener("")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: SNIConnector(host),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: SNIHandler(),
|
||||||
|
}
|
||||||
|
|
||||||
|
go server.Run()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
return sniRoundtrip(client, server, targetURL, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSNIProxy(t *testing.T) {
|
||||||
|
// SetLogger(&LogLogger{})
|
||||||
|
// Debug = true
|
||||||
|
httpSrv := httptest.NewTLSServer(httpTestHandler)
|
||||||
|
defer httpSrv.Close()
|
||||||
|
|
||||||
|
sendData := make([]byte, 128)
|
||||||
|
rand.Read(sendData)
|
||||||
|
|
||||||
|
err := sniProxyRoundtrip("https://github.com", sendData, "google.com")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("got error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
371
socks_test.go
Normal file
371
socks_test.go
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
package gost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"net/http/httptest"
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var socks5ProxyTests = []struct {
|
||||||
|
cliUser *url.Userinfo
|
||||||
|
srvUsers []*url.Userinfo
|
||||||
|
pass bool
|
||||||
|
}{
|
||||||
|
{nil, nil, true},
|
||||||
|
{nil, []*url.Userinfo{url.User("admin")}, false},
|
||||||
|
{nil, []*url.Userinfo{url.UserPassword("", "123456")}, false},
|
||||||
|
{url.User("admin"), []*url.Userinfo{url.User("test")}, false},
|
||||||
|
{url.User("admin"), []*url.Userinfo{url.UserPassword("admin", "123456")}, false},
|
||||||
|
{url.User("admin"), []*url.Userinfo{url.User("admin")}, true},
|
||||||
|
{url.User("admin"), []*url.Userinfo{url.UserPassword("admin", "")}, true},
|
||||||
|
{url.UserPassword("admin", "123456"), nil, true},
|
||||||
|
{url.UserPassword("admin", "123456"), []*url.Userinfo{url.User("admin")}, true},
|
||||||
|
{url.UserPassword("admin", "123456"), []*url.Userinfo{url.UserPassword("", "123456")}, true},
|
||||||
|
{url.UserPassword("", "123456"), []*url.Userinfo{url.UserPassword("", "123456")}, true},
|
||||||
|
{url.UserPassword("admin", "123456"), []*url.Userinfo{url.UserPassword("admin", "123456")}, true},
|
||||||
|
{url.UserPassword("admin", "123456"), []*url.Userinfo{url.UserPassword("user", "pass"), url.UserPassword("admin", "123456")}, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
func socks5ProxyRoundtrip(targetURL string, data []byte, clientInfo *url.Userinfo, serverInfo []*url.Userinfo) error {
|
||||||
|
ln, err := TCPListener("")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: SOCKS5Connector(clientInfo),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Handler: SOCKS5Handler(UsersHandlerOption(serverInfo...)),
|
||||||
|
Listener: ln,
|
||||||
|
}
|
||||||
|
|
||||||
|
go server.Run()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
return proxyRoundtrip(client, server, targetURL, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSOCKS5Proxy(t *testing.T) {
|
||||||
|
cert, err := GenCertificate()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
DefaultTLSConfig = &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
|
||||||
|
httpSrv := httptest.NewServer(httpTestHandler)
|
||||||
|
defer httpSrv.Close()
|
||||||
|
|
||||||
|
sendData := make([]byte, 128)
|
||||||
|
rand.Read(sendData)
|
||||||
|
|
||||||
|
for i, tc := range socks5ProxyTests {
|
||||||
|
tc := tc
|
||||||
|
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
|
||||||
|
err := socks5ProxyRoundtrip(httpSrv.URL, sendData,
|
||||||
|
tc.cliUser,
|
||||||
|
tc.srvUsers,
|
||||||
|
)
|
||||||
|
if err == nil {
|
||||||
|
if !tc.pass {
|
||||||
|
t.Errorf("#%d should failed", i)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// t.Logf("#%d %v", i, err)
|
||||||
|
if tc.pass {
|
||||||
|
t.Errorf("#%d got error: %v", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSOCKS5Proxy(b *testing.B) {
|
||||||
|
cert, err := GenCertificate()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
DefaultTLSConfig = &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
|
||||||
|
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: SOCKS5Connector(url.UserPassword("admin", "123456")),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Handler: SOCKS5Handler(UsersHandlerOption(url.UserPassword("admin", "123456"))),
|
||||||
|
Listener: ln,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 BenchmarkSOCKS5ProxyParallel(b *testing.B) {
|
||||||
|
cert, err := GenCertificate()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
DefaultTLSConfig = &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
|
||||||
|
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: SOCKS5Connector(url.UserPassword("admin", "123456")),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Handler: SOCKS5Handler(UsersHandlerOption(url.UserPassword("admin", "123456"))),
|
||||||
|
Listener: ln,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 socks4ProxyRoundtrip(targetURL string, data []byte) error {
|
||||||
|
ln, err := TCPListener("")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: SOCKS4Connector(),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: SOCKS4Handler(),
|
||||||
|
}
|
||||||
|
go server.Run()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
return proxyRoundtrip(client, server, targetURL, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSOCKS4Proxy(t *testing.T) {
|
||||||
|
httpSrv := httptest.NewServer(httpTestHandler)
|
||||||
|
defer httpSrv.Close()
|
||||||
|
|
||||||
|
sendData := make([]byte, 128)
|
||||||
|
rand.Read(sendData)
|
||||||
|
|
||||||
|
err := socks4ProxyRoundtrip(httpSrv.URL, sendData)
|
||||||
|
// t.Logf("#%d %v", i, err)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("got error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSOCKS4Proxy(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: SOCKS4Connector(),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: SOCKS4Handler(),
|
||||||
|
}
|
||||||
|
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 BenchmarkSOCKS4ProxyParallel(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: SOCKS4Connector(),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: SOCKS4Handler(),
|
||||||
|
}
|
||||||
|
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 socks4aProxyRoundtrip(targetURL string, data []byte) error {
|
||||||
|
ln, err := TCPListener("")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: SOCKS4AConnector(),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: SOCKS4Handler(),
|
||||||
|
}
|
||||||
|
|
||||||
|
go server.Run()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
return proxyRoundtrip(client, server, targetURL, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSOCKS4AProxy(t *testing.T) {
|
||||||
|
httpSrv := httptest.NewServer(httpTestHandler)
|
||||||
|
defer httpSrv.Close()
|
||||||
|
|
||||||
|
sendData := make([]byte, 128)
|
||||||
|
rand.Read(sendData)
|
||||||
|
|
||||||
|
err := socks4aProxyRoundtrip(httpSrv.URL, sendData)
|
||||||
|
// t.Logf("#%d %v", i, err)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("got error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSOCKS4AProxy(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: SOCKS4AConnector(),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: SOCKS4Handler(),
|
||||||
|
}
|
||||||
|
|
||||||
|
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 BenchmarkSOCKS4AProxyParallel(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: SOCKS4AConnector(),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: SOCKS4Handler(),
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
314
ss_test.go
Normal file
314
ss_test.go
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
package gost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"fmt"
|
||||||
|
"net/http/httptest"
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ssProxyTests = []struct {
|
||||||
|
clientCipher *url.Userinfo
|
||||||
|
serverCipher *url.Userinfo
|
||||||
|
pass bool
|
||||||
|
}{
|
||||||
|
{nil, nil, false},
|
||||||
|
{&url.Userinfo{}, &url.Userinfo{}, false},
|
||||||
|
{url.User("abc"), url.User("abc"), false},
|
||||||
|
{url.UserPassword("abc", "def"), url.UserPassword("abc", "def"), false},
|
||||||
|
|
||||||
|
{url.User("aes-128-cfb"), url.User("aes-128-cfb"), false},
|
||||||
|
{url.User("aes-128-cfb"), url.UserPassword("aes-128-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.User("aes-128-cfb"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("aes-128-cfb", "abc"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("aes-128-cfb", "123456"), true},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("aes-192-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("aes-256-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("aes-128-ctr", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("aes-192-ctr", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("aes-256-ctr", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("des-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("bf-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("cast5-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("rc4-md5", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("chacha20", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("chacha20-ietf", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-cfb", "123456"), url.UserPassword("salsa20", "123456"), false},
|
||||||
|
|
||||||
|
{url.User("aes-192-cfb"), url.User("aes-192-cfb"), false},
|
||||||
|
{url.User("aes-192-cfb"), url.UserPassword("aes-192-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.User("aes-192-cfb"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("aes-192-cfb", "abc"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("aes-192-cfb", "123456"), true},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("aes-128-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("aes-256-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("aes-128-ctr", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("aes-192-ctr", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("aes-256-ctr", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("des-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("bf-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("cast5-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("rc4-md5", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("chacha20", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("chacha20-ietf", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-cfb", "123456"), url.UserPassword("salsa20", "123456"), false},
|
||||||
|
|
||||||
|
{url.User("aes-256-cfb"), url.User("aes-256-cfb"), false},
|
||||||
|
{url.User("aes-256-cfb"), url.UserPassword("aes-256-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.User("aes-256-cfb"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("aes-256-cfb", "abc"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("aes-256-cfb", "123456"), true},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("aes-128-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("aes-192-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("aes-128-ctr", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("aes-192-ctr", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("aes-256-ctr", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("des-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("bf-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("cast5-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("rc4-md5", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("chacha20", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("chacha20-ietf", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-cfb", "123456"), url.UserPassword("salsa20", "123456"), false},
|
||||||
|
|
||||||
|
{url.User("aes-128-ctr"), url.User("aes-128-ctr"), false},
|
||||||
|
{url.User("aes-128-ctr"), url.UserPassword("aes-128-ctr", "123456"), false},
|
||||||
|
{url.UserPassword("aes-128-ctr", "123456"), url.User("aes-128-ctr"), false},
|
||||||
|
{url.UserPassword("aes-128-ctr", "123456"), url.UserPassword("aes-128-ctr", "abc"), false},
|
||||||
|
{url.UserPassword("aes-128-ctr", "123456"), url.UserPassword("aes-128-ctr", "123456"), true},
|
||||||
|
|
||||||
|
{url.User("aes-192-ctr"), url.User("aes-192-ctr"), false},
|
||||||
|
{url.User("aes-192-ctr"), url.UserPassword("aes-192-ctr", "123456"), false},
|
||||||
|
{url.UserPassword("aes-192-ctr", "123456"), url.User("aes-192-ctr"), false},
|
||||||
|
{url.UserPassword("aes-192-ctr", "123456"), url.UserPassword("aes-192-ctr", "abc"), false},
|
||||||
|
{url.UserPassword("aes-192-ctr", "123456"), url.UserPassword("aes-192-ctr", "123456"), true},
|
||||||
|
|
||||||
|
{url.User("aes-256-ctr"), url.User("aes-256-ctr"), false},
|
||||||
|
{url.User("aes-256-ctr"), url.UserPassword("aes-256-ctr", "123456"), false},
|
||||||
|
{url.UserPassword("aes-256-ctr", "123456"), url.User("aes-256-ctr"), false},
|
||||||
|
{url.UserPassword("aes-256-ctr", "123456"), url.UserPassword("aes-256-ctr", "abc"), false},
|
||||||
|
{url.UserPassword("aes-256-ctr", "123456"), url.UserPassword("aes-256-ctr", "123456"), true},
|
||||||
|
|
||||||
|
{url.User("des-cfb"), url.User("des-cfb"), false},
|
||||||
|
{url.User("des-cfb"), url.UserPassword("des-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("des-cfb", "123456"), url.User("des-cfb"), false},
|
||||||
|
{url.UserPassword("des-cfb", "123456"), url.UserPassword("des-cfb", "abc"), false},
|
||||||
|
{url.UserPassword("des-cfb", "123456"), url.UserPassword("des-cfb", "123456"), true},
|
||||||
|
|
||||||
|
{url.User("bf-cfb"), url.User("bf-cfb"), false},
|
||||||
|
{url.User("bf-cfb"), url.UserPassword("bf-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("bf-cfb", "123456"), url.User("bf-cfb"), false},
|
||||||
|
{url.UserPassword("bf-cfb", "123456"), url.UserPassword("bf-cfb", "abc"), false},
|
||||||
|
{url.UserPassword("bf-cfb", "123456"), url.UserPassword("bf-cfb", "123456"), true},
|
||||||
|
|
||||||
|
{url.User("cast5-cfb"), url.User("cast5-cfb"), false},
|
||||||
|
{url.User("cast5-cfb"), url.UserPassword("cast5-cfb", "123456"), false},
|
||||||
|
{url.UserPassword("cast5-cfb", "123456"), url.User("cast5-cfb"), false},
|
||||||
|
{url.UserPassword("cast5-cfb", "123456"), url.UserPassword("cast5-cfb", "abc"), false},
|
||||||
|
{url.UserPassword("cast5-cfb", "123456"), url.UserPassword("cast5-cfb", "123456"), true},
|
||||||
|
|
||||||
|
{url.User("rc4-md5"), url.User("rc4-md5"), false},
|
||||||
|
{url.User("rc4-md5"), url.UserPassword("rc4-md5", "123456"), false},
|
||||||
|
{url.UserPassword("rc4-md5", "123456"), url.User("rc4-md5"), false},
|
||||||
|
{url.UserPassword("rc4-md5", "123456"), url.UserPassword("rc4-md5", "abc"), false},
|
||||||
|
{url.UserPassword("rc4-md5", "123456"), url.UserPassword("rc4-md5", "123456"), true},
|
||||||
|
|
||||||
|
{url.User("chacha20"), url.User("chacha20"), false},
|
||||||
|
{url.User("chacha20"), url.UserPassword("chacha20", "123456"), false},
|
||||||
|
{url.UserPassword("chacha20", "123456"), url.User("chacha20"), false},
|
||||||
|
{url.UserPassword("chacha20", "123456"), url.UserPassword("chacha20", "abc"), false},
|
||||||
|
{url.UserPassword("chacha20", "123456"), url.UserPassword("chacha20", "123456"), true},
|
||||||
|
|
||||||
|
{url.User("chacha20-ietf"), url.User("chacha20-ietf"), false},
|
||||||
|
{url.User("chacha20-ietf"), url.UserPassword("chacha20-ietf", "123456"), false},
|
||||||
|
{url.UserPassword("chacha20-ietf", "123456"), url.User("chacha20-ietf"), false},
|
||||||
|
{url.UserPassword("chacha20-ietf", "123456"), url.UserPassword("chacha20-ietf", "abc"), false},
|
||||||
|
{url.UserPassword("chacha20-ietf", "123456"), url.UserPassword("chacha20-ietf", "123456"), true},
|
||||||
|
|
||||||
|
{url.User("salsa20"), url.User("salsa20"), false},
|
||||||
|
{url.User("salsa20"), url.UserPassword("salsa20", "123456"), false},
|
||||||
|
{url.UserPassword("salsa20", "123456"), url.User("salsa20"), false},
|
||||||
|
{url.UserPassword("salsa20", "123456"), url.UserPassword("salsa20", "abc"), false},
|
||||||
|
{url.UserPassword("salsa20", "123456"), url.UserPassword("salsa20", "123456"), true},
|
||||||
|
}
|
||||||
|
|
||||||
|
func ssProxyRoundtrip(targetURL string, data []byte, clientInfo *url.Userinfo, serverInfo *url.Userinfo) error {
|
||||||
|
ln, err := TCPListener("")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: ShadowConnector(clientInfo),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Handler: ShadowHandler(UsersHandlerOption(serverInfo)),
|
||||||
|
Listener: ln,
|
||||||
|
}
|
||||||
|
|
||||||
|
go server.Run()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
return proxyRoundtrip(client, server, targetURL, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSSProxy(t *testing.T) {
|
||||||
|
httpSrv := httptest.NewServer(httpTestHandler)
|
||||||
|
defer httpSrv.Close()
|
||||||
|
|
||||||
|
sendData := make([]byte, 128)
|
||||||
|
rand.Read(sendData)
|
||||||
|
|
||||||
|
for i, tc := range ssProxyTests {
|
||||||
|
tc := tc
|
||||||
|
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
|
||||||
|
err := ssProxyRoundtrip(httpSrv.URL, sendData,
|
||||||
|
tc.clientCipher,
|
||||||
|
tc.serverCipher,
|
||||||
|
)
|
||||||
|
if err == nil {
|
||||||
|
if !tc.pass {
|
||||||
|
t.Errorf("#%d should failed", i)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// t.Logf("#%d %v", i, err)
|
||||||
|
if tc.pass {
|
||||||
|
t.Errorf("#%d got error: %v", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSSProxy_AES256(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: ShadowConnector(url.UserPassword("aes-256-cfb", "123456")),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Handler: ShadowHandler(UsersHandlerOption(url.UserPassword("aes-256-cfb", "123456"))),
|
||||||
|
Listener: ln,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 BenchmarkSSProxy_Chacha20(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: ShadowConnector(url.UserPassword("chacha20", "123456")),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Handler: ShadowHandler(UsersHandlerOption(url.UserPassword("chacha20", "123456"))),
|
||||||
|
Listener: ln,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 BenchmarkSSProxy_Chacha20_ietf(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: ShadowConnector(url.UserPassword("chacha20-ietf", "123456")),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Handler: ShadowHandler(UsersHandlerOption(url.UserPassword("chacha20-ietf", "123456"))),
|
||||||
|
Listener: ln,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 BenchmarkSSProxyParallel(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: ShadowConnector(url.UserPassword("chacha20-ietf", "123456")),
|
||||||
|
Transporter: TCPTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Handler: ShadowHandler(UsersHandlerOption(url.UserPassword("chacha20-ietf", "123456"))),
|
||||||
|
Listener: ln,
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
371
tls_test.go
Normal file
371
tls_test.go
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
package gost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"net/http/httptest"
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func httpOverTLSRoundtrip(targetURL string, data []byte, tlsConfig *tls.Config,
|
||||||
|
clientInfo *url.Userinfo, serverInfo []*url.Userinfo) error {
|
||||||
|
|
||||||
|
ln, err := TLSListener("", tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: HTTPConnector(clientInfo),
|
||||||
|
Transporter: TLSTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: HTTPHandler(
|
||||||
|
UsersHandlerOption(serverInfo...),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
go server.Run()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
return proxyRoundtrip(client, server, targetURL, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHTTPOverTLS(t *testing.T) {
|
||||||
|
cert, err := GenCertificate()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
|
||||||
|
httpSrv := httptest.NewServer(httpTestHandler)
|
||||||
|
defer httpSrv.Close()
|
||||||
|
|
||||||
|
sendData := make([]byte, 128)
|
||||||
|
rand.Read(sendData)
|
||||||
|
|
||||||
|
for i, tc := range httpProxyTests {
|
||||||
|
tc := tc
|
||||||
|
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
|
||||||
|
err := httpOverTLSRoundtrip(httpSrv.URL, sendData, tlsConfig, tc.cliUser, tc.srvUsers)
|
||||||
|
if err == nil {
|
||||||
|
if tc.errStr != "" {
|
||||||
|
t.Errorf("#%d should failed with error %s", i, tc.errStr)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if tc.errStr == "" {
|
||||||
|
t.Errorf("#%d got error %v", i, err)
|
||||||
|
}
|
||||||
|
if err.Error() != tc.errStr {
|
||||||
|
t.Errorf("#%d got error %v, want %v", i, err, tc.errStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHTTPOverTLS(b *testing.B) {
|
||||||
|
httpSrv := httptest.NewServer(httpTestHandler)
|
||||||
|
defer httpSrv.Close()
|
||||||
|
|
||||||
|
sendData := make([]byte, 128)
|
||||||
|
rand.Read(sendData)
|
||||||
|
|
||||||
|
cert, err := GenCertificate()
|
||||||
|
if err != nil {
|
||||||
|
b.Error(err)
|
||||||
|
}
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
|
||||||
|
ln, err := TLSListener("", tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
b.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: HTTPConnector(url.UserPassword("admin", "123456")),
|
||||||
|
Transporter: TLSTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: HTTPHandler(
|
||||||
|
UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
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 BenchmarkHTTPOverTLSParallel(b *testing.B) {
|
||||||
|
httpSrv := httptest.NewServer(httpTestHandler)
|
||||||
|
defer httpSrv.Close()
|
||||||
|
|
||||||
|
sendData := make([]byte, 128)
|
||||||
|
rand.Read(sendData)
|
||||||
|
|
||||||
|
cert, err := GenCertificate()
|
||||||
|
if err != nil {
|
||||||
|
b.Error(err)
|
||||||
|
}
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
|
||||||
|
ln, err := TLSListener("", tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
b.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: HTTPConnector(url.UserPassword("admin", "123456")),
|
||||||
|
Transporter: TLSTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: HTTPHandler(
|
||||||
|
UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
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 socks5OverTLSRoundtrip(targetURL string, data []byte, tlsConfig *tls.Config,
|
||||||
|
clientInfo *url.Userinfo, serverInfo []*url.Userinfo) error {
|
||||||
|
|
||||||
|
ln, err := TLSListener("", tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: SOCKS5Connector(clientInfo),
|
||||||
|
Transporter: TLSTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: SOCKS5Handler(
|
||||||
|
UsersHandlerOption(serverInfo...),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
go server.Run()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
return proxyRoundtrip(client, server, targetURL, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSOCKS5OverTLS(t *testing.T) {
|
||||||
|
cert, err := GenCertificate()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
DefaultTLSConfig = tlsConfig
|
||||||
|
|
||||||
|
httpSrv := httptest.NewServer(httpTestHandler)
|
||||||
|
defer httpSrv.Close()
|
||||||
|
|
||||||
|
sendData := make([]byte, 128)
|
||||||
|
rand.Read(sendData)
|
||||||
|
|
||||||
|
for i, tc := range socks5ProxyTests {
|
||||||
|
tc := tc
|
||||||
|
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
|
||||||
|
err := socks5OverTLSRoundtrip(httpSrv.URL, sendData,
|
||||||
|
tlsConfig,
|
||||||
|
tc.cliUser,
|
||||||
|
tc.srvUsers,
|
||||||
|
)
|
||||||
|
if err == nil {
|
||||||
|
if !tc.pass {
|
||||||
|
t.Errorf("#%d should failed", i)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// t.Logf("#%d %v", i, err)
|
||||||
|
if tc.pass {
|
||||||
|
t.Errorf("#%d got error: %v", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func socks4OverTLSRoundtrip(targetURL string, data []byte, tlsConfig *tls.Config) error {
|
||||||
|
ln, err := TLSListener("", tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: SOCKS4Connector(),
|
||||||
|
Transporter: TLSTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: SOCKS4Handler(),
|
||||||
|
}
|
||||||
|
|
||||||
|
go server.Run()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
return proxyRoundtrip(client, server, targetURL, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSOCKS4OverTLS(t *testing.T) {
|
||||||
|
cert, err := GenCertificate()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
|
||||||
|
httpSrv := httptest.NewServer(httpTestHandler)
|
||||||
|
defer httpSrv.Close()
|
||||||
|
|
||||||
|
sendData := make([]byte, 128)
|
||||||
|
rand.Read(sendData)
|
||||||
|
|
||||||
|
err = socks4OverTLSRoundtrip(httpSrv.URL, sendData, tlsConfig)
|
||||||
|
// t.Logf("#%d %v", i, err)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("got error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func socks4aOverTLSRoundtrip(targetURL string, data []byte, tlsConfig *tls.Config) error {
|
||||||
|
ln, err := TLSListener("", tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: SOCKS4AConnector(),
|
||||||
|
Transporter: TLSTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: SOCKS4Handler(),
|
||||||
|
}
|
||||||
|
|
||||||
|
go server.Run()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
return proxyRoundtrip(client, server, targetURL, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSOCKS4AOverTLS(t *testing.T) {
|
||||||
|
cert, err := GenCertificate()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
|
||||||
|
httpSrv := httptest.NewServer(httpTestHandler)
|
||||||
|
defer httpSrv.Close()
|
||||||
|
|
||||||
|
sendData := make([]byte, 128)
|
||||||
|
rand.Read(sendData)
|
||||||
|
|
||||||
|
err = socks4aOverTLSRoundtrip(httpSrv.URL, sendData, tlsConfig)
|
||||||
|
// t.Logf("#%d %v", i, err)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("got error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ssOverTLSRoundtrip(targetURL string, data []byte, tlsConfig *tls.Config,
|
||||||
|
clientInfo, serverInfo *url.Userinfo) error {
|
||||||
|
|
||||||
|
ln, err := TLSListener("", tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
Connector: ShadowConnector(clientInfo),
|
||||||
|
Transporter: TLSTransporter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Listener: ln,
|
||||||
|
Handler: ShadowHandler(
|
||||||
|
UsersHandlerOption(serverInfo),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
go server.Run()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
return proxyRoundtrip(client, server, targetURL, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSSOverTLS(t *testing.T) {
|
||||||
|
cert, err := GenCertificate()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
DefaultTLSConfig = tlsConfig
|
||||||
|
|
||||||
|
httpSrv := httptest.NewServer(httpTestHandler)
|
||||||
|
defer httpSrv.Close()
|
||||||
|
|
||||||
|
sendData := make([]byte, 128)
|
||||||
|
rand.Read(sendData)
|
||||||
|
|
||||||
|
for i, tc := range ssProxyTests {
|
||||||
|
tc := tc
|
||||||
|
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
|
||||||
|
err := ssOverTLSRoundtrip(httpSrv.URL, sendData,
|
||||||
|
tlsConfig,
|
||||||
|
tc.clientCipher,
|
||||||
|
tc.serverCipher,
|
||||||
|
)
|
||||||
|
if err == nil {
|
||||||
|
if !tc.pass {
|
||||||
|
t.Errorf("#%d should failed", i)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// t.Logf("#%d %v", i, err)
|
||||||
|
if tc.pass {
|
||||||
|
t.Errorf("#%d got error: %v", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user