go-socks5/server_test.go

294 lines
6.6 KiB
Go
Raw Normal View History

2014-01-23 22:16:44 +00:00
package socks5
import (
"bytes"
"io"
"log"
2014-01-23 22:16:44 +00:00
"net"
"os"
2014-01-23 22:16:44 +00:00
"testing"
"time"
2020-04-20 11:56:35 +00:00
"golang.org/x/net/proxy"
2014-01-23 22:16:44 +00:00
)
func TestSOCKS5_Connect(t *testing.T) {
// Create a local listener
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("err: %v", err)
}
go func() {
conn, err := l.Accept()
if err != nil {
t.Fatalf("err: %v", err)
}
defer conn.Close()
buf := make([]byte, 4)
if _, err := io.ReadAtLeast(conn, buf, 4); err != nil {
t.Fatalf("err: %v", err)
}
if !bytes.Equal(buf, []byte("ping")) {
t.Fatalf("bad: %v", buf)
}
2020-04-22 02:32:03 +00:00
_, _ = conn.Write([]byte("pong"))
2014-01-23 22:16:44 +00:00
}()
lAddr := l.Addr().(*net.TCPAddr)
// Create a socks server
2020-04-20 08:19:51 +00:00
cator := UserPassAuthenticator{
Credentials: StaticCredentials{"foo": "bar"},
2014-01-23 22:16:44 +00:00
}
2020-04-20 13:17:38 +00:00
serv := New(
WithAuthMethods([]Authenticator{cator}),
WithLogger(NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags))),
)
2014-01-23 22:16:44 +00:00
// Start listening
go func() {
if err := serv.ListenAndServe("tcp", "127.0.0.1:12365"); err != nil {
t.Fatalf("err: %v", err)
}
}()
time.Sleep(10 * time.Millisecond)
// Get a local conn
conn, err := net.Dial("tcp", "127.0.0.1:12365")
if err != nil {
t.Fatalf("err: %v", err)
}
// Connect, auth and connec to local
2020-04-20 08:19:51 +00:00
req := new(bytes.Buffer)
2020-04-21 06:03:20 +00:00
req.Write([]byte{VersionSocks5, 2, MethodNoAuth, MethodUserPassAuth})
req.Write([]byte{UserPassAuthVersion, 3, 'f', 'o', 'o', 3, 'b', 'a', 'r'})
2020-04-20 08:19:51 +00:00
reqHead := Header{
2020-04-21 06:03:20 +00:00
Version: VersionSocks5,
Command: CommandConnect,
2020-04-20 08:19:51 +00:00
Reserved: 0,
Address: AddrSpec{
"",
net.ParseIP("127.0.0.1"),
lAddr.Port,
},
2020-04-21 06:03:20 +00:00
addrType: ATYPIPv4,
2020-04-20 08:19:51 +00:00
}
req.Write(reqHead.Bytes())
2014-01-23 22:16:44 +00:00
// Send a ping
req.Write([]byte("ping"))
// Send all the bytes
conn.Write(req.Bytes())
// Verify response
expected := []byte{
2020-04-21 06:03:20 +00:00
VersionSocks5, MethodUserPassAuth, // use user password auth
UserPassAuthVersion, AuthSuccess, // response auth success
2014-01-23 22:16:44 +00:00
}
2020-04-20 08:19:51 +00:00
rspHead := Header{
2020-04-21 06:03:20 +00:00
Version: VersionSocks5,
2020-04-22 02:32:03 +00:00
Command: RepSuccess,
2020-04-20 08:19:51 +00:00
Reserved: 0,
Address: AddrSpec{
"",
net.ParseIP("127.0.0.1"),
0, // Ignore the port
},
2020-04-21 06:03:20 +00:00
addrType: ATYPIPv4,
2020-04-20 08:19:51 +00:00
}
expected = append(expected, rspHead.Bytes()...)
expected = append(expected, []byte("pong")...)
2014-01-23 22:16:44 +00:00
out := make([]byte, len(expected))
2020-04-22 02:32:03 +00:00
_ = conn.SetDeadline(time.Now().Add(time.Second))
2020-04-20 08:19:51 +00:00
if _, err := io.ReadFull(conn, out); err != nil {
t.Fatalf("err: %v", err)
}
t.Logf("proxy bind port: %d", buildPort(out[12], out[13]))
// Ignore the port
out[12] = 0
out[13] = 0
if !bytes.Equal(out, expected) {
t.Fatalf("bad: %v", out)
}
}
2014-01-23 22:16:44 +00:00
2020-04-20 08:19:51 +00:00
func TestSOCKS5_Associate(t *testing.T) {
locIP := net.ParseIP("127.0.0.1")
// Create a local listener
lAddr := &net.UDPAddr{
IP: locIP,
Port: 12398,
}
2020-04-20 09:09:16 +00:00
l, err := net.ListenUDP("udp", lAddr)
2020-04-20 08:19:51 +00:00
if err != nil {
t.Fatalf("err: %v", err)
}
defer l.Close()
go func() {
buf := make([]byte, 2048)
for {
n, remote, err := l.ReadFrom(buf)
if err != nil {
return
}
2020-04-23 15:40:00 +00:00
2020-04-20 08:19:51 +00:00
if !bytes.Equal(buf[:n], []byte("ping")) {
t.Fatalf("bad: %v", buf)
}
2020-04-22 02:32:03 +00:00
_, _ = l.WriteTo([]byte("pong"), remote)
2020-04-20 08:19:51 +00:00
}
}()
// Create a socks server
cator := UserPassAuthenticator{Credentials: StaticCredentials{"foo": "bar"}}
2020-04-20 13:17:38 +00:00
serv := New(
WithAuthMethods([]Authenticator{cator}),
WithLogger(NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags))),
)
2020-04-20 08:19:51 +00:00
// Start listening
go func() {
if err := serv.ListenAndServe("tcp", "127.0.0.1:12355"); err != nil {
t.Fatalf("err: %v", err)
}
}()
time.Sleep(10 * time.Millisecond)
// Get a local conn
conn, err := net.Dial("tcp", "127.0.0.1:12355")
if err != nil {
t.Fatalf("err: %v", err)
}
// Connect, auth and connec to local
req := new(bytes.Buffer)
2020-04-21 06:03:20 +00:00
req.Write([]byte{VersionSocks5, 2, MethodNoAuth, MethodUserPassAuth})
req.Write([]byte{UserPassAuthVersion, 3, 'f', 'o', 'o', 3, 'b', 'a', 'r'})
2020-04-20 08:19:51 +00:00
reqHead := Header{
2020-04-21 06:03:20 +00:00
Version: VersionSocks5,
Command: CommandAssociate,
2020-04-20 08:19:51 +00:00
Reserved: 0,
Address: AddrSpec{
"",
locIP,
lAddr.Port,
},
2020-04-21 06:03:20 +00:00
addrType: ATYPIPv4,
2020-04-20 08:19:51 +00:00
}
req.Write(reqHead.Bytes())
// Send all the bytes
conn.Write(req.Bytes())
// Verify response
expected := []byte{
2020-04-21 06:03:20 +00:00
VersionSocks5, MethodUserPassAuth, // use user password auth
UserPassAuthVersion, AuthSuccess, // response auth success
2020-04-20 08:19:51 +00:00
}
out := make([]byte, len(expected))
2020-04-22 02:32:03 +00:00
_ = conn.SetDeadline(time.Now().Add(time.Second))
2020-04-20 08:19:51 +00:00
if _, err := io.ReadFull(conn, out); err != nil {
2014-01-23 22:16:44 +00:00
t.Fatalf("err: %v", err)
}
if !bytes.Equal(out, expected) {
t.Fatalf("bad: %v", out)
}
2020-04-20 08:19:51 +00:00
2020-08-05 02:34:29 +00:00
rspHead, err := ParseHeader(conn)
2020-04-20 09:09:16 +00:00
if err != nil {
t.Fatalf("bad response header: %v", err)
}
2020-04-22 02:32:03 +00:00
if rspHead.Version != VersionSocks5 && rspHead.Command != RepSuccess {
2020-04-20 09:09:16 +00:00
t.Fatalf("parse success but bad header: %v", rspHead)
}
t.Logf("proxy bind listen port: %d", rspHead.Address.Port)
udpConn, err := net.DialUDP("udp", nil, &net.UDPAddr{
IP: locIP,
Port: rspHead.Address.Port,
2020-04-20 08:19:51 +00:00
})
if err != nil {
t.Fatalf("bad dial: %v", err)
}
// Send a ping
2020-04-22 02:32:03 +00:00
_, _ = udpConn.Write(append([]byte{0, 0, 0, ATYPIPv4, 0, 0, 0, 0, 0, 0}, []byte("ping")...))
2020-04-20 08:19:51 +00:00
response := make([]byte, 1024)
n, _, err := udpConn.ReadFrom(response)
2020-04-22 02:32:03 +00:00
if err != nil || !bytes.Equal(response[n-4:n], []byte("pong")) {
2020-04-20 08:19:51 +00:00
t.Fatalf("bad udp read: %v", string(response[:n]))
}
time.Sleep(time.Second * 1)
2014-01-23 22:16:44 +00:00
}
2020-04-20 11:56:35 +00:00
func Test_SocksWithProxy(t *testing.T) {
// Create a local listener
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("err: %v", err)
}
go func() {
conn, err := l.Accept()
if err != nil {
t.Fatalf("err: %v", err)
}
defer conn.Close()
buf := make([]byte, 4)
if _, err := io.ReadAtLeast(conn, buf, 4); err != nil {
t.Fatalf("err: %v", err)
}
if !bytes.Equal(buf, []byte("ping")) {
t.Fatalf("bad: %v", buf)
}
conn.Write([]byte("pong"))
}()
lAddr := l.Addr().(*net.TCPAddr)
// Create a socks server
cator := UserPassAuthenticator{Credentials: StaticCredentials{"foo": "bar"}}
2020-04-20 13:17:38 +00:00
serv := New(
WithAuthMethods([]Authenticator{cator}),
WithLogger(NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags))),
)
2020-04-20 11:56:35 +00:00
// Start listening
go func() {
if err := serv.ListenAndServe("tcp", "127.0.0.1:12395"); err != nil {
t.Fatalf("err: %v", err)
}
}()
time.Sleep(10 * time.Millisecond)
2020-04-21 14:28:34 +00:00
dial, err := proxy.SOCKS5("tcp", "127.0.0.1:12395", &proxy.Auth{User: "foo", Password: "bar"}, proxy.Direct)
2020-04-20 11:56:35 +00:00
if err != nil {
t.Fatalf("err: %v", err)
}
// Connect, auth and connect to local
conn, err := dial.Dial("tcp", lAddr.String())
if err != nil {
t.Fatalf("err: %v", err)
}
// Send a ping
2020-04-22 02:32:03 +00:00
_, _ = conn.Write([]byte("ping"))
2020-04-20 11:56:35 +00:00
out := make([]byte, 4)
2020-04-22 02:32:03 +00:00
_ = conn.SetDeadline(time.Now().Add(time.Second))
2020-04-20 11:56:35 +00:00
if _, err := io.ReadFull(conn, out); err != nil {
t.Fatalf("err: %v", err)
}
if !bytes.Equal(out, []byte("pong")) {
t.Fatalf("bad: %v", out)
}
}