add test for SOCKS5 bind & UDP relay
This commit is contained in:
parent
c7b3111e89
commit
45022d2415
@ -4,12 +4,14 @@ ADD . /data
|
||||
|
||||
WORKDIR /data
|
||||
|
||||
RUN cd cmd/gost && go install
|
||||
ENV GO111MODULE=on
|
||||
|
||||
RUN cd cmd/gost && go build
|
||||
|
||||
FROM alpine:latest
|
||||
|
||||
WORKDIR /bin/
|
||||
|
||||
COPY --from=builder /go/bin/gost .
|
||||
COPY --from=builder /data/cmd/gost/gost .
|
||||
|
||||
ENTRYPOINT ["/bin/gost"]
|
13
bypass.go
13
bypass.go
@ -152,13 +152,24 @@ func NewBypassPatterns(reversed bool, patterns ...string) *Bypass {
|
||||
|
||||
// Contains reports whether the bypass includes addr.
|
||||
func (bp *Bypass) Contains(addr string) bool {
|
||||
if bp == nil || len(bp.matchers) == 0 || addr == "" {
|
||||
if bp == nil || addr == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// try to strip the port
|
||||
if host, port, _ := net.SplitHostPort(addr); host != "" && port != "" {
|
||||
if p, _ := strconv.Atoi(port); p > 0 { // port is valid
|
||||
addr = host
|
||||
}
|
||||
}
|
||||
|
||||
bp.mux.RLock()
|
||||
defer bp.mux.RUnlock()
|
||||
|
||||
if len(bp.matchers) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var matched bool
|
||||
for _, matcher := range bp.matchers {
|
||||
if matcher == nil {
|
||||
|
@ -58,21 +58,21 @@ var bypassContainTests = []struct {
|
||||
{[]string{"www.example.com"}, true, "example.com", true},
|
||||
|
||||
// host:port
|
||||
{[]string{"192.168.1.1"}, false, "192.168.1.1:80", false},
|
||||
{[]string{"192.168.1.1"}, true, "192.168.1.1:80", true},
|
||||
{[]string{"192.168.1.1"}, false, "192.168.1.1:80", true},
|
||||
{[]string{"192.168.1.1"}, true, "192.168.1.1:80", false},
|
||||
{[]string{"192.168.1.1:80"}, false, "192.168.1.1", false},
|
||||
{[]string{"192.168.1.1:80"}, true, "192.168.1.1", true},
|
||||
{[]string{"192.168.1.1:80"}, false, "192.168.1.1:80", true},
|
||||
{[]string{"192.168.1.1:80"}, true, "192.168.1.1:80", false},
|
||||
{[]string{"192.168.1.1:80"}, false, "192.168.1.1:80", false},
|
||||
{[]string{"192.168.1.1:80"}, true, "192.168.1.1:80", true},
|
||||
{[]string{"192.168.1.1:80"}, false, "192.168.1.1:8080", false},
|
||||
{[]string{"192.168.1.1:80"}, true, "192.168.1.1:8080", true},
|
||||
|
||||
{[]string{"example.com"}, false, "example.com:80", false},
|
||||
{[]string{"example.com"}, true, "example.com:80", true},
|
||||
{[]string{"example.com"}, false, "example.com:80", true},
|
||||
{[]string{"example.com"}, true, "example.com:80", false},
|
||||
{[]string{"example.com:80"}, false, "example.com", false},
|
||||
{[]string{"example.com:80"}, true, "example.com", true},
|
||||
{[]string{"example.com:80"}, false, "example.com:80", true},
|
||||
{[]string{"example.com:80"}, true, "example.com:80", false},
|
||||
{[]string{"example.com:80"}, false, "example.com:80", false},
|
||||
{[]string{"example.com:80"}, true, "example.com:80", true},
|
||||
{[]string{"example.com:80"}, false, "example.com:8080", false},
|
||||
{[]string{"example.com:80"}, true, "example.com:8080", true},
|
||||
|
||||
@ -139,18 +139,20 @@ var bypassContainTests = []struct {
|
||||
{[]string{".example.com"}, false, "example.com", true},
|
||||
{[]string{".example.com"}, false, "www.example.com.cn", false},
|
||||
|
||||
{[]string{"example.com*"}, false, "example.com", true},
|
||||
{[]string{"example.com:*"}, false, "example.com", false},
|
||||
{[]string{"example.com:*"}, false, "example.com:80", true},
|
||||
{[]string{"example.com:*"}, false, "example.com:8080", true},
|
||||
{[]string{"example.com:*"}, false, "example.com:80", false},
|
||||
{[]string{"example.com:*"}, false, "example.com:8080", false},
|
||||
{[]string{"example.com:*"}, false, "example.com:http", true},
|
||||
{[]string{"example.com:*"}, false, "http://example.com:80", false},
|
||||
|
||||
{[]string{"*example.com:*"}, false, "example.com:80", true},
|
||||
{[]string{"*example.com*"}, false, "example.com:80", true},
|
||||
{[]string{"*example.com:*"}, false, "example.com:80", false},
|
||||
|
||||
{[]string{".example.com:*"}, false, "www.example.com", false},
|
||||
{[]string{".example.com:*"}, false, "http://www.example.com", false},
|
||||
{[]string{".example.com:*"}, false, "example.com:80", true},
|
||||
{[]string{".example.com:*"}, false, "www.example.com:8080", true},
|
||||
{[]string{".example.com:*"}, false, "example.com:80", false},
|
||||
{[]string{".example.com:*"}, false, "www.example.com:8080", false},
|
||||
{[]string{".example.com:*"}, false, "http://www.example.com:80", true},
|
||||
}
|
||||
|
||||
|
25
gost.go
25
gost.go
@ -9,6 +9,7 @@ import (
|
||||
"encoding/pem"
|
||||
"io"
|
||||
"math/big"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
@ -27,15 +28,33 @@ var (
|
||||
largeBufferSize = 32 * 1024 // 32KB large buffer
|
||||
)
|
||||
|
||||
var (
|
||||
sPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, smallBufferSize)
|
||||
},
|
||||
}
|
||||
mPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, mediumBufferSize)
|
||||
},
|
||||
}
|
||||
lPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, largeBufferSize)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
// KeepAliveTime is the keep alive time period for TCP connection.
|
||||
KeepAliveTime = 180 * time.Second
|
||||
// DialTimeout is the timeout of dial.
|
||||
DialTimeout = 30 * time.Second
|
||||
DialTimeout = 5 * time.Second
|
||||
// ReadTimeout is the timeout for reading.
|
||||
ReadTimeout = 30 * time.Second
|
||||
ReadTimeout = 5 * time.Second
|
||||
// WriteTimeout is the timeout for writing.
|
||||
WriteTimeout = 60 * time.Second
|
||||
WriteTimeout = 5 * time.Second
|
||||
// PingTimeout is the timeout for pinging.
|
||||
PingTimeout = 30 * time.Second
|
||||
// PingRetries is the reties of ping.
|
||||
|
17
server.go
17
server.go
@ -3,7 +3,6 @@ package gost
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
@ -137,27 +136,19 @@ func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
|
||||
return tc, nil
|
||||
}
|
||||
|
||||
var (
|
||||
trPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, 32*1024)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func transport(rw1, rw2 io.ReadWriter) error {
|
||||
errc := make(chan error, 1)
|
||||
go func() {
|
||||
buf := trPool.Get().([]byte)
|
||||
defer trPool.Put(buf)
|
||||
buf := lPool.Get().([]byte)
|
||||
defer lPool.Put(buf)
|
||||
|
||||
_, err := io.CopyBuffer(rw1, rw2, buf)
|
||||
errc <- err
|
||||
}()
|
||||
|
||||
go func() {
|
||||
buf := trPool.Get().([]byte)
|
||||
defer trPool.Put(buf)
|
||||
buf := lPool.Get().([]byte)
|
||||
defer lPool.Put(buf)
|
||||
|
||||
_, err := io.CopyBuffer(rw2, rw1, buf)
|
||||
errc <- err
|
||||
|
250
socks.go
250
socks.go
@ -9,6 +9,7 @@ import (
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ginuerzh/gosocks4"
|
||||
@ -254,6 +255,131 @@ func (c *socks5Connector) Connect(conn net.Conn, addr string, options ...Connect
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
type socks5BindConnector struct {
|
||||
User *url.Userinfo
|
||||
}
|
||||
|
||||
// SOCKS5BindConnector creates a connector for SOCKS5 bind.
|
||||
// It accepts an optional auth info for SOCKS5 Username/Password Authentication.
|
||||
func SOCKS5BindConnector(user *url.Userinfo) Connector {
|
||||
return &socks5BindConnector{User: user}
|
||||
}
|
||||
|
||||
func (c *socks5BindConnector) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) {
|
||||
cc, err := socks5Handshake(conn, c.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn = cc
|
||||
|
||||
laddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||
if err != nil {
|
||||
log.Log(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := gosocks5.NewRequest(gosocks5.CmdBind, &gosocks5.Addr{
|
||||
Type: gosocks5.AddrIPv4,
|
||||
Host: laddr.IP.String(),
|
||||
Port: uint16(laddr.Port),
|
||||
})
|
||||
|
||||
if err := req.Write(conn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if Debug {
|
||||
log.Log("[socks5] bind\n", req)
|
||||
}
|
||||
|
||||
conn.SetReadDeadline(time.Now().Add(ReadTimeout))
|
||||
reply, err := gosocks5.ReadReply(conn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
|
||||
if Debug {
|
||||
log.Log("[socks5] bind\n", reply)
|
||||
}
|
||||
|
||||
if reply.Rep != gosocks5.Succeeded {
|
||||
log.Logf("[socks5] bind on %s failure", addr)
|
||||
return nil, fmt.Errorf("SOCKS5 bind on %s failure", addr)
|
||||
}
|
||||
baddr, err := net.ResolveTCPAddr("tcp", reply.Addr.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Logf("[socks5] bind on %s OK", baddr)
|
||||
|
||||
return &socks5BindConn{Conn: conn, laddr: baddr}, nil
|
||||
}
|
||||
|
||||
type socks5UDPConnector struct {
|
||||
User *url.Userinfo
|
||||
}
|
||||
|
||||
// SOCKS5UDPConnector creates a connector for SOCKS5 UDP relay.
|
||||
// It accepts an optional auth info for SOCKS5 Username/Password Authentication.
|
||||
func SOCKS5UDPConnector(user *url.Userinfo) Connector {
|
||||
return &socks5UDPConnector{User: user}
|
||||
}
|
||||
|
||||
func (c *socks5UDPConnector) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) {
|
||||
cc, err := socks5Handshake(conn, c.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn = cc
|
||||
|
||||
taddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := gosocks5.NewRequest(gosocks5.CmdUdp, &gosocks5.Addr{
|
||||
Type: gosocks5.AddrIPv4,
|
||||
})
|
||||
|
||||
if err := req.Write(conn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if Debug {
|
||||
log.Log("[socks5] udp\n", req)
|
||||
}
|
||||
|
||||
conn.SetReadDeadline(time.Now().Add(ReadTimeout))
|
||||
reply, err := gosocks5.ReadReply(conn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
|
||||
if Debug {
|
||||
log.Log("[socks5] udp\n", reply)
|
||||
}
|
||||
|
||||
if reply.Rep != gosocks5.Succeeded {
|
||||
log.Logf("[socks5] udp relay failure")
|
||||
return nil, fmt.Errorf("SOCKS5 udp relay failure")
|
||||
}
|
||||
baddr, err := net.ResolveUDPAddr("udp", reply.Addr.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Logf("[socks5] udp associate on %s OK", baddr)
|
||||
|
||||
uc, err := net.DialUDP("udp", nil, baddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Logf("udp laddr:%s, raddr:%s", uc.LocalAddr(), uc.RemoteAddr())
|
||||
|
||||
return &socks5UDPConn{UDPConn: uc, taddr: taddr}, nil
|
||||
}
|
||||
|
||||
type socks4Connector struct{}
|
||||
|
||||
// SOCKS4Connector creates a Connector for SOCKS4 proxy client.
|
||||
@ -773,7 +899,8 @@ func (h *socks5Handler) transportUDP(relay, peer *net.UDPConn) (err error) {
|
||||
var clientAddr *net.UDPAddr
|
||||
|
||||
go func() {
|
||||
b := make([]byte, largeBufferSize)
|
||||
b := mPool.Get().([]byte)
|
||||
defer mPool.Put(b)
|
||||
|
||||
for {
|
||||
n, laddr, err := relay.ReadFromUDP(b)
|
||||
@ -809,7 +936,8 @@ func (h *socks5Handler) transportUDP(relay, peer *net.UDPConn) (err error) {
|
||||
}()
|
||||
|
||||
go func() {
|
||||
b := make([]byte, largeBufferSize)
|
||||
b := mPool.Get().([]byte)
|
||||
defer mPool.Put(b)
|
||||
|
||||
for {
|
||||
n, raddr, err := peer.ReadFromUDP(b)
|
||||
@ -851,7 +979,8 @@ func (h *socks5Handler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error
|
||||
var clientAddr *net.UDPAddr
|
||||
|
||||
go func() {
|
||||
b := make([]byte, mediumBufferSize)
|
||||
b := mPool.Get().([]byte)
|
||||
defer mPool.Put(b)
|
||||
|
||||
for {
|
||||
n, addr, err := uc.ReadFromUDP(b)
|
||||
@ -990,7 +1119,8 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error
|
||||
errc := make(chan error, 2)
|
||||
|
||||
go func() {
|
||||
b := make([]byte, mediumBufferSize)
|
||||
b := mPool.Get().([]byte)
|
||||
defer mPool.Put(b)
|
||||
|
||||
for {
|
||||
n, addr, err := uc.ReadFromUDP(b)
|
||||
@ -1453,3 +1583,115 @@ func (c *udpTunnelConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// socks5BindConn is a connection for SOCKS5 bind request.
|
||||
type socks5BindConn struct {
|
||||
raddr net.Addr
|
||||
laddr net.Addr
|
||||
net.Conn
|
||||
handshaked bool
|
||||
handshakeMux sync.Mutex
|
||||
}
|
||||
|
||||
// Handshake waits for a peer to connect to the bind port.
|
||||
func (c *socks5BindConn) Handshake() (err error) {
|
||||
c.handshakeMux.Lock()
|
||||
defer c.handshakeMux.Unlock()
|
||||
|
||||
if c.handshaked {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.handshaked = true
|
||||
|
||||
rep, err := gosocks5.ReadReply(c.Conn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("bind: read reply %v", err)
|
||||
}
|
||||
if rep.Rep != gosocks5.Succeeded {
|
||||
return fmt.Errorf("bind: peer connect failure")
|
||||
}
|
||||
c.raddr, err = net.ResolveTCPAddr("tcp", rep.Addr.String())
|
||||
return
|
||||
}
|
||||
|
||||
func (c *socks5BindConn) Read(b []byte) (n int, err error) {
|
||||
if err = c.Handshake(); err != nil {
|
||||
return
|
||||
}
|
||||
return c.Conn.Read(b)
|
||||
}
|
||||
|
||||
func (c *socks5BindConn) Write(b []byte) (n int, err error) {
|
||||
if err = c.Handshake(); err != nil {
|
||||
return
|
||||
}
|
||||
return c.Conn.Write(b)
|
||||
}
|
||||
|
||||
func (c *socks5BindConn) LocalAddr() net.Addr {
|
||||
return c.laddr
|
||||
}
|
||||
|
||||
func (c *socks5BindConn) RemoteAddr() net.Addr {
|
||||
return c.raddr
|
||||
}
|
||||
|
||||
type socks5UDPConn struct {
|
||||
*net.UDPConn
|
||||
taddr net.Addr
|
||||
}
|
||||
|
||||
func (c *socks5UDPConn) Read(b []byte) (int, error) {
|
||||
data := mPool.Get().([]byte)
|
||||
defer mPool.Put(data)
|
||||
|
||||
n, err := c.UDPConn.Read(data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
dg, err := gosocks5.ReadUDPDatagram(bytes.NewReader(data[:n]))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return copy(b, dg.Data), nil
|
||||
}
|
||||
|
||||
func (c *socks5UDPConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
||||
dg, err := gosocks5.ReadUDPDatagram(c.UDPConn)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
n = copy(b, dg.Data)
|
||||
addr, err = net.ResolveUDPAddr("udp", dg.Header.Addr.String())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *socks5UDPConn) Write(b []byte) (int, error) {
|
||||
addr, err := gosocks5.NewAddr(c.taddr.String())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
h := gosocks5.NewUDPHeader(0, 0, addr)
|
||||
dg := gosocks5.NewUDPDatagram(h, b)
|
||||
if err = dg.Write(c.UDPConn); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
func (c *socks5UDPConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
||||
adr, err := gosocks5.NewAddr(addr.String())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
h := gosocks5.NewUDPHeader(0, 0, adr)
|
||||
dg := gosocks5.NewUDPDatagram(h, b)
|
||||
if err = dg.Write(c.UDPConn); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
125
socks_test.go
125
socks_test.go
@ -2,7 +2,7 @@ package gost
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
@ -51,14 +51,6 @@ func socks5ProxyRoundtrip(targetURL string, data []byte, clientInfo *url.Userinf
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
@ -84,14 +76,6 @@ func TestSOCKS5Proxy(t *testing.T) {
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
@ -124,14 +108,6 @@ func BenchmarkSOCKS5Proxy(b *testing.B) {
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
@ -365,3 +341,102 @@ func BenchmarkSOCKS4AProxyParallel(b *testing.B) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func socks5BindRoundtrip(t *testing.T, targetURL string, data []byte) (err error) {
|
||||
ln, err := TCPListener("")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: SOCKS5BindConnector(url.UserPassword("admin", "123456")),
|
||||
Transporter: TCPTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Handler: SOCKS5Handler(UsersHandlerOption(url.UserPassword("admin", "123456"))),
|
||||
Listener: ln,
|
||||
}
|
||||
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
conn, err := proxyConn(client, server)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
conn, err = client.Connect(conn, "")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cc, err := net.Dial("tcp", conn.LocalAddr().String())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer cc.Close()
|
||||
|
||||
if err = conn.(*socks5BindConn).Handshake(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
u, err := url.Parse(targetURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
hc, err := net.Dial("tcp", u.Host)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
go transport(hc, conn)
|
||||
|
||||
return httpRoundtrip(cc, targetURL, data)
|
||||
}
|
||||
|
||||
func TestSOCKS5Bind(t *testing.T) {
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
if err := socks5BindRoundtrip(t, httpSrv.URL, sendData); err != nil {
|
||||
t.Errorf("got error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func socks5UDPRoundtrip(t *testing.T, host string, data []byte) (err error) {
|
||||
ln, err := TCPListener("")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: SOCKS5UDPConnector(url.UserPassword("admin", "123456")),
|
||||
Transporter: TCPTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Handler: SOCKS5Handler(UsersHandlerOption(url.UserPassword("admin", "123456"))),
|
||||
Listener: ln,
|
||||
}
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
return udpRoundtrip(client, server, host, data)
|
||||
}
|
||||
|
||||
func TestSOCKS5UDP(t *testing.T) {
|
||||
udpSrv := newUDPTestServer(udpTestHandler)
|
||||
udpSrv.Start()
|
||||
defer udpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
if err := socks5UDPRoundtrip(t, udpSrv.Addr(), sendData); err != nil {
|
||||
t.Errorf("got error: %v", err)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user