add all testing

This commit is contained in:
mo 2020-08-06 15:59:48 +08:00
parent 372b42cd09
commit 10f96879ba
6 changed files with 148 additions and 15 deletions

@ -9,7 +9,7 @@ go-socks5
[![License](https://img.shields.io/github/license/thinkgos/go-socks5)](https://github.com/thinkgos/go-socks5/raw/master/LICENSE)
[![Tag](https://img.shields.io/github/v/tag/thinkgos/go-socks5)](https://github.com/thinkgos/go-socks5/tags)
Provides the `socks5` package that implements a [SOCKS5 server](http://en.wikipedia.org/wiki/SOCKS).
Provides the `socks5` package that implements a [SOCKS5](http://en.wikipedia.org/wiki/SOCKS).
SOCKS (Secure Sockets) is used to route traffic between a client and server through
an intermediate proxy layer. This can be used to bypass firewalls or NATs.
@ -17,22 +17,24 @@ Feature
=======
The package has the following features:
* Unit tests
* "No Auth" mode
* User/Password authentication optional user addr limit
* Support for the CONNECT command
* Support for the ASSOCIATE command
* Rules to do granular filtering of commands
* Custom DNS resolution
* Custom goroutine pool
* buffer pool design and optional custom buffer pool
* Custom logger
- Support client(**under ccsocks5 directory**) and server(**under root directory**)
- Support TCP/UDP and IPv4/IPv6
- Unit tests
- "No Auth" mode
- User/Password authentication optional user addr limit
- Support for the CONNECT command
- Support for the ASSOCIATE command
- Rules to do granular filtering of commands
- Custom DNS resolution
- Custom goroutine pool
- buffer pool design and optional custom buffer pool
- Custom logger
TODO
====
The package still needs the following:
* Support for the BIND command
- Support for the BIND command
Example
=======

@ -22,7 +22,8 @@ type Client struct {
bufferPool bufferpool.BufPool
}
// NewClient This is just create a client, you need to use Dial to create conn.
// NewClient This is just create a client.
// you need to use Dial to create conn.
func NewClient(proxyAddr string, opts ...Option) (*Client, error) {
c := &Client{
proxyAddr: proxyAddr,
@ -37,7 +38,9 @@ func NewClient(proxyAddr string, opts ...Option) (*Client, error) {
// Close closes the connection.
func (sf *Client) Close() (err error) {
err = sf.tcpConn.Close()
if sf.tcpConn != nil {
err = sf.tcpConn.Close()
}
if sf.Conn != nil {
err = sf.Conn.Close()
}

@ -106,7 +106,7 @@ func (sf *Server) Serve(l net.Listener) error {
}
sf.submit(func() {
if err := sf.ServeConn(conn); err != nil {
sf.logger.Errorf("server conn %v", err)
sf.logger.Errorf("server: %v", err)
}
})
}

128
testing/socks5_test.go Normal file

@ -0,0 +1,128 @@
package testing
import (
"io"
"log"
"net"
"os"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/net/proxy"
"github.com/thinkgos/go-socks5"
"github.com/thinkgos/go-socks5/bufferpool"
"github.com/thinkgos/go-socks5/ccsocks5"
)
func Test_Socks5_Connect(t *testing.T) {
// Create a local listener
l, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
go func() {
conn, err := l.Accept()
require.NoError(t, err)
defer conn.Close()
buf := make([]byte, 4)
_, err = io.ReadAtLeast(conn, buf, 4)
require.NoError(t, err)
assert.Equal(t, []byte("ping"), buf)
conn.Write([]byte("pong")) // nolint: errcheck
}()
// Create a socks server with UserPass auth.
cator := socks5.UserPassAuthenticator{Credentials: socks5.StaticCredentials{"user": "pass"}}
srv := socks5.NewServer(
socks5.WithAuthMethods([]socks5.Authenticator{cator}),
socks5.WithLogger(socks5.NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags))),
)
// Start listening
go func() {
err := srv.ListenAndServe("tcp", "127.0.0.1:12389")
require.NoError(t, err)
}()
time.Sleep(10 * time.Millisecond)
// Get a local conn
client, err := ccsocks5.NewClient("127.0.0.1:12389",
ccsocks5.WithAuth(&proxy.Auth{User: "user", Password: "pass"}),
ccsocks5.WithBufferPool(bufferpool.NewPool(32*1024)),
)
require.NoError(t, err)
conn, err := client.Dial("tcp", l.Addr().String())
require.NoError(t, err)
defer conn.Close()
// Send all the bytes
conn.Write([]byte("ping")) // nolint: errcheck
out := make([]byte, 4)
conn.SetDeadline(time.Now().Add(time.Second)) // nolint: errcheck
_, err = io.ReadFull(conn, out)
conn.SetDeadline(time.Time{}) // nolint: errcheck
require.NoError(t, err)
assert.Equal(t, []byte("pong"), out)
}
func Test_socks5_Associate(t *testing.T) {
locIP := net.ParseIP("127.0.0.1")
// Create a local listener
lAddr := &net.UDPAddr{IP: locIP, Port: 12312}
l, err := net.ListenUDP("udp", lAddr)
require.NoError(t, err)
defer l.Close()
go func() {
buf := make([]byte, 2048)
for {
n, remote, err := l.ReadFrom(buf)
if err != nil {
return
}
require.Equal(t, []byte("ping"), buf[:n])
l.WriteTo([]byte("pong"), remote) // nolint: errcheck
}
}()
// Create a socks server
cator := socks5.UserPassAuthenticator{Credentials: socks5.StaticCredentials{"user": "pass"}}
proxySrv := socks5.NewServer(
socks5.WithAuthMethods([]socks5.Authenticator{cator}),
socks5.WithLogger(socks5.NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags))),
)
// Start listening
go func() {
err := proxySrv.ListenAndServe("tcp", "127.0.0.1:12385")
require.NoError(t, err)
}()
time.Sleep(10 * time.Millisecond)
// Get a local conn
client, err := ccsocks5.NewClient(
"127.0.0.1:12385",
ccsocks5.WithAuth(&proxy.Auth{User: "user", Password: "pass"}),
)
require.NoError(t, err)
conn, err := client.Dial("udp", lAddr.String())
require.NoError(t, err)
// send ping
conn.Write([]byte("ping")) // nolint: errcheck
// read response
out := make([]byte, 4)
conn.SetDeadline(time.Now().Add(time.Second)) // nolint: errcheck
_, err = io.ReadFull(conn, out)
conn.SetDeadline(time.Time{}) // nolint: errcheck
require.NoError(t, err)
require.Equal(t, []byte("pong"), out)
time.Sleep(time.Second * 1)
}